From 5d8abb65e126abce2a4d21e24808216910ad663c Mon Sep 17 00:00:00 2001 From: Chris Loer Date: Tue, 21 Aug 2018 12:12:15 -0700 Subject: [core] Mark allow-overlap symbols visible even outside of collision grid. Fixes issue #12683. --- src/mbgl/text/placement.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) 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(); + const bool iconAllowOverlap = bucket.layout.get(); + // 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()); + const bool alwaysShowIcon = iconAllowOverlap && (textAllowOverlap || !bucket.hasTextData() || bucket.layout.get()); + 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); } } -- cgit v1.2.1 From 50f9381ad3538045a84a0cf6d51dc9f2252d1c2d Mon Sep 17 00:00:00 2001 From: Chris Loer Date: Wed, 5 Sep 2018 12:07:58 -0700 Subject: [core] Fix cubic-bezier interpolation for zooms outside stop range. Fixes issue #12812. Using `util::interpolationFactor` handles the case where inputLevels.min == inputLevels.max, so it returns an interpolation factor of "0" instead of dividing by 0. --- include/mbgl/style/expression/interpolator.hpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) 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& inputLevels, const double input) const { - return ub.solve(input / (inputLevels.max - inputLevels.min), 1e-6); + return ub.solve(util::interpolationFactor(1.0, + Range { + static_cast(inputLevels.min), + static_cast(inputLevels.max) + }, + input), + 1e-6); } bool operator==(const CubicBezierInterpolator& rhs) const { -- cgit v1.2.1 From 3ca20500bdef7f5c1b8ac789650c68c4a9ffda72 Mon Sep 17 00:00:00 2001 From: Jason Wray Date: Thu, 6 Sep 2018 18:22:37 -0400 Subject: [ios] Simplify 4.4.0 changelog text --- platform/ios/CHANGELOG.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index e7c061aff1..dc78220b48 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -26,9 +26,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 -- cgit v1.2.1 From 794ba54a27ca1a3db89966157d3c6c40b9941aed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Paczos?= Date: Fri, 24 Aug 2018 19:53:56 +0200 Subject: [android] minor reference app fixes --- .../src/main/AndroidManifest.xml | 15 +++++++++ .../activity/annotation/PolylineActivity.java | 2 +- .../annotation/PressForMarkerActivity.java | 8 +++-- .../activity/camera/LatLngBoundsActivity.java | 6 ++++ .../feature/QuerySourceFeaturesActivity.java | 39 +++++++++++++++------- .../activity/maplayout/DoubleMapActivity.java | 2 +- .../snapshot/MapSnapshotterReuseActivity.java | 14 ++++---- .../activity/style/SymbolGeneratorActivity.java | 2 +- .../res/layout/activity_query_source_features.xml | 24 +++++++++---- 9 files changed, 79 insertions(+), 33 deletions(-) diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml index e23b1d64f3..d9e2001479 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml @@ -266,6 +266,9 @@ + + @@ -716,6 +722,9 @@ + + + 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 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/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/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 features = mapboxMap.queryRenderedFeatures(screenPoint, LAYER_ID); if (!features.isEmpty()) { 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 @@ - + android:layout_height="match_parent" + android:orientation="vertical"> + app:mapbox_cameraTargetLat="51" + app:mapbox_cameraTargetLng="17.25" + app:mapbox_cameraZoom="8" /> - + + + -- cgit v1.2.1 From 1c103fa09a0beef3dd673f831dbfb86f0f456ef3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Paczos?= Date: Fri, 7 Sep 2018 14:07:54 +0200 Subject: [android] "is-supported-script" expression support --- .../mapboxsdk/style/expressions/Expression.java | 60 ++++++++++++++++++++++ .../style/expressions/ExpressionTest.java | 15 ++++++ 2 files changed, 75 insertions(+) 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 @@ -2848,6 +2848,66 @@ public class Expression { return new Expression("resolved-locale", collator); } + /** + * 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). + *

+ * Example usage: + *

+ *
+   * {@code
+   * mapboxMap.addLayer(new SymbolLayer("layer-id", "source-id")
+   *   .withProperties(
+   *     textField(
+   *       switchCase(
+   *         isSupportedScript(get("name_property")), get("name_property"),
+   *         literal("not-compatible")
+   *       )
+   *     )
+   *   ));
+   * }
+   * 
+ * + * @param expression the expression to evaluate + * @return expression + * @see Style specification + */ + 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). + *

+ * Example usage: + *

+ *
+   * {@code
+   * mapboxMap.addLayer(new SymbolLayer("layer-id", "source-id")
+   * .withProperties(
+   *   textField(
+   *     switchCase(
+   *       isSupportedScript("ಗೌರವಾರ್ಥವಾಗಿ"), literal("ಗೌರವಾರ್ಥವಾಗಿ"),
+   *       literal("not-compatible")
+   *     )
+   *   )
+   * );
+   * }
+   * 
+ * + * @param string the string to evaluate + * @return expression + * @see Style specification + */ + public static Expression isSupportedScript(String string) { + return new Expression("is-supported-script", literal(string)); + } + /** * Returns the input string converted to uppercase. *

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 -- cgit v1.2.1 From 6806ba5b52129050c0944bd7c8b1fe285baeeddc Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Tue, 21 Aug 2018 11:39:05 -0700 Subject: [android] Put function inverses next to each other --- platform/android/src/conversion/collection.cpp | 15 +++++++++++++ platform/android/src/conversion/collection.hpp | 1 + platform/android/src/jni/collection.hpp | 26 ----------------------- platform/android/src/snapshotter/map_snapshot.cpp | 4 ++-- 4 files changed, 18 insertions(+), 28 deletions(-) delete mode 100644 platform/android/src/jni/collection.hpp diff --git a/platform/android/src/conversion/collection.cpp b/platform/android/src/conversion/collection.cpp index 27b614e8cd..6775228e15 100644 --- a/platform/android/src/conversion/collection.cpp +++ b/platform/android/src/conversion/collection.cpp @@ -19,6 +19,21 @@ std::vector toVector(JNIEnv& env, jni::Array array) { return vector; } +jni::Array toArray(JNIEnv& env, const std::vector& vector) { + static auto clazz = *jni::Class::Find(env).NewGlobalRef(env).release(); + auto result = jni::Array::New(env, vector.size(), clazz); + + std::size_t index = 0; + for (auto&& item : vector) { + auto element = jni::Make(env, item); + result.Set(env, index, element); + DeleteLocalRef(env, element); + index++; + } + + return result; +} + } } } diff --git a/platform/android/src/conversion/collection.hpp b/platform/android/src/conversion/collection.hpp index bb8941c984..c6b08370ee 100644 --- a/platform/android/src/conversion/collection.hpp +++ b/platform/android/src/conversion/collection.hpp @@ -11,6 +11,7 @@ namespace android { namespace conversion { std::vector toVector(JNIEnv& env, jni::Array array); +jni::Array toArray(JNIEnv& env, const std::vector&); } } 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 - -#include -#include - -namespace jni { - -inline Array MakeAnything(ThingToMake>, JNIEnv& env, const std::vector& vector) -{ - static auto clazz = *Class::Find(env).NewGlobalRef(env).release(); - auto result = Array::New(env, vector.size(), clazz); - - std::size_t index = 0; - for (auto&& item : vector) { - auto element = Make(env, item); - result.Set(env, index, element); - DeleteLocalRef(env, element); - index++; - } - - return result; -} - -} diff --git a/platform/android/src/snapshotter/map_snapshot.cpp b/platform/android/src/snapshotter/map_snapshot.cpp index 42c1c16ca1..379ac89d52 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 @@ -40,7 +40,7 @@ jni::Object MapSnapshot::New(JNIEnv& env, // Create the Mapsnapshot peers static auto constructor = javaClass.GetConstructor, jni::Array, jni::jboolean>(env); auto nativePeer = std::make_unique(pixelRatio, pointForFn, latLngForFn); - return javaClass.New(env, constructor, reinterpret_cast(nativePeer.release()), bitmap, jni::Make>(env, attributions), (jni::jboolean) showLogo); + return javaClass.New(env, constructor, reinterpret_cast(nativePeer.release()), bitmap, conversion::toArray(env, attributions), (jni::jboolean) showLogo); } jni::Class MapSnapshot::javaClass; -- cgit v1.2.1 From 53c3c327f0ebea276d977f58a59cdb9449165518 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 17 Aug 2018 13:43:07 -0700 Subject: [android] Upgrade to latest jni.hpp --- cmake/mason-dependencies.cmake | 2 +- platform/android/core-files.txt | 2 - platform/android/src/annotation/marker.cpp | 22 +-- platform/android/src/annotation/marker.hpp | 2 - platform/android/src/annotation/multi_point.hpp | 14 +- platform/android/src/annotation/polygon.cpp | 39 +++-- platform/android/src/annotation/polygon.hpp | 2 - platform/android/src/annotation/polyline.cpp | 23 ++- platform/android/src/annotation/polyline.hpp | 2 - platform/android/src/asset_manager_file_source.hpp | 2 +- platform/android/src/bitmap.cpp | 37 ++--- platform/android/src/bitmap.hpp | 16 +- platform/android/src/bitmap_factory.cpp | 10 +- platform/android/src/bitmap_factory.hpp | 7 +- platform/android/src/connectivity_listener.cpp | 6 +- platform/android/src/connectivity_listener.hpp | 2 - platform/android/src/conversion/collection.cpp | 17 +-- platform/android/src/file_source.cpp | 31 ++-- platform/android/src/file_source.hpp | 4 - .../android/src/geojson/conversion/feature.cpp | 162 ++------------------- .../android/src/geojson/conversion/feature.hpp | 11 -- platform/android/src/geojson/feature.cpp | 43 +++--- platform/android/src/geojson/feature.hpp | 3 - .../android/src/geojson/feature_collection.cpp | 21 +-- .../android/src/geojson/feature_collection.hpp | 2 - platform/android/src/geojson/geometry.cpp | 27 ++-- platform/android/src/geojson/geometry.hpp | 5 +- .../android/src/geojson/geometry_collection.cpp | 36 ++--- .../android/src/geojson/geometry_collection.hpp | 2 - platform/android/src/geojson/line_string.cpp | 30 ++-- platform/android/src/geojson/line_string.hpp | 2 - platform/android/src/geojson/multi_line_string.cpp | 31 ++-- platform/android/src/geojson/multi_line_string.hpp | 2 - platform/android/src/geojson/multi_point.cpp | 20 +-- platform/android/src/geojson/multi_point.hpp | 2 - platform/android/src/geojson/multi_polygon.cpp | 44 ++---- platform/android/src/geojson/multi_polygon.hpp | 2 - platform/android/src/geojson/point.cpp | 29 ++-- platform/android/src/geojson/point.hpp | 2 - platform/android/src/geojson/polygon.cpp | 19 +-- platform/android/src/geojson/polygon.hpp | 2 - platform/android/src/geojson/util.hpp | 22 +-- platform/android/src/geometry/lat_lng.cpp | 16 +- platform/android/src/geometry/lat_lng.hpp | 2 - platform/android/src/geometry/lat_lng_bounds.cpp | 20 ++- platform/android/src/geometry/lat_lng_bounds.hpp | 3 - platform/android/src/geometry/lat_lng_quad.cpp | 20 ++- platform/android/src/geometry/lat_lng_quad.hpp | 3 - platform/android/src/geometry/projected_meters.cpp | 11 +- platform/android/src/geometry/projected_meters.hpp | 5 - platform/android/src/graphics/pointf.cpp | 16 +- platform/android/src/graphics/pointf.hpp | 3 - platform/android/src/graphics/rectf.cpp | 18 +-- platform/android/src/graphics/rectf.hpp | 3 - platform/android/src/gson/json_array.cpp | 28 ++-- platform/android/src/gson/json_array.hpp | 8 +- platform/android/src/gson/json_element.cpp | 33 +++-- platform/android/src/gson/json_element.hpp | 9 +- platform/android/src/gson/json_object.cpp | 52 +++---- platform/android/src/gson/json_object.hpp | 8 +- platform/android/src/gson/json_primitive.cpp | 82 +++++------ platform/android/src/gson/json_primitive.hpp | 12 +- platform/android/src/http_file_source.cpp | 11 +- platform/android/src/image.cpp | 13 +- platform/android/src/java/lang.cpp | 76 ---------- platform/android/src/java/lang.hpp | 67 --------- platform/android/src/java/util.cpp | 17 +-- platform/android/src/java/util.hpp | 39 ++--- platform/android/src/jni.cpp | 6 - .../android/src/jni/generic_global_ref_deleter.hpp | 42 +++--- platform/android/src/jni/local_object.hpp | 33 ----- platform/android/src/logger.cpp | 21 ++- platform/android/src/logger.hpp | 3 - platform/android/src/map/camera_position.cpp | 24 ++- platform/android/src/map/camera_position.hpp | 5 - platform/android/src/map/image.cpp | 33 ++--- platform/android/src/map/image.hpp | 5 - platform/android/src/map_renderer.cpp | 14 +- platform/android/src/map_renderer.hpp | 4 +- platform/android/src/map_renderer_runnable.cpp | 9 +- platform/android/src/map_renderer_runnable.hpp | 6 +- platform/android/src/native_map_view.cpp | 48 ++---- platform/android/src/native_map_view.hpp | 4 +- platform/android/src/offline/offline_manager.cpp | 67 +++------ platform/android/src/offline/offline_manager.hpp | 10 -- platform/android/src/offline/offline_region.cpp | 148 +++++++------------ platform/android/src/offline/offline_region.hpp | 18 --- .../src/offline/offline_region_definition.cpp | 94 ++++-------- .../src/offline/offline_region_definition.hpp | 8 - .../android/src/offline/offline_region_error.cpp | 19 +-- .../android/src/offline/offline_region_error.hpp | 2 - .../android/src/offline/offline_region_status.cpp | 5 +- .../android/src/offline/offline_region_status.hpp | 2 - platform/android/src/snapshotter/map_snapshot.cpp | 7 +- platform/android/src/snapshotter/map_snapshot.hpp | 2 - .../android/src/snapshotter/map_snapshotter.cpp | 14 +- .../android/src/snapshotter/map_snapshotter.hpp | 4 +- platform/android/src/style/conversion/filter.cpp | 6 +- platform/android/src/style/conversion/filter.hpp | 2 +- .../android/src/style/layers/background_layer.cpp | 11 +- .../android/src/style/layers/background_layer.hpp | 2 - platform/android/src/style/layers/circle_layer.cpp | 11 +- platform/android/src/style/layers/circle_layer.hpp | 2 - platform/android/src/style/layers/custom_layer.cpp | 11 +- platform/android/src/style/layers/custom_layer.hpp | 6 - .../src/style/layers/fill_extrusion_layer.cpp | 11 +- .../src/style/layers/fill_extrusion_layer.hpp | 2 - platform/android/src/style/layers/fill_layer.cpp | 11 +- platform/android/src/style/layers/fill_layer.hpp | 2 - .../android/src/style/layers/heatmap_layer.cpp | 11 +- .../android/src/style/layers/heatmap_layer.hpp | 2 - .../android/src/style/layers/hillshade_layer.cpp | 11 +- .../android/src/style/layers/hillshade_layer.hpp | 2 - platform/android/src/style/layers/layer.cpp | 12 +- platform/android/src/style/layers/layer.cpp.ejs | 11 +- platform/android/src/style/layers/layer.hpp | 2 - platform/android/src/style/layers/layer.hpp.ejs | 2 - platform/android/src/style/layers/line_layer.cpp | 11 +- platform/android/src/style/layers/line_layer.hpp | 2 - platform/android/src/style/layers/raster_layer.cpp | 11 +- platform/android/src/style/layers/raster_layer.hpp | 2 - platform/android/src/style/layers/symbol_layer.cpp | 11 +- platform/android/src/style/layers/symbol_layer.hpp | 2 - .../android/src/style/layers/unknown_layer.cpp | 11 +- .../android/src/style/layers/unknown_layer.hpp | 2 - platform/android/src/style/light.cpp | 11 +- platform/android/src/style/light.cpp.ejs | 11 +- platform/android/src/style/position.cpp | 19 +-- platform/android/src/style/position.hpp | 5 - .../src/style/sources/custom_geometry_source.cpp | 35 +++-- .../src/style/sources/custom_geometry_source.hpp | 7 +- .../android/src/style/sources/geojson_source.cpp | 23 +-- .../android/src/style/sources/geojson_source.hpp | 17 +-- .../android/src/style/sources/image_source.cpp | 11 +- .../android/src/style/sources/image_source.hpp | 2 - .../src/style/sources/raster_dem_source.cpp | 13 +- .../src/style/sources/raster_dem_source.hpp | 5 - .../android/src/style/sources/raster_source.cpp | 13 +- .../android/src/style/sources/raster_source.hpp | 5 - platform/android/src/style/sources/source.cpp | 7 +- platform/android/src/style/sources/source.hpp | 4 +- .../android/src/style/sources/unknown_source.cpp | 11 +- .../android/src/style/sources/unknown_source.hpp | 2 - .../android/src/style/sources/vector_source.cpp | 16 +- .../android/src/style/sources/vector_source.hpp | 7 +- platform/android/src/style/transition_options.cpp | 11 +- platform/android/src/style/transition_options.hpp | 5 - platform/android/src/style/value.cpp | 52 +++---- platform/android/src/style/value.hpp | 4 +- platform/android/src/text/collator.cpp | 67 ++++----- platform/android/src/text/collator_jni.hpp | 4 - .../android/src/text/local_glyph_rasterizer.cpp | 26 ++-- .../src/text/local_glyph_rasterizer_jni.hpp | 4 +- 153 files changed, 817 insertions(+), 1753 deletions(-) delete mode 100644 platform/android/src/java/lang.cpp delete mode 100644 platform/android/src/java/lang.hpp delete mode 100644 platform/android/src/jni/local_object.hpp diff --git a/cmake/mason-dependencies.cmake b/cmake/mason-dependencies.cmake index 4caa6d4d88..7330f2f3a2 100644 --- a/cmake/mason-dependencies.cmake +++ b/cmake/mason-dependencies.cmake @@ -19,7 +19,7 @@ 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-rc8 HEADER_ONLY) elseif(MBGL_PLATFORM STREQUAL "ios") mason_use(icu VERSION 58.1-min-size) elseif(MBGL_PLATFORM STREQUAL "linux") diff --git a/platform/android/core-files.txt b/platform/android/core-files.txt index eca7529c0b..9a57e76808 100644 --- a/platform/android/core-files.txt +++ b/platform/android/core-files.txt @@ -137,8 +137,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 diff --git a/platform/android/src/annotation/marker.cpp b/platform/android/src/annotation/marker.cpp index a1fe436dbd..b9a8c714a1 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::javaClass; - mbgl::Point Marker::getPosition(jni::JNIEnv& env, jni::Object marker) { - static auto positionField = Marker::javaClass.GetField>(env, "position"); - auto jPosition = marker.Get(env, positionField); - auto position = LatLng::getGeometry(env, jPosition); - jni::DeleteLocalRef(env, jPosition); - return position; + static auto javaClass = jni::Class::Singleton(env); + static auto positionField = javaClass.GetField>(env, "position"); + return LatLng::getGeometry(env, *jni::SeizeLocal(env, marker.Get(env, positionField))); } std::string Marker::getIconId(jni::JNIEnv& env, jni::Object marker) { - static auto iconIdField = Marker::javaClass.GetField(env, "iconId"); - auto jIconId = marker.Get(env, iconIdField); - auto iconId = jni::Make(env, jIconId); - jni::DeleteLocalRef(env, jIconId); - return iconId; + static auto javaClass = jni::Class::Singleton(env); + static auto iconIdField = javaClass.GetField(env, "iconId"); + return jni::Make(env, *jni::SeizeLocal(env, marker.Get(env, iconIdField))); } void Marker::registerNative(jni::JNIEnv& env) { - // Lookup the class - Marker::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::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..d03c244921 100644 --- a/platform/android/src/annotation/marker.hpp +++ b/platform/android/src/annotation/marker.hpp @@ -15,8 +15,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/annotations/Marker"; }; - static jni::Class javaClass; - static mbgl::Point getPosition(jni::JNIEnv&, jni::Object); static std::string getIconId(jni::JNIEnv&, jni::Object); diff --git a/platform/android/src/annotation/multi_point.hpp b/platform/android/src/annotation/multi_point.hpp index e1152dfd60..1a6b945261 100644 --- a/platform/android/src/annotation/multi_point.hpp +++ b/platform/android/src/annotation/multi_point.hpp @@ -15,25 +15,17 @@ protected: template static Geometry toGeometry(JNIEnv& env, jni::Object pointsList) { - NullCheck(env, &pointsList); - auto jarray = java::util::List::toArray(env, pointsList); - NullCheck(env, &jarray); + auto jarray = jni::SeizeLocal(env, java::util::List::toArray(env, pointsList)); - std::size_t size = jarray.Length(env); + std::size_t size = jarray->Length(env); Geometry geometry; 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, *jni::SeizeLocal(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..f049911be0 100644 --- a/platform/android/src/annotation/polygon.cpp +++ b/platform/android/src/annotation/polygon.cpp @@ -5,63 +5,60 @@ namespace mbgl { namespace android { -jni::Class Polygon::javaClass; - mbgl::FillAnnotation Polygon::toAnnotation(jni::JNIEnv& env, jni::Object polygon) { - auto points = Polygon::getPoints(env, polygon); - auto holes = Polygon::getHoles(env, polygon); + auto points = jni::SeizeLocal(env, Polygon::getPoints(env, polygon)); + auto holes = jni::SeizeLocal(env, Polygon::getHoles(env, polygon)); - mbgl::Polygon geometry { MultiPoint::toGeometry>(env, points) }; + mbgl::Polygon geometry { MultiPoint::toGeometry>(env, *points) }; - auto jHoleListsArray = java::util::List::toArray(env, holes); - std::size_t jHoleListsSize = jHoleListsArray.Length(env); + auto jHoleListsArray = jni::SeizeLocal(env, java::util::List::toArray(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>(env, jHoleList)); - jni::DeleteLocalRef(env, jHoleList); + geometry.push_back(MultiPoint::toGeometry>(env, + *jni::SeizeLocal(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); - return annotation; } jni::Object Polygon::getPoints(jni::JNIEnv& env, jni::Object polygon) { - static auto field = Polygon::javaClass.GetField>(env, "points"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField>(env, "points"); return polygon.Get(env, field); } jni::Object Polygon::getHoles(jni::JNIEnv& env, jni::Object polygon) { - static auto field = Polygon::javaClass.GetField>(env, "holes"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField>(env, "holes"); return polygon.Get(env, field); } float Polygon::getOpacity(jni::JNIEnv& env, jni::Object polygon) { - static auto field = Polygon::javaClass.GetField(env, "alpha"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(env, "alpha"); return polygon.Get(env, field); } mbgl::Color Polygon::getFillColor(jni::JNIEnv& env, jni::Object polygon) { - static auto field = Polygon::javaClass.GetField(env, "fillColor"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(env, "fillColor"); return *conversion::convert(env, polygon.Get(env, field)); } mbgl::Color Polygon::getOutlineColor(jni::JNIEnv& env, jni::Object polygon) { - static auto field = Polygon::javaClass.GetField(env, "strokeColor"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(env, "strokeColor"); return *conversion::convert(env, polygon.Get(env, field)); } void Polygon::registerNative(jni::JNIEnv& env) { - Polygon::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::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..f7cc015c8a 100644 --- a/platform/android/src/annotation/polygon.hpp +++ b/platform/android/src/annotation/polygon.hpp @@ -18,8 +18,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/annotations/Polygon"; }; - static jni::Class javaClass; - static mbgl::FillAnnotation toAnnotation(jni::JNIEnv&, jni::Object); static void registerNative(jni::JNIEnv&); diff --git a/platform/android/src/annotation/polyline.cpp b/platform/android/src/annotation/polyline.cpp index 3723dc1871..22d25a0f75 100644 --- a/platform/android/src/annotation/polyline.cpp +++ b/platform/android/src/annotation/polyline.cpp @@ -5,45 +5,44 @@ namespace mbgl { namespace android { -jni::Class Polyline::javaClass; - mbgl::LineAnnotation Polyline::toAnnotation(jni::JNIEnv& env, jni::Object polyline) { - auto points = Polyline::getPoints(env, polyline); + auto points = jni::SeizeLocal(env, Polyline::getPoints(env, polyline)); - mbgl::LineAnnotation annotation { MultiPoint::toGeometry>(env, points) }; + mbgl::LineAnnotation annotation { MultiPoint::toGeometry>(env, *points) }; annotation.opacity = { Polyline::getOpacity(env, polyline) }; annotation.color = { Polyline::getColor(env, polyline) }; annotation.width = { Polyline::getWidth(env, polyline) }; - jni::DeleteLocalRef(env, points); - return annotation; } jni::Object Polyline::getPoints(jni::JNIEnv& env, jni::Object polyline) { - static auto field = Polyline::javaClass.GetField>(env, "points"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField>(env, "points"); return polyline.Get(env, field); } float Polyline::getOpacity(jni::JNIEnv& env, jni::Object polyline) { - static auto field = Polyline::javaClass.GetField(env, "alpha"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(env, "alpha"); return polyline.Get(env, field); } mbgl::Color Polyline::getColor(jni::JNIEnv& env, jni::Object polyline) { - static auto field = Polyline::javaClass.GetField(env, "color"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(env, "color"); return *conversion::convert(env, polyline.Get(env, field)); } float Polyline::getWidth(jni::JNIEnv& env, jni::Object polyline) { - static auto field = Polyline::javaClass.GetField(env, "width"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(env, "width"); return polyline.Get(env, field); } void Polyline::registerNative(jni::JNIEnv& env) { - Polyline::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::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..69f5d19c1f 100644 --- a/platform/android/src/annotation/polyline.hpp +++ b/platform/android/src/annotation/polyline.hpp @@ -18,8 +18,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/annotations/Polyline"; }; - static jni::Class javaClass; - static mbgl::LineAnnotation toAnnotation(jni::JNIEnv&, jni::Object); static void registerNative(jni::JNIEnv&); diff --git a/platform/android/src/asset_manager_file_source.hpp b/platform/android/src/asset_manager_file_source.hpp index dcad95664a..bb0809a442 100644 --- a/platform/android/src/asset_manager_file_source.hpp +++ b/platform/android/src/asset_manager_file_source.hpp @@ -22,7 +22,7 @@ public: private: class Impl; - jni::UniqueObject assetManager; + jni::Global> assetManager; std::unique_ptr> impl; }; diff --git a/platform/android/src/bitmap.cpp b/platform/android/src/bitmap.cpp index 0d3670b666..53136b868e 100644 --- a/platform/android/src/bitmap.cpp +++ b/platform/android/src/bitmap.cpp @@ -15,6 +15,7 @@ public: 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,23 +27,14 @@ public: return address; } - const auto* get() const { - return address; - } - private: jni::JNIEnv& env; jni::Object bitmap; uint8_t* address; }; -void Bitmap::Config::registerNative(jni::JNIEnv& env) { - _class = *jni::Class::Find(env).NewGlobalRef(env).release(); -} - -jni::Class Bitmap::Config::_class; - jni::Object Bitmap::Config::Create(jni::JNIEnv& env, Value value) { + static auto _class = jni::Class::Singleton(env); switch (value) { case ALPHA_8: return _class.Get(env, @@ -62,18 +54,17 @@ jni::Object Bitmap::Config::Create(jni::JNIEnv& env, Value value } void Bitmap::registerNative(jni::JNIEnv& env) { - _class = *jni::Class::Find(env).NewGlobalRef(env).release(); - Config::registerNative(env); + jni::Class::Singleton(env); + jni::Class::Singleton(env); } -jni::Class Bitmap::_class; - jni::Object Bitmap::CreateBitmap(jni::JNIEnv& env, jni::jint width, jni::jint height, jni::Object config) { - using Signature = jni::Object(jni::jint, jni::jint, jni::Object); - auto method = _class.GetStaticMethod(env, "createBitmap"); + static auto _class = jni::Class::Singleton(env); + static auto method = _class.GetStaticMethod (jni::jint, jni::jint, jni::Object)>(env, "createBitmap"); + return _class.Call(env, method, width, height, config); } @@ -106,15 +97,13 @@ PremultipliedImage Bitmap::GetImage(jni::JNIEnv& env, jni::Object 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); + return Bitmap::GetImage(env, Bitmap::Copy(env, bitmap)); } - const PixelGuard guard(env, bitmap); + PixelGuard guard(env, bitmap); // Copy the Android Bitmap into the PremultipliedImage. auto pixels = @@ -129,10 +118,10 @@ PremultipliedImage Bitmap::GetImage(jni::JNIEnv& env, jni::Object bitmap } jni::Object Bitmap::Copy(jni::JNIEnv& env, jni::Object bitmap) { - using Signature = jni::Object(jni::Object, jni::jboolean); - auto static method = _class.GetMethod(env, "copy"); - auto config = Bitmap::Config::Create(env, Bitmap::Config::Value::ARGB_8888); - return bitmap.Call(env, method, config, (jni::jboolean) false); + static auto klass = jni::Class::Singleton(env); + static auto copy = klass.GetMethod (jni::Object, jni::jboolean)>(env, "copy"); + + 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..2266bc0e67 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, @@ -24,18 +21,14 @@ public: }; static jni::Object Create(jni::JNIEnv&, Value); - - private: - static jni::Class _class; }; - static constexpr auto Name() { - return "android/graphics/Bitmap"; - }; + static constexpr auto Name() { return "android/graphics/Bitmap"; }; static void registerNative(jni::JNIEnv&); static jni::Object CreateBitmap(jni::JNIEnv&, jni::jint width, jni::jint height, jni::Object); + static jni::Object CreateBitmap(jni::JNIEnv& env, jni::jint width, jni::jint height, Config::Value config) { return CreateBitmap(env, width, height, Config::Create(env, config)); @@ -44,9 +37,6 @@ public: static PremultipliedImage GetImage(jni::JNIEnv&, jni::Object); static jni::Object CreateBitmap(jni::JNIEnv&, const PremultipliedImage&); static jni::Object Copy(jni::JNIEnv&, jni::Object); - -private: - static jni::Class _class; }; } // namespace android diff --git a/platform/android/src/bitmap_factory.cpp b/platform/android/src/bitmap_factory.cpp index 7d9b068b20..79cdc913a0 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::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class BitmapFactory::_class; - jni::Object BitmapFactory::DecodeByteArray(jni::JNIEnv& env, jni::Array data, jni::jint offset, jni::jint length) { + static auto _class = jni::Class::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(jni::Array, jni::jint, jni::jint); - auto method = _class.GetStaticMethod(env, "decodeByteArray"); + using Signature = jni::Object (jni::Array, jni::jint, jni::jint); + static auto method = _class.GetStaticMethod(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..6e019d017c 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 DecodeByteArray(jni::JNIEnv&, jni::Array data, jni::jint offset, jni::jint length); - -private: - static jni::Class _class; }; } // namespace android diff --git a/platform/android/src/connectivity_listener.cpp b/platform/android/src/connectivity_listener.cpp index 5b1c0a86e4..3fcc580aab 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::javaClass; - void ConnectivityListener::registerNative(jni::JNIEnv& env) { // Lookup the class - ConnectivityListener::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( env, - ConnectivityListener::javaClass, + javaClass, "nativePtr", std::make_unique, "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 javaClass; - static void registerNative(jni::JNIEnv&); /* diff --git a/platform/android/src/conversion/collection.cpp b/platform/android/src/conversion/collection.cpp index 6775228e15..3195458aa6 100644 --- a/platform/android/src/conversion/collection.cpp +++ b/platform/android/src/conversion/collection.cpp @@ -11,24 +11,17 @@ std::vector toVector(JNIEnv& env, jni::Array array) { vector.reserve(len); for (std::size_t i = 0; i < len; i++) { - jni::String jstr = array.Get(env, i); - vector.push_back(*convert(env, jstr)); - jni::DeleteLocalRef(env, jstr); + vector.push_back(*convert(env, *jni::SeizeLocal(env, array.Get(env, i)))); } return vector; } jni::Array toArray(JNIEnv& env, const std::vector& vector) { - static auto clazz = *jni::Class::Find(env).NewGlobalRef(env).release(); - auto result = jni::Array::New(env, vector.size(), clazz); - - std::size_t index = 0; - for (auto&& item : vector) { - auto element = jni::Make(env, item); - result.Set(env, index, element); - DeleteLocalRef(env, element); - index++; + auto result = jni::Array::New(env, vector.size()); + + for (std::size_t i = 0; i < vector.size(); i++) { + result.Set(env, i, *jni::SeizeLocal(env, jni::Make(env, vector.at(i)))); } return result; diff --git a/platform/android/src/file_source.cpp b/platform/android/src/file_source.cpp index 2a6cac3b02..32c304b909 100644 --- a/platform/android/src/file_source.cpp +++ b/platform/android/src/file_source.cpp @@ -51,7 +51,7 @@ void FileSource::setResourceTransform(jni::JNIEnv& env, jni::Object(transformCallback.NewGlobalRef(env).release()->Get(), GenericGlobalRefDeleter())] + [callback = std::shared_ptr(transformCallback.NewGlobalRef(env).release().Get(), GenericGlobalRefDeleter())] (mbgl::Resource::Kind kind, const std::string&& url_) { android::UniqueEnv _env = android::AttachEnv(); return FileSource::ResourceTransformCallback::onURL(*_env, jni::Object(*callback), int(kind), url_); @@ -92,10 +92,9 @@ jni::jboolean FileSource::isResumed(jni::JNIEnv&) { return (jboolean) false; } -jni::Class FileSource::javaClass; - FileSource* FileSource::getNativePeer(jni::JNIEnv& env, jni::Object jFileSource) { - static auto field = FileSource::javaClass.GetField(env, "nativePtr"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(env, "nativePtr"); return reinterpret_cast(jFileSource.Get(env, field)); } @@ -106,15 +105,18 @@ mbgl::DefaultFileSource& FileSource::getDefaultFileSource(jni::JNIEnv& env, jni: } void FileSource::registerNative(jni::JNIEnv& env) { - //Register classes - FileSource::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); - FileSource::ResourceTransformCallback::javaClass = *jni::Class::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::Singleton(env); + + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, FileSource::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique>, "initialize", "finalize", @@ -131,16 +133,13 @@ void FileSource::registerNative(jni::JNIEnv& env) { // FileSource::ResourceTransformCallback // -jni::Class FileSource::ResourceTransformCallback::javaClass; - std::string FileSource::ResourceTransformCallback::onURL(jni::JNIEnv& env, jni::Object callback, int kind, std::string url_) { - static auto method = FileSource::ResourceTransformCallback::javaClass.GetMethod(env, "onURL"); - auto url = jni::Make(env, url_); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "onURL"); - url = callback.Call(env, method, kind, url); - auto urlStr = jni::Make(env, url); - jni::DeleteLocalRef(env, url); - return urlStr; + return jni::Make(env, + *jni::SeizeLocal(env, callback.Call(env, method, kind, + *jni::SeizeLocal(env, jni::Make(env, url_))))); } } // namespace android diff --git a/platform/android/src/file_source.hpp b/platform/android/src/file_source.hpp index e4295e1b84..f1b11c754c 100644 --- a/platform/android/src/file_source.hpp +++ b/platform/android/src/file_source.hpp @@ -25,8 +25,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/storage/FileSource$ResourceTransformCallback"; } static std::string onURL(jni::JNIEnv&, jni::Object, int, std::string); - - static jni::Class javaClass; }; FileSource(jni::JNIEnv&, jni::String, jni::String, jni::Object); @@ -47,8 +45,6 @@ public: jni::jboolean isResumed(jni::JNIEnv&); - static jni::Class javaClass; - static FileSource* getNativePeer(jni::JNIEnv&, jni::Object); static mbgl::DefaultFileSource& getDefaultFileSource(jni::JNIEnv&, jni::Object); diff --git a/platform/android/src/geojson/conversion/feature.cpp b/platform/android/src/geojson/conversion/feature.cpp index 3cb6d37b17..7386e29df5 100644 --- a/platform/android/src/geojson/conversion/feature.cpp +++ b/platform/android/src/geojson/conversion/feature.cpp @@ -1,13 +1,13 @@ #include "feature.hpp" -#include "../../conversion/constant.hpp" -#include "../../conversion/conversion.hpp" -#include "../../jni/local_object.hpp" +#include "../../gson/json_object.hpp" namespace mbgl { namespace android { namespace conversion { +using namespace gson; + /** * Turn feature identifier into std::string */ @@ -29,158 +29,22 @@ public: }; -/** - * 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, "", "(Ljava/lang/Boolean;)V"); - - // Create JsonPrimitive - jni::LocalObject converted = jni::NewLocalObject(env, *convert(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, "", "(Ljava/lang/String;)V"); - - // Create JsonPrimitive - jni::LocalObject converted = jni::NewLocalObject(env, *convert(env, value)); - jni::jobject* object = &jni::NewObject(env, *javaClass, *constructor, converted.get()); - - return object; - } - - /** - * Number primitives - */ - template - 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, "", "(Ljava/lang/Number;)V"); - - // Create JsonPrimitive - jni::LocalObject converted = jni::NewLocalObject(env, *convert(env, value)); - jni::jobject* object = &jni::NewObject(env, *javaClass, *constructor, converted.get()); - - return object; - } - - - /** - * Json Array - */ - jni::jobject* operator()(const std::vector &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, "", "()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 converted = jni::NewLocalObject(env, mbgl::Value::visit(v, *this)); - jni::CallMethod(env, jarray, *add, converted.get()); - } - - return jarray; - } - - /** - * Json Object - */ - jni::jobject* operator()(const std::unordered_map &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, "", "()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 converted = jni::NewLocalObject(env, mbgl::Value::visit(item.second, *this)); - jni::LocalObject key = jni::NewLocalObject(env, *convert(env, item.first)); - jni::CallMethod(env, jsonObject, *add, key.get(), converted.get()); - } - - return jsonObject; - } -}; - -Result Converter>::operator()(jni::JNIEnv& env, const std::unordered_map& 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, "", "()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 converted = jni::NewLocalObject(env, mbgl::Value::visit(item.second, evaluator)); - jni::LocalObject key = jni::NewLocalObject(env, *convert(env, item.first)); - jni::CallMethod(env, jsonObject, *add, key.get(), converted.get()); - } - - return {jsonObject}; -} - -Result> Converter, 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(env, id); - - // Convert properties - auto properties = jni::Object(*convert(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); +jni::Object convertFeature(jni::JNIEnv& env, const mbgl::Feature& value) { + using namespace mbgl::android::geojson; - return feature; + return Feature::fromGeometry(env, + *jni::SeizeLocal(env, Geometry::New(env, value.geometry)), + *jni::SeizeLocal(env, JsonObject::New(env, value.properties)), + *jni::SeizeLocal(env, jni::Make(env, value.id ? value.id.value().match(FeatureIdVisitor()) : ""))); } Result>> Converter>, std::vector>::operator()(jni::JNIEnv& env, const std::vector& value) const { using namespace mbgl::android::geojson; - auto features = jni::Array>::New(env, value.size(), Feature::javaClass); - for(size_t i = 0; i < value.size(); i = i + 1) { - auto converted = *convert, mbgl::Feature>(env, value.at(i)); - features.Set(env, i, converted); - jni::DeleteLocalRef(env, converted); + auto features = jni::Array>::New(env, value.size()); + + for (size_t i = 0; i < value.size(); i = i + 1) { + features.Set(env, i, *jni::SeizeLocal(env, convertFeature(env, value.at(i)))); } return {features}; diff --git a/platform/android/src/geojson/conversion/feature.hpp b/platform/android/src/geojson/conversion/feature.hpp index 031449cd23..d9fc0a0b67 100644 --- a/platform/android/src/geojson/conversion/feature.hpp +++ b/platform/android/src/geojson/conversion/feature.hpp @@ -7,22 +7,11 @@ #include #include -#include namespace mbgl { namespace android { namespace conversion { -template <> -struct Converter> { - Result operator()(jni::JNIEnv& env, const std::unordered_map& value) const; -}; - -template <> -struct Converter, mbgl::Feature> { - Result> operator()(jni::JNIEnv& env, const mbgl::Feature& value) const; -}; - template <> struct Converter>, std::vector> { Result>> operator()(jni::JNIEnv& env, const std::vector& value) const; diff --git a/platform/android/src/geojson/feature.cpp b/platform/android/src/geojson/feature.cpp index d8a4e829e2..1e02c756eb 100644 --- a/platform/android/src/geojson/feature.cpp +++ b/platform/android/src/geojson/feature.cpp @@ -7,57 +7,50 @@ namespace android { namespace geojson { mbgl::Feature Feature::convert(jni::JNIEnv& env, jni::Object jFeature) { - // Convert - auto jGeometry = geometry(env, jFeature); - auto jProperties = Feature::properties(env, jFeature); + auto jGeometry = jni::SeizeLocal(env, geometry(env, jFeature)); + auto jProperties = jni::SeizeLocal(env, Feature::properties(env, jFeature)); std::experimental::optional id; - auto jId = Feature::id(env, jFeature); + auto jId = jni::SeizeLocal(env, Feature::id(env, jFeature)); if (jId) { - id = { jni::Make(env, jId) }; + id = { jni::Make(env, *jId) }; } - auto feature = mbgl::Feature { - Geometry::convert(env, jGeometry), - gson::JsonObject::convert(env, jProperties), - id + return mbgl::Feature { + Geometry::convert(env, *jGeometry), + gson::JsonObject::convert(env, *jProperties), + id }; - - // Cleanup - jni::DeleteLocalRef(env, jGeometry); - jni::DeleteLocalRef(env, jProperties); - jni::DeleteLocalRef(env, jId); - - return feature; } jni::Object Feature::geometry(jni::JNIEnv& env, jni::Object jFeature) { - static auto method = Feature::javaClass.GetMethod ()>(env, "geometry"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod ()>(env, "geometry"); return jFeature.Call(env, method); } jni::Object Feature::properties(jni::JNIEnv& env, jni::Object jFeature) { - static auto method = Feature::javaClass.GetMethod ()>(env, "properties"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod ()>(env, "properties"); return jFeature.Call(env, method); } jni::String Feature::id(jni::JNIEnv& env, jni::Object jFeature) { - static auto method = Feature::javaClass.GetMethod(env, "id"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "id"); return jFeature.Call(env, method); } jni::Object Feature::fromGeometry(jni::JNIEnv& env, jni::Object geometry, jni::Object properties, jni::String id) { - static auto method = Feature::javaClass.GetStaticMethod (jni::Object, jni::Object, jni::String)>(env, "fromGeometry"); - return Feature::javaClass.Call(env, method, geometry, properties, id); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetStaticMethod (jni::Object, jni::Object, jni::String)>(env, "fromGeometry"); + return javaClass.Call(env, method, geometry, properties, id); } void Feature::registerNative(jni::JNIEnv& env) { - // Lookup the class - Feature::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class 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..de38e9b1e3 100644 --- a/platform/android/src/geojson/feature.hpp +++ b/platform/android/src/geojson/feature.hpp @@ -28,10 +28,7 @@ public: static jni::Object properties(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - 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..c2825e037b 100644 --- a/platform/android/src/geojson/feature_collection.cpp +++ b/platform/android/src/geojson/feature_collection.cpp @@ -10,35 +10,28 @@ mbgl::FeatureCollection FeatureCollection::convert(jni::JNIEnv& env, jni::Object auto collection = mbgl::FeatureCollection(); if (jCollection) { - auto jFeatureList = FeatureCollection::features(env, jCollection); - auto jFeatures = java::util::List::toArray(env, jFeatureList); - auto size = size_t(jFeatures.Length(env)); + auto jFeatureList = jni::SeizeLocal(env, FeatureCollection::features(env, jCollection)); + auto jFeatures = jni::SeizeLocal(env, java::util::List::toArray(env, *jFeatureList)); + auto size = size_t(jFeatures->Length(env)); 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, *jni::SeizeLocal(env, jFeatures->Get(env, i)))); } - - jni::DeleteLocalRef(env, jFeatures); - jni::DeleteLocalRef(env, jFeatureList); } return collection; } jni::Object FeatureCollection::features(jni::JNIEnv& env, jni::Object jCollection) { - static auto method = FeatureCollection::javaClass.GetMethod ()>(env, "features"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod ()>(env, "features"); return jCollection.Call(env, method); } void FeatureCollection::registerNative(jni::JNIEnv& env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class 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..1b45cca5de 100644 --- a/platform/android/src/geojson/feature_collection.hpp +++ b/platform/android/src/geojson/feature_collection.hpp @@ -19,8 +19,6 @@ public: static jni::Object features(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/geometry.cpp b/platform/android/src/geojson/geometry.cpp index 5635b5a0f5..4262b4ee69 100644 --- a/platform/android/src/geojson/geometry.cpp +++ b/platform/android/src/geojson/geometry.cpp @@ -23,31 +23,31 @@ public: jni::JNIEnv& env; jni::Object operator()(const mbgl::Point &geometry) const { - return jni::Cast(env, Point::New(env, geometry), Geometry::javaClass); + return Point::New(env, geometry); } jni::Object operator()(const mbgl::LineString &geometry) const { - return jni::Cast(env, LineString::New(env, geometry), Geometry::javaClass); + return LineString::New(env, geometry); } jni::Object operator()(const mbgl::MultiLineString &geometry) const { - return jni::Cast(env, MultiLineString::New(env, geometry), Geometry::javaClass); + return MultiLineString::New(env, geometry); } jni::Object operator()(const mbgl::MultiPoint &geometry) const { - return jni::Cast(env, MultiPoint::New(env, geometry), Geometry::javaClass); + return MultiPoint::New(env, geometry); } jni::Object operator()(const mbgl::Polygon &geometry) const { - return jni::Cast(env, Polygon::New(env, geometry), Geometry::javaClass); + return Polygon::New(env, geometry); } jni::Object operator()(const mbgl::MultiPolygon &geometry) const { - return jni::Cast(env, MultiPolygon::New(env, geometry), Geometry::javaClass); + return MultiPolygon::New(env, geometry); } jni::Object operator()(const mapbox::geometry::geometry_collection &geometry) const { - return jni::Cast(env, GeometryCollection::New(env, geometry), Geometry::javaClass); + return GeometryCollection::New(env, geometry); } }; @@ -78,20 +78,15 @@ mbgl::Geometry Geometry::convert(jni::JNIEnv &env, jni::Object } std::string Geometry::getType(jni::JNIEnv &env, jni::Object jGeometry) { - static auto method = Geometry::javaClass.GetMethod(env, "type"); - auto jType = jGeometry.Call(env, method); - auto type = jni::Make(env, jType); - jni::DeleteLocalRef(env, jType); - return type; + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "type"); + return jni::Make(env, *jni::SeizeLocal(env, jGeometry.Call(env, method))); } void Geometry::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class 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..836c3bd5a0 100644 --- a/platform/android/src/geojson/geometry.hpp +++ b/platform/android/src/geojson/geometry.hpp @@ -1,7 +1,6 @@ #pragma once #include -#include #include "../java/util.hpp" @@ -11,7 +10,7 @@ namespace mbgl { namespace android { namespace geojson { -class Geometry : private mbgl::util::noncopyable { +class Geometry { public: static constexpr auto Name() { return "com/mapbox/geojson/Geometry"; }; @@ -21,8 +20,6 @@ public: static std::string getType(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - 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..ad0af71214 100644 --- a/platform/android/src/geojson/geometry_collection.cpp +++ b/platform/android/src/geojson/geometry_collection.cpp @@ -7,57 +7,43 @@ namespace geojson { jni::Object GeometryCollection::New(jni::JNIEnv& env, const mapbox::geometry::geometry_collection& collection) { // Create an array of geometries - auto jarray = jni::Array>::New(env, collection.size(), Geometry::javaClass); + auto jarray = jni::SeizeLocal(env, jni::Array>::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, *jni::SeizeLocal(env, 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::Singleton(env); static auto method = javaClass.GetStaticMethod (jni::Object)>(env, "fromGeometries"); - auto jCollection = javaClass.Call(env, method, jList); - - jni::DeleteLocalRef(env, jList); - return jCollection; + return javaClass.Call(env, method, *jni::SeizeLocal(env, java::util::Arrays::asList(env, *jarray))); } mapbox::geometry::geometry_collection GeometryCollection::convert(jni::JNIEnv &env, jni::Object jCollection) { // Get geometries + static auto javaClass = jni::Class::Singleton(env); static auto getGeometries = javaClass.GetMethod ()>(env, "geometries"); - auto jList = jCollection.Call(env, getGeometries); // Turn into array - auto jarray = java::util::List::toArray(env, jList); - jni::DeleteLocalRef(env, jList); + auto jarray = jni::SeizeLocal(env, + java::util::List::toArray(env, + *jni::SeizeLocal(env, jCollection.Call(env, getGeometries)))); // Convert each geometry mapbox::geometry::geometry_collection collection{}; - auto size = jarray.Length(env); + 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, *jni::SeizeLocal(env, jarray->Get(env, i)))); } - jni::DeleteLocalRef(env, jarray); return collection; } void GeometryCollection::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class 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..a301d86933 100644 --- a/platform/android/src/geojson/geometry_collection.hpp +++ b/platform/android/src/geojson/geometry_collection.hpp @@ -18,8 +18,6 @@ public: static mapbox::geometry::geometry_collection convert(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - 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..5a18a02bb7 100644 --- a/platform/android/src/geojson/line_string.cpp +++ b/platform/android/src/geojson/line_string.cpp @@ -8,22 +8,18 @@ namespace android { namespace geojson { jni::Object LineString::New(jni::JNIEnv& env, const mbgl::LineString& lineString) { - auto jList = asPointsList(env, lineString); - + static auto javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetStaticMethod(jni::Object)>(env, "fromLngLats"); - auto jLineString = javaClass.Call(env, method, jList); - jni::DeleteLocalRef(env, jList); - return jLineString; + return javaClass.Call(env, method, + *jni::SeizeLocal(env, asPointsList(env, lineString))); } mapbox::geojson::line_string LineString::convert(jni::JNIEnv &env, jni::Object 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, *jni::SeizeLocal(env, LineString::coordinates(env, jLineString))); } return lineString; @@ -33,34 +29,28 @@ mapbox::geojson::line_string LineString::convert(jni::JNIEnv &env, jni::Object(env, jPointList); - auto size = jPointArray.Length(env); + auto jPointArray = jni::SeizeLocal(env, java::util::List::toArray(env, jPointList)); + auto size = jPointArray->Length(env); 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, *jni::SeizeLocal(env, jPointArray->Get(env, i)))); } - - jni::DeleteLocalRef(env, jPointArray); } return lineString; } jni::Object LineString::coordinates(jni::JNIEnv &env, jni::Object jLineString) { - static auto method = LineString::javaClass.GetMethod ()>(env, "coordinates"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod ()>(env, "coordinates"); return jLineString.Call(env, method); } void LineString::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class 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..4df9349185 100644 --- a/platform/android/src/geojson/line_string.hpp +++ b/platform/android/src/geojson/line_string.hpp @@ -28,8 +28,6 @@ public: static jni::Object coordinates(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - 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..0a0974062c 100644 --- a/platform/android/src/geojson/multi_line_string.cpp +++ b/platform/android/src/geojson/multi_line_string.cpp @@ -8,22 +8,19 @@ namespace android { namespace geojson { jni::Object MultiLineString::New(jni::JNIEnv& env, const mbgl::MultiLineString& multiLineString) { - auto jList = asPointsListsList(env, multiLineString); - + static auto javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetStaticMethod (jni::Object)>(env, "fromLngLats"); - auto jMultiLineString = javaClass.Call(env, method, jList); - jni::DeleteLocalRef(env, jList); - return jMultiLineString; + return javaClass.Call(env, method, + *jni::SeizeLocal(env, asPointsListsList(env, multiLineString))); } mapbox::geojson::multi_line_string MultiLineString::convert(jni::JNIEnv &env, jni::Object 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, + *jni::SeizeLocal(env, MultiLineString::coordinates(env, jMultiLineString))); } return multiLineString; @@ -33,35 +30,29 @@ mapbox::geojson::multi_line_string MultiLineString::convert(jni::JNIEnv &env, jn mapbox::geojson::multi_line_string multiLineString; if (jPointListsList) { - auto jPositionListsArray = java::util::List::toArray(env, jPointListsList); + auto jPositionListsArray = jni::SeizeLocal(env, java::util::List::toArray(env, jPointListsList)); - auto size = jPositionListsArray.Length(env); + auto size = jPositionListsArray->Length(env); 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, *jni::SeizeLocal(env, jPositionListsArray->Get(env, i)))); } - - jni::DeleteLocalRef(env, jPositionListsArray); } return multiLineString; } jni::Object MultiLineString::coordinates(jni::JNIEnv &env, jni::Object jLineString) { - static auto method = MultiLineString::javaClass.GetMethod ()>(env, "coordinates"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod ()>(env, "coordinates"); return jLineString.Call(env, method); } void MultiLineString::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class 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..c66aadaf03 100644 --- a/platform/android/src/geojson/multi_line_string.hpp +++ b/platform/android/src/geojson/multi_line_string.hpp @@ -26,8 +26,6 @@ public: static jni::Object coordinates(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - 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..5f51058f38 100644 --- a/platform/android/src/geojson/multi_point.cpp +++ b/platform/android/src/geojson/multi_point.cpp @@ -9,39 +9,33 @@ namespace android { namespace geojson { jni::Object MultiPoint::New(JNIEnv& env, const mbgl::MultiPoint& multiPoint) { - auto jList = asPointsList(env, multiPoint); - + static auto javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetStaticMethod(jni::Object)>(env, "fromLngLats"); - auto jMultiPoint = javaClass.Call(env, method, jList); - jni::DeleteLocalRef(env, jList); - return jMultiPoint; + return javaClass.Call(env, method, *jni::SeizeLocal(env, asPointsList(env, multiPoint))); } mapbox::geojson::multi_point MultiPoint::convert(jni::JNIEnv &env, jni::Object jMultiPoint) { mapbox::geojson::multi_point multiPoint; if (jMultiPoint) { - auto jPointListsList = MultiPoint::coordinates(env, jMultiPoint); - multiPoint = convertExplicit(LineString::convert(env, jPointListsList)); - jni::DeleteLocalRef(env, jPointListsList); + multiPoint = convertExplicit( + LineString::convert(env, *jni::SeizeLocal(env, MultiPoint::coordinates(env, jMultiPoint)))); } return multiPoint; } jni::Object MultiPoint::coordinates(jni::JNIEnv &env, jni::Object jMultiPoint) { - static auto method = MultiPoint::javaClass.GetMethod ()>(env, "coordinates"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod ()>(env, "coordinates"); return jMultiPoint.Call(env, method); } void MultiPoint::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class 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..0df16bfd6a 100644 --- a/platform/android/src/geojson/multi_point.hpp +++ b/platform/android/src/geojson/multi_point.hpp @@ -25,8 +25,6 @@ public: static jni::Object coordinates(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - 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..109ac714c3 100644 --- a/platform/android/src/geojson/multi_polygon.cpp +++ b/platform/android/src/geojson/multi_polygon.cpp @@ -8,62 +8,48 @@ namespace android { namespace geojson { jni::Object MultiPolygon::New(JNIEnv& env, const mbgl::MultiPolygon& multiPolygon) { - auto jarray = jni::Array>::New(env, multiPolygon.size(), java::util::List::javaClass); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetStaticMethod (jni::Object)>(env, "fromLngLats"); + + auto jarray = jni::SeizeLocal(env, + jni::Array>::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, *jni::SeizeLocal(env, 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)>(env, "fromLngLats"); - auto jMultiPolygon = javaClass.Call(env, method, jList); - - jni::DeleteLocalRef(env, jList); - return jMultiPolygon; + return javaClass.Call(env, method, + *jni::SeizeLocal(env, java::util::Arrays::asList(env, *jarray))); } mapbox::geojson::multi_polygon MultiPolygon::convert(jni::JNIEnv &env, jni::Object jMultiPolygon) { mapbox::geojson::multi_polygon multiPolygon; if (jMultiPolygon) { - auto jPointListsListList = MultiPolygon::coordinates(env, jMultiPolygon); - auto jPointListsListArray = java::util::List::toArray(env, jPointListsListList); + auto jPointListsListList = jni::SeizeLocal(env, MultiPolygon::coordinates(env, jMultiPolygon)); + auto jPointListsListArray = jni::SeizeLocal(env, java::util::List::toArray(env, *jPointListsListList)); - auto size = jPointListsListArray.Length(env); + auto size = jPointListsListArray->Length(env); 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, *jni::SeizeLocal(env, jPointListsListArray->Get(env, i)))); } - - jni::DeleteLocalRef(env, jPointListsListArray); - jni::DeleteLocalRef(env, jPointListsListList); } return multiPolygon; } jni::Object MultiPolygon::coordinates(jni::JNIEnv &env, jni::Object jPolygon) { - static auto method = MultiPolygon::javaClass.GetMethod ()>(env, "coordinates"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod ()>(env, "coordinates"); return jPolygon.Call(env, method); } void MultiPolygon::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class 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..3477e989ea 100644 --- a/platform/android/src/geojson/multi_polygon.hpp +++ b/platform/android/src/geojson/multi_polygon.hpp @@ -24,8 +24,6 @@ public: static jni::Object coordinates(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/point.cpp b/platform/android/src/geojson/point.cpp index 8a9656ea14..69da997250 100644 --- a/platform/android/src/geojson/point.cpp +++ b/platform/android/src/geojson/point.cpp @@ -8,6 +8,7 @@ namespace android { namespace geojson { jni::Object Point::New(jni::JNIEnv& env, const mbgl::Point& point) { + static auto javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetStaticMethod (jni::jdouble, jni::jdouble)>(env, "fromLngLat"); return javaClass.Call(env, method, point.x, point.y); } @@ -16,9 +17,7 @@ mapbox::geojson::point Point::convert(jni::JNIEnv &env, jni::Object jPoin mapbox::geojson::point point; if (jPoint) { - auto jDoubleList = Point::coordinates(env, jPoint); - point = Point::convert(env, jDoubleList); - jni::DeleteLocalRef(env, jDoubleList); + point = Point::convert(env, *jni::SeizeLocal(env, Point::coordinates(env, jPoint))); } return point; @@ -28,35 +27,29 @@ mapbox::geojson::point Point::convert(jni::JNIEnv &env, jni::Object(env, jDoubleList); + auto jDoubleArray = jni::SeizeLocal(env, java::util::List::toArray(env, jDoubleList)); - auto lonObject = jDoubleArray.Get(env, 0); - auto latObject = jDoubleArray.Get(env, 1); + auto lonObject = jni::SeizeLocal(env, jDoubleArray->Get(env, 0)); + auto latObject = jni::SeizeLocal(env, jDoubleArray->Get(env, 1)); - point.x = jni::CallMethod(env, lonObject, + point.x = jni::CallMethod(env, *lonObject, *java::Number::doubleValueMethodId); - point.y = jni::CallMethod(env, latObject, + point.y = jni::CallMethod(env, *latObject, *java::Number::doubleValueMethodId); - - jni::DeleteLocalRef(env, lonObject); - jni::DeleteLocalRef(env, latObject); - jni::DeleteLocalRef(env, jDoubleArray); } return point; } jni::Object Point::coordinates(jni::JNIEnv &env, jni::Object jPoint) { - static auto method = Point::javaClass.GetMethod ()>(env, "coordinates"); - return jPoint.Call(env, method); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod ()>(env, "coordinates"); + return jPoint.Call(env, method); } void Point::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class 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..3a852a3e74 100644 --- a/platform/android/src/geojson/point.hpp +++ b/platform/android/src/geojson/point.hpp @@ -26,8 +26,6 @@ public: static jni::Object coordinates(JNIEnv&, jni::Object); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/polygon.cpp b/platform/android/src/geojson/polygon.cpp index 96058b63b3..add843e294 100644 --- a/platform/android/src/geojson/polygon.cpp +++ b/platform/android/src/geojson/polygon.cpp @@ -9,22 +9,17 @@ namespace android { namespace geojson { jni::Object Polygon::New(jni::JNIEnv& env, const mbgl::Polygon& polygon) { - auto jList = asPointsListsList(env, polygon); - + static auto javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetStaticMethod (jni::Object)>(env, "fromLngLats"); - auto jPolygon = javaClass.Call(env, method, jList); - jni::DeleteLocalRef(env, jList); - return jPolygon; + return javaClass.Call(env, method, *jni::SeizeLocal(env, asPointsListsList(env, polygon))); } mapbox::geojson::polygon Polygon::convert(jni::JNIEnv &env, jni::Object 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, *jni::SeizeLocal(env, Polygon::coordinates(env, jPolygon))); } return polygon; @@ -46,17 +41,15 @@ mapbox::geojson::polygon Polygon::convert(jni::JNIEnv &env, jni::Object Polygon::coordinates(jni::JNIEnv &env, jni::Object jPolygon) { - static auto method = Polygon::javaClass.GetMethod ()>(env, "coordinates"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod ()>(env, "coordinates"); return jPolygon.Call(env, method); } void Polygon::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class 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..adfa60df4d 100644 --- a/platform/android/src/geojson/polygon.hpp +++ b/platform/android/src/geojson/polygon.hpp @@ -27,8 +27,6 @@ public: static jni::Object coordinates(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv &); }; diff --git a/platform/android/src/geojson/util.hpp b/platform/android/src/geojson/util.hpp index 5e6d90a953..e889931c56 100644 --- a/platform/android/src/geojson/util.hpp +++ b/platform/android/src/geojson/util.hpp @@ -24,17 +24,13 @@ To convertExplicit(From&& src) { */ template static jni::Object asPointsList(jni::JNIEnv& env, const T& pointsList) { - auto jarray = jni::Array>::New(env, pointsList.size(), Point::javaClass); + auto jarray = jni::SeizeLocal(env, jni::Array>::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, *jni::SeizeLocal(env, 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); } /** @@ -42,17 +38,13 @@ static jni::Object asPointsList(jni::JNIEnv& env, const T& poi */ template static jni::Object asPointsListsList(JNIEnv& env, SHAPE value) { - auto jarray = jni::Array>::New(env, value.size(), java::util::List::javaClass); + auto jarray = jni::SeizeLocal(env, jni::Array>::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, *jni::SeizeLocal(env, 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..135755d67e 100644 --- a/platform/android/src/geometry/lat_lng.cpp +++ b/platform/android/src/geometry/lat_lng.cpp @@ -4,13 +4,15 @@ namespace mbgl { namespace android { jni::Object LatLng::New(jni::JNIEnv& env, const mbgl::LatLng& latLng) { - static auto constructor = LatLng::javaClass.GetConstructor(env); - return LatLng::javaClass.New(env, constructor, latLng.latitude(), latLng.longitude()); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, latLng.latitude(), latLng.longitude()); } mbgl::Point LatLng::getGeometry(jni::JNIEnv& env, jni::Object latLng) { - static auto latitudeField = LatLng::javaClass.GetField(env, "latitude"); - static auto longitudeField = LatLng::javaClass.GetField(env, "longitude"); + static auto javaClass = jni::Class::Singleton(env); + static auto latitudeField = javaClass.GetField(env, "latitude"); + static auto longitudeField = javaClass.GetField(env, "longitude"); return mbgl::Point(latLng.Get(env, longitudeField), latLng.Get(env, latitudeField)); } @@ -20,12 +22,8 @@ mbgl::LatLng LatLng::getLatLng(jni::JNIEnv& env, jni::Object latLng) { } void LatLng::registerNative(jni::JNIEnv& env) { - // Lookup the class - LatLng::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class 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..4431f1c739 100644 --- a/platform/android/src/geometry/lat_lng.hpp +++ b/platform/android/src/geometry/lat_lng.hpp @@ -20,10 +20,8 @@ public: static mbgl::LatLng getLatLng(jni::JNIEnv&, jni::Object); - static jni::Class 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..583120cb68 100644 --- a/platform/android/src/geometry/lat_lng_bounds.cpp +++ b/platform/android/src/geometry/lat_lng_bounds.cpp @@ -4,15 +4,17 @@ namespace mbgl { namespace android { jni::Object LatLngBounds::New(jni::JNIEnv& env, mbgl::LatLngBounds bounds) { - static auto constructor = LatLngBounds::javaClass.GetConstructor(env); - return LatLngBounds::javaClass.New(env, constructor, bounds.north(), bounds.east(), bounds.south(), bounds.west()); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, bounds.north(), bounds.east(), bounds.south(), bounds.west()); } mbgl::LatLngBounds LatLngBounds::getLatLngBounds(jni::JNIEnv& env, jni::Object bounds) { - static auto swLatField = LatLngBounds::javaClass.GetField(env, "latitudeSouth"); - static auto swLonField = LatLngBounds::javaClass.GetField(env, "longitudeWest"); - static auto neLatField = LatLngBounds::javaClass.GetField(env, "latitudeNorth"); - static auto neLonField = LatLngBounds::javaClass.GetField(env, "longitudeEast"); + static auto javaClass = jni::Class::Singleton(env); + static auto swLatField = javaClass.GetField(env, "latitudeSouth"); + static auto swLonField = javaClass.GetField(env, "longitudeWest"); + static auto neLatField = javaClass.GetField(env, "latitudeNorth"); + static auto neLonField = javaClass.GetField(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::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class 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..751e0babda 100644 --- a/platform/android/src/geometry/lat_lng_bounds.hpp +++ b/platform/android/src/geometry/lat_lng_bounds.hpp @@ -18,10 +18,7 @@ public: static mbgl::LatLngBounds getLatLngBounds(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - 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..5530a22903 100644 --- a/platform/android/src/geometry/lat_lng_quad.cpp +++ b/platform/android/src/geometry/lat_lng_quad.cpp @@ -5,8 +5,9 @@ namespace mbgl { namespace android { jni::Object LatLngQuad::New(jni::JNIEnv& env, std::array coordinates) { - static auto quadConstructor = LatLngQuad::javaClass.GetConstructor, jni::Object, jni::Object, jni::Object>(env); - return LatLngQuad::javaClass.New(env, quadConstructor, + static auto javaClass = jni::Class::Singleton(env); + static auto quadConstructor = javaClass.GetConstructor, jni::Object, jni::Object, jni::Object>(env); + return javaClass.New(env, quadConstructor, LatLng::New(env, coordinates[0]), LatLng::New(env, coordinates[1]), LatLng::New(env, coordinates[2]), @@ -14,10 +15,11 @@ jni::Object LatLngQuad::New(jni::JNIEnv& env, std::array LatLngQuad::getLatLngArray(jni::JNIEnv& env, jni::Object quad) { - static auto topLeftField = LatLngQuad::javaClass.GetField >(env, "topLeft"); - static auto topRightField = LatLngQuad::javaClass.GetField >(env, "topRight"); - static auto bottomRightField = LatLngQuad::javaClass.GetField >(env, "bottomRight"); - static auto bottomLeftField = LatLngQuad::javaClass.GetField >(env, "bottomLeft"); + static auto javaClass = jni::Class::Singleton(env); + static auto topLeftField = javaClass.GetField >(env, "topLeft"); + static auto topRightField = javaClass.GetField >(env, "topRight"); + static auto bottomRightField = javaClass.GetField >(env, "bottomRight"); + static auto bottomLeftField = javaClass.GetField >(env, "bottomLeft"); return std::array < mbgl::LatLng, 4 > {{ LatLng::getLatLng(env, quad.Get(env, topLeftField)), @@ -28,12 +30,8 @@ std::array LatLngQuad::getLatLngArray(jni::JNIEnv& env, jni::Ob } void LatLngQuad::registerNative(jni::JNIEnv& env) { - // Lookup the class - LatLngQuad::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class 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..ca1430ffbc 100644 --- a/platform/android/src/geometry/lat_lng_quad.hpp +++ b/platform/android/src/geometry/lat_lng_quad.hpp @@ -19,10 +19,7 @@ public: static std::array getLatLngArray(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - 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..4dfd7b57b2 100644 --- a/platform/android/src/geometry/projected_meters.cpp +++ b/platform/android/src/geometry/projected_meters.cpp @@ -4,17 +4,14 @@ namespace mbgl { namespace android { jni::Object ProjectedMeters::New(jni::JNIEnv& env, double northing, double easting) { - static auto constructor = ProjectedMeters::javaClass.GetConstructor(env); - return ProjectedMeters::javaClass.New(env, constructor, northing, easting); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, northing, easting); } void ProjectedMeters::registerNative(jni::JNIEnv& env) { - // Lookup the class - ProjectedMeters::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class 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..5279e6bef2 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 New(jni::JNIEnv&, double, double); - static jni::Class javaClass; - 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..eceb65b07a 100644 --- a/platform/android/src/graphics/pointf.cpp +++ b/platform/android/src/graphics/pointf.cpp @@ -5,23 +5,21 @@ namespace mbgl { namespace android { jni::Object PointF::New(jni::JNIEnv& env, float x, float y) { - static auto constructor = PointF::javaClass.GetConstructor(env); - return PointF::javaClass.New(env, constructor, x, y); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, x, y); } mbgl::ScreenCoordinate PointF::getScreenCoordinate(jni::JNIEnv& env, jni::Object point) { - static auto xField = PointF::javaClass.GetField(env, "x"); - static auto yField = PointF::javaClass.GetField(env, "y"); + static auto javaClass = jni::Class::Singleton(env); + static auto xField = javaClass.GetField(env, "x"); + static auto yField = javaClass.GetField(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::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class 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..27bd49138f 100644 --- a/platform/android/src/graphics/pointf.hpp +++ b/platform/android/src/graphics/pointf.hpp @@ -16,10 +16,7 @@ public: static mbgl::ScreenCoordinate getScreenCoordinate(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); - }; diff --git a/platform/android/src/graphics/rectf.cpp b/platform/android/src/graphics/rectf.cpp index 1b375dad18..9f05728b4c 100644 --- a/platform/android/src/graphics/rectf.cpp +++ b/platform/android/src/graphics/rectf.cpp @@ -4,32 +4,32 @@ namespace mbgl { namespace android { float RectF::getLeft(jni::JNIEnv& env, jni::Object rectf) { - static auto field = RectF::javaClass.GetField(env, "left"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(env, "left"); return rectf.Get(env, field); } float RectF::getTop(jni::JNIEnv& env, jni::Object rectf) { - static auto field = RectF::javaClass.GetField(env, "top"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(env, "top"); return rectf.Get(env, field); } float RectF::getRight(jni::JNIEnv& env, jni::Object rectf) { - static auto field = RectF::javaClass.GetField(env, "right"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(env, "right"); return rectf.Get(env, field); } float RectF::getBottom(jni::JNIEnv& env, jni::Object rectf) { - static auto field = RectF::javaClass.GetField(env, "bottom"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(env, "bottom"); return rectf.Get(env, field); } void RectF::registerNative(jni::JNIEnv& env) { - // Lookup the class - RectF::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class 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..db836e78ba 100644 --- a/platform/android/src/graphics/rectf.hpp +++ b/platform/android/src/graphics/rectf.hpp @@ -20,10 +20,7 @@ public: static float getBottom(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - 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..333b402aa0 100644 --- a/platform/android/src/gson/json_array.cpp +++ b/platform/android/src/gson/json_array.cpp @@ -7,15 +7,14 @@ namespace android { namespace gson { jni::Object JsonArray::New(jni::JNIEnv& env, const std::vector& values){ - static auto constructor = JsonArray::javaClass.GetConstructor(env); - static auto addMethod = JsonArray::javaClass.GetMethod)>(env, "add"); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + static auto addMethod = javaClass.GetMethod)>(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, *jni::SeizeLocal(env, JsonElement::New(env, v))); } return jsonArray; @@ -25,18 +24,18 @@ std::vector JsonArray::convert(jni::JNIEnv& env, const std::vector values; if (jsonArray) { - static auto getMethod = JsonArray::javaClass.GetMethod (jni::jint)>(env, "get"); - static auto sizeMethod = JsonArray::javaClass.GetMethod(env, "size"); + static auto javaClass = jni::Class::Singleton(env); + static auto getMethod = javaClass.GetMethod (jni::jint)>(env, "get"); + static auto sizeMethod = javaClass.GetMethod(env, "size"); int size = jsonArray.Call(env, sizeMethod); values.reserve(uint(size)); for (int i = 0; i < size; i++) { - auto entry = jsonArray.Call(env, getMethod, i); - if (entry) { - values.push_back(JsonElement::convert(env, entry)); + auto entry = jni::SeizeLocal(env, jsonArray.Call(env, getMethod, i)); + if (*entry) { + values.push_back(JsonElement::convert(env, *entry)); } - jni::DeleteLocalRef(env, entry); } } @@ -44,12 +43,9 @@ std::vector JsonArray::convert(jni::JNIEnv& env, const } void JsonArray::registerNative(jni::JNIEnv& env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class 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..e74b92176f 100644 --- a/platform/android/src/gson/json_array.hpp +++ b/platform/android/src/gson/json_array.hpp @@ -1,7 +1,8 @@ #pragma once +#include "json_element.hpp" + #include -#include #include @@ -9,16 +10,13 @@ namespace mbgl { namespace android { namespace gson { -class JsonArray : private mbgl::util::noncopyable { +class JsonArray : public JsonElement { public: static constexpr auto Name() { return "com/google/gson/JsonArray"; }; static jni::Object New(jni::JNIEnv&, const std::vector&); - static std::vector convert(JNIEnv&, jni::Object); - static jni::Class javaClass; - 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..d5304ed674 100644 --- a/platform/android/src/gson/json_element.cpp +++ b/platform/android/src/gson/json_element.cpp @@ -20,17 +20,16 @@ public: jni::JNIEnv& env; jni::Object operator()(const JsonPrimitive::value value) const { - return jni::Cast(env, JsonPrimitive::New(env, value), JsonElement::javaClass); + return JsonPrimitive::New(env, value); } jni::Object operator()(const std::vector &values) const { - return jni::Cast(env, JsonArray::New(env, values), JsonElement::javaClass); + return JsonArray::New(env, values); } jni::Object operator()(const std::unordered_map &values) const { - return jni::Cast(env, JsonObject::New(env, values), JsonElement::javaClass); + return JsonObject::New(env, values); } - }; @@ -44,13 +43,16 @@ mapbox::geometry::value JsonElement::convert(jni::JNIEnv &env, jni::Object::Singleton(env); + auto primitive = JsonPrimitive::convert(env, jni::Cast(env, primitiveClass, jsonElement)); 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)); + static auto objectClass = jni::Class::Singleton(env); + mapbox::geometry::property_map map = JsonObject::convert(env, jni::Cast(env, objectClass, jsonElement)); value = mapbox::util::recursive_wrapper> { map } ; } else if (isJsonArray(env, jsonElement)) { - value = JsonArray::convert(env, jni::Cast(env, jsonElement, JsonArray::javaClass)); + static auto arrayClass = jni::Class::Singleton(env); + value = JsonArray::convert(env, jni::Cast(env, arrayClass, jsonElement)); } else { value = mapbox::geometry::null_value; } @@ -59,32 +61,33 @@ mapbox::geometry::value JsonElement::convert(jni::JNIEnv &env, jni::Object jsonElement) { - static auto method = JsonElement::javaClass.GetMethod(env, "isJsonObject"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "isJsonObject"); return jsonElement.Call(env, method); } bool JsonElement::isJsonArray(JNIEnv& env, jni::Object jsonElement) { - static auto method = JsonElement::javaClass.GetMethod(env, "isJsonArray"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "isJsonArray"); return jsonElement.Call(env, method); } bool JsonElement::isJsonPrimitive(JNIEnv& env, jni::Object jsonElement) { - static auto method = JsonElement::javaClass.GetMethod(env, "isJsonPrimitive"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "isJsonPrimitive"); return jsonElement.Call(env, method); } bool JsonElement::isJsonNull(JNIEnv& env, jni::Object jsonElement) { - static auto method = JsonElement::javaClass.GetMethod(env, "isJsonNull"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "isJsonNull"); return jsonElement.Call(env, method); } void JsonElement::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class 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..5c68934871 100644 --- a/platform/android/src/gson/json_element.hpp +++ b/platform/android/src/gson/json_element.hpp @@ -1,7 +1,6 @@ #pragma once #include -#include #include @@ -9,24 +8,18 @@ namespace mbgl { namespace android { namespace gson { -class JsonElement : private mbgl::util::noncopyable { +class JsonElement : public jni::ObjectTag { public: static constexpr auto Name() { return "com/google/gson/JsonElement"; }; static jni::Object New(jni::JNIEnv&, const mapbox::geometry::value&); - static mapbox::geometry::value convert(JNIEnv&, jni::Object); static bool isJsonObject(JNIEnv&, jni::Object); - static bool isJsonArray(JNIEnv&, jni::Object); - static bool isJsonPrimitive(JNIEnv&, jni::Object); - static bool isJsonNull(JNIEnv&, jni::Object); - static jni::Class javaClass; - 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..4a2ec07563 100644 --- a/platform/android/src/gson/json_object.cpp +++ b/platform/android/src/gson/json_object.cpp @@ -10,17 +10,16 @@ namespace gson { jni::Object JsonObject::New(jni::JNIEnv& env, const std::unordered_map& values) { - static auto constructor = JsonObject::javaClass.GetConstructor(env); - static auto addMethod = JsonObject::javaClass.GetMethod)>(env, "add"); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + static auto addMethod = javaClass.GetMethod)>(env, "add"); - jni::Object jsonObject = JsonObject::javaClass.New(env, constructor); + jni::Object jsonObject = javaClass.New(env, constructor); for (auto &item : values) { - jni::Object jsonElement = JsonElement::New(env, item.second); - jni::String key = jni::Make(env, item.first); - jsonObject.Call(env, addMethod, key, jsonElement); - jni::DeleteLocalRef(env, jsonElement); - jni::DeleteLocalRef(env, key); + jsonObject.Call(env, addMethod, + *jni::SeizeLocal(env, jni::Make(env, item.first)), + *jni::SeizeLocal(env, JsonElement::New(env, item.second))); } return jsonObject; @@ -29,32 +28,22 @@ jni::Object JsonObject::New(jni::JNIEnv& env, const std::unordered_m template // void (jni::String, jni::Object) static void iterateEntrySet(jni::JNIEnv& env, jni::Object jsonObject, F callback) { // Get Set> - static auto method = JsonObject::javaClass.GetMethod ()>(env, "entrySet"); - auto entrySet = jsonObject.Call(env, method); - jni::Array> entryArray = java::util::Set::toArray(env, entrySet); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod ()>(env, "entrySet"); - size_t size = entryArray.Length(env); + auto entryArray = + jni::SeizeLocal(env, java::util::Set::toArray(env, + *jni::SeizeLocal(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); + auto entry = jni::SeizeLocal(env, entryArray->Get(env, i)); if (entry) { - // Convert - auto jKey = java::util::Map::Entry::getKey(env, entry); - auto jKeyString = jni::String(reinterpret_cast(jKey.Get())); - auto jValue = java::util::Map::Entry::getValue(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( + *jni::SeizeLocal(env, java::util::Map::Entry::getKey(env, *entry)), + *jni::SeizeLocal(env, java::util::Map::Entry::getValue(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) { @@ -70,12 +59,9 @@ mapbox::geometry::property_map JsonObject::convert(jni::JNIEnv &env, jni::Object } void JsonObject::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class 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..85e8828d91 100644 --- a/platform/android/src/gson/json_object.hpp +++ b/platform/android/src/gson/json_object.hpp @@ -1,7 +1,8 @@ #pragma once +#include "json_element.hpp" + #include -#include #include @@ -9,16 +10,13 @@ namespace mbgl { namespace android { namespace gson { -class JsonObject : private mbgl::util::noncopyable { +class JsonObject : public JsonElement { public: static constexpr auto Name() { return "com/google/gson/JsonObject"; }; static jni::Object New(jni::JNIEnv&, const std::unordered_map&); - static mapbox::geometry::property_map convert(JNIEnv&, jni::Object); - static jni::Class javaClass; - 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..2b03629135 100644 --- a/platform/android/src/gson/json_primitive.cpp +++ b/platform/android/src/gson/json_primitive.cpp @@ -1,5 +1,4 @@ #include "json_primitive.hpp" -#include "../java/lang.hpp" namespace mbgl { namespace android { @@ -24,58 +23,55 @@ public: * Create a primitive containing a string value */ jni::Object operator()(const std::string value) const { - static auto constructor = JsonPrimitive::javaClass.GetConstructor(env); - auto jvalue = jni::Make(env, value); - auto jsonPrimitive = JsonPrimitive::javaClass.New(env, constructor, jvalue); - jni::DeleteLocalRef(env, jvalue); - return jsonPrimitive; + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + + return javaClass.New(env, constructor, + *jni::SeizeLocal(env, jni::Make(env, value))); } /** * Create a primitive containing a number value with type double */ jni::Object operator()(const double value) const { - static auto constructor = JsonPrimitive::javaClass.GetConstructor>(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; + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + + return javaClass.New(env, constructor, + *jni::SeizeLocal(env, jni::Number(jni::Box(env, value)))); } /** * Create a primitive containing a number value with type long */ jni::Object operator()(const int64_t value) const { - static auto constructor = JsonPrimitive::javaClass.GetConstructor>(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; + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + + return javaClass.New(env, constructor, + *jni::SeizeLocal(env, jni::Number(jni::Box(env, value)))); } /** * Create a primitive containing a number value with type long */ jni::Object operator()(const uint64_t value) const { - static auto constructor = JsonPrimitive::javaClass.GetConstructor>(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; + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + + return javaClass.New(env, constructor, + *jni::SeizeLocal(env, jni::Number(jni::Box(env, int64_t(value))))); // TODO: should use BigInteger } /** * Create a primitive containing a boolean value */ jni::Object operator()(const bool value) const { - static auto constructor = JsonPrimitive::javaClass.GetConstructor>(env); - auto boxedValue = java::lang::Boolean::valueOf(env, value); - auto jsonPrimitive = JsonPrimitive::javaClass.New(env, constructor, boxedValue); - jni::DeleteLocalRef(env, boxedValue); - return jsonPrimitive; + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + + return javaClass.New(env, constructor, + *jni::SeizeLocal(env, jni::Box(env, value ? jni::jni_true : jni::jni_false))); } }; @@ -102,45 +98,45 @@ JsonPrimitive::value JsonPrimitive::convert(jni::JNIEnv &env, jni::Object jsonPrimitive) { - static auto method = JsonPrimitive::javaClass.GetMethod(env, "isBoolean"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "isBoolean"); return jsonPrimitive.Call(env, method); } bool JsonPrimitive::isString(JNIEnv& env, jni::Object jsonPrimitive) { - static auto method = JsonPrimitive::javaClass.GetMethod(env, "isString"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "isString"); return jsonPrimitive.Call(env, method); } bool JsonPrimitive::isNumber(JNIEnv& env, jni::Object jsonPrimitive) { - static auto method = JsonPrimitive::javaClass.GetMethod(env, "isNumber"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "isNumber"); return jsonPrimitive.Call(env, method); } bool JsonPrimitive::getAsBoolean(JNIEnv& env, jni::Object jsonPrimitive) { - static auto method = JsonPrimitive::javaClass.GetMethod(env, "getAsBoolean"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "getAsBoolean"); return jsonPrimitive.Call(env, method); } std::string JsonPrimitive::getAsString(JNIEnv& env, jni::Object jsonPrimitive) { - static auto method = JsonPrimitive::javaClass.GetMethod(env, "getAsString"); - auto jString = jsonPrimitive.Call(env, method); - auto string = jni::Make(env, jString); - jni::DeleteLocalRef(env, jString); - return string; + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "getAsString"); + return jni::Make(env, *jni::SeizeLocal(env, jsonPrimitive.Call(env, method))); } double JsonPrimitive::getAsDouble(JNIEnv& env, jni::Object jsonPrimitive) { - static auto method = JsonPrimitive::javaClass.GetMethod(env, "getAsDouble"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "getAsDouble"); return jsonPrimitive.Call(env, method); } void JsonPrimitive::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class 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..d9e90507f9 100644 --- a/platform/android/src/gson/json_primitive.hpp +++ b/platform/android/src/gson/json_primitive.hpp @@ -1,7 +1,8 @@ #pragma once +#include "json_element.hpp" + #include -#include #include @@ -9,30 +10,23 @@ namespace mbgl { namespace android { namespace gson { -class JsonPrimitive : private mbgl::util::noncopyable { +class JsonPrimitive : public JsonElement { public: using value = mapbox::util::variant; static constexpr auto Name() { return "com/google/gson/JsonPrimitive"; }; static jni::Object New(jni::JNIEnv&, const value&); - static value convert(JNIEnv&, jni::Object); static bool isBoolean(JNIEnv&, jni::Object); - static bool isString(JNIEnv&, jni::Object); - static bool isNumber(JNIEnv&, jni::Object); static bool getAsBoolean(JNIEnv&, jni::Object); - static std::string getAsString(JNIEnv&, jni::Object); - static double getAsDouble(JNIEnv&, jni::Object); - static jni::Class 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..6b359aab8c 100644 --- a/platform/android/src/http_file_source.cpp +++ b/platform/android/src/http_file_source.cpp @@ -32,8 +32,7 @@ public: jni::String retryAfter, jni::String xRateLimitReset, jni::Array body); - static jni::Class javaClass; - jni::UniqueObject javaRequest; + jni::Global> javaRequest; private: Resource resource; @@ -52,16 +51,14 @@ private: static const int permanentError = 2; }; -jni::Class HTTPRequest::javaClass; - namespace android { void RegisterNativeHTTPRequest(jni::JNIEnv& env) { - HTTPRequest::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) - jni::RegisterNativePeer(env, HTTPRequest::javaClass, "nativePtr", + jni::RegisterNativePeer(env, javaClass, "nativePtr", METHOD(&HTTPRequest::onFailure, "nativeOnFailure"), METHOD(&HTTPRequest::onResponse, "nativeOnResponse")); } @@ -82,6 +79,7 @@ HTTPRequest::HTTPRequest(jni::JNIEnv& env, const Resource& resource_, FileSource jni::UniqueLocalFrame frame = jni::PushLocalFrame(env, 10); + static auto javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); @@ -95,6 +93,7 @@ HTTPRequest::HTTPRequest(jni::JNIEnv& env, const Resource& resource_, FileSource HTTPRequest::~HTTPRequest() { android::UniqueEnv env = android::AttachEnv(); + static auto javaClass = jni::Class::Singleton(*env); static auto cancel = javaClass.GetMethod(*env, "cancel"); javaRequest->Call(*env, cancel); diff --git a/platform/android/src/image.cpp b/platform/android/src/image.cpp index 0456381578..a85e9aeaa2 100644 --- a/platform/android/src/image.cpp +++ b/platform/android/src/image.cpp @@ -11,17 +11,12 @@ namespace mbgl { PremultipliedImage decodeImage(const std::string& string) { auto env{ android::AttachEnv() }; - auto array = jni::Array::New(*env, string.size()); - jni::SetArrayRegion(*env, *array, 0, string.size(), + auto array = jni::SeizeLocal(*env, jni::Array::New(*env, string.size())); + jni::SetArrayRegion(*env, **array, 0, string.size(), reinterpret_cast(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, + *jni::SeizeLocal(*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::valueOf(JNIEnv &env, jfloat value) { - static auto method = javaClass.GetStaticMethod (jni::jfloat)>(env, "valueOf"); - return javaClass.Call(env, method, value); -} - -void Float::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); -} - -jni::Class Float::javaClass; - -// Long - -jni::Object Long::valueOf(JNIEnv &env, jlong value) { - static auto method = javaClass.GetStaticMethod (jni::jlong)>(env, "valueOf"); - return javaClass.Call(env, method, value); -} - -void Long::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); -} - -jni::Class Long::javaClass; - -// Double - -jni::Object Double::valueOf(JNIEnv &env, jdouble value) { - static auto method = javaClass.GetStaticMethod (jni::jdouble)>(env, "valueOf"); - return javaClass.Call(env, method, value); -} - -void Double::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); -} - -jni::Class Double::javaClass; - -// Boolean - -jni::Object Boolean::valueOf(JNIEnv &env, jboolean value) { - static auto method = javaClass.GetStaticMethod (jni::jboolean)>(env, "valueOf"); - return javaClass.Call(env, method, value); -} - -void Boolean::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); -} - -jni::Class Boolean::javaClass; - -// Number - -void Number::registerNative(jni::JNIEnv &env) { - // Lookup the class - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); -} - -jni::Class 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 -#include - -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 valueOf(JNIEnv&, jfloat); - - static jni::Class javaClass; - - static void registerNative(jni::JNIEnv&); -}; - -class Double : private mbgl::util::noncopyable { -public: - static constexpr auto Name() { return "java/lang/Double"; }; - - static jni::Object valueOf(JNIEnv&, jdouble); - - static jni::Class javaClass; - - static void registerNative(jni::JNIEnv&); -}; - -class Long : private mbgl::util::noncopyable { -public: - static constexpr auto Name() { return "java/lang/Long"; }; - - static jni::Object valueOf(JNIEnv&, jlong); - - static jni::Class javaClass; - - static void registerNative(jni::JNIEnv&); -}; - -class Boolean : private mbgl::util::noncopyable { -public: - static constexpr auto Name() { return "java/lang/Boolean"; }; - - static jni::Object valueOf(JNIEnv&, jboolean); - - static jni::Class javaClass; - - static void registerNative(jni::JNIEnv&); -}; - -class Number : private mbgl::util::noncopyable { -public: - static constexpr auto Name() { return "java/lang/Number"; }; - - static jni::Class 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::javaClass; -jni::Class List::javaClass; -jni::Class Set::javaClass; -jni::Class Map::javaClass; -jni::Class Map::Entry::javaClass; - void registerNative(jni::JNIEnv& env) { - Arrays::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); - List::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); - Set::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); - Map::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); - Map::Entry::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); + jni::Class::Singleton(env); + jni::Class::Singleton(env); + jni::Class::Singleton(env); + jni::Class::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..808f14be15 100644 --- a/platform/android/src/java/util.hpp +++ b/platform/android/src/java/util.hpp @@ -11,51 +11,43 @@ namespace util { class List : private mbgl::util::noncopyable { public: - static constexpr auto Name() { return "java/util/List"; }; template static jni::Array> toArray(jni::JNIEnv& env, jni::Object list) { - static auto toArray = List::javaClass.GetMethod> ()>(env, "toArray"); + static auto javaClass = jni::Class::Singleton(env); + static auto toArray = javaClass.GetMethod> ()>(env, "toArray"); return (jni::Array>) list.Call(env, toArray); }; - - static jni::Class javaClass; - }; class Arrays : private mbgl::util::noncopyable { public: - static constexpr auto Name() { return "java/util/Arrays"; }; template static jni::Object asList(jni::JNIEnv& env, jni::Array> array) { - static auto asList = Arrays::javaClass.GetStaticMethod(jni::Array>)>(env, "asList"); + static auto javaClass = jni::Class::Singleton(env); + static auto asList = javaClass.GetStaticMethod(jni::Array>)>(env, "asList"); return javaClass.Call(env, asList, (jni::Array>) array); } - - static jni::Class javaClass; - }; class Set : private mbgl::util::noncopyable { public: - static constexpr auto Name() { return "java/util/Set"; }; template static jni::Array> toArray(jni::JNIEnv& env, jni::Object list) { - static auto toArray = Set::javaClass.GetMethod> ()>(env, "toArray"); + static auto javaClass = jni::Class::Singleton(env); + static auto toArray = javaClass.GetMethod> ()>(env, "toArray"); return (jni::Array>) list.Call(env, toArray); }; - - static jni::Class javaClass; - }; class Map : private mbgl::util::noncopyable { public: + static constexpr auto Name() { return "java/util/Map"; }; class Entry : private mbgl::util::noncopyable { public: @@ -63,27 +55,22 @@ public: template static jni::Object getKey(jni::JNIEnv& env, jni::Object entry) { - static auto method = Entry::javaClass.GetMethod ()>(env, "getKey"); - return (jni::Object) entry.Call(env, method); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod ()>(env, "getKey"); + return jni::Cast(env, jni::Class::Singleton(env), entry.Call(env, method)); } template static jni::Object getValue(jni::JNIEnv& env, jni::Object entry) { - static auto method = Entry::javaClass.GetMethod ()>(env, "getValue"); - return (jni::Object) entry.Call(env, method).Get(); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod ()>(env, "getValue"); + return jni::Cast(env, jni::Class::Singleton(env), entry.Call(env, method)); } - - static jni::Class javaClass; }; - - static constexpr auto Name() { return "java/util/Map"; }; - - static jni::Class 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..abea7f4502 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); diff --git a/platform/android/src/jni/generic_global_ref_deleter.hpp b/platform/android/src/jni/generic_global_ref_deleter.hpp index 7239e361a7..b865ee9f8b 100644 --- a/platform/android/src/jni/generic_global_ref_deleter.hpp +++ b/platform/android/src/jni/generic_global_ref_deleter.hpp @@ -12,39 +12,33 @@ namespace android { struct GenericGlobalRefDeleter { void operator()(jni::jobject* p) const { if (p) { - auto env = AttachEnv(); - env->DeleteGlobalRef(jni::Unwrap(p)); + AttachEnv()->DeleteGlobalRef(jni::Unwrap(p)); } } }; +struct GenericWeakGlobalRefDeleter { + void operator()(jni::jobject* p) const { + if (p) { + AttachEnv()->DeleteWeakGlobalRef(jni::Unwrap(p)); + } + } +}; -template < class TagType > -class GenericWeakObjectRefDeleter; - -template < class TagType = jni::ObjectTag > -using GenericUniqueWeakObject = std::unique_ptr< const jni::Object, GenericWeakObjectRefDeleter >; +template < class T > +using GenericGlobal = jni::UniquePointerlike< T, GenericGlobalRefDeleter >; -template < class TagType > -class GenericWeakObjectRefDeleter -{ -public: - using pointer = jni::PointerToValue< jni::Object >; +template < class T > +using GenericWeak = jni::UniquePointerlike< T, GenericWeakGlobalRefDeleter >; - void operator()(pointer p) const - { - if (p) - { - auto env = AttachEnv(); - env->DeleteWeakGlobalRef(jni::Unwrap(p->Get())); - } - } +template < class T > +GenericGlobal SeizeGenericGlobal(T&& t) { + return GenericGlobal(std::move(t), GenericGlobalRefDeleter()); }; -template < class TagType > -GenericUniqueWeakObject SeizeGenericWeakRef(JNIEnv&, jni::Object&& object) -{ - return GenericUniqueWeakObject(jni::PointerToValue>(std::move(object)), GenericWeakObjectRefDeleter()); +template < class T > +GenericWeak SeizeGenericWeak(T&& t) { + return GenericWeak(std::move(t), GenericWeakGlobalRefDeleter()); }; } // namespace android 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 - -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 NewLocalObject(JNIEnv& env, T* t) { - return LocalObject(t, LocalRefDeleter(env)); - } -} diff --git a/platform/android/src/logger.cpp b/platform/android/src/logger.cpp index 0ade914604..ddc4d84525 100644 --- a/platform/android/src/logger.cpp +++ b/platform/android/src/logger.cpp @@ -5,32 +5,29 @@ namespace mbgl { namespace android { void Logger::registerNative(jni::JNIEnv& env) { - _class = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class Logger::_class; - void Logger::log(jni::JNIEnv& env, EventSeverity severity, const std::string &msg) { - auto tag = jni::Make(env, "Mbgl"); - auto message = jni::Make(env, msg); + static auto _class = jni::Class::Singleton(env); + + auto tag = jni::SeizeLocal(env, jni::Make(env, "Mbgl")); + auto message = jni::SeizeLocal(env, jni::Make(env, msg)); using Signature = void(jni::String, jni::String); if (severity == EventSeverity::Debug) { auto static debug = _class.GetStaticMethod(env, "d"); - _class.Call(env, debug, tag, message); + _class.Call(env, debug, *tag, *message); } else if (severity == EventSeverity::Info) { auto static info = _class.GetStaticMethod(env, "i"); - _class.Call(env, info, tag, message); + _class.Call(env, info, *tag, *message); } else if(severity == EventSeverity::Warning) { auto static warning = _class.GetStaticMethod(env, "w"); - _class.Call(env, warning, tag, message); + _class.Call(env, warning, *tag, *message); } else { auto static error = _class.GetStaticMethod(env, "e"); - _class.Call(env, error, tag, message); + _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 _class; }; } // namespace android diff --git a/platform/android/src/map/camera_position.cpp b/platform/android/src/map/camera_position.cpp index 01ffc6530b..5700341d65 100644 --- a/platform/android/src/map/camera_position.cpp +++ b/platform/android/src/map/camera_position.cpp @@ -5,7 +5,8 @@ namespace mbgl { namespace android { jni::Object CameraPosition::New(jni::JNIEnv &env, mbgl::CameraOptions options) { - static auto constructor = CameraPosition::javaClass.GetConstructor, double, double, double>(env); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor, double, double, double>(env); // wrap LatLng values coming from core auto center = options.center.value(); @@ -24,18 +25,17 @@ jni::Object 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 position) { - static auto bearing = CameraPosition::javaClass.GetField(env, "bearing"); - static auto target = CameraPosition::javaClass.GetField>(env, "target"); - static auto tilt = CameraPosition::javaClass.GetField(env, "tilt"); - static auto zoom = CameraPosition::javaClass.GetField(env, "zoom"); + static auto javaClass = jni::Class::Singleton(env); + static auto bearing = javaClass.GetField(env, "bearing"); + static auto target = javaClass.GetField>(env, "target"); + static auto tilt = javaClass.GetField(env, "tilt"); + static auto zoom = javaClass.GetField(env, "zoom"); - auto jtarget = position.Get(env, target); - auto center = LatLng::getLatLng(env, jtarget); - jni::DeleteLocalRef(env, jtarget); + auto center = LatLng::getLatLng(env, *jni::SeizeLocal(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::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class 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..d577811915 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 New(jni::JNIEnv&, mbgl::CameraOptions); static mbgl::CameraOptions getCameraOptions(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - 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..ee3c7012a7 100644 --- a/platform/android/src/map/image.cpp +++ b/platform/android/src/map/image.cpp @@ -6,43 +6,36 @@ namespace mbgl { namespace android { mbgl::style::Image Image::getImage(jni::JNIEnv& env, jni::Object image) { - static auto widthField = Image::javaClass.GetField(env, "width"); - static auto heightField = Image::javaClass.GetField(env, "height"); - static auto pixelRatioField = Image::javaClass.GetField(env, "pixelRatio"); - static auto bufferField = Image::javaClass.GetField>(env, "buffer"); - static auto nameField = Image::javaClass.GetField(env, "name"); - static auto sdfField = Image::javaClass.GetField(env, "sdf"); + static auto javaClass = jni::Class::Singleton(env); + static auto widthField = javaClass.GetField(env, "width"); + static auto heightField = javaClass.GetField(env, "height"); + static auto pixelRatioField = javaClass.GetField(env, "pixelRatio"); + static auto bufferField = javaClass.GetField>(env, "buffer"); + static auto nameField = javaClass.GetField(env, "name"); + static auto sdfField = javaClass.GetField(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(env, jName); + auto pixels = jni::SeizeLocal(env, image.Get(env, bufferField)); + auto name = jni::Make(env, *jni::SeizeLocal(env, image.Get(env, nameField))); auto sdf = (bool) image.Get(env, sdfField); - jni::DeleteLocalRef(env, jName); - jni::NullCheck(env, &pixels); - std::size_t size = pixels.Length(env); + jni::NullCheck(env, pixels->Get()); + std::size_t size = pixels->Length(env); mbgl::PremultipliedImage premultipliedImage({ static_cast(width), static_cast(height) }); if (premultipliedImage.bytes() != uint32_t(size)) { throw mbgl::util::SpriteImageException("Sprite image pixel count mismatch"); } - jni::GetArrayRegion(env, *pixels, 0, size, reinterpret_cast(premultipliedImage.data.get())); - jni::DeleteLocalRef(env, pixels); + jni::GetArrayRegion(env, **pixels, 0, size, reinterpret_cast(premultipliedImage.data.get())); return mbgl::style::Image {name, std::move(premultipliedImage), pixelRatio, sdf}; } void Image::registerNative(jni::JNIEnv &env) { - // Lookup the class - Image::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class Image::javaClass; - - } // namespace android } // namespace mb - diff --git a/platform/android/src/map/image.hpp b/platform/android/src/map/image.hpp index 1513e13ee7..17ed4cbef8 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); - static jni::Class javaClass; - 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..1f8c82ac05 100644 --- a/platform/android/src/map_renderer.cpp +++ b/platform/android/src/map_renderer.cpp @@ -18,7 +18,8 @@ MapRenderer::MapRenderer(jni::JNIEnv& _env, jni::Object obj, jni::Object _fileSource, jni::jfloat pixelRatio_, jni::String programCacheDir_, jni::String localIdeographFontFamily_) - : javaPeer(SeizeGenericWeakRef(_env, jni::Object(jni::NewWeakGlobalRef(_env, obj.Get()).release()))), pixelRatio(pixelRatio_) + : javaPeer(SeizeGenericWeak(obj.NewWeakGlobalRef(_env).release())) + , pixelRatio(pixelRatio_) , fileSource(FileSource::getDefaultFileSource(_env, _fileSource)) , programCacheDir(jni::Make(_env, programCacheDir_)) , localIdeographFontFamily(localIdeographFontFamily_ == nullptr ? optional{} : jni::Make(_env, localIdeographFontFamily_ )) @@ -52,6 +53,7 @@ void MapRenderer::schedule(std::weak_ptr scheduled) { auto peer = runnable->peer(); // Queue the event on the Java Peer + static auto javaClass = jni::Class::Singleton(*_env); static auto queueEvent = javaClass.GetMethod)>(*_env, "queueEvent"); javaPeer->Call(*_env, queueEvent, *peer); @@ -62,6 +64,7 @@ void MapRenderer::schedule(std::weak_ptr scheduled) { void MapRenderer::requestRender() { android::UniqueEnv _env = android::AttachEnv(); + static auto javaClass = jni::Class::Singleton(*_env); static auto onInvalidate = javaClass.GetMethod(*_env, "requestRender"); javaPeer->Call(*_env, onInvalidate); } @@ -179,16 +182,14 @@ void MapRenderer::onSurfaceChanged(JNIEnv&, jint width, jint height) { // Static methods // -jni::Class MapRenderer::javaClass; - void MapRenderer::registerNative(jni::JNIEnv& env) { // Lookup the class - MapRenderer::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer - jni::RegisterNativePeer(env, MapRenderer::javaClass, "nativePtr", + jni::RegisterNativePeer(env, javaClass, "nativePtr", std::make_unique, jni::Object, jni::jfloat, jni::String, jni::String>, "nativeInitialize", "finalize", METHOD(&MapRenderer::render, "nativeRender"), @@ -199,7 +200,8 @@ void MapRenderer::registerNative(jni::JNIEnv& env) { } MapRenderer& MapRenderer::getNativePeer(JNIEnv& env, jni::Object jObject) { - static auto field = MapRenderer::javaClass.GetField(env, "nativePtr"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(env, "nativePtr"); MapRenderer* mapRenderer = reinterpret_cast(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..6fcf2fee71 100644 --- a/platform/android/src/map_renderer.hpp +++ b/platform/android/src/map_renderer.hpp @@ -38,8 +38,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/maps/renderer/MapRenderer"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); static MapRenderer& getNativePeer(JNIEnv&, jni::Object); @@ -99,7 +97,7 @@ private: void onSurfaceChanged(JNIEnv&, jint width, jint height); private: - GenericUniqueWeakObject javaPeer; + GenericWeak> 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..1bfccebd2d 100644 --- a/platform/android/src/map_renderer_runnable.cpp +++ b/platform/android/src/map_renderer_runnable.cpp @@ -12,6 +12,7 @@ MapRendererRunnable::MapRendererRunnable(jni::JNIEnv& env, std::weak_ptr::Singleton(env); static auto constructor = javaClass.GetConstructor(env); auto instance = javaClass.New(env, constructor, reinterpret_cast(this)); javaPeer = instance.NewGlobalRef(env); @@ -23,23 +24,21 @@ void MapRendererRunnable::run(jni::JNIEnv&) { Mailbox::maybeReceive(mailbox); } -jni::UniqueObject MapRendererRunnable::peer() { +jni::Global> MapRendererRunnable::peer() { return std::move(javaPeer); } // Static methods // -jni::Class MapRendererRunnable::javaClass; - void MapRendererRunnable::registerNative(jni::JNIEnv& env) { // Lookup the class - MapRendererRunnable::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) jni::RegisterNativePeer( env, - MapRendererRunnable::javaClass, + javaClass, "nativePtr", std::make_unique, "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 javaClass; - static void registerNative(jni::JNIEnv&); MapRendererRunnable(jni::JNIEnv&, std::weak_ptr); @@ -38,10 +36,10 @@ public: void run(jni::JNIEnv&); // Transfers ownership of the Peer object to the caller - jni::UniqueObject peer(); + jni::Global> peer(); private: - jni::UniqueObject javaPeer; + jni::Global> javaPeer; std::weak_ptr mailbox; }; diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp index 8c76332b39..26814fd6b8 100755 --- a/platform/android/src/native_map_view.cpp +++ b/platform/android/src/native_map_view.cpp @@ -103,6 +103,7 @@ void NativeMapView::notifyMapChange(mbgl::MapChange change) { assert(vm != nullptr); android::UniqueEnv _env = android::AttachEnv(); + static auto javaClass = jni::Class::Singleton(*_env); static auto onMapChanged = javaClass.GetMethod(*_env, "onMapChanged"); javaPeer->Call(*_env, onMapChanged, (int) change); } @@ -376,9 +377,7 @@ void NativeMapView::setVisibleCoordinateBounds(JNIEnv& env, jni::Array::Singleton(*_env); static auto onSnapshotReady = javaClass.GetMethod)>(*_env, "onSnapshotReady"); javaPeer->Call(*_env, onSnapshotReady, bitmap); }); @@ -436,13 +436,11 @@ jni::Array NativeMapView::addMarkers(jni::JNIEnv& env, jni::Array marker = jmarkers.Get(env, i); + auto marker = jni::SeizeLocal(env, jmarkers.Get(env, i)); ids.push_back(map->addAnnotation(mbgl::SymbolAnnotation { - Marker::getPosition(env, marker), - Marker::getIconId(env, marker) + Marker::getPosition(env, *marker), + Marker::getIconId(env, *marker) })); - - jni::DeleteLocalRef(env, marker); } auto result = jni::Array::New(env, len); @@ -505,12 +503,8 @@ jni::Array NativeMapView::addPolylines(JNIEnv& env, jni::ArrayaddAnnotation(annotation)); - - jni::DeleteLocalRef(env, polyline); } auto result = jni::Array::New(env, len); @@ -528,12 +522,8 @@ jni::Array NativeMapView::addPolygons(JNIEnv& env, jni::ArrayaddAnnotation(annotation)); - - jni::DeleteLocalRef(env, polygon); } auto result = jni::Array::New(env, len); @@ -670,7 +660,7 @@ jni::Array> NativeMapView::queryRenderedFeaturesFo return *convert>, std::vector>( env, - rendererFrontend->queryRenderedFeatures(point, { layers, toFilter(env, jfilter) })); + rendererFrontend->queryRenderedFeatures(point, { layers, toFilter(env, jni::SeizeLocal(env, std::move(jfilter))) })); } jni::Array> NativeMapView::queryRenderedFeaturesForBox(JNIEnv& env, jni::jfloat left, jni::jfloat top, @@ -690,7 +680,7 @@ jni::Array> NativeMapView::queryRenderedFeaturesFo return *convert>, std::vector>( env, - rendererFrontend->queryRenderedFeatures(box, { layers, toFilter(env, jfilter) })); + rendererFrontend->queryRenderedFeatures(box, { layers, toFilter(env, jni::SeizeLocal(env, std::move(jfilter))) })); } jni::Object NativeMapView::getLight(JNIEnv& env) { @@ -708,12 +698,10 @@ jni::Array> NativeMapView::getLayers(JNIEnv& env) { std::vector layers = map->getStyle().getLayers(); // Convert - jni::Array> jLayers = jni::Array>::New(env, layers.size(), Layer::javaClass); + jni::Array> jLayers = jni::Array>::New(env, layers.size()); int index = 0; for (auto layer : layers) { - auto jLayer = jni::Object(createJavaLayerPeer(env, *map, *layer)); - jLayers.Set(env, index, jLayer); - jni::DeleteLocalRef(env, jLayer); + jLayers.Set(env, index, *jni::SeizeLocal(env, jni::Object(createJavaLayerPeer(env, *map, *layer)))); index++; } @@ -855,7 +843,7 @@ jni::Array> NativeMapView::getSources(JNIEnv& env) { std::vector sources = map->getStyle().getSources(); // Convert - jni::Array> jSources = jni::Array>::New(env, sources.size(), Source::javaClass); + jni::Array> jSources = jni::Array>::New(env, sources.size()); int index = 0; for (auto source : sources) { jSources.Set(env, index, Source::peerForCoreSource(env, *source, *rendererFrontend)); @@ -914,10 +902,8 @@ void NativeMapView::addImages(JNIEnv& env, jni::Array jimage = jimages.Get(env, i); - auto image = mbgl::android::Image::getImage(env, jimage); + auto image = mbgl::android::Image::getImage(env, *jni::SeizeLocal(env, jimages.Get(env, i))); map->getStyle().addImage(std::make_unique(image)); - jni::DeleteLocalRef(env, jimage); } } @@ -948,16 +934,14 @@ mbgl::Map& NativeMapView::getMap() { // Static methods // -jni::Class NativeMapView::javaClass; - void NativeMapView::registerNative(jni::JNIEnv& env) { // Lookup the class - NativeMapView::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer - jni::RegisterNativePeer(env, NativeMapView::javaClass, "nativePtr", + jni::RegisterNativePeer(env, javaClass, "nativePtr", std::make_unique, jni::Object, jni::Object, jni::jfloat>, "nativeInitialize", "nativeDestroy", diff --git a/platform/android/src/native_map_view.hpp b/platform/android/src/native_map_view.hpp index e577670323..d398b39bf7 100755 --- a/platform/android/src/native_map_view.hpp +++ b/platform/android/src/native_map_view.hpp @@ -45,8 +45,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/maps/NativeMapView"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); NativeMapView(jni::JNIEnv&, @@ -254,7 +252,7 @@ private: std::unique_ptr rendererFrontend; JavaVM *vm = nullptr; - jni::UniqueWeakObject javaPeer; + jni::Weak> javaPeer; MapRenderer& mapRenderer; diff --git a/platform/android/src/offline/offline_manager.cpp b/platform/android/src/offline/offline_manager.cpp index e96ed7e4d2..263f7b9d8b 100644 --- a/platform/android/src/offline/offline_manager.cpp +++ b/platform/android/src/offline/offline_manager.cpp @@ -24,8 +24,8 @@ void OfflineManager::listOfflineRegions(jni::JNIEnv& env_, jni::Object(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()), - jFileSource = std::shared_ptr(jFileSource_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()) + callback = std::shared_ptr(callback_.NewGlobalRef(env_).release().Get(), GenericGlobalRefDeleter()), + jFileSource = std::shared_ptr(jFileSource_.NewGlobalRef(env_).release().Get(), GenericGlobalRefDeleter()) ](mbgl::expected regions) mutable { // Reattach, the callback comes from a different thread @@ -58,8 +58,8 @@ void OfflineManager::createOfflineRegion(jni::JNIEnv& env_, // 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(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()), - jFileSource = std::shared_ptr(jFileSource_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()) + callback = std::shared_ptr(callback_.NewGlobalRef(env_).release().Get(), GenericGlobalRefDeleter()), + jFileSource = std::shared_ptr(jFileSource_.NewGlobalRef(env_).release().Get(), GenericGlobalRefDeleter()) ](mbgl::expected region) mutable { // Reattach, the callback comes from a different thread @@ -77,13 +77,11 @@ void OfflineManager::createOfflineRegion(jni::JNIEnv& env_, }); } -jni::Class OfflineManager::javaClass; - void OfflineManager::registerNative(jni::JNIEnv& env) { - OfflineManager::ListOfflineRegionsCallback::registerNative(env); - OfflineManager::CreateOfflineRegionCallback::registerNative(env); + jni::Class::Singleton(env); + jni::Class::Singleton(env); - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) @@ -101,37 +99,28 @@ void OfflineManager::registerNative(jni::JNIEnv& env) { void OfflineManager::ListOfflineRegionsCallback::onError(jni::JNIEnv& env, jni::Object callback, std::exception_ptr error) { + static auto javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod(env, "onError"); - std::string message = mbgl::util::toString(error); - auto jmessage = jni::Make(env, message); - callback.Call(env, method, jmessage); - jni::DeleteLocalRef(env, jmessage); + + callback.Call(env, method, + *jni::SeizeLocal(env, jni::Make(env, mbgl::util::toString(error)))); } void OfflineManager::ListOfflineRegionsCallback::onList(jni::JNIEnv& env, jni::Object jFileSource, jni::Object callback, mbgl::optional> regions) { - //Convert the regions to java peer objects + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod>)>(env, "onList"); + std::size_t index = 0; - auto jregions = jni::Array>::New(env, regions->size(), OfflineRegion::javaClass); + auto jregions = jni::SeizeLocal(env, jni::Array>::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, *jni::SeizeLocal(env, OfflineRegion::New(env, jFileSource, std::move(region)))); index++; } - // Trigger callback - static auto method = javaClass.GetMethod>)>(env, "onList"); - callback.Call(env, method, jregions); - jni::DeleteLocalRef(env, jregions); -} - -jni::Class OfflineManager::ListOfflineRegionsCallback::javaClass; - -void OfflineManager::ListOfflineRegionsCallback::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + callback.Call(env, method, *jregions); } // OfflineManager::CreateOfflineRegionCallback // @@ -139,30 +128,22 @@ void OfflineManager::ListOfflineRegionsCallback::registerNative(jni::JNIEnv& env void OfflineManager::CreateOfflineRegionCallback::onError(jni::JNIEnv& env, jni::Object callback, std::exception_ptr error) { + static auto javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod(env, "onError"); - std::string message = mbgl::util::toString(error); - auto jmessage = jni::Make(env, message); - callback.Call(env, method, jmessage); - jni::DeleteLocalRef(env, jmessage); + + callback.Call(env, method, + *jni::SeizeLocal(env, jni::Make(env, mbgl::util::toString(error)))); } void OfflineManager::CreateOfflineRegionCallback::onCreate(jni::JNIEnv& env, jni::Object jFileSource, jni::Object callback, mbgl::optional region) { - // Convert the region to java peer object - auto jregion = OfflineRegion::New(env, jFileSource, std::move(*region)); - - // Trigger callback + static auto javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod)>(env, "onCreate"); - callback.Call(env, method, jregion); - jni::DeleteLocalRef(env, jregion); -} - -jni::Class OfflineManager::CreateOfflineRegionCallback::javaClass; -void OfflineManager::CreateOfflineRegionCallback::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + callback.Call(env, method, + *jni::SeizeLocal(env, 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..43f5045c71 100644 --- a/platform/android/src/offline/offline_manager.hpp +++ b/platform/android/src/offline/offline_manager.hpp @@ -26,10 +26,6 @@ public: jni::Object, jni::Object, mbgl::optional>); - - static jni::Class javaClass; - - static void registerNative(jni::JNIEnv&); }; class CreateOfflineRegionCallback { @@ -42,16 +38,10 @@ public: jni::Object, jni::Object, mbgl::optional); - - static jni::Class javaClass; - - static void registerNative(jni::JNIEnv&); }; static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineManager"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); OfflineManager(jni::JNIEnv&, jni::Object); diff --git a/platform/android/src/offline/offline_region.cpp b/platform/android/src/offline/offline_region.cpp index 5ed37eda73..949377e221 100644 --- a/platform/android/src/offline/offline_region.cpp +++ b/platform/android/src/offline/offline_region.cpp @@ -25,9 +25,9 @@ void OfflineRegion::setOfflineRegionObserver(jni::JNIEnv& env_, jni::Object&& callback_) + Observer(jni::Global>&& callback_) //TODO add a generic deleter for jni::Object - : callback(callback_.release()->Get()) { + : callback(callback_.release().Get()) { } ~Observer() override { @@ -39,41 +39,31 @@ void OfflineRegion::setOfflineRegionObserver(jni::JNIEnv& env_, jni::Object::Singleton(*env); + static auto method = javaClass.GetMethod)>(*env, "onStatusChanged"); - // Call - static auto method = OfflineRegion::OfflineRegionObserver::javaClass - .GetMethod)>(*env, "onStatusChanged"); - callback.Call(*env, method, jStatus); - - // Delete references - jni::DeleteLocalRef(*env, jStatus); + callback.Call(*env, method, + *jni::SeizeLocal(*env, 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)>(*env, "onError"); - callback.Call(*env, method, jError); + static auto javaClass = jni::Class::Singleton(*env); + static auto method = javaClass.GetMethod)>(*env, "onError"); - // Delete references - jni::DeleteLocalRef(*env, jError); + callback.Call(*env, method, + *jni::SeizeLocal(*env, 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(*env, "mapboxTileCountLimitExceeded"); + static auto javaClass = jni::Class::Singleton(*env); + static auto method = javaClass.GetMethod(*env, "mapboxTileCountLimitExceeded"); + callback.Call(*env, method, jlong(limit)); } @@ -106,7 +96,7 @@ void OfflineRegion::getOfflineRegionStatus(jni::JNIEnv& env_, jni::Object(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()) + callback = std::shared_ptr(callback_.NewGlobalRef(env_).release().Get(), GenericGlobalRefDeleter()) ](mbgl::expected status) mutable { // Reattach, the callback comes from a different thread android::UniqueEnv env = android::AttachEnv(); @@ -123,7 +113,7 @@ void OfflineRegion::deleteOfflineRegion(jni::JNIEnv& env_, jni::Object(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()) + callback = std::shared_ptr(callback_.NewGlobalRef(env_).release().Get(), GenericGlobalRefDeleter()) ](std::exception_ptr error) mutable { // Reattach, the callback comes from a different thread android::UniqueEnv env = android::AttachEnv(); @@ -143,7 +133,7 @@ void OfflineRegion::updateOfflineRegionMetadata(jni::JNIEnv& env_, jni::ArraygetID(), metadata, [ //Ensure the object is not gc'd in the meanwhile - callback = std::shared_ptr(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()) + callback = std::shared_ptr(callback_.NewGlobalRef(env_).release().Get(), GenericGlobalRefDeleter()) ](mbgl::expected data) mutable { // Reattach, the callback comes from a different thread android::UniqueEnv env = android::AttachEnv(); @@ -159,29 +149,25 @@ void OfflineRegion::updateOfflineRegionMetadata(jni::JNIEnv& env_, jni::Array OfflineRegion::New(jni::JNIEnv& env, jni::Object jFileSource, mbgl::OfflineRegion region) { // Definition - auto definition = region.getDefinition().match( + auto definition = jni::SeizeLocal(env, region.getDefinition().match( [&](const mbgl::OfflineTilePyramidRegionDefinition def) { return jni::Object( *OfflineTilePyramidRegionDefinition::New(env, def)); }, [&](const mbgl::OfflineGeometryRegionDefinition def) { return jni::Object( *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, jni::Array>(env); - auto jregion = OfflineRegion::javaClass.New(env, constructor, - reinterpret_cast(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::Singleton(env); + static auto constructor = javaClass.GetConstructor, jni::jlong, jni::Object, jni::Array>(env); - return jregion; + return javaClass.New(env, constructor, + reinterpret_cast(new mbgl::OfflineRegion(std::move(region))), //Copy a region to the heap + jFileSource, + jni::jlong(region.getID()), + *definition, + *jni::SeizeLocal(env, OfflineRegion::metadata(env, region.getMetadata()))); } jni::Array OfflineRegion::metadata(jni::JNIEnv& env, mbgl::OfflineRegionMetadata metadata_) { @@ -201,15 +187,13 @@ mbgl::OfflineRegionMetadata OfflineRegion::metadata(jni::JNIEnv& env, jni::Array return metadata; } -jni::Class 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::Singleton(env); + jni::Class::Singleton(env); + jni::Class::Singleton(env); + jni::Class::Singleton(env); - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) @@ -227,94 +211,68 @@ void OfflineRegion::registerNative(jni::JNIEnv& env) { // OfflineRegionObserver // -jni::Class OfflineRegion::OfflineRegionObserver::javaClass; - -void OfflineRegion::OfflineRegionObserver::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); -} - // OfflineRegionStatusCallback // -jni::Class OfflineRegion::OfflineRegionStatusCallback::javaClass; - -void OfflineRegion::OfflineRegionStatusCallback::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); -} - void OfflineRegion::OfflineRegionStatusCallback::onError(jni::JNIEnv& env, jni::Object callback, std::exception_ptr error) { + static auto javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod(env, "onError"); - std::string message = mbgl::util::toString(error); - auto jmessage = jni::Make(env, message); - callback.Call(env, method, jmessage); - jni::DeleteLocalRef(env, jmessage); + + callback.Call(env, method, + *jni::SeizeLocal(env, jni::Make(env, mbgl::util::toString(error)))); } void OfflineRegion::OfflineRegionStatusCallback::onStatus(jni::JNIEnv& env, jni::Object callback, mbgl::optional status) { - //Convert to java peer object - auto jStatus = OfflineRegionStatus::New(env, std::move(*status)); - - // Trigger callback + static auto javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod)>(env, "onStatus"); - callback.Call(env, method, jStatus); - jni::DeleteLocalRef(env, jStatus); + + callback.Call(env, method, + *jni::SeizeLocal(env, OfflineRegionStatus::New(env, std::move(*status)))); } // OfflineRegionDeleteCallback // -jni::Class OfflineRegion::OfflineRegionDeleteCallback::javaClass; - -void OfflineRegion::OfflineRegionDeleteCallback::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); -} - void OfflineRegion::OfflineRegionDeleteCallback::onError(jni::JNIEnv& env, jni::Object callback, std::exception_ptr error) { + static auto javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod(env, "onError"); - std::string message = mbgl::util::toString(error); - auto jmessage = jni::Make(env, message); - callback.Call(env, method, jmessage); - jni::DeleteLocalRef(env, jmessage); + + callback.Call(env, method, + *jni::SeizeLocal(env, jni::Make(env, mbgl::util::toString(error)))); } void OfflineRegion::OfflineRegionDeleteCallback::onDelete(jni::JNIEnv& env, jni::Object callback) { // Trigger callback + static auto javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod(env, "onDelete"); + callback.Call(env, method); } // OfflineRegionUpdateMetadataCallback // -jni::Class OfflineRegion::OfflineRegionUpdateMetadataCallback::javaClass; - -void OfflineRegion::OfflineRegionUpdateMetadataCallback::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); -} - void OfflineRegion::OfflineRegionUpdateMetadataCallback::onError(jni::JNIEnv& env, jni::Object callback, std::exception_ptr error) { + static auto javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod(env, "onError"); - std::string message = mbgl::util::toString(error); - auto jmessage = jni::Make(env, message); - callback.Call(env, method, jmessage); - jni::DeleteLocalRef(env, jmessage); + + callback.Call(env, method, + *jni::SeizeLocal(env, jni::Make(env, mbgl::util::toString(error)))); } void OfflineRegion::OfflineRegionUpdateMetadataCallback::onUpdate(jni::JNIEnv& env, jni::Object callback, mbgl::optional metadata) { - //Convert to java peer object - auto jMetadata = OfflineRegion::metadata(env, std::move(*metadata)); - - // Trigger callback + static auto javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod)>(env, "onUpdate"); - callback.Call(env, method, jMetadata); - jni::DeleteLocalRef(env, jMetadata); + + callback.Call(env, method, + *jni::SeizeLocal(env, 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..11aecb82a9 100644 --- a/platform/android/src/offline/offline_region.hpp +++ b/platform/android/src/offline/offline_region.hpp @@ -15,10 +15,6 @@ public: class OfflineRegionObserver { public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegion$OfflineRegionObserver"; }; - - static jni::Class javaClass; - - static void registerNative(jni::JNIEnv&); }; class OfflineRegionStatusCallback { @@ -30,10 +26,6 @@ public: static void onStatus(jni::JNIEnv&, jni::Object, mbgl::optional); - - static jni::Class javaClass; - - static void registerNative(jni::JNIEnv&); }; class OfflineRegionDeleteCallback { @@ -43,10 +35,6 @@ public: static void onError(jni::JNIEnv&, jni::Object, std::exception_ptr); static void onDelete(jni::JNIEnv&, jni::Object); - - static jni::Class javaClass; - - static void registerNative(jni::JNIEnv&); }; class OfflineRegionUpdateMetadataCallback { @@ -58,10 +46,6 @@ public: static void onUpdate(jni::JNIEnv&, jni::Object, mbgl::optional); - - static jni::Class javaClass; - - static void registerNative(jni::JNIEnv&); }; static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegion"; }; @@ -86,8 +70,6 @@ public: static mbgl::OfflineRegionMetadata metadata(jni::JNIEnv&, jni::Array); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); private: diff --git a/platform/android/src/offline/offline_region_definition.cpp b/platform/android/src/offline/offline_region_definition.cpp index a856672902..2a69181f5b 100644 --- a/platform/android/src/offline/offline_region_definition.cpp +++ b/platform/android/src/offline/offline_region_definition.cpp @@ -10,18 +10,15 @@ namespace android { // OfflineRegionDefinition // -jni::Class OfflineRegionDefinition::javaClass; - void OfflineRegionDefinition::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } mbgl::OfflineRegionDefinition OfflineRegionDefinition::getDefinition(JNIEnv& env, jni::Object jDefinition) { - - if (jDefinition.IsInstanceOf(env, OfflineTilePyramidRegionDefinition::javaClass)) { + if (jDefinition.IsInstanceOf(env, jni::Class::Singleton(env))) { return OfflineTilePyramidRegionDefinition::getDefinition(env, jni::Object(*jDefinition)); - } else if (jDefinition.IsInstanceOf(env, OfflineGeometryRegionDefinition::javaClass)) { + } else if (jDefinition.IsInstanceOf(env, jni::Class::Singleton(env))) { return OfflineGeometryRegionDefinition::getDefinition(env, jni::Object(*jDefinition)); } @@ -31,104 +28,73 @@ mbgl::OfflineRegionDefinition OfflineRegionDefinition::getDefinition(JNIEnv& env // OfflineTilePyramidRegionDefinition // jni::Object OfflineTilePyramidRegionDefinition::New(jni::JNIEnv& env, const mbgl::OfflineTilePyramidRegionDefinition& definition) { - - //Convert objects - auto styleURL = jni::Make(env, definition.styleURL); - auto bounds = LatLngBounds::New(env, definition.bounds); - + static auto javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor, 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::SeizeLocal(env, jni::Make(env, definition.styleURL)), + *jni::SeizeLocal(env, LatLngBounds::New(env, definition.bounds)), + definition.minZoom, + definition.maxZoom, + definition.pixelRatio); } mbgl::OfflineTilePyramidRegionDefinition OfflineTilePyramidRegionDefinition::getDefinition(jni::JNIEnv& env, jni::Object jDefinition) { // Field references + static auto javaClass = jni::Class::Singleton(env); static auto styleURLF = javaClass.GetField(env, "styleURL"); static auto boundsF = javaClass.GetField>(env, "bounds"); static auto minZoomF = javaClass.GetField(env, "minZoom"); static auto maxZoomF = javaClass.GetField(env, "maxZoom"); static auto pixelRatioF = javaClass.GetField(env, "pixelRatio"); - // Get objects - auto jStyleURL = jDefinition.Get(env, styleURLF); - auto jBounds = jDefinition.Get(env, boundsF); - - // Create definition - mbgl::OfflineTilePyramidRegionDefinition definition( - jni::Make(env, jStyleURL), - LatLngBounds::getLatLngBounds(env, jBounds), + return mbgl::OfflineTilePyramidRegionDefinition( + jni::Make(env, *jni::SeizeLocal(env, jDefinition.Get(env, styleURLF))), + LatLngBounds::getLatLngBounds(env, *jni::SeizeLocal(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::javaClass; - void OfflineTilePyramidRegionDefinition::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } // OfflineGeometryRegionDefinition // jni::Object OfflineGeometryRegionDefinition::New(jni::JNIEnv& env, const mbgl::OfflineGeometryRegionDefinition& definition) { - //Convert objects - auto styleURL = jni::Make(env, definition.styleURL); - auto geometry = geojson::Geometry::New(env, definition.geometry); - + static auto javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor, 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::SeizeLocal(env, jni::Make(env, definition.styleURL)), + *jni::SeizeLocal(env, geojson::Geometry::New(env, definition.geometry)), + definition.minZoom, + definition.maxZoom, + definition.pixelRatio); } mbgl::OfflineGeometryRegionDefinition OfflineGeometryRegionDefinition::getDefinition(jni::JNIEnv& env, jni::Object jDefinition) { // Field references + static auto javaClass = jni::Class::Singleton(env); static auto styleURLF = javaClass.GetField(env, "styleURL"); static auto geometryF = javaClass.GetField>(env, "geometry"); static auto minZoomF = javaClass.GetField(env, "minZoom"); static auto maxZoomF = javaClass.GetField(env, "maxZoom"); static auto pixelRatioF = javaClass.GetField(env, "pixelRatio"); - // Get objects - auto jStyleURL = jDefinition.Get(env, styleURLF); - auto jGeometry = jDefinition.Get(env, geometryF); - - // Create definition - mbgl::OfflineGeometryRegionDefinition definition( - jni::Make(env, jStyleURL), - geojson::Geometry::convert(env, jGeometry), - jDefinition.Get(env, minZoomF), - jDefinition.Get(env, maxZoomF), - jDefinition.Get(env, pixelRatioF) + return mbgl::OfflineGeometryRegionDefinition( + jni::Make(env, *jni::SeizeLocal(env, jDefinition.Get(env, styleURLF))), + geojson::Geometry::convert(env, *jni::SeizeLocal(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::javaClass; - void OfflineGeometryRegionDefinition::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::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..853cc833bf 100644 --- a/platform/android/src/offline/offline_region_definition.hpp +++ b/platform/android/src/offline/offline_region_definition.hpp @@ -10,8 +10,6 @@ class OfflineRegionDefinition { public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegionDefinition"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); static mbgl::OfflineRegionDefinition getDefinition(JNIEnv& env, jni::Object jDefinition); @@ -25,10 +23,7 @@ public: static mbgl::OfflineTilePyramidRegionDefinition getDefinition(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); - }; class OfflineGeometryRegionDefinition: public OfflineRegionDefinition { @@ -39,10 +34,7 @@ public: static mbgl::OfflineGeometryRegionDefinition getDefinition(jni::JNIEnv&, jni::Object); - static jni::Class javaClass; - 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..02432757d4 100644 --- a/platform/android/src/offline/offline_region_error.cpp +++ b/platform/android/src/offline/offline_region_error.cpp @@ -28,25 +28,16 @@ jni::Object OfflineRegionError::New(jni::JNIEnv& env, mbgl:: break; } - // Convert - auto jReason = jni::Make(env, reason); - auto jMessage = jni::Make(env, error.message); - - // Create java object + static auto javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(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::SeizeLocal(env, jni::Make(env, reason)), + *jni::SeizeLocal(env, jni::Make(env, error.message))); } -jni::Class OfflineRegionError::javaClass; - void OfflineRegionError::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::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..c51f08a745 100644 --- a/platform/android/src/offline/offline_region_error.hpp +++ b/platform/android/src/offline/offline_region_error.hpp @@ -12,8 +12,6 @@ public: static jni::Object New(jni::JNIEnv&, mbgl::Response::Error); - static jni::Class javaClass; - 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..0a415bdb5f 100644 --- a/platform/android/src/offline/offline_region_status.cpp +++ b/platform/android/src/offline/offline_region_status.cpp @@ -17,6 +17,7 @@ jni::Object OfflineRegionStatus::New(jni::JNIEnv& env, mbgl } // Create java object + static auto javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); return javaClass.New(env, constructor, downloadState, @@ -29,10 +30,8 @@ jni::Object OfflineRegionStatus::New(jni::JNIEnv& env, mbgl ); } -jni::Class OfflineRegionStatus::javaClass; - void OfflineRegionStatus::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::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..9f638e1093 100644 --- a/platform/android/src/offline/offline_region_status.hpp +++ b/platform/android/src/offline/offline_region_status.hpp @@ -12,8 +12,6 @@ public: static jni::Object New(jni::JNIEnv&, mbgl::OfflineRegionStatus status); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/snapshotter/map_snapshot.cpp b/platform/android/src/snapshotter/map_snapshot.cpp index 379ac89d52..d626ae68b7 100644 --- a/platform/android/src/snapshotter/map_snapshot.cpp +++ b/platform/android/src/snapshotter/map_snapshot.cpp @@ -38,21 +38,20 @@ jni::Object MapSnapshot::New(JNIEnv& env, auto bitmap = Bitmap::CreateBitmap(env, std::move(image)); // Create the Mapsnapshot peers + static auto javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor, jni::Array, jni::jboolean>(env); auto nativePeer = std::make_unique(pixelRatio, pointForFn, latLngForFn); return javaClass.New(env, constructor, reinterpret_cast(nativePeer.release()), bitmap, conversion::toArray(env, attributions), (jni::jboolean) showLogo); } -jni::Class MapSnapshot::javaClass; - void MapSnapshot::registerNative(jni::JNIEnv& env) { // Lookup the class - MapSnapshot::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer - jni::RegisterNativePeer(env, MapSnapshot::javaClass, + jni::RegisterNativePeer(env, javaClass, "nativePtr", std::make_unique, "initialize", diff --git a/platform/android/src/snapshotter/map_snapshot.hpp b/platform/android/src/snapshotter/map_snapshot.hpp index f168be85b4..3cd293b621 100644 --- a/platform/android/src/snapshotter/map_snapshot.hpp +++ b/platform/android/src/snapshotter/map_snapshot.hpp @@ -39,8 +39,6 @@ public: jni::Object latLngForPixel(jni::JNIEnv&, jni::Object); private: - static jni::Class 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..4df0749aa0 100644 --- a/platform/android/src/snapshotter/map_snapshotter.cpp +++ b/platform/android/src/snapshotter/map_snapshotter.cpp @@ -25,7 +25,7 @@ MapSnapshotter::MapSnapshotter(jni::JNIEnv& _env, jni::Object position, jni::jboolean _showLogo, jni::String _programCacheDir) - : javaPeer(SeizeGenericWeakRef(_env, jni::Object(jni::NewWeakGlobalRef(_env, _obj.Get()).release()))) + : javaPeer(SeizeGenericWeak(_obj.NewWeakGlobalRef(_env).release())) , pixelRatio(_pixelRatio) , threadPool(sharedThreadPool()) { @@ -80,13 +80,13 @@ void MapSnapshotter::start(JNIEnv& env) { [this](std::exception_ptr err, PremultipliedImage image, std::vector attributions, mbgl::MapSnapshotter::PointForFn pointForFn, mbgl::MapSnapshotter::LatLngForFn latLngForFn) { MBGL_VERIFY_THREAD(tid); android::UniqueEnv _env = android::AttachEnv(); + static auto javaClass = jni::Class::Singleton(*_env); if (err) { // error handler callback static auto onSnapshotFailed = javaClass.GetMethod(*_env, "onSnapshotFailed"); - auto message = jni::Make(*_env, util::toString(err)); - javaPeer->Call(*_env, onSnapshotFailed, message); - jni::DeleteLocalRef(*_env, message); + javaPeer->Call(*_env, onSnapshotFailed, + *jni::SeizeLocal(*_env, jni::Make(*_env, util::toString(err)))); } else { // Create the wrapper auto mapSnapshot = android::MapSnapshot::New(*_env, std::move(image), pixelRatio, attributions, showLogo, pointForFn, latLngForFn); @@ -149,16 +149,14 @@ void MapSnapshotter::deactivateFilesource(JNIEnv& env) { // Static methods // -jni::Class MapSnapshotter::javaClass; - void MapSnapshotter::registerNative(jni::JNIEnv& env) { // Lookup the class - MapSnapshotter::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer - jni::RegisterNativePeer(env, MapSnapshotter::javaClass, "nativePtr", + jni::RegisterNativePeer(env, javaClass, "nativePtr", std::make_unique, jni::Object, jni::jfloat, jni::jint, jni::jint, jni::String, jni::String, jni::Object, jni::Object, jni::jboolean, jni::String>, "nativeInitialize", "finalize", diff --git a/platform/android/src/snapshotter/map_snapshotter.hpp b/platform/android/src/snapshotter/map_snapshotter.hpp index 7b72452c45..05a27256aa 100644 --- a/platform/android/src/snapshotter/map_snapshotter.hpp +++ b/platform/android/src/snapshotter/map_snapshotter.hpp @@ -23,8 +23,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/snapshotter/MapSnapshotter"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); MapSnapshotter(jni::JNIEnv&, @@ -60,7 +58,7 @@ private: MBGL_STORE_THREAD(tid); JavaVM *vm = nullptr; - GenericUniqueWeakObject javaPeer; + GenericWeak> javaPeer; float pixelRatio; bool showLogo; diff --git a/platform/android/src/style/conversion/filter.cpp b/platform/android/src/style/conversion/filter.cpp index 4eac0cf82b..44b5a71aa3 100644 --- a/platform/android/src/style/conversion/filter.cpp +++ b/platform/android/src/style/conversion/filter.cpp @@ -8,11 +8,11 @@ namespace mbgl { namespace android { namespace conversion { -optional toFilter(jni::JNIEnv& env, jni::Array> jfilter) { +optional toFilter(jni::JNIEnv& env, jni::Local>> jfilter) { mbgl::optional filter; if (jfilter) { mbgl::style::conversion::Error error; - auto converted = mbgl::style::conversion::convert(Value(env, jfilter), error); + auto converted = mbgl::style::conversion::convert(Value(env, std::move(jfilter)), error); if (!converted) { mbgl::Log::Error(mbgl::Event::JNI, "Error converting filter: " + error.message); } @@ -23,4 +23,4 @@ optional toFilter(jni::JNIEnv& env, jni::Array toFilter(jni::JNIEnv&, jni::Array>); +optional toFilter(jni::JNIEnv&, jni::Local>>); } // namespace conversion } // namespace android diff --git a/platform/android/src/style/layers/background_layer.cpp b/platform/android/src/style/layers/background_layer.cpp index a8f013b230..00c348b232 100644 --- a/platform/android/src/style/layers/background_layer.cpp +++ b/platform/android/src/style/layers/background_layer.cpp @@ -93,22 +93,21 @@ namespace android { } - jni::Class BackgroundLayer::javaClass; - jni::jobject* BackgroundLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = BackgroundLayer::javaClass.template GetConstructor(env); - return BackgroundLayer::javaClass.New(env, constructor, reinterpret_cast(this)); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void BackgroundLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - BackgroundLayer::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, BackgroundLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique, "initialize", "finalize", diff --git a/platform/android/src/style/layers/background_layer.hpp b/platform/android/src/style/layers/background_layer.hpp index 95555a2d78..3b7f03ddb6 100644 --- a/platform/android/src/style/layers/background_layer.hpp +++ b/platform/android/src/style/layers/background_layer.hpp @@ -15,8 +15,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/BackgroundLayer"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); BackgroundLayer(jni::JNIEnv&, jni::String); diff --git a/platform/android/src/style/layers/circle_layer.cpp b/platform/android/src/style/layers/circle_layer.cpp index 4c7f69e956..47a492dd43 100644 --- a/platform/android/src/style/layers/circle_layer.cpp +++ b/platform/android/src/style/layers/circle_layer.cpp @@ -206,22 +206,21 @@ namespace android { } - jni::Class CircleLayer::javaClass; - jni::jobject* CircleLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = CircleLayer::javaClass.template GetConstructor(env); - return CircleLayer::javaClass.New(env, constructor, reinterpret_cast(this)); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void CircleLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - CircleLayer::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, CircleLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique, "initialize", "finalize", diff --git a/platform/android/src/style/layers/circle_layer.hpp b/platform/android/src/style/layers/circle_layer.hpp index 9d323e92bb..03063b1fc1 100644 --- a/platform/android/src/style/layers/circle_layer.hpp +++ b/platform/android/src/style/layers/circle_layer.hpp @@ -15,8 +15,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/CircleLayer"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); CircleLayer(jni::JNIEnv&, jni::String, jni::String); diff --git a/platform/android/src/style/layers/custom_layer.cpp b/platform/android/src/style/layers/custom_layer.cpp index 61e74a9cf5..c0dcc24f06 100644 --- a/platform/android/src/style/layers/custom_layer.cpp +++ b/platform/android/src/style/layers/custom_layer.cpp @@ -33,22 +33,21 @@ namespace android { } } - jni::Class CustomLayer::javaClass; - jni::jobject* CustomLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = CustomLayer::javaClass.template GetConstructor(env); - return CustomLayer::javaClass.New(env, constructor, reinterpret_cast(this)); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void CustomLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - CustomLayer::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, CustomLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique, "initialize", "finalize", diff --git a/platform/android/src/style/layers/custom_layer.hpp b/platform/android/src/style/layers/custom_layer.hpp index 7eb649d923..75e1957717 100644 --- a/platform/android/src/style/layers/custom_layer.hpp +++ b/platform/android/src/style/layers/custom_layer.hpp @@ -9,19 +9,13 @@ namespace android { class CustomLayer : public Layer { public: - static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/CustomLayer"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); CustomLayer(jni::JNIEnv&, jni::String, jni::jlong); - CustomLayer(mbgl::Map&, mbgl::style::CustomLayer&); - CustomLayer(mbgl::Map&, std::unique_ptr); - ~CustomLayer(); void update(jni::JNIEnv&); diff --git a/platform/android/src/style/layers/fill_extrusion_layer.cpp b/platform/android/src/style/layers/fill_extrusion_layer.cpp index 492e1729b9..6c6a0bef5a 100644 --- a/platform/android/src/style/layers/fill_extrusion_layer.cpp +++ b/platform/android/src/style/layers/fill_extrusion_layer.cpp @@ -156,22 +156,21 @@ namespace android { } - jni::Class FillExtrusionLayer::javaClass; - jni::jobject* FillExtrusionLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = FillExtrusionLayer::javaClass.template GetConstructor(env); - return FillExtrusionLayer::javaClass.New(env, constructor, reinterpret_cast(this)); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void FillExtrusionLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - FillExtrusionLayer::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, FillExtrusionLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique, "initialize", "finalize", diff --git a/platform/android/src/style/layers/fill_extrusion_layer.hpp b/platform/android/src/style/layers/fill_extrusion_layer.hpp index 11a74bc8ef..233c3cc334 100644 --- a/platform/android/src/style/layers/fill_extrusion_layer.hpp +++ b/platform/android/src/style/layers/fill_extrusion_layer.hpp @@ -15,8 +15,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/FillExtrusionLayer"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); FillExtrusionLayer(jni::JNIEnv&, jni::String, jni::String); diff --git a/platform/android/src/style/layers/fill_layer.cpp b/platform/android/src/style/layers/fill_layer.cpp index f4cddc8858..5182c546c8 100644 --- a/platform/android/src/style/layers/fill_layer.cpp +++ b/platform/android/src/style/layers/fill_layer.cpp @@ -143,22 +143,21 @@ namespace android { } - jni::Class FillLayer::javaClass; - jni::jobject* FillLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = FillLayer::javaClass.template GetConstructor(env); - return FillLayer::javaClass.New(env, constructor, reinterpret_cast(this)); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void FillLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - FillLayer::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, FillLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique, "initialize", "finalize", diff --git a/platform/android/src/style/layers/fill_layer.hpp b/platform/android/src/style/layers/fill_layer.hpp index a773cf785b..db1fee1667 100644 --- a/platform/android/src/style/layers/fill_layer.hpp +++ b/platform/android/src/style/layers/fill_layer.hpp @@ -15,8 +15,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/FillLayer"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); FillLayer(jni::JNIEnv&, jni::String, jni::String); diff --git a/platform/android/src/style/layers/heatmap_layer.cpp b/platform/android/src/style/layers/heatmap_layer.cpp index b3d90faab7..e83d92873f 100644 --- a/platform/android/src/style/layers/heatmap_layer.cpp +++ b/platform/android/src/style/layers/heatmap_layer.cpp @@ -109,22 +109,21 @@ namespace android { } - jni::Class HeatmapLayer::javaClass; - jni::jobject* HeatmapLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = HeatmapLayer::javaClass.template GetConstructor(env); - return HeatmapLayer::javaClass.New(env, constructor, reinterpret_cast(this)); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void HeatmapLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - HeatmapLayer::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, HeatmapLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique, "initialize", "finalize", diff --git a/platform/android/src/style/layers/heatmap_layer.hpp b/platform/android/src/style/layers/heatmap_layer.hpp index 9e8908b062..00ab27d854 100644 --- a/platform/android/src/style/layers/heatmap_layer.hpp +++ b/platform/android/src/style/layers/heatmap_layer.hpp @@ -15,8 +15,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/HeatmapLayer"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); HeatmapLayer(jni::JNIEnv&, jni::String, jni::String); diff --git a/platform/android/src/style/layers/hillshade_layer.cpp b/platform/android/src/style/layers/hillshade_layer.cpp index d98e3ee074..b6409b3b3e 100644 --- a/platform/android/src/style/layers/hillshade_layer.cpp +++ b/platform/android/src/style/layers/hillshade_layer.cpp @@ -124,22 +124,21 @@ namespace android { } - jni::Class HillshadeLayer::javaClass; - jni::jobject* HillshadeLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = HillshadeLayer::javaClass.template GetConstructor(env); - return HillshadeLayer::javaClass.New(env, constructor, reinterpret_cast(this)); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void HillshadeLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - HillshadeLayer::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, HillshadeLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique, "initialize", "finalize", diff --git a/platform/android/src/style/layers/hillshade_layer.hpp b/platform/android/src/style/layers/hillshade_layer.hpp index 4b68251775..f824698058 100644 --- a/platform/android/src/style/layers/hillshade_layer.hpp +++ b/platform/android/src/style/layers/hillshade_layer.hpp @@ -15,8 +15,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/HillshadeLayer"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); HillshadeLayer(jni::JNIEnv&, jni::String, jni::String); diff --git a/platform/android/src/style/layers/layer.cpp b/platform/android/src/style/layers/layer.cpp index 48e09674e8..fe4fb9aeb6 100644 --- a/platform/android/src/style/layers/layer.cpp +++ b/platform/android/src/style/layers/layer.cpp @@ -93,7 +93,7 @@ namespace android { void Layer::setLayoutProperty(jni::JNIEnv& env, jni::String jname, jni::Object<> jvalue) { // Convert and set property - optional error = layer.setLayoutProperty(jni::Make(env, jname), Value(env, jvalue)); + optional error = layer.setLayoutProperty(jni::Make(env, jname), Value(env, jni::SeizeLocal(env, std::move(jvalue)))); if (error) { mbgl::Log::Error(mbgl::Event::JNI, "Error setting property: " + jni::Make(env, jname) + " " + error->message); return; @@ -102,7 +102,7 @@ namespace android { void Layer::setPaintProperty(jni::JNIEnv& env, jni::String jname, jni::Object<> jvalue) { // Convert and set property - optional error = layer.setPaintProperty(jni::Make(env, jname), Value(env, jvalue)); + optional error = layer.setPaintProperty(jni::Make(env, jname), Value(env, jni::SeizeLocal(env, std::move(jvalue)))); if (error) { mbgl::Log::Error(mbgl::Event::JNI, "Error setting property: " + jni::Make(env, jname) + " " + error->message); return; @@ -128,7 +128,7 @@ namespace android { using namespace mbgl::style::conversion; Error error; - optional converted = convert(Value(env, jfilter), error); + optional converted = convert(Value(env, jni::SeizeLocal(env, std::move(jfilter))), error); if (!converted) { mbgl::Log::Error(mbgl::Event::JNI, "Error setting filter: " + error.message); return; @@ -246,16 +246,14 @@ namespace android { return jni::Object(*convert(env, layer.getVisibility())); } - jni::Class Layer::javaClass; - void Layer::registerNative(jni::JNIEnv& env) { // Lookup the class - Layer::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer - jni::RegisterNativePeer(env, Layer::javaClass, "nativePtr", + jni::RegisterNativePeer(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..7dbb031b25 100644 --- a/platform/android/src/style/layers/layer.cpp.ejs +++ b/platform/android/src/style/layers/layer.cpp.ejs @@ -84,22 +84,21 @@ 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(env); - return <%- camelize(type) %>Layer::javaClass.New(env, constructor, reinterpret_cast(this)); + static auto javaClass = jni::Class<<%- camelize(type) %>Layer>::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(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(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>, <% } else { -%> diff --git a/platform/android/src/style/layers/layer.hpp b/platform/android/src/style/layers/layer.hpp index 41022bf74a..8112dd18d6 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 javaClass; - static void registerNative(jni::JNIEnv&); /* diff --git a/platform/android/src/style/layers/layer.hpp.ejs b/platform/android/src/style/layers/layer.hpp.ejs index 837049b4c3..dd599d71df 100644 --- a/platform/android/src/style/layers/layer.hpp.ejs +++ b/platform/android/src/style/layers/layer.hpp.ejs @@ -19,8 +19,6 @@ public: 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') { -%> diff --git a/platform/android/src/style/layers/line_layer.cpp b/platform/android/src/style/layers/line_layer.cpp index f143ecc236..2656bd9c09 100644 --- a/platform/android/src/style/layers/line_layer.cpp +++ b/platform/android/src/style/layers/line_layer.cpp @@ -243,22 +243,21 @@ namespace android { } - jni::Class LineLayer::javaClass; - jni::jobject* LineLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = LineLayer::javaClass.template GetConstructor(env); - return LineLayer::javaClass.New(env, constructor, reinterpret_cast(this)); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void LineLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - LineLayer::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, LineLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique, "initialize", "finalize", diff --git a/platform/android/src/style/layers/line_layer.hpp b/platform/android/src/style/layers/line_layer.hpp index 9eef1349cb..4d1e759c1b 100644 --- a/platform/android/src/style/layers/line_layer.hpp +++ b/platform/android/src/style/layers/line_layer.hpp @@ -15,8 +15,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/LineLayer"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); LineLayer(jni::JNIEnv&, jni::String, jni::String); diff --git a/platform/android/src/style/layers/raster_layer.cpp b/platform/android/src/style/layers/raster_layer.cpp index 53086951e4..c52891b662 100644 --- a/platform/android/src/style/layers/raster_layer.cpp +++ b/platform/android/src/style/layers/raster_layer.cpp @@ -162,22 +162,21 @@ namespace android { } - jni::Class RasterLayer::javaClass; - jni::jobject* RasterLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = RasterLayer::javaClass.template GetConstructor(env); - return RasterLayer::javaClass.New(env, constructor, reinterpret_cast(this)); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void RasterLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - RasterLayer::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, RasterLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique, "initialize", "finalize", diff --git a/platform/android/src/style/layers/raster_layer.hpp b/platform/android/src/style/layers/raster_layer.hpp index d1c1b45234..4e268c36e5 100644 --- a/platform/android/src/style/layers/raster_layer.hpp +++ b/platform/android/src/style/layers/raster_layer.hpp @@ -15,8 +15,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/RasterLayer"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); RasterLayer(jni::JNIEnv&, jni::String, jni::String); diff --git a/platform/android/src/style/layers/symbol_layer.cpp b/platform/android/src/style/layers/symbol_layer.cpp index d44744a6cf..953c73e221 100644 --- a/platform/android/src/style/layers/symbol_layer.cpp +++ b/platform/android/src/style/layers/symbol_layer.cpp @@ -492,22 +492,21 @@ namespace android { } - jni::Class SymbolLayer::javaClass; - jni::jobject* SymbolLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = SymbolLayer::javaClass.template GetConstructor(env); - return SymbolLayer::javaClass.New(env, constructor, reinterpret_cast(this)); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void SymbolLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - SymbolLayer::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, SymbolLayer::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique, "initialize", "finalize", diff --git a/platform/android/src/style/layers/symbol_layer.hpp b/platform/android/src/style/layers/symbol_layer.hpp index 417e5e143f..3835e01bf1 100644 --- a/platform/android/src/style/layers/symbol_layer.hpp +++ b/platform/android/src/style/layers/symbol_layer.hpp @@ -15,8 +15,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/SymbolLayer"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); SymbolLayer(jni::JNIEnv&, jni::String, jni::String); diff --git a/platform/android/src/style/layers/unknown_layer.cpp b/platform/android/src/style/layers/unknown_layer.cpp index 8ffda82bfc..9f877e4896 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::javaClass; - jni::jobject* UnknownLayer::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = UnknownLayer::javaClass.template GetConstructor(env); - return UnknownLayer::javaClass.New(env, constructor, reinterpret_cast(this)); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void UnknownLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - UnknownLayer::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) @@ -39,7 +38,7 @@ namespace android { // Register the peer jni::RegisterNativePeer( - 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..0610c843f1 100644 --- a/platform/android/src/style/layers/unknown_layer.hpp +++ b/platform/android/src/style/layers/unknown_layer.hpp @@ -12,8 +12,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/UnknownLayer"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); UnknownLayer(mbgl::Map&, mbgl::style::Layer&); diff --git a/platform/android/src/style/light.cpp b/platform/android/src/style/light.cpp index 71f1cb076e..64afb89204 100644 --- a/platform/android/src/style/light.cpp +++ b/platform/android/src/style/light.cpp @@ -23,11 +23,10 @@ jni::jobject* Light::createJavaLightPeer(jni::JNIEnv& env, Map& map, mbgl::style return result; } -jni::Class Light::javaClass; - jni::jobject* Light::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = Light::javaClass.template GetConstructor(env); - return Light::javaClass.New(env, constructor, reinterpret_cast(this)); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void Light::setAnchor(jni::JNIEnv& env, jni::String property) { @@ -121,11 +120,11 @@ void Light::setIntensityTransition(jni::JNIEnv&, jlong duration, jlong delay) { void Light::registerNative(jni::JNIEnv& env) { // Lookup the class - Light::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer - jni::RegisterNativePeer(env, Light::javaClass, "nativePtr", + jni::RegisterNativePeer(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 index 17f0bba09d..f18dc57a4f 100644 --- a/platform/android/src/style/light.cpp.ejs +++ b/platform/android/src/style/light.cpp.ejs @@ -26,11 +26,10 @@ jni::jobject* Light::createJavaLightPeer(jni::JNIEnv& env, Map& map, mbgl::style return result; } -jni::Class Light::javaClass; - jni::jobject* Light::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = Light::javaClass.template GetConstructor(env); - return Light::javaClass.New(env, constructor, reinterpret_cast(this)); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(this)); } <% for (const property of properties) { -%> @@ -106,11 +105,11 @@ void Light::set<%- camelize(property.name) %>Transition(jni::JNIEnv&, jlong dura <% } -%> void Light::registerNative(jni::JNIEnv& env) { // Lookup the class - Light::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer - jni::RegisterNativePeer(env, Light::javaClass, "nativePtr",<% for(var i = 0; i < properties.length; i++) {%> + jni::RegisterNativePeer(env, 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"), diff --git a/platform/android/src/style/position.cpp b/platform/android/src/style/position.cpp index 0bbcefcbcd..c6918a2e9a 100644 --- a/platform/android/src/style/position.cpp +++ b/platform/android/src/style/position.cpp @@ -4,29 +4,30 @@ namespace mbgl { namespace android { jni::Object Position::fromPosition(jni::JNIEnv& env, jfloat radialCoordinate, jfloat azimuthalAngle, jfloat polarAngle) { - static auto method = Position::javaClass.GetStaticMethod (jfloat, jfloat, jfloat)>(env, "fromPosition"); - return Position::javaClass.Call(env, method, radialCoordinate, azimuthalAngle, polarAngle); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetStaticMethod (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::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class Position::javaClass; - float Position::getRadialCoordinate(jni::JNIEnv& env, jni::Object position){ - static auto field = Position::javaClass.GetField(env, "radialCoordinate"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(env, "radialCoordinate"); return position.Get(env, field); } float Position::getAzimuthalAngle(jni::JNIEnv& env, jni::Object position){ - static auto field = Position::javaClass.GetField(env, "azimuthalAngle"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(env, "azimuthalAngle"); return position.Get(env, field); } float Position::getPolarAngle(jni::JNIEnv& env, jni::Object position){ - static auto field = Position::javaClass.GetField(env, "polarAngle"); + static auto javaClass = jni::Class::Singleton(env); + static auto field = javaClass.GetField(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..4f3738da9f 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 fromPosition(jni::JNIEnv&, jfloat, jfloat, jfloat); - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); static float getRadialCoordinate(jni::JNIEnv&, jni::Object); static float getAzimuthalAngle(jni::JNIEnv&, jni::Object); static float getPolarAngle(jni::JNIEnv&, jni::Object); - }; - } // 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..029824eae0 100644 --- a/platform/android/src/style/sources/custom_geometry_source.cpp +++ b/platform/android/src/style/sources/custom_geometry_source.cpp @@ -21,7 +21,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, + jni::Local> options, style::TileFunction fetchFn, style::TileFunction cancelFn) { using namespace mbgl::style::conversion; @@ -29,7 +29,7 @@ namespace android { return style::CustomGeometrySource::Options(); } Error error; - optional result = convert(Value(env, options), error); + optional result = convert(Value(env, std::move(options)), error); if (!result) { throw std::logic_error(error.message); } @@ -43,7 +43,7 @@ namespace android { jni::Object<> options) : Source(env, std::make_unique( jni::Make(env, sourceId), - convertCustomGeometrySourceOptions(env, options, + convertCustomGeometrySourceOptions(env, jni::SeizeLocal(env, std::move(options)), std::bind(&CustomGeometrySource::fetchTile, this, std::placeholders::_1), std::bind(&CustomGeometrySource::cancelTile, this, std::placeholders::_1)))) { } @@ -61,44 +61,48 @@ namespace android { void CustomGeometrySource::fetchTile (const mbgl::CanonicalTileID& tileID) { android::UniqueEnv _env = android::AttachEnv(); + static auto javaClass = jni::Class::Singleton(*_env); static auto fetchTile = javaClass.GetMethod(*_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::Singleton(*_env); static auto cancelTile = javaClass.GetMethod(*_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::Singleton(*_env); static auto startThreads = javaClass.GetMethod(*_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::Singleton(*_env); static auto releaseThreads = javaClass.GetMethod(*_env, "releaseThreads"); assert(javaPeer); - auto peer = jni::Cast(*_env, *javaPeer, javaClass); + auto peer = jni::Cast(*_env, javaClass, *javaPeer); peer.Call(*_env, releaseThreads); }; @@ -107,11 +111,12 @@ namespace android { jni::jint y) { android::UniqueEnv _env = android::AttachEnv(); + static auto javaClass = jni::Class::Singleton(*_env); static auto isCancelled = javaClass.GetMethod(*_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); }; @@ -147,16 +152,16 @@ namespace android { std::vector features; if (rendererFrontend) { - features = rendererFrontend->querySourceFeatures(source.getID(), { {}, toFilter(env, jfilter) }); + features = rendererFrontend->querySourceFeatures(source.getID(), + { {}, toFilter(env, jni::SeizeLocal(env, std::move(jfilter))) }); } return *convert>, std::vector>(env, features); } - jni::Class CustomGeometrySource::javaClass; - jni::Object CustomGeometrySource::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = CustomGeometrySource::javaClass.template GetConstructor(env); - return jni::Object(CustomGeometrySource::javaClass.New(env, constructor, reinterpret_cast(this)).Get()); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return jni::Object(javaClass.New(env, constructor, reinterpret_cast(this)).Get()); } void CustomGeometrySource::addToMap(JNIEnv& env, jni::Object obj, mbgl::Map& map, AndroidRendererFrontend& frontend) { @@ -174,13 +179,13 @@ namespace android { void CustomGeometrySource::registerNative(jni::JNIEnv& env) { // Lookup the class - CustomGeometrySource::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, CustomGeometrySource::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique>, "initialize", "finalize", diff --git a/platform/android/src/style/sources/custom_geometry_source.hpp b/platform/android/src/style/sources/custom_geometry_source.hpp index 801f81b089..ecfadd659c 100644 --- a/platform/android/src/style/sources/custom_geometry_source.hpp +++ b/platform/android/src/style/sources/custom_geometry_source.hpp @@ -18,14 +18,10 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/CustomGeometrySource"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); CustomGeometrySource(jni::JNIEnv&, jni::String, jni::Object<>); - CustomGeometrySource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); - ~CustomGeometrySource(); bool removeFromMap(JNIEnv&, jni::Object, mbgl::Map&) override; @@ -36,6 +32,8 @@ public: bool isCancelled(jni::jint z, jni::jint x, jni::jint y); void startThreads(); void releaseThreads(); + +private: void setTileData(jni::JNIEnv& env, jni::jint z, jni::jint x, jni::jint y, jni::Object jf); void invalidateTile(jni::JNIEnv& env, jni::jint z, jni::jint x, jni::jint y); @@ -44,7 +42,6 @@ public: jni::Array> querySourceFeatures(jni::JNIEnv&, jni::Array> ); -private: jni::Object 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..b9f3f73801 100644 --- a/platform/android/src/style/sources/geojson_source.cpp +++ b/platform/android/src/style/sources/geojson_source.cpp @@ -29,13 +29,14 @@ 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, jni::Local> options) { using namespace mbgl::style::conversion; if (!options) { return style::GeoJSONOptions(); } Error error; - optional result = convert(mbgl::android::Value(env, options), error); + optional result = convert( + mbgl::android::Value(env, std::move(options)), error); if (!result) { throw std::logic_error(error.message); } @@ -45,7 +46,7 @@ namespace android { GeoJSONSource::GeoJSONSource(jni::JNIEnv& env, jni::String sourceId, jni::Object<> options) : Source(env, std::make_unique( jni::Make(env, sourceId), - convertGeoJSONOptions(env, options))) + convertGeoJSONOptions(env, jni::SeizeLocal(env, std::move(options))))) , threadPool(sharedThreadPool()) , converter(std::make_unique>(*threadPool)) { } @@ -100,22 +101,22 @@ namespace android { std::vector features; if (rendererFrontend) { - features = rendererFrontend->querySourceFeatures(source.getID(), { {}, toFilter(env, jfilter) }); + features = rendererFrontend->querySourceFeatures(source.getID(), + { {}, toFilter(env, jni::SeizeLocal(env, std::move(jfilter))) }); } return *convert>, std::vector>(env, features); } - jni::Class GeoJSONSource::javaClass; - jni::Object GeoJSONSource::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = GeoJSONSource::javaClass.template GetConstructor(env); - return jni::Object(GeoJSONSource::javaClass.New(env, constructor, reinterpret_cast(this)).Get()); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return jni::Object(javaClass.New(env, constructor, reinterpret_cast(this)).Get()); } template void GeoJSONSource::setCollectionAsync(jni::JNIEnv& env, jni::Object jObject) { - std::shared_ptr object = std::shared_ptr(jObject.NewGlobalRef(env).release()->Get(), GenericGlobalRefDeleter()); + std::shared_ptr object = std::shared_ptr(jObject.NewGlobalRef(env).release().Get(), GenericGlobalRefDeleter()); Update::Converter converterFn = [this, object](ActorRef _callback) { converter->self().invoke(&FeatureConverter::convertObject, jni::Object(*object), _callback); @@ -158,13 +159,13 @@ namespace android { void GeoJSONSource::registerNative(jni::JNIEnv& env) { // Lookup the class - GeoJSONSource::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, GeoJSONSource::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique>, "initialize", "finalize", diff --git a/platform/android/src/style/sources/geojson_source.hpp b/platform/android/src/style/sources/geojson_source.hpp index 24ea3c73f8..eb28e2470b 100644 --- a/platform/android/src/style/sources/geojson_source.hpp +++ b/platform/android/src/style/sources/geojson_source.hpp @@ -30,35 +30,26 @@ struct Update { class GeoJSONSource : public Source { public: - static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/GeoJsonSource"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); GeoJSONSource(jni::JNIEnv&, jni::String, jni::Object<>); - GeoJSONSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); - ~GeoJSONSource(); +private: void setGeoJSONString(jni::JNIEnv&, jni::String); - void setFeatureCollection(jni::JNIEnv&, jni::Object); - void setFeature(jni::JNIEnv&, jni::Object); - void setGeometry(jni::JNIEnv&, jni::Object); - void setURL(jni::JNIEnv&, jni::String); - jni::String getURL(jni::JNIEnv&); - jni::Array> querySourceFeatures(jni::JNIEnv&, - jni::Array> jfilter); + jni::Array>); + + jni::String getURL(jni::JNIEnv&); -private: jni::Object createJavaPeer(jni::JNIEnv&); std::unique_ptr awaitingUpdate; std::unique_ptr update; diff --git a/platform/android/src/style/sources/image_source.cpp b/platform/android/src/style/sources/image_source.cpp index 278564485d..343b7439c8 100644 --- a/platform/android/src/style/sources/image_source.cpp +++ b/platform/android/src/style/sources/image_source.cpp @@ -50,22 +50,21 @@ namespace android { LatLngQuad::getLatLngArray(env, coordinatesObject)); } - jni::Class ImageSource::javaClass; - jni::Object ImageSource::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = ImageSource::javaClass.template GetConstructor(env); - return jni::Object(ImageSource::javaClass.New(env, constructor, reinterpret_cast(this)).Get()); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return jni::Object(javaClass.New(env, constructor, reinterpret_cast(this)).Get()); } void ImageSource::registerNative(jni::JNIEnv& env) { // Lookup the class - ImageSource::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, ImageSource::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique>, "initialize", "finalize", diff --git a/platform/android/src/style/sources/image_source.hpp b/platform/android/src/style/sources/image_source.hpp index 6021a03dc3..b09d4f8c95 100644 --- a/platform/android/src/style/sources/image_source.hpp +++ b/platform/android/src/style/sources/image_source.hpp @@ -15,8 +15,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/ImageSource"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); ImageSource(jni::JNIEnv&, jni::String, jni::Object); diff --git a/platform/android/src/style/sources/raster_dem_source.cpp b/platform/android/src/style/sources/raster_dem_source.cpp index 75e0159d7c..73d04f27c1 100644 --- a/platform/android/src/style/sources/raster_dem_source.cpp +++ b/platform/android/src/style/sources/raster_dem_source.cpp @@ -17,7 +17,7 @@ namespace android { env, std::make_unique( jni::Make(env, sourceId), - convertURLOrTileset(Value(env, urlOrTileSet)), + convertURLOrTileset(Value(env, jni::SeizeLocal(env, std::move(urlOrTileSet)))), tileSize ) ) { @@ -36,22 +36,21 @@ namespace android { return url ? jni::Make(env, *url) : jni::String(); } - jni::Class RasterDEMSource::javaClass; - jni::Object RasterDEMSource::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = RasterDEMSource::javaClass.template GetConstructor(env); - return jni::Object(RasterDEMSource::javaClass.New(env, constructor, reinterpret_cast(this)).Get()); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return jni::Object(javaClass.New(env, constructor, reinterpret_cast(this)).Get()); } void RasterDEMSource::registerNative(jni::JNIEnv& env) { // Lookup the class - RasterDEMSource::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, RasterDEMSource::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique, jni::jint>, "initialize", "finalize", diff --git a/platform/android/src/style/sources/raster_dem_source.hpp b/platform/android/src/style/sources/raster_dem_source.hpp index 56924c1f8d..25d9fe90cd 100644 --- a/platform/android/src/style/sources/raster_dem_source.hpp +++ b/platform/android/src/style/sources/raster_dem_source.hpp @@ -9,17 +9,12 @@ namespace android { class RasterDEMSource : public Source { public: - static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/RasterDemSource"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); RasterDEMSource(jni::JNIEnv&, jni::String, jni::Object<>, jni::jint); - RasterDEMSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); - ~RasterDEMSource(); jni::String getURL(jni::JNIEnv&); diff --git a/platform/android/src/style/sources/raster_source.cpp b/platform/android/src/style/sources/raster_source.cpp index 33223a5b69..4eef41c8b1 100644 --- a/platform/android/src/style/sources/raster_source.cpp +++ b/platform/android/src/style/sources/raster_source.cpp @@ -16,7 +16,7 @@ namespace android { env, std::make_unique( jni::Make(env, sourceId), - convertURLOrTileset(Value(env, urlOrTileSet)), + convertURLOrTileset(Value(env, jni::SeizeLocal(env, std::move(urlOrTileSet)))), tileSize ) ) { @@ -35,22 +35,21 @@ namespace android { return url ? jni::Make(env, *url) : jni::String(); } - jni::Class RasterSource::javaClass; - jni::Object RasterSource::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = RasterSource::javaClass.template GetConstructor(env); - return jni::Object(RasterSource::javaClass.New(env, constructor, reinterpret_cast(this)).Get()); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return jni::Object(javaClass.New(env, constructor, reinterpret_cast(this)).Get()); } void RasterSource::registerNative(jni::JNIEnv& env) { // Lookup the class - RasterSource::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, RasterSource::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique, jni::jint>, "initialize", "finalize", diff --git a/platform/android/src/style/sources/raster_source.hpp b/platform/android/src/style/sources/raster_source.hpp index a1da22f40d..888d9f601d 100644 --- a/platform/android/src/style/sources/raster_source.hpp +++ b/platform/android/src/style/sources/raster_source.hpp @@ -9,17 +9,12 @@ namespace android { class RasterSource : public Source { public: - static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/RasterSource"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); RasterSource(jni::JNIEnv&, jni::String, jni::Object<>, jni::jint); - RasterSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); - ~RasterSource(); jni::String getURL(jni::JNIEnv&); diff --git a/platform/android/src/style/sources/source.cpp b/platform/android/src/style/sources/source.cpp index d2e2426c0b..c7968786ec 100644 --- a/platform/android/src/style/sources/source.cpp +++ b/platform/android/src/style/sources/source.cpp @@ -76,6 +76,7 @@ namespace android { if (ownedSource.get() == nullptr && javaPeer.get() != nullptr) { // Manually clear the java peer android::UniqueEnv env = android::AttachEnv(); + static auto javaClass = jni::Class::Singleton(*env); static auto nativePtrField = javaClass.GetField(*env, "nativePtr"); javaPeer->Set(*env, nativePtrField, (jlong) 0); javaPeer.reset(); @@ -140,16 +141,14 @@ namespace android { rendererFrontend = nullptr; } - jni::Class Source::javaClass; - void Source::registerNative(jni::JNIEnv& env) { // Lookup the class - Source::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer - jni::RegisterNativePeer(env, Source::javaClass, "nativePtr", + jni::RegisterNativePeer(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..492be8dfec 100644 --- a/platform/android/src/style/sources/source.hpp +++ b/platform/android/src/style/sources/source.hpp @@ -17,8 +17,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/Source"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); static jni::Object peerForCoreSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); @@ -53,7 +51,7 @@ protected: mbgl::style::Source& source; // Set when the source is added to a map. - jni::UniqueObject javaPeer; + jni::Global> 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..8e91798392 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::javaClass; - jni::Object UnknownSource::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = UnknownSource::javaClass.template GetConstructor(env); - return jni::Object(UnknownSource::javaClass.New(env, constructor, reinterpret_cast(this)).Get()); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return jni::Object(javaClass.New(env, constructor, reinterpret_cast(this)).Get()); } void UnknownSource::registerNative(jni::JNIEnv& env) { // Lookup the class - UnknownSource::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - 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..855aea7c63 100644 --- a/platform/android/src/style/sources/unknown_source.hpp +++ b/platform/android/src/style/sources/unknown_source.hpp @@ -12,8 +12,6 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/UnknownSource"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); UnknownSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); diff --git a/platform/android/src/style/sources/vector_source.cpp b/platform/android/src/style/sources/vector_source.cpp index 9a9548d283..69052bd98c 100644 --- a/platform/android/src/style/sources/vector_source.cpp +++ b/platform/android/src/style/sources/vector_source.cpp @@ -25,7 +25,7 @@ namespace android { env, std::make_unique( jni::Make(env, sourceId), - convertURLOrTileset(Value(env, urlOrTileSet)) + convertURLOrTileset(Value(env, jni::SeizeLocal(env, std::move(urlOrTileSet)))) ) ) { } @@ -51,27 +51,27 @@ namespace android { std::vector features; if (rendererFrontend) { - features = rendererFrontend->querySourceFeatures(source.getID(), { toVector(env, jSourceLayerIds), toFilter(env, jfilter) }); + features = rendererFrontend->querySourceFeatures(source.getID(), + { toVector(env, jSourceLayerIds), toFilter(env, jni::SeizeLocal(env, std::move(jfilter))) }); } return *convert>, std::vector>(env, features); } - jni::Class VectorSource::javaClass; - jni::Object VectorSource::createJavaPeer(jni::JNIEnv& env) { - static auto constructor = VectorSource::javaClass.template GetConstructor(env); - return jni::Object(VectorSource::javaClass.New(env, constructor, reinterpret_cast(this)).Get()); + static auto javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return jni::Object(javaClass.New(env, constructor, reinterpret_cast(this)).Get()); } void VectorSource::registerNative(jni::JNIEnv& env) { // Lookup the class - VectorSource::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + static auto javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( - env, VectorSource::javaClass, "nativePtr", + env, javaClass, "nativePtr", std::make_unique>, "initialize", "finalize", diff --git a/platform/android/src/style/sources/vector_source.hpp b/platform/android/src/style/sources/vector_source.hpp index 16049f5c77..587a4be208 100644 --- a/platform/android/src/style/sources/vector_source.hpp +++ b/platform/android/src/style/sources/vector_source.hpp @@ -10,25 +10,20 @@ namespace android { class VectorSource : public Source { public: - static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/VectorSource"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); VectorSource(jni::JNIEnv&, jni::String, jni::Object<>); - VectorSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); - ~VectorSource(); +private: jni::Array> querySourceFeatures(jni::JNIEnv&, jni::Array, jni::Array> jfilter); jni::String getURL(jni::JNIEnv&); -private: jni::Object 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..84bd909125 100644 --- a/platform/android/src/style/transition_options.cpp +++ b/platform/android/src/style/transition_options.cpp @@ -4,17 +4,14 @@ namespace mbgl { namespace android { jni::Object TransitionOptions::fromTransitionOptions(jni::JNIEnv& env, jlong duration, jlong delay) { - static auto method = TransitionOptions::javaClass.GetStaticMethod (jlong, jlong)>(env, "fromTransitionOptions"); - return TransitionOptions::javaClass.Call(env, method, duration, delay); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetStaticMethod (jlong, jlong)>(env, "fromTransitionOptions"); + return javaClass.Call(env, method, duration, delay); } void TransitionOptions::registerNative(jni::JNIEnv& env) { - // Lookup the class - TransitionOptions::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class 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..83276ca1d8 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 fromTransitionOptions(jni::JNIEnv&, jlong duration, jlong offset); - static jni::Class javaClass; - 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..6cdf134931 100644 --- a/platform/android/src/style/value.cpp +++ b/platform/android/src/style/value.cpp @@ -4,84 +4,70 @@ 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> _value) + : env(_env), + value(std::move(_value)) {} bool Value::isNull() const { - return value == nullptr; + return !value; } bool Value::isArray() const { - return jni::IsInstanceOf(env, value.get(), *java::ObjectArray::jclass); + return jni::IsInstanceOf(env, value->Get(), *java::ObjectArray::jclass); } 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 { - return jni::IsInstanceOf(env, value.get(), *java::String::jclass); + return jni::IsInstanceOf(env, value->Get(), *java::String::jclass); } bool Value::isBool() const { - return jni::IsInstanceOf(env, value.get(), *java::Boolean::jclass); + return jni::IsInstanceOf(env, value->Get(), *java::Boolean::jclass); } bool Value::isNumber() const { - return jni::IsInstanceOf(env, value.get(), *java::Number::jclass); + return jni::IsInstanceOf(env, value->Get(), *java::Number::jclass); } std::string Value::toString() const { - jni::jstring* string = reinterpret_cast(value.get()); + jni::jstring* string = reinterpret_cast(value->Get()); return jni::Make(env, jni::String(string)); } float Value::toFloat() const { - return jni::CallMethod(env, value.get(), *java::Number::floatValueMethodId); + return jni::CallMethod(env, value->Get(), *java::Number::floatValueMethodId); } double Value::toDouble() const { - return jni::CallMethod(env, value.get(), *java::Number::doubleValueMethodId); + return jni::CallMethod(env, value->Get(), *java::Number::doubleValueMethodId); } long Value::toLong() const { - return jni::CallMethod(env, value.get(), *java::Number::longValueMethodId); + return jni::CallMethod(env, value->Get(), *java::Number::longValueMethodId); } bool Value::toBool() const { - return jni::CallMethod(env, value.get(), *java::Boolean::booleanValueMethodId); + return jni::CallMethod(env, value->Get(), *java::Boolean::booleanValueMethodId); } Value Value::get(const char* key) const { - jni::jobject* member = jni::CallMethod(env, value.get(), *java::Map::getMethodId, jni::Make(env, std::string(key)).Get()); - return Value(env, member); + jni::jobject* member = jni::CallMethod(env, value->Get(), *java::Map::getMethodId, jni::Make(env, std::string(key)).Get()); + return Value(env, jni::SeizeLocal(env, jni::Object<>(member))); } int Value::getLength() const { - auto array = (jni::jarray*) value.get(); + auto array = (jni::jarray*) value->Get(); return jni::GetArrayLength(env, *array); } Value Value::get(const int index) const { - auto array = (jni::jarray*) value.get(); - return Value(env, jni::GetObjectArrayElement(env, *array, index)); + auto array = (jni::jarray*) value->Get(); + return Value(env, jni::SeizeLocal(env, jni::Object<>(jni::GetObjectArrayElement(env, *array, index)))); } } } diff --git a/platform/android/src/style/value.hpp b/platform/android/src/style/value.hpp index 2057b93454..bd1c552be0 100644 --- a/platform/android/src/style/value.hpp +++ b/platform/android/src/style/value.hpp @@ -9,7 +9,7 @@ namespace android { class Value { public: - Value(jni::JNIEnv&, jni::jobject*); + Value(jni::JNIEnv&, jni::Local>); Value(Value&&) = default; Value& operator=(Value&&) = default; @@ -34,7 +34,7 @@ public: Value get(const int index ) const; jni::JNIEnv& env; - std::shared_ptr value; + jni::Local> value; }; } diff --git a/platform/android/src/text/collator.cpp b/platform/android/src/text/collator.cpp index 37af0a1c5b..86e72a1dac 100644 --- a/platform/android/src/text/collator.cpp +++ b/platform/android/src/text/collator.cpp @@ -13,34 +13,32 @@ namespace mbgl { namespace android { void Collator::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class Collator::javaClass; - jni::Object Collator::getInstance(jni::JNIEnv& env, jni::Object locale) { - using Signature = jni::Object(jni::Object); - auto method = javaClass.GetStaticMethod(env, "getInstance"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetStaticMethod (jni::Object)>(env, "getInstance"); return javaClass.Call(env, method, locale); } void Collator::setStrength(jni::JNIEnv& env, jni::Object collator, jni::jint strength) { - using Signature = void(jni::jint); - auto static method = javaClass.GetMethod(env, "setStrength"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "setStrength"); collator.Call(env, method, strength); } jni::jint Collator::compare(jni::JNIEnv& env, jni::Object collator, jni::String lhs, jni::String rhs) { - using Signature = jni::jint(jni::String, jni::String); - auto static method = javaClass.GetMethod(env, "compare"); + static auto javaClass = jni::Class::Singleton(env); + auto static method = javaClass.GetMethod(env, "compare"); return collator.Call(env, method, lhs, rhs); } void Locale::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } - /* +/* We would prefer to use for/toLanguageTag, but they're only available in API level 21+ jni::Object Locale::forLanguageTag(jni::JNIEnv& env, jni::String languageTag) { @@ -54,39 +52,38 @@ jni::String Locale::toLanguageTag(jni::JNIEnv& env, jni::Object locale) auto static method = javaClass.GetMethod(env, "toLanguageTag"); return locale.Call(env, method); } - */ - +*/ jni::String Locale::getLanguage(jni::JNIEnv& env, jni::Object locale) { - using Signature = jni::String(); - auto static method = javaClass.GetMethod(env, "getLanguage"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "getLanguage"); return locale.Call(env, method); } jni::String Locale::getCountry(jni::JNIEnv& env, jni::Object locale) { - using Signature = jni::String(); - auto static method = javaClass.GetMethod(env, "getCountry"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetMethod(env, "getCountry"); return locale.Call(env, method); } jni::Object Locale::getDefault(jni::JNIEnv& env) { - using Signature = jni::Object(); - auto method = javaClass.GetStaticMethod(env, "getDefault"); + static auto javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetStaticMethod ()>(env, "getDefault"); return javaClass.Call(env, method); } jni::Object Locale::New(jni::JNIEnv& env, jni::String language) { + static auto javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); return javaClass.New(env, constructor, language); } jni::Object Locale::New(jni::JNIEnv& env, jni::String language, jni::String region) { + static auto javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); return javaClass.New(env, constructor, language, region); } -jni::Class Locale::javaClass; - } // namespace android namespace style { @@ -138,28 +135,23 @@ 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(*env, useUnaccent ? + jni::Local jlhs = jni::SeizeLocal(*env, jni::Make(*env, useUnaccent ? platform::unaccent(lhs) : - lhs); - jni::String jrhs = jni::Make(*env, useUnaccent ? + lhs)); + jni::Local jrhs = jni::SeizeLocal(*env, jni::Make(*env, useUnaccent ? platform::unaccent(rhs) : - rhs); - - jni::jint result = android::Collator::compare(*env, *collator, jlhs, jrhs);; + rhs)); - 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(*env, jLanguage); - jni::DeleteLocalRef(*env, jLanguage); - jni::String jRegion = android::Locale::getCountry(*env, *locale); - std::string region = jni::Make(*env, jRegion); - jni::DeleteLocalRef(*env, jRegion); + std::string language = jni::Make(*env, + *jni::SeizeLocal(*env, android::Locale::getLanguage(*env, *locale))); + std::string region = jni::Make(*env, + *jni::SeizeLocal(*env, android::Locale::getCountry(*env, *locale))); optional resultLanguage; if (!language.empty()) resultLanguage = language; @@ -168,13 +160,14 @@ public: return LanguageTag(resultLanguage, {}, resultRegion).toBCP47(); } + private: bool caseSensitive; bool diacriticSensitive; android::UniqueEnv env; - jni::UniqueObject collator; - jni::UniqueObject locale; + jni::Global> collator; + jni::Global> locale; }; diff --git a/platform/android/src/text/collator_jni.hpp b/platform/android/src/text/collator_jni.hpp index 96c381b1c1..30fb6a4369 100644 --- a/platform/android/src/text/collator_jni.hpp +++ b/platform/android/src/text/collator_jni.hpp @@ -31,10 +31,8 @@ public: static jni::Object New(jni::JNIEnv&, jni::String); static jni::Object New(jni::JNIEnv&, jni::String, jni::String); - static jni::Class javaClass; static void registerNative(jni::JNIEnv&); - }; class Collator { @@ -47,10 +45,8 @@ public: static jni::jint compare(jni::JNIEnv&, jni::Object, jni::String, jni::String); - static jni::Class javaClass; 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..adfa0559f3 100644 --- a/platform/android/src/text/local_glyph_rasterizer.cpp +++ b/platform/android/src/text/local_glyph_rasterizer.cpp @@ -36,6 +36,7 @@ namespace android { LocalGlyphRasterizer::LocalGlyphRasterizer() { UniqueEnv env { AttachEnv() }; + static auto javaClass = jni::Class::Singleton(*env); static auto constructor = javaClass.GetConstructor(*env); javaObject = javaClass.New(*env, constructor).NewGlobalRef(*env); @@ -44,29 +45,22 @@ LocalGlyphRasterizer::LocalGlyphRasterizer() { PremultipliedImage LocalGlyphRasterizer::drawGlyphBitmap(const std::string& fontFamily, const bool bold, const GlyphID glyphID) { UniqueEnv env { AttachEnv() }; - using Signature = jni::Object(jni::String, jni::jboolean, jni::jchar); - static auto method = javaClass.GetMethod(*env, "drawGlyphBitmap"); + static auto javaClass = jni::Class::Singleton(*env); + static auto drawGlyphBitmap = javaClass.GetMethod (jni::String, jni::jboolean, jni::jchar)>(*env, "drawGlyphBitmap"); - jni::String jniFontFamily = jni::Make(*env, fontFamily); + auto javaBitmap = jni::SeizeLocal(*env, + javaObject->Call(*env, drawGlyphBitmap, + *jni::SeizeLocal(*env, jni::Make(*env, fontFamily)), + static_cast(bold), + static_cast(glyphID))); - auto javaBitmap = javaObject->Call(*env, - method, - jniFontFamily, - static_cast(bold), - static_cast(glyphID)); - jni::DeleteLocalRef(*env, jniFontFamily); - - PremultipliedImage result = Bitmap::GetImage(*env, javaBitmap); - jni::DeleteLocalRef(*env, javaBitmap); - return result; + return Bitmap::GetImage(*env, *javaBitmap); } void LocalGlyphRasterizer::registerNative(jni::JNIEnv& env) { - javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); + jni::Class::Singleton(env); } -jni::Class 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 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 javaObject; + jni::Global> javaObject; }; } // namespace android -- cgit v1.2.1 From 115e8625e14d15f3fe18681e1e05a06271e2c2e0 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Wed, 22 Aug 2018 10:22:23 -0700 Subject: [android] Simplify Feature conversion --- platform/android/core-files.txt | 2 - .../android/src/geojson/conversion/feature.cpp | 55 ----------------- .../android/src/geojson/conversion/feature.hpp | 22 ------- platform/android/src/geojson/feature.cpp | 72 +++++++++++++--------- platform/android/src/geojson/feature.hpp | 17 +---- platform/android/src/native_map_view.cpp | 6 +- .../src/style/sources/custom_geometry_source.cpp | 4 +- .../android/src/style/sources/geojson_source.cpp | 4 +- .../android/src/style/sources/vector_source.cpp | 4 +- 9 files changed, 55 insertions(+), 131 deletions(-) delete mode 100644 platform/android/src/geojson/conversion/feature.cpp delete mode 100644 platform/android/src/geojson/conversion/feature.hpp diff --git a/platform/android/core-files.txt b/platform/android/core-files.txt index 9a57e76808..cd4028cd59 100644 --- a/platform/android/core-files.txt +++ b/platform/android/core-files.txt @@ -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 diff --git a/platform/android/src/geojson/conversion/feature.cpp b/platform/android/src/geojson/conversion/feature.cpp deleted file mode 100644 index 7386e29df5..0000000000 --- a/platform/android/src/geojson/conversion/feature.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include "feature.hpp" - -#include "../../gson/json_object.hpp" - -namespace mbgl { -namespace android { -namespace conversion { - -using namespace gson; - -/** - * Turn feature identifier into std::string - */ -class FeatureIdVisitor { -public: - - template - 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 ""; - } - -}; - -jni::Object convertFeature(jni::JNIEnv& env, const mbgl::Feature& value) { - using namespace mbgl::android::geojson; - - return Feature::fromGeometry(env, - *jni::SeizeLocal(env, Geometry::New(env, value.geometry)), - *jni::SeizeLocal(env, JsonObject::New(env, value.properties)), - *jni::SeizeLocal(env, jni::Make(env, value.id ? value.id.value().match(FeatureIdVisitor()) : ""))); -} - -Result>> Converter>, std::vector>::operator()(jni::JNIEnv& env, const std::vector& value) const { - using namespace mbgl::android::geojson; - - auto features = jni::Array>::New(env, value.size()); - - for (size_t i = 0; i < value.size(); i = i + 1) { - features.Set(env, i, *jni::SeizeLocal(env, convertFeature(env, value.at(i)))); - } - - 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 d9fc0a0b67..0000000000 --- a/platform/android/src/geojson/conversion/feature.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include "../../conversion/conversion.hpp" -#include "../feature.hpp" - -#include -#include - -#include - -namespace mbgl { -namespace android { -namespace conversion { - -template <> -struct Converter>, std::vector> { - Result>> operator()(jni::JNIEnv& env, const std::vector& 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 1e02c756eb..809ac42ef7 100644 --- a/platform/android/src/geojson/feature.cpp +++ b/platform/android/src/geojson/feature.cpp @@ -1,50 +1,66 @@ #include "feature.hpp" - #include "geometry.hpp" +#include "../gson/json_object.hpp" namespace mbgl { namespace android { namespace geojson { +using namespace gson; + mbgl::Feature Feature::convert(jni::JNIEnv& env, jni::Object jFeature) { - auto jGeometry = jni::SeizeLocal(env, geometry(env, jFeature)); - auto jProperties = jni::SeizeLocal(env, Feature::properties(env, jFeature)); + static auto javaClass = jni::Class::Singleton(env); + static auto id = javaClass.GetMethod(env, "id"); + static auto geometry = javaClass.GetMethod ()>(env, "geometry"); + static auto properties = javaClass.GetMethod ()>(env, "properties"); - std::experimental::optional id; - auto jId = jni::SeizeLocal(env, Feature::id(env, jFeature)); - if (jId) { - id = { jni::Make(env, *jId) }; - } + auto jId = jni::SeizeLocal(env, jFeature.Call(env, id)); return mbgl::Feature { - Geometry::convert(env, *jGeometry), - gson::JsonObject::convert(env, *jProperties), - id + Geometry::convert(env, *jni::SeizeLocal(env, jFeature.Call(env, geometry))), + JsonObject::convert(env, *jni::SeizeLocal(env, jFeature.Call(env, properties))), + jId ? std::experimental::optional(jni::Make(env, *jId)) + : std::experimental::nullopt }; } -jni::Object Feature::geometry(jni::JNIEnv& env, jni::Object jFeature) { - static auto javaClass = jni::Class::Singleton(env); - static auto method = javaClass.GetMethod ()>(env, "geometry"); - return jFeature.Call(env, method); -} +/** + * Turn feature identifier into std::string + */ +class FeatureIdVisitor { +public: + template + std::string operator()(const T& i) const { + return std::to_string(i); + } -jni::Object Feature::properties(jni::JNIEnv& env, jni::Object jFeature) { - static auto javaClass = jni::Class::Singleton(env); - static auto method = javaClass.GetMethod ()>(env, "properties"); - return jFeature.Call(env, method); -} + std::string operator()(const std::string& i) const { + return i; + } + + std::string operator()(const std::nullptr_t&) const { + return ""; + } +}; -jni::String Feature::id(jni::JNIEnv& env, jni::Object jFeature) { +jni::Object convertFeature(jni::JNIEnv& env, const mbgl::Feature& value) { static auto javaClass = jni::Class::Singleton(env); - static auto method = javaClass.GetMethod(env, "id"); - return jFeature.Call(env, method); + static auto method = javaClass.GetStaticMethod (jni::Object, jni::Object, jni::String)>(env, "fromGeometry"); + + return javaClass.Call(env, method, + *jni::SeizeLocal(env, Geometry::New(env, value.geometry)), + *jni::SeizeLocal(env, JsonObject::New(env, value.properties)), + *jni::SeizeLocal(env, jni::Make(env, value.id ? value.id.value().match(FeatureIdVisitor()) : ""))); } -jni::Object Feature::fromGeometry(jni::JNIEnv& env, jni::Object geometry, jni::Object properties, jni::String id) { - static auto javaClass = jni::Class::Singleton(env); - static auto method = javaClass.GetStaticMethod (jni::Object, jni::Object, jni::String)>(env, "fromGeometry"); - return javaClass.Call(env, method, geometry, properties, id); +jni::Array> Feature::convert(jni::JNIEnv& env, const std::vector& value) { + auto features = jni::Array>::New(env, value.size()); + + for (size_t i = 0; i < value.size(); i = i + 1) { + features.Set(env, i, *jni::SeizeLocal(env, convertFeature(env, value.at(i)))); + } + + return features; } void Feature::registerNative(jni::JNIEnv& env) { diff --git a/platform/android/src/geojson/feature.hpp b/platform/android/src/geojson/feature.hpp index de38e9b1e3..fba4815e0c 100644 --- a/platform/android/src/geojson/feature.hpp +++ b/platform/android/src/geojson/feature.hpp @@ -1,32 +1,19 @@ #pragma once #include -#include -#include #include -#include "geometry.hpp" -#include "../gson/json_object.hpp" - namespace mbgl { namespace android { namespace geojson { -class Feature : private mbgl::util::noncopyable { +class Feature : public jni::ObjectTag { public: - static constexpr auto Name() { return "com/mapbox/geojson/Feature"; }; - static jni::Object fromGeometry(jni::JNIEnv&, jni::Object, jni::Object, jni::String); - static mbgl::Feature convert(jni::JNIEnv&, jni::Object); - - static jni::Object geometry(jni::JNIEnv&, jni::Object); - - static jni::String id(jni::JNIEnv&, jni::Object); - - static jni::Object properties(jni::JNIEnv&, jni::Object); + static jni::Array> convert(jni::JNIEnv&, const std::vector&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp index 26814fd6b8..d396e00b47 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" @@ -658,7 +658,7 @@ jni::Array> NativeMapView::queryRenderedFeaturesFo } mapbox::geometry::point point = {x, y}; - return *convert>, std::vector>( + return Feature::convert( env, rendererFrontend->queryRenderedFeatures(point, { layers, toFilter(env, jni::SeizeLocal(env, std::move(jfilter))) })); } @@ -678,7 +678,7 @@ jni::Array> NativeMapView::queryRenderedFeaturesFo mapbox::geometry::point{ right, bottom } }; - return *convert>, std::vector>( + return Feature::convert( env, rendererFrontend->queryRenderedFeatures(box, { layers, toFilter(env, jni::SeizeLocal(env, std::move(jfilter))) })); } diff --git a/platform/android/src/style/sources/custom_geometry_source.cpp b/platform/android/src/style/sources/custom_geometry_source.cpp index 029824eae0..9012948b0b 100644 --- a/platform/android/src/style/sources/custom_geometry_source.cpp +++ b/platform/android/src/style/sources/custom_geometry_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 #include @@ -155,7 +155,7 @@ namespace android { features = rendererFrontend->querySourceFeatures(source.getID(), { {}, toFilter(env, jni::SeizeLocal(env, std::move(jfilter))) }); } - return *convert>, std::vector>(env, features); + return Feature::convert(env, features); } jni::Object CustomGeometrySource::createJavaPeer(jni::JNIEnv& env) { diff --git a/platform/android/src/style/sources/geojson_source.cpp b/platform/android/src/style/sources/geojson_source.cpp index b9f3f73801..943cc48386 100644 --- a/platform/android/src/style/sources/geojson_source.cpp +++ b/platform/android/src/style/sources/geojson_source.cpp @@ -12,7 +12,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 @@ -104,7 +104,7 @@ namespace android { features = rendererFrontend->querySourceFeatures(source.getID(), { {}, toFilter(env, jni::SeizeLocal(env, std::move(jfilter))) }); } - return *convert>, std::vector>(env, features); + return Feature::convert(env, features); } jni::Object GeoJSONSource::createJavaPeer(jni::JNIEnv& env) { diff --git a/platform/android/src/style/sources/vector_source.cpp b/platform/android/src/style/sources/vector_source.cpp index 69052bd98c..48eb4ca51c 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 @@ -54,7 +54,7 @@ namespace android { features = rendererFrontend->querySourceFeatures(source.getID(), { toVector(env, jSourceLayerIds), toFilter(env, jni::SeizeLocal(env, std::move(jfilter))) }); } - return *convert>, std::vector>(env, features); + return Feature::convert(env, features); } jni::Object VectorSource::createJavaPeer(jni::JNIEnv& env) { -- cgit v1.2.1 From 3948bbd7775ea336e54fa6f152f05a139ee88750 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Wed, 22 Aug 2018 10:48:21 -0700 Subject: [android] Simplify Point conversion --- platform/android/src/geojson/point.cpp | 41 +++++++++------------------------- platform/android/src/geojson/point.hpp | 12 ++-------- 2 files changed, 12 insertions(+), 41 deletions(-) diff --git a/platform/android/src/geojson/point.cpp b/platform/android/src/geojson/point.cpp index 69da997250..7fcc183dc1 100644 --- a/platform/android/src/geojson/point.cpp +++ b/platform/android/src/geojson/point.cpp @@ -1,7 +1,4 @@ #include "point.hpp" -#include "../java/util.hpp" -#include "../java_types.hpp" -#include "../style/value.hpp" namespace mbgl { namespace android { @@ -13,37 +10,19 @@ jni::Object Point::New(jni::JNIEnv& env, const mbgl::Point& point return javaClass.Call(env, method, point.x, point.y); } -mapbox::geojson::point Point::convert(jni::JNIEnv &env, jni::Object jPoint) { - mapbox::geojson::point point; - - if (jPoint) { - point = Point::convert(env, *jni::SeizeLocal(env, Point::coordinates(env, jPoint))); - } - - return point; -} - -mapbox::geojson::point Point::convert(jni::JNIEnv &env, jni::Object*/> jDoubleList) { - mapbox::geojson::point point; - - if (jDoubleList) { - auto jDoubleArray = jni::SeizeLocal(env, java::util::List::toArray(env, jDoubleList)); - - auto lonObject = jni::SeizeLocal(env, jDoubleArray->Get(env, 0)); - auto latObject = jni::SeizeLocal(env, jDoubleArray->Get(env, 1)); +mbgl::Point Point::convert(jni::JNIEnv &env, jni::Object jPoint) { + static auto javaClass = jni::Class::Singleton(env); + static auto longitude = javaClass.GetMethod(env, "longitude"); + static auto latitude = javaClass.GetMethod(env, "latitude"); - point.x = jni::CallMethod(env, *lonObject, - *java::Number::doubleValueMethodId); - point.y = jni::CallMethod(env, *latObject, - *java::Number::doubleValueMethodId); + if (!jPoint) { + return {}; } - return point; -} -jni::Object Point::coordinates(jni::JNIEnv &env, jni::Object jPoint) { - static auto javaClass = jni::Class::Singleton(env); - static auto method = javaClass.GetMethod ()>(env, "coordinates"); - return jPoint.Call(env, method); + return { + jPoint.Call(env, longitude), + jPoint.Call(env, latitude) + }; } void Point::registerNative(jni::JNIEnv &env) { diff --git a/platform/android/src/geojson/point.hpp b/platform/android/src/geojson/point.hpp index 3a852a3e74..d5cc7780f3 100644 --- a/platform/android/src/geojson/point.hpp +++ b/platform/android/src/geojson/point.hpp @@ -1,9 +1,7 @@ #pragma once -#include -#include +#include -#include "../java/util.hpp" #include "geometry.hpp" #include @@ -15,16 +13,10 @@ namespace geojson { class Point : public Geometry { public: static constexpr auto Name() { return "com/mapbox/geojson/Point"; }; - static constexpr auto Type() { return "Point"; }; static jni::Object New(jni::JNIEnv&, const mbgl::Point&); - - static mapbox::geojson::point convert(jni::JNIEnv&, jni::Object); - - static mapbox::geojson::point convert(jni::JNIEnv&, jni::Object*/>); - - static jni::Object coordinates(JNIEnv&, jni::Object); + static mbgl::Point convert(jni::JNIEnv&, jni::Object); static void registerNative(jni::JNIEnv&); }; -- cgit v1.2.1 From 6be8302296147515e0b0d7ed7cc46d195227118e Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Wed, 22 Aug 2018 11:28:07 -0700 Subject: [android] Simplify JSON conversion --- platform/android/src/gson/json_array.cpp | 7 +- platform/android/src/gson/json_array.hpp | 6 +- platform/android/src/gson/json_element.cpp | 138 +++++++++++++-------------- platform/android/src/gson/json_element.hpp | 11 +-- platform/android/src/gson/json_object.cpp | 6 +- platform/android/src/gson/json_object.hpp | 6 +- platform/android/src/gson/json_primitive.cpp | 129 ------------------------- platform/android/src/gson/json_primitive.hpp | 15 --- 8 files changed, 82 insertions(+), 236 deletions(-) diff --git a/platform/android/src/gson/json_array.cpp b/platform/android/src/gson/json_array.cpp index 333b402aa0..b5fb85e5d9 100644 --- a/platform/android/src/gson/json_array.cpp +++ b/platform/android/src/gson/json_array.cpp @@ -1,12 +1,11 @@ #include "json_array.hpp" - #include "json_element.hpp" namespace mbgl { namespace android { namespace gson { -jni::Object JsonArray::New(jni::JNIEnv& env, const std::vector& values){ +jni::Object JsonArray::New(jni::JNIEnv& env, const std::vector& values){ static auto javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); static auto addMethod = javaClass.GetMethod)>(env, "add"); @@ -20,8 +19,8 @@ jni::Object JsonArray::New(jni::JNIEnv& env, const std::vector JsonArray::convert(jni::JNIEnv& env, const jni::Object jsonArray) { - std::vector values; +std::vector JsonArray::convert(jni::JNIEnv& env, const jni::Object jsonArray) { + std::vector values; if (jsonArray) { static auto javaClass = jni::Class::Singleton(env); diff --git a/platform/android/src/gson/json_array.hpp b/platform/android/src/gson/json_array.hpp index e74b92176f..b41596819f 100644 --- a/platform/android/src/gson/json_array.hpp +++ b/platform/android/src/gson/json_array.hpp @@ -2,8 +2,6 @@ #include "json_element.hpp" -#include - #include namespace mbgl { @@ -14,8 +12,8 @@ class JsonArray : public JsonElement { public: static constexpr auto Name() { return "com/google/gson/JsonArray"; }; - static jni::Object New(jni::JNIEnv&, const std::vector&); - static std::vector convert(JNIEnv&, jni::Object); + static jni::Object New(jni::JNIEnv&, const std::vector&); + static std::vector convert(JNIEnv&, jni::Object); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/gson/json_element.cpp b/platform/android/src/gson/json_element.cpp index d5304ed674..28cb368386 100644 --- a/platform/android/src/gson/json_element.cpp +++ b/platform/android/src/gson/json_element.cpp @@ -1,87 +1,87 @@ #include "json_element.hpp" - #include "json_array.hpp" #include "json_object.hpp" #include "json_primitive.hpp" -#include -#include - namespace mbgl { namespace android { namespace gson { -/** - * Turn mapbox::geometry::value into Java Gson JsonElement - */ -class JsonElementEvaluator { -public: - - jni::JNIEnv& env; - - jni::Object operator()(const JsonPrimitive::value value) const { - return JsonPrimitive::New(env, value); - } - - jni::Object operator()(const std::vector &values) const { - return JsonArray::New(env, values); - } - - jni::Object operator()(const std::unordered_map &values) const { - return JsonObject::New(env, values); - } -}; - - -jni::Object JsonElement::New(jni::JNIEnv& env, const mapbox::geometry::value& value) { - JsonElementEvaluator evaluator { env } ; - return mapbox::geometry::value::visit(value, evaluator); +jni::Object JsonElement::New(jni::JNIEnv& env, const mbgl::Value& value) { + static auto primitive = jni::Class::Singleton(env); + static auto stringConstructor = primitive.GetConstructor(env); + static auto numberConstructor = primitive.GetConstructor(env); + static auto booleanConstructor = primitive.GetConstructor(env); + + return value.match( + [&] (const mbgl::NullValue&) { + return jni::Object(); + }, + [&] (const std::string& value) { + return primitive.New(env, stringConstructor, + *jni::SeizeLocal(env, jni::Make(env, value))); + }, + [&] (const double value) { + return primitive.New(env, numberConstructor, + *jni::SeizeLocal(env, jni::Number(jni::Box(env, value)))); + }, + [&] (const int64_t value) { + return primitive.New(env, numberConstructor, + *jni::SeizeLocal(env, jni::Number(jni::Box(env, value)))); + }, + [&] (const uint64_t value) { + return primitive.New(env, numberConstructor, + *jni::SeizeLocal(env, jni::Number(jni::Box(env, int64_t(value))))); // TODO: should use BigInteger + }, + [&] (const bool value) { + return primitive.New(env, booleanConstructor, + *jni::SeizeLocal(env, jni::Box(env, value ? jni::jni_true : jni::jni_false))); + }, + [&] (const std::vector& 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) { - mapbox::geometry::value value; +mbgl::Value JsonElement::convert(jni::JNIEnv &env, jni::Object jsonElement) { + if (!jsonElement) { + return mbgl::NullValue(); + } - if (jsonElement) { - if (isJsonPrimitive(env, jsonElement)) { - static auto primitiveClass = jni::Class::Singleton(env); - auto primitive = JsonPrimitive::convert(env, jni::Cast(env, primitiveClass, jsonElement)); - value = mapbox::util::apply_visitor([](auto t) { return mapbox::geometry::value { t }; }, primitive); - } else if (isJsonObject(env, jsonElement)) { - static auto objectClass = jni::Class::Singleton(env); - mapbox::geometry::property_map map = JsonObject::convert(env, jni::Cast(env, objectClass, jsonElement)); - value = mapbox::util::recursive_wrapper> { map } ; - } else if (isJsonArray(env, jsonElement)) { - static auto arrayClass = jni::Class::Singleton(env); - value = JsonArray::convert(env, jni::Cast(env, arrayClass, jsonElement)); + static auto elementClass = jni::Class::Singleton(env); + static auto isJsonObject = elementClass.GetMethod(env, "isJsonObject"); + static auto isJsonArray = elementClass.GetMethod(env, "isJsonArray"); + static auto isJsonPrimitive = elementClass.GetMethod(env, "isJsonPrimitive"); + + static auto primitiveClass = jni::Class::Singleton(env); + static auto isBoolean = primitiveClass.GetMethod(env, "isBoolean"); + static auto isString = primitiveClass.GetMethod(env, "isString"); + static auto isNumber = primitiveClass.GetMethod(env, "isNumber"); + static auto getAsBoolean = primitiveClass.GetMethod(env, "getAsBoolean"); + static auto getAsString = primitiveClass.GetMethod(env, "getAsString"); + static auto getAsDouble = primitiveClass.GetMethod(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(env, *jni::SeizeLocal(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::Singleton(env), jsonElement)); + } else if (jsonElement.Call(env, isJsonArray)) { + return JsonArray::convert(env, jni::Cast(env, jni::Class::Singleton(env), jsonElement)); + } else { + return mbgl::NullValue(); } - return value; -} - -bool JsonElement::isJsonObject(JNIEnv& env, jni::Object jsonElement) { - static auto javaClass = jni::Class::Singleton(env); - static auto method = javaClass.GetMethod(env, "isJsonObject"); - return jsonElement.Call(env, method); -} - -bool JsonElement::isJsonArray(JNIEnv& env, jni::Object jsonElement) { - static auto javaClass = jni::Class::Singleton(env); - static auto method = javaClass.GetMethod(env, "isJsonArray"); - return jsonElement.Call(env, method); -} - -bool JsonElement::isJsonPrimitive(JNIEnv& env, jni::Object jsonElement) { - static auto javaClass = jni::Class::Singleton(env); - static auto method = javaClass.GetMethod(env, "isJsonPrimitive"); - return jsonElement.Call(env, method); -} - -bool JsonElement::isJsonNull(JNIEnv& env, jni::Object jsonElement) { - static auto javaClass = jni::Class::Singleton(env); - static auto method = javaClass.GetMethod(env, "isJsonNull"); - return jsonElement.Call(env, method); } void JsonElement::registerNative(jni::JNIEnv &env) { diff --git a/platform/android/src/gson/json_element.hpp b/platform/android/src/gson/json_element.hpp index 5c68934871..384459dc41 100644 --- a/platform/android/src/gson/json_element.hpp +++ b/platform/android/src/gson/json_element.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include @@ -12,13 +12,8 @@ class JsonElement : public jni::ObjectTag { public: static constexpr auto Name() { return "com/google/gson/JsonElement"; }; - static jni::Object New(jni::JNIEnv&, const mapbox::geometry::value&); - static mapbox::geometry::value convert(JNIEnv&, jni::Object); - - static bool isJsonObject(JNIEnv&, jni::Object); - static bool isJsonArray(JNIEnv&, jni::Object); - static bool isJsonPrimitive(JNIEnv&, jni::Object); - static bool isJsonNull(JNIEnv&, jni::Object); + static jni::Object New(jni::JNIEnv&, const mbgl::Value&); + static mbgl::Value convert(JNIEnv&, jni::Object); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/gson/json_object.cpp b/platform/android/src/gson/json_object.cpp index 4a2ec07563..5dcb07642f 100644 --- a/platform/android/src/gson/json_object.cpp +++ b/platform/android/src/gson/json_object.cpp @@ -9,7 +9,7 @@ namespace android { namespace gson { -jni::Object JsonObject::New(jni::JNIEnv& env, const std::unordered_map& values) { +jni::Object JsonObject::New(jni::JNIEnv& env, const mbgl::PropertyMap& values) { static auto javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); static auto addMethod = javaClass.GetMethod)>(env, "add"); @@ -46,8 +46,8 @@ static void iterateEntrySet(jni::JNIEnv& env, jni::Object jsonObject } } -mapbox::geometry::property_map JsonObject::convert(jni::JNIEnv &env, jni::Object jsonObject) { - mapbox::geometry::property_map map; +mbgl::PropertyMap JsonObject::convert(jni::JNIEnv &env, jni::Object jsonObject) { + mbgl::PropertyMap map; if (jsonObject) { iterateEntrySet(env, jsonObject, [&map, &env](jni::String jId, jni::Object jsonElement) { diff --git a/platform/android/src/gson/json_object.hpp b/platform/android/src/gson/json_object.hpp index 85e8828d91..256161f0d9 100644 --- a/platform/android/src/gson/json_object.hpp +++ b/platform/android/src/gson/json_object.hpp @@ -2,8 +2,6 @@ #include "json_element.hpp" -#include - #include namespace mbgl { @@ -14,8 +12,8 @@ class JsonObject : public JsonElement { public: static constexpr auto Name() { return "com/google/gson/JsonObject"; }; - static jni::Object New(jni::JNIEnv&, const std::unordered_map&); - static mapbox::geometry::property_map convert(JNIEnv&, jni::Object); + static jni::Object New(jni::JNIEnv&, const mbgl::PropertyMap&); + static mbgl::PropertyMap convert(JNIEnv&, jni::Object); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/gson/json_primitive.cpp b/platform/android/src/gson/json_primitive.cpp index 2b03629135..79d6b07617 100644 --- a/platform/android/src/gson/json_primitive.cpp +++ b/platform/android/src/gson/json_primitive.cpp @@ -4,135 +4,6 @@ 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 operator()(const mapbox::geometry::null_value_t) const { - return jni::Object(); - } - - /** - * Create a primitive containing a string value - */ - jni::Object operator()(const std::string value) const { - static auto javaClass = jni::Class::Singleton(env); - static auto constructor = javaClass.GetConstructor(env); - - return javaClass.New(env, constructor, - *jni::SeizeLocal(env, jni::Make(env, value))); - } - - /** - * Create a primitive containing a number value with type double - */ - jni::Object operator()(const double value) const { - static auto javaClass = jni::Class::Singleton(env); - static auto constructor = javaClass.GetConstructor(env); - - return javaClass.New(env, constructor, - *jni::SeizeLocal(env, jni::Number(jni::Box(env, value)))); - } - - /** - * Create a primitive containing a number value with type long - */ - jni::Object operator()(const int64_t value) const { - static auto javaClass = jni::Class::Singleton(env); - static auto constructor = javaClass.GetConstructor(env); - - return javaClass.New(env, constructor, - *jni::SeizeLocal(env, jni::Number(jni::Box(env, value)))); - } - - /** - * Create a primitive containing a number value with type long - */ - jni::Object operator()(const uint64_t value) const { - static auto javaClass = jni::Class::Singleton(env); - static auto constructor = javaClass.GetConstructor(env); - - return javaClass.New(env, constructor, - *jni::SeizeLocal(env, jni::Number(jni::Box(env, int64_t(value))))); // TODO: should use BigInteger - } - - /** - * Create a primitive containing a boolean value - */ - jni::Object operator()(const bool value) const { - static auto javaClass = jni::Class::Singleton(env); - static auto constructor = javaClass.GetConstructor(env); - - return javaClass.New(env, constructor, - *jni::SeizeLocal(env, jni::Box(env, value ? jni::jni_true : jni::jni_false))); - } -}; - -jni::Object 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) { - 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) { - static auto javaClass = jni::Class::Singleton(env); - static auto method = javaClass.GetMethod(env, "isBoolean"); - return jsonPrimitive.Call(env, method); -} - -bool JsonPrimitive::isString(JNIEnv& env, jni::Object jsonPrimitive) { - static auto javaClass = jni::Class::Singleton(env); - static auto method = javaClass.GetMethod(env, "isString"); - return jsonPrimitive.Call(env, method); -} - -bool JsonPrimitive::isNumber(JNIEnv& env, jni::Object jsonPrimitive) { - static auto javaClass = jni::Class::Singleton(env); - static auto method = javaClass.GetMethod(env, "isNumber"); - return jsonPrimitive.Call(env, method); -} - -bool JsonPrimitive::getAsBoolean(JNIEnv& env, jni::Object jsonPrimitive) { - static auto javaClass = jni::Class::Singleton(env); - static auto method = javaClass.GetMethod(env, "getAsBoolean"); - return jsonPrimitive.Call(env, method); -} - -std::string JsonPrimitive::getAsString(JNIEnv& env, jni::Object jsonPrimitive) { - static auto javaClass = jni::Class::Singleton(env); - static auto method = javaClass.GetMethod(env, "getAsString"); - return jni::Make(env, *jni::SeizeLocal(env, jsonPrimitive.Call(env, method))); -} - -double JsonPrimitive::getAsDouble(JNIEnv& env, jni::Object jsonPrimitive) { - static auto javaClass = jni::Class::Singleton(env); - static auto method = javaClass.GetMethod(env, "getAsDouble"); - return jsonPrimitive.Call(env, method); -} - void JsonPrimitive::registerNative(jni::JNIEnv &env) { jni::Class::Singleton(env); } diff --git a/platform/android/src/gson/json_primitive.hpp b/platform/android/src/gson/json_primitive.hpp index d9e90507f9..fb3eefc855 100644 --- a/platform/android/src/gson/json_primitive.hpp +++ b/platform/android/src/gson/json_primitive.hpp @@ -2,8 +2,6 @@ #include "json_element.hpp" -#include - #include namespace mbgl { @@ -12,21 +10,8 @@ namespace gson { class JsonPrimitive : public JsonElement { public: - using value = mapbox::util::variant; - static constexpr auto Name() { return "com/google/gson/JsonPrimitive"; }; - static jni::Object New(jni::JNIEnv&, const value&); - static value convert(JNIEnv&, jni::Object); - - static bool isBoolean(JNIEnv&, jni::Object); - static bool isString(JNIEnv&, jni::Object); - static bool isNumber(JNIEnv&, jni::Object); - - static bool getAsBoolean(JNIEnv&, jni::Object); - static std::string getAsString(JNIEnv&, jni::Object); - static double getAsDouble(JNIEnv&, jni::Object); - static void registerNative(jni::JNIEnv&); }; -- cgit v1.2.1 From 5911e3b13f2f2b6741e26db3e41513ed21cc95b4 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Wed, 22 Aug 2018 11:44:07 -0700 Subject: [android] Simplify annotation conversion --- platform/android/src/annotation/polygon.cpp | 53 +++++++++------------------- platform/android/src/annotation/polygon.hpp | 19 ---------- platform/android/src/annotation/polyline.cpp | 39 ++++++-------------- platform/android/src/annotation/polyline.hpp | 17 --------- 4 files changed, 27 insertions(+), 101 deletions(-) diff --git a/platform/android/src/annotation/polygon.cpp b/platform/android/src/annotation/polygon.cpp index f049911be0..4168c3ceef 100644 --- a/platform/android/src/annotation/polygon.cpp +++ b/platform/android/src/annotation/polygon.cpp @@ -6,12 +6,21 @@ namespace mbgl { namespace android { mbgl::FillAnnotation Polygon::toAnnotation(jni::JNIEnv& env, jni::Object polygon) { - auto points = jni::SeizeLocal(env, Polygon::getPoints(env, polygon)); - auto holes = jni::SeizeLocal(env, Polygon::getHoles(env, polygon)); + static auto javaClass = jni::Class::Singleton(env); + static auto points = javaClass.GetField>(env, "points"); + static auto holes = javaClass.GetField>(env, "holes"); + static auto alpha = javaClass.GetField(env, "alpha"); + static auto fillColor = javaClass.GetField(env, "fillColor"); + static auto strokeColor = javaClass.GetField(env, "strokeColor"); + + mbgl::Polygon geometry { + MultiPoint::toGeometry>(env, *jni::SeizeLocal(env, polygon.Get(env, points))) + }; - mbgl::Polygon geometry { MultiPoint::toGeometry>(env, *points) }; + auto jHoleListsArray = jni::SeizeLocal(env, + java::util::List::toArray(env, + *jni::SeizeLocal(env, polygon.Get(env, holes)))); - auto jHoleListsArray = jni::SeizeLocal(env, java::util::List::toArray(env, *holes)); std::size_t jHoleListsSize = jHoleListsArray->Length(env); for (std::size_t i = 0; i < jHoleListsSize; i++) { geometry.push_back(MultiPoint::toGeometry>(env, @@ -19,43 +28,13 @@ mbgl::FillAnnotation Polygon::toAnnotation(jni::JNIEnv& env, jni::Object(env, polygon.Get(env, fillColor)); + annotation.outlineColor = *conversion::convert(env, polygon.Get(env, strokeColor)); return annotation; } -jni::Object Polygon::getPoints(jni::JNIEnv& env, jni::Object polygon) { - static auto javaClass = jni::Class::Singleton(env); - static auto field = javaClass.GetField>(env, "points"); - return polygon.Get(env, field); -} - -jni::Object Polygon::getHoles(jni::JNIEnv& env, jni::Object polygon) { - static auto javaClass = jni::Class::Singleton(env); - static auto field = javaClass.GetField>(env, "holes"); - return polygon.Get(env, field); -} - -float Polygon::getOpacity(jni::JNIEnv& env, jni::Object polygon) { - static auto javaClass = jni::Class::Singleton(env); - static auto field = javaClass.GetField(env, "alpha"); - return polygon.Get(env, field); -} - -mbgl::Color Polygon::getFillColor(jni::JNIEnv& env, jni::Object polygon) { - static auto javaClass = jni::Class::Singleton(env); - static auto field = javaClass.GetField(env, "fillColor"); - return *conversion::convert(env, polygon.Get(env, field)); -} - -mbgl::Color Polygon::getOutlineColor(jni::JNIEnv& env, jni::Object polygon) { - static auto javaClass = jni::Class::Singleton(env); - static auto field = javaClass.GetField(env, "strokeColor"); - return *conversion::convert(env, polygon.Get(env, field)); -} - void Polygon::registerNative(jni::JNIEnv& env) { jni::Class::Singleton(env); } diff --git a/platform/android/src/annotation/polygon.hpp b/platform/android/src/annotation/polygon.hpp index f7cc015c8a..92d3fe0a71 100644 --- a/platform/android/src/annotation/polygon.hpp +++ b/platform/android/src/annotation/polygon.hpp @@ -1,38 +1,19 @@ #pragma once #include -#include - -#include #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 mbgl::FillAnnotation toAnnotation(jni::JNIEnv&, jni::Object); static void registerNative(jni::JNIEnv&); - -private: - - static jni::Object getPoints(jni::JNIEnv&, jni::Object); - - static jni::Object getHoles(jni::JNIEnv&, jni::Object); - - static float getOpacity(jni::JNIEnv&, jni::Object); - - static mbgl::Color getFillColor(jni::JNIEnv&, jni::Object); - - static mbgl::Color getOutlineColor(jni::JNIEnv&, jni::Object); }; diff --git a/platform/android/src/annotation/polyline.cpp b/platform/android/src/annotation/polyline.cpp index 22d25a0f75..080efa1960 100644 --- a/platform/android/src/annotation/polyline.cpp +++ b/platform/android/src/annotation/polyline.cpp @@ -6,38 +6,21 @@ namespace mbgl { namespace android { mbgl::LineAnnotation Polyline::toAnnotation(jni::JNIEnv& env, jni::Object polyline) { - auto points = jni::SeizeLocal(env, Polyline::getPoints(env, polyline)); - - mbgl::LineAnnotation annotation { MultiPoint::toGeometry>(env, *points) }; - annotation.opacity = { Polyline::getOpacity(env, polyline) }; - annotation.color = { Polyline::getColor(env, polyline) }; - annotation.width = { Polyline::getWidth(env, polyline) }; - - return annotation; -} - -jni::Object Polyline::getPoints(jni::JNIEnv& env, jni::Object polyline) { static auto javaClass = jni::Class::Singleton(env); - static auto field = javaClass.GetField>(env, "points"); - return polyline.Get(env, field); -} + static auto points = javaClass.GetField>(env, "points"); + static auto alpha = javaClass.GetField(env, "alpha"); + static auto color = javaClass.GetField(env, "color"); + static auto width = javaClass.GetField(env, "width"); -float Polyline::getOpacity(jni::JNIEnv& env, jni::Object polyline) { - static auto javaClass = jni::Class::Singleton(env); - static auto field = javaClass.GetField(env, "alpha"); - return polyline.Get(env, field); -} + mbgl::LineAnnotation annotation { + MultiPoint::toGeometry>(env, *jni::SeizeLocal(env, polyline.Get(env, points))) + }; -mbgl::Color Polyline::getColor(jni::JNIEnv& env, jni::Object polyline) { - static auto javaClass = jni::Class::Singleton(env); - static auto field = javaClass.GetField(env, "color"); - return *conversion::convert(env, polyline.Get(env, field)); -} + annotation.opacity = polyline.Get(env, alpha); + annotation.color = *conversion::convert(env, polyline.Get(env, color)); + annotation.width = polyline.Get(env, width); -float Polyline::getWidth(jni::JNIEnv& env, jni::Object polyline) { - static auto javaClass = jni::Class::Singleton(env); - static auto field = javaClass.GetField(env, "width"); - return polyline.Get(env, field); + return annotation; } void Polyline::registerNative(jni::JNIEnv& env) { diff --git a/platform/android/src/annotation/polyline.hpp b/platform/android/src/annotation/polyline.hpp index 69f5d19c1f..36c2d49e6d 100644 --- a/platform/android/src/annotation/polyline.hpp +++ b/platform/android/src/annotation/polyline.hpp @@ -1,36 +1,19 @@ #pragma once #include -#include - -#include #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 mbgl::LineAnnotation toAnnotation(jni::JNIEnv&, jni::Object); static void registerNative(jni::JNIEnv&); - -private: - - static jni::Object getPoints(jni::JNIEnv&, jni::Object); - - static float getOpacity(jni::JNIEnv&, jni::Object); - - static mbgl::Color getColor(jni::JNIEnv&, jni::Object); - - static float getWidth(jni::JNIEnv&, jni::Object); }; -- cgit v1.2.1 From 79bf0e8af6bf9ec829a352d56b8e70ccc8f4fa41 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Wed, 22 Aug 2018 12:27:43 -0700 Subject: [android] jni.hpp 4.0.0 --- cmake/mason-dependencies.cmake | 2 +- platform/android/scripts/generate-style-code.js | 4 - platform/android/src/annotation/marker.cpp | 12 +- platform/android/src/annotation/marker.hpp | 4 +- platform/android/src/annotation/multi_point.hpp | 8 +- platform/android/src/annotation/polygon.cpp | 15 +- platform/android/src/annotation/polygon.hpp | 2 +- platform/android/src/annotation/polyline.cpp | 6 +- platform/android/src/annotation/polyline.hpp | 2 +- platform/android/src/asset_manager_file_source.cpp | 6 +- platform/android/src/asset_manager_file_source.hpp | 2 +- platform/android/src/bitmap.cpp | 84 +++--- platform/android/src/bitmap.hpp | 14 +- platform/android/src/bitmap_factory.cpp | 10 +- platform/android/src/bitmap_factory.hpp | 4 +- platform/android/src/connectivity_listener.cpp | 2 +- platform/android/src/conversion/collection.cpp | 8 +- platform/android/src/conversion/collection.hpp | 4 +- platform/android/src/conversion/constant.cpp | 58 ++-- platform/android/src/conversion/constant.hpp | 57 ++-- platform/android/src/file_source.cpp | 39 +-- platform/android/src/file_source.hpp | 16 +- platform/android/src/geojson/feature.cpp | 26 +- platform/android/src/geojson/feature.hpp | 6 +- .../android/src/geojson/feature_collection.cpp | 14 +- .../android/src/geojson/feature_collection.hpp | 7 +- platform/android/src/geojson/geometry.cpp | 38 +-- platform/android/src/geojson/geometry.hpp | 6 +- .../android/src/geojson/geometry_collection.cpp | 22 +- .../android/src/geojson/geometry_collection.hpp | 8 +- platform/android/src/geojson/line_string.cpp | 23 +- platform/android/src/geojson/line_string.hpp | 12 +- platform/android/src/geojson/multi_line_string.cpp | 24 +- platform/android/src/geojson/multi_line_string.hpp | 12 +- platform/android/src/geojson/multi_point.cpp | 14 +- platform/android/src/geojson/multi_point.hpp | 10 +- platform/android/src/geojson/multi_polygon.cpp | 26 +- platform/android/src/geojson/multi_polygon.hpp | 10 +- platform/android/src/geojson/point.cpp | 8 +- platform/android/src/geojson/point.hpp | 7 +- platform/android/src/geojson/polygon.cpp | 16 +- platform/android/src/geojson/polygon.hpp | 12 +- platform/android/src/geojson/util.hpp | 16 +- platform/android/src/geometry/lat_lng.cpp | 10 +- platform/android/src/geometry/lat_lng.hpp | 6 +- platform/android/src/geometry/lat_lng_bounds.cpp | 8 +- platform/android/src/geometry/lat_lng_bounds.hpp | 4 +- platform/android/src/geometry/lat_lng_quad.cpp | 8 +- platform/android/src/geometry/lat_lng_quad.hpp | 4 +- platform/android/src/geometry/projected_meters.cpp | 4 +- platform/android/src/geometry/projected_meters.hpp | 2 +- platform/android/src/graphics/pointf.cpp | 8 +- platform/android/src/graphics/pointf.hpp | 4 +- platform/android/src/graphics/rectf.cpp | 16 +- platform/android/src/graphics/rectf.hpp | 8 +- platform/android/src/gson/json_array.cpp | 16 +- platform/android/src/gson/json_array.hpp | 7 +- platform/android/src/gson/json_element.cpp | 29 +- platform/android/src/gson/json_element.hpp | 7 +- platform/android/src/gson/json_object.cpp | 30 +- platform/android/src/gson/json_object.hpp | 7 +- platform/android/src/gson/json_primitive.hpp | 3 +- platform/android/src/http_file_source.cpp | 39 +-- platform/android/src/image.cpp | 7 +- platform/android/src/java/util.hpp | 30 +- .../android/src/jni/generic_global_ref_deleter.hpp | 45 --- platform/android/src/logger.cpp | 14 +- platform/android/src/map/camera_position.cpp | 10 +- platform/android/src/map/camera_position.hpp | 4 +- platform/android/src/map/image.cpp | 14 +- platform/android/src/map/image.hpp | 2 +- platform/android/src/map_renderer.cpp | 30 +- platform/android/src/map_renderer.hpp | 14 +- platform/android/src/map_renderer_runnable.cpp | 6 +- platform/android/src/native_map_view.cpp | 166 +++++------ platform/android/src/native_map_view.hpp | 104 +++---- platform/android/src/offline/offline_manager.cpp | 79 +++--- platform/android/src/offline/offline_manager.hpp | 24 +- platform/android/src/offline/offline_region.cpp | 127 ++++----- platform/android/src/offline/offline_region.hpp | 28 +- .../src/offline/offline_region_definition.cpp | 38 +-- .../src/offline/offline_region_definition.hpp | 16 +- .../android/src/offline/offline_region_error.cpp | 8 +- .../android/src/offline/offline_region_error.hpp | 2 +- .../android/src/offline/offline_region_status.cpp | 4 +- .../android/src/offline/offline_region_status.hpp | 2 +- platform/android/src/snapshotter/map_snapshot.cpp | 10 +- platform/android/src/snapshotter/map_snapshot.hpp | 6 +- .../android/src/snapshotter/map_snapshotter.cpp | 35 ++- .../android/src/snapshotter/map_snapshotter.hpp | 25 +- platform/android/src/style/conversion/filter.cpp | 4 +- platform/android/src/style/conversion/filter.hpp | 2 +- platform/android/src/style/conversion/position.cpp | 2 +- platform/android/src/style/conversion/position.hpp | 4 +- .../src/style/conversion/property_expression.hpp | 4 +- .../src/style/conversion/property_value.hpp | 22 +- .../src/style/conversion/transition_options.cpp | 2 +- .../src/style/conversion/transition_options.hpp | 4 +- .../android/src/style/layers/background_layer.cpp | 37 ++- .../android/src/style/layers/background_layer.hpp | 18 +- platform/android/src/style/layers/circle_layer.cpp | 97 +++---- platform/android/src/style/layers/circle_layer.hpp | 44 +-- platform/android/src/style/layers/custom_layer.cpp | 10 +- platform/android/src/style/layers/custom_layer.hpp | 5 +- .../src/style/layers/fill_extrusion_layer.cpp | 69 +++-- .../src/style/layers/fill_extrusion_layer.hpp | 32 +-- platform/android/src/style/layers/fill_layer.cpp | 65 ++--- platform/android/src/style/layers/fill_layer.hpp | 30 +- .../android/src/style/layers/heatmap_layer.cpp | 47 ++-- .../android/src/style/layers/heatmap_layer.hpp | 22 +- .../android/src/style/layers/hillshade_layer.cpp | 56 ++-- .../android/src/style/layers/hillshade_layer.hpp | 26 +- platform/android/src/style/layers/layer.cpp | 30 +- platform/android/src/style/layers/layer.cpp.ejs | 28 +- platform/android/src/style/layers/layer.hpp | 20 +- platform/android/src/style/layers/layer.hpp.ejs | 12 +- platform/android/src/style/layers/layers.cpp | 8 +- platform/android/src/style/layers/layers.hpp | 4 +- platform/android/src/style/layers/line_layer.cpp | 121 ++++---- platform/android/src/style/layers/line_layer.hpp | 54 ++-- platform/android/src/style/layers/raster_layer.cpp | 74 +++-- platform/android/src/style/layers/raster_layer.hpp | 34 +-- platform/android/src/style/layers/symbol_layer.cpp | 308 +++++++++------------ platform/android/src/style/layers/symbol_layer.hpp | 130 ++++----- .../android/src/style/layers/unknown_layer.cpp | 6 +- .../android/src/style/layers/unknown_layer.hpp | 4 +- platform/android/src/style/light.cpp | 38 ++- platform/android/src/style/light.cpp.ejs | 122 -------- platform/android/src/style/light.hpp | 26 +- platform/android/src/style/light.hpp.ejs | 59 ---- platform/android/src/style/position.cpp | 16 +- platform/android/src/style/position.hpp | 8 +- .../src/style/sources/custom_geometry_source.cpp | 56 ++-- .../src/style/sources/custom_geometry_source.hpp | 18 +- .../android/src/style/sources/geojson_source.cpp | 53 ++-- .../android/src/style/sources/geojson_source.hpp | 25 +- .../android/src/style/sources/image_source.cpp | 22 +- .../android/src/style/sources/image_source.hpp | 14 +- .../src/style/sources/raster_dem_source.cpp | 18 +- .../src/style/sources/raster_dem_source.hpp | 7 +- .../android/src/style/sources/raster_source.cpp | 18 +- .../android/src/style/sources/raster_source.hpp | 7 +- platform/android/src/style/sources/source.cpp | 25 +- platform/android/src/style/sources/source.hpp | 12 +- .../android/src/style/sources/unknown_source.cpp | 8 +- .../android/src/style/sources/unknown_source.hpp | 4 +- .../android/src/style/sources/vector_source.cpp | 26 +- .../android/src/style/sources/vector_source.hpp | 11 +- platform/android/src/style/transition_options.cpp | 4 +- platform/android/src/style/transition_options.hpp | 2 +- platform/android/src/style/value.cpp | 35 +-- platform/android/src/style/value.hpp | 1 + platform/android/src/test/main.jni.cpp | 4 +- platform/android/src/text/collator.cpp | 71 +++-- platform/android/src/text/collator_jni.hpp | 16 +- .../android/src/text/local_glyph_rasterizer.cpp | 19 +- 156 files changed, 1765 insertions(+), 2161 deletions(-) delete mode 100644 platform/android/src/jni/generic_global_ref_deleter.hpp delete mode 100644 platform/android/src/style/light.cpp.ejs delete mode 100644 platform/android/src/style/light.hpp.ejs diff --git a/cmake/mason-dependencies.cmake b/cmake/mason-dependencies.cmake index 7330f2f3a2..6c571db259 100644 --- a/cmake/mason-dependencies.cmake +++ b/cmake/mason-dependencies.cmake @@ -19,7 +19,7 @@ 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 4.0.0-rc8 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) elseif(MBGL_PLATFORM STREQUAL "linux") 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/src/annotation/marker.cpp b/platform/android/src/annotation/marker.cpp index b9a8c714a1..899f87a74f 100644 --- a/platform/android/src/annotation/marker.cpp +++ b/platform/android/src/annotation/marker.cpp @@ -3,16 +3,16 @@ namespace mbgl { namespace android { -mbgl::Point Marker::getPosition(jni::JNIEnv& env, jni::Object marker) { - static auto javaClass = jni::Class::Singleton(env); +mbgl::Point Marker::getPosition(jni::JNIEnv& env, const jni::Object& marker) { + static auto& javaClass = jni::Class::Singleton(env); static auto positionField = javaClass.GetField>(env, "position"); - return LatLng::getGeometry(env, *jni::SeizeLocal(env, marker.Get(env, positionField))); + return LatLng::getGeometry(env, marker.Get(env, positionField)); } -std::string Marker::getIconId(jni::JNIEnv& env, jni::Object marker) { - static auto javaClass = jni::Class::Singleton(env); +std::string Marker::getIconId(jni::JNIEnv& env, const jni::Object& marker) { + static auto& javaClass = jni::Class::Singleton(env); static auto iconIdField = javaClass.GetField(env, "iconId"); - return jni::Make(env, *jni::SeizeLocal(env, marker.Get(env, iconIdField))); + return jni::Make(env, marker.Get(env, iconIdField)); } void Marker::registerNative(jni::JNIEnv& env) { diff --git a/platform/android/src/annotation/marker.hpp b/platform/android/src/annotation/marker.hpp index d03c244921..b38a25b4fb 100644 --- a/platform/android/src/annotation/marker.hpp +++ b/platform/android/src/annotation/marker.hpp @@ -15,9 +15,9 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/annotations/Marker"; }; - static mbgl::Point getPosition(jni::JNIEnv&, jni::Object); + static mbgl::Point getPosition(jni::JNIEnv&, const jni::Object&); - static std::string getIconId(jni::JNIEnv&, jni::Object); + static std::string getIconId(jni::JNIEnv&, const jni::Object&); static void registerNative(jni::JNIEnv&); diff --git a/platform/android/src/annotation/multi_point.hpp b/platform/android/src/annotation/multi_point.hpp index 1a6b945261..20f1b3eaf2 100644 --- a/platform/android/src/annotation/multi_point.hpp +++ b/platform/android/src/annotation/multi_point.hpp @@ -14,16 +14,16 @@ class MultiPoint : protected mbgl::util::noncopyable { protected: template - static Geometry toGeometry(JNIEnv& env, jni::Object pointsList) { - auto jarray = jni::SeizeLocal(env, java::util::List::toArray(env, pointsList)); + static Geometry toGeometry(JNIEnv& env, const jni::Object& pointsList) { + auto jarray = java::util::List::toArray(env, pointsList); - std::size_t size = jarray->Length(env); + std::size_t size = jarray.Length(env); Geometry geometry; geometry.reserve(size); for (std::size_t i = 0; i < size; i++) { - geometry.push_back(LatLng::getGeometry(env, *jni::SeizeLocal(env, jarray->Get(env, i)))); + geometry.push_back(LatLng::getGeometry(env, jarray.Get(env, i))); } return geometry; diff --git a/platform/android/src/annotation/polygon.cpp b/platform/android/src/annotation/polygon.cpp index 4168c3ceef..f22cffb100 100644 --- a/platform/android/src/annotation/polygon.cpp +++ b/platform/android/src/annotation/polygon.cpp @@ -5,8 +5,8 @@ namespace mbgl { namespace android { -mbgl::FillAnnotation Polygon::toAnnotation(jni::JNIEnv& env, jni::Object polygon) { - static auto javaClass = jni::Class::Singleton(env); +mbgl::FillAnnotation Polygon::toAnnotation(jni::JNIEnv& env, const jni::Object& polygon) { + static auto& javaClass = jni::Class::Singleton(env); static auto points = javaClass.GetField>(env, "points"); static auto holes = javaClass.GetField>(env, "holes"); static auto alpha = javaClass.GetField(env, "alpha"); @@ -14,17 +14,14 @@ mbgl::FillAnnotation Polygon::toAnnotation(jni::JNIEnv& env, jni::Object(env, "strokeColor"); mbgl::Polygon geometry { - MultiPoint::toGeometry>(env, *jni::SeizeLocal(env, polygon.Get(env, points))) + MultiPoint::toGeometry>(env, polygon.Get(env, points)) }; - auto jHoleListsArray = jni::SeizeLocal(env, - java::util::List::toArray(env, - *jni::SeizeLocal(env, polygon.Get(env, holes)))); + auto jHoleListsArray = java::util::List::toArray(env, polygon.Get(env, holes)); - std::size_t jHoleListsSize = jHoleListsArray->Length(env); + std::size_t jHoleListsSize = jHoleListsArray.Length(env); for (std::size_t i = 0; i < jHoleListsSize; i++) { - geometry.push_back(MultiPoint::toGeometry>(env, - *jni::SeizeLocal(env, jHoleListsArray->Get(env, i)))); + geometry.push_back(MultiPoint::toGeometry>(env, jHoleListsArray.Get(env, i))); } mbgl::FillAnnotation annotation { geometry }; diff --git a/platform/android/src/annotation/polygon.hpp b/platform/android/src/annotation/polygon.hpp index 92d3fe0a71..bc21878ef3 100644 --- a/platform/android/src/annotation/polygon.hpp +++ b/platform/android/src/annotation/polygon.hpp @@ -11,7 +11,7 @@ class Polygon : private MultiPoint { public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/annotations/Polygon"; }; - static mbgl::FillAnnotation toAnnotation(jni::JNIEnv&, jni::Object); + static mbgl::FillAnnotation toAnnotation(jni::JNIEnv&, const jni::Object&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/annotation/polyline.cpp b/platform/android/src/annotation/polyline.cpp index 080efa1960..d6161e856e 100644 --- a/platform/android/src/annotation/polyline.cpp +++ b/platform/android/src/annotation/polyline.cpp @@ -5,15 +5,15 @@ namespace mbgl { namespace android { -mbgl::LineAnnotation Polyline::toAnnotation(jni::JNIEnv& env, jni::Object polyline) { - static auto javaClass = jni::Class::Singleton(env); +mbgl::LineAnnotation Polyline::toAnnotation(jni::JNIEnv& env, const jni::Object& polyline) { + static auto& javaClass = jni::Class::Singleton(env); static auto points = javaClass.GetField>(env, "points"); static auto alpha = javaClass.GetField(env, "alpha"); static auto color = javaClass.GetField(env, "color"); static auto width = javaClass.GetField(env, "width"); mbgl::LineAnnotation annotation { - MultiPoint::toGeometry>(env, *jni::SeizeLocal(env, polyline.Get(env, points))) + MultiPoint::toGeometry>(env, polyline.Get(env, points)) }; annotation.opacity = polyline.Get(env, alpha); diff --git a/platform/android/src/annotation/polyline.hpp b/platform/android/src/annotation/polyline.hpp index 36c2d49e6d..6178e98cfc 100644 --- a/platform/android/src/annotation/polyline.hpp +++ b/platform/android/src/annotation/polyline.hpp @@ -11,7 +11,7 @@ class Polyline : private MultiPoint { public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/annotations/Polyline"; }; - static mbgl::LineAnnotation toAnnotation(jni::JNIEnv&, jni::Object); + static mbgl::LineAnnotation toAnnotation(jni::JNIEnv&, const jni::Object&); static void registerNative(jni::JNIEnv&); }; 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 assetManager_) - : assetManager(assetManager_.NewGlobalRef(env)), +AssetManagerFileSource::AssetManagerFileSource(jni::JNIEnv& env, const jni::Object& assetManager_) + : assetManager(jni::NewGlobal(env, assetManager_)), impl(std::make_unique>("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 bb0809a442..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 class Thread; class AssetManagerFileSource : public FileSource { public: - AssetManagerFileSource(jni::JNIEnv&, jni::Object); + AssetManagerFileSource(jni::JNIEnv&, const jni::Object&); ~AssetManagerFileSource() override; std::unique_ptr request(const Resource&, Callback) override; diff --git a/platform/android/src/bitmap.cpp b/platform/android/src/bitmap.cpp index 53136b868e..eb7c676b12 100644 --- a/platform/android/src/bitmap.cpp +++ b/platform/android/src/bitmap.cpp @@ -8,7 +8,7 @@ namespace android { class PixelGuard { public: - PixelGuard(jni::JNIEnv& env_, jni::Object bitmap_) : env(env_), bitmap(bitmap_) { + PixelGuard(jni::JNIEnv& env_, const jni::Object& bitmap_) : env(env_), bitmap(bitmap_) { const int result = AndroidBitmap_lockPixels(&env, jni::Unwrap(*bitmap), reinterpret_cast(&address)); if (result != ANDROID_BITMAP_RESULT_SUCCESS) { @@ -29,25 +29,21 @@ public: private: jni::JNIEnv& env; - jni::Object bitmap; + const jni::Object& bitmap; uint8_t* address; }; -jni::Object Bitmap::Config::Create(jni::JNIEnv& env, Value value) { - static auto _class = jni::Class::Singleton(env); +jni::Local> Bitmap::Config::Create(jni::JNIEnv& env, Value value) { + static auto& _class = jni::Class::Singleton(env); switch (value) { case ALPHA_8: - return _class.Get(env, - jni::StaticField>(env, _class, "ALPHA_8")); + return _class.Get(env, _class.GetStaticField>(env, "ALPHA_8")); case ARGB_4444: - return _class.Get(env, - jni::StaticField>(env, _class, "ARGB_4444")); + return _class.Get(env, _class.GetStaticField>(env, "ARGB_4444")); case ARGB_8888: - return _class.Get(env, - jni::StaticField>(env, _class, "ARGB_8888")); + return _class.Get(env, _class.GetStaticField>(env, "ARGB_8888")); case RGB_565: - return _class.Get(env, - jni::StaticField>(env, _class, "RGB_565")); + return _class.Get(env, _class.GetStaticField>(env, "RGB_565")); default: throw std::runtime_error("invalid enum value for Bitmap.Config"); } @@ -58,17 +54,41 @@ void Bitmap::registerNative(jni::JNIEnv& env) { jni::Class::Singleton(env); } -jni::Object Bitmap::CreateBitmap(jni::JNIEnv& env, - jni::jint width, - jni::jint height, - jni::Object config) { - static auto _class = jni::Class::Singleton(env); +jni::Local> Bitmap::CreateBitmap(jni::JNIEnv& env, + jni::jint width, + jni::jint height, + const jni::Object& config) { + static auto& _class = jni::Class::Singleton(env); static auto method = _class.GetStaticMethod (jni::jint, jni::jint, jni::Object)>(env, "createBitmap"); return _class.Call(env, method, width, height, config); } -jni::Object Bitmap::CreateBitmap(jni::JNIEnv& env, const PremultipliedImage& image) { +PremultipliedImage Bitmap::GetImage(jni::JNIEnv& env, const jni::Object& 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(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> Bitmap::CreateBitmap(jni::JNIEnv& env, const PremultipliedImage& image) { auto bitmap = CreateBitmap(env, image.size.width, image.size.height, Config::ARGB_8888); AndroidBitmapInfo info; @@ -93,32 +113,8 @@ jni::Object Bitmap::CreateBitmap(jni::JNIEnv& env, const PremultipliedIm return bitmap; } -PremultipliedImage Bitmap::GetImage(jni::JNIEnv& env, jni::Object 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(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::Object Bitmap::Copy(jni::JNIEnv& env, jni::Object bitmap) { - static auto klass = jni::Class::Singleton(env); +jni::Local> Bitmap::Copy(jni::JNIEnv& env, const jni::Object& bitmap) { + static auto& klass = jni::Class::Singleton(env); static auto copy = klass.GetMethod (jni::Object, jni::jboolean)>(env, "copy"); return bitmap.Call(env, copy, Bitmap::Config::Create(env, Bitmap::Config::Value::ARGB_8888), jni::jni_false); diff --git a/platform/android/src/bitmap.hpp b/platform/android/src/bitmap.hpp index 2266bc0e67..9d96405c26 100644 --- a/platform/android/src/bitmap.hpp +++ b/platform/android/src/bitmap.hpp @@ -20,23 +20,23 @@ public: RGB_565, }; - static jni::Object Create(jni::JNIEnv&, Value); + static jni::Local> Create(jni::JNIEnv&, Value); }; static constexpr auto Name() { return "android/graphics/Bitmap"; }; static void registerNative(jni::JNIEnv&); - static jni::Object - CreateBitmap(jni::JNIEnv&, jni::jint width, jni::jint height, jni::Object); + static jni::Local> + CreateBitmap(jni::JNIEnv&, jni::jint width, jni::jint height, const jni::Object&); - static jni::Object + static jni::Local> 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); - static jni::Object CreateBitmap(jni::JNIEnv&, const PremultipliedImage&); - static jni::Object Copy(jni::JNIEnv&, jni::Object); + static PremultipliedImage GetImage(jni::JNIEnv&, const jni::Object&); + static jni::Local> CreateBitmap(jni::JNIEnv&, const PremultipliedImage&); + static jni::Local> Copy(jni::JNIEnv&, const jni::Object&); }; } // namespace android diff --git a/platform/android/src/bitmap_factory.cpp b/platform/android/src/bitmap_factory.cpp index 79cdc913a0..170bd52ea5 100644 --- a/platform/android/src/bitmap_factory.cpp +++ b/platform/android/src/bitmap_factory.cpp @@ -7,11 +7,11 @@ void BitmapFactory::registerNative(jni::JNIEnv& env) { jni::Class::Singleton(env); } -jni::Object BitmapFactory::DecodeByteArray(jni::JNIEnv& env, - jni::Array data, - jni::jint offset, - jni::jint length) { - static auto _class = jni::Class::Singleton(env); +jni::Local> BitmapFactory::DecodeByteArray(jni::JNIEnv& env, + jni::Array& data, + jni::jint offset, + jni::jint length) { + static auto& _class = jni::Class::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. diff --git a/platform/android/src/bitmap_factory.hpp b/platform/android/src/bitmap_factory.hpp index 6e019d017c..f73b7a2906 100644 --- a/platform/android/src/bitmap_factory.hpp +++ b/platform/android/src/bitmap_factory.hpp @@ -12,8 +12,8 @@ public: static constexpr auto Name() { return "android/graphics/BitmapFactory"; }; static void registerNative(jni::JNIEnv&); - static jni::Object - DecodeByteArray(jni::JNIEnv&, jni::Array data, jni::jint offset, jni::jint length); + static jni::Local> + DecodeByteArray(jni::JNIEnv&, jni::Array& 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 3fcc580aab..9c13f1f749 100644 --- a/platform/android/src/connectivity_listener.cpp +++ b/platform/android/src/connectivity_listener.cpp @@ -21,7 +21,7 @@ namespace android { void ConnectivityListener::registerNative(jni::JNIEnv& env) { // Lookup the class - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) diff --git a/platform/android/src/conversion/collection.cpp b/platform/android/src/conversion/collection.cpp index 3195458aa6..954a161baf 100644 --- a/platform/android/src/conversion/collection.cpp +++ b/platform/android/src/conversion/collection.cpp @@ -5,23 +5,23 @@ namespace mbgl { namespace android { namespace conversion { -std::vector toVector(JNIEnv& env, jni::Array array) { +std::vector toVector(JNIEnv& env, const jni::Array& array) { std::size_t len = array.Length(env); std::vector vector; vector.reserve(len); for (std::size_t i = 0; i < len; i++) { - vector.push_back(*convert(env, *jni::SeizeLocal(env, array.Get(env, i)))); + vector.push_back(jni::Make(env, array.Get(env, i))); } return vector; } -jni::Array toArray(JNIEnv& env, const std::vector& vector) { +jni::Local> toArray(JNIEnv& env, const std::vector& vector) { auto result = jni::Array::New(env, vector.size()); for (std::size_t i = 0; i < vector.size(); i++) { - result.Set(env, i, *jni::SeizeLocal(env, jni::Make(env, vector.at(i)))); + result.Set(env, i, jni::Make(env, vector.at(i))); } return result; diff --git a/platform/android/src/conversion/collection.hpp b/platform/android/src/conversion/collection.hpp index c6b08370ee..322ebb62e0 100644 --- a/platform/android/src/conversion/collection.hpp +++ b/platform/android/src/conversion/collection.hpp @@ -10,8 +10,8 @@ namespace mbgl { namespace android { namespace conversion { -std::vector toVector(JNIEnv& env, jni::Array array); -jni::Array toArray(JNIEnv& env, const std::vector&); +std::vector toVector(JNIEnv& env, const jni::Array& array); +jni::Local> toArray(JNIEnv& env, const std::vector&); } } 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 @@ -6,63 +7,46 @@ namespace mbgl { namespace android { namespace conversion { -Result Converter::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, "", "(Z)V"); - return {&jni::NewObject(env, *javaClass, *constructor, (jboolean) value)}; +Result>> Converter>, bool>::operator()(jni::JNIEnv& env, const bool& value) const { + return jni::Box(env, value ? jni::jni_true : jni::jni_false); } -Result Converter::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, "", "(F)V"); - return {&jni::NewObject(env, *javaClass, *constructor, (jfloat) value)}; +Result>> Converter>, float>::operator()(jni::JNIEnv& env, const float& value) const { + return jni::Box(env, value); } -Result Converter::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, "", "(D)V"); - return {&jni::NewObject(env, *javaClass, *constructor, (jfloat) value)}; +Result>> Converter>, double>::operator()(jni::JNIEnv& env, const double& value) const { + return jni::Box(env, value); } -Result Converter::operator()(jni::JNIEnv& env, const std::string& value) const { - return {jni::Make(env, value).Get()}; +Result>> Converter>, std::string>::operator()(jni::JNIEnv& env, const std::string& value) const { + return jni::Make(env, value); } -Result Converter::operator()(jni::JNIEnv& env, const Color& value) const { +Result>> Converter>, 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(env, result); + return jni::Make(env, sstream.str()); } -Result Converter>::operator()(jni::JNIEnv& env, const std::vector& value) const { - static jni::jclass* stringCass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/String")).release(); - jni::jarray& jarray = jni::NewObjectArray(env, value.size(), *stringCass); +Result>> Converter>, std::vector>::operator()(jni::JNIEnv& env, const std::vector& value) const { + auto result = jni::Array::New(env, value.size()); - for(size_t i = 0; i < value.size(); i = i + 1) { - Result converted = convert(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(env, value.at(i))); } - return &jarray; + return result; } -Result Converter>::operator()(jni::JNIEnv& env, const std::vector& value) const { - static jni::jclass* floatClass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/Float")).release(); - jni::jarray& jarray = jni::NewObjectArray(env, value.size(), *floatClass); +Result>> Converter>, std::vector>::operator()(jni::JNIEnv& env, const std::vector& value) const { + auto result = jni::Array::New(env, value.size()); - for(size_t i = 0; i < value.size(); i = i + 1) { - Result converted = convert(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 Converter::operator()(jni::JNIEnv& env, const jni::String& value) const { - return { jni::Make(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 { - Result operator()(jni::JNIEnv& env, const bool& value) const; +struct Converter>, bool> { + Result>> operator()(jni::JNIEnv& env, const bool& value) const; }; template <> -struct Converter { - Result operator()(jni::JNIEnv& env, const float& value) const; +struct Converter>, float> { + Result>> operator()(jni::JNIEnv& env, const float& value) const; }; template <> -struct Converter { - Result operator()(jni::JNIEnv& env, const double& value) const; +struct Converter>, double> { + Result>> operator()(jni::JNIEnv& env, const double& value) const; }; /** @@ -35,61 +35,52 @@ struct Converter { * TODO: use BigDecimal for > 64 / unsigned? */ template -struct Converter::value>::type> { - Result 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, "", "(J)V"); - return {&jni::NewObject(env, *javaClass, *constructor, (jlong) value)}; +struct Converter>, T, typename std::enable_if::value>::type> { + Result>> 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 { - Result operator()(jni::JNIEnv& env, const std::string& value) const; +struct Converter>, std::string> { + Result>> operator()(jni::JNIEnv& env, const std::string& value) const; }; template <> -struct Converter { - Result operator()(jni::JNIEnv& env, const Color& value) const; +struct Converter>, Color> { + Result>> operator()(jni::JNIEnv& env, const Color& value) const; }; template -struct Converter> { - Result operator()(jni::JNIEnv& env, const std::array& value) const { +struct Converter>, std::array> { + Result>> operator()(jni::JNIEnv& env, const std::array& value) const { std::vector v; for (const float& id : value) { v.push_back(id); } - return convert>(env, v); + return convert>, std::vector>(env, v); } }; template <> -struct Converter> { - Result operator()(jni::JNIEnv& env, const std::vector& value) const; +struct Converter>, std::vector> { + Result>> operator()(jni::JNIEnv& env, const std::vector& value) const; }; template <> -struct Converter> { - Result operator()(jni::JNIEnv& env, const std::vector& value) const; +struct Converter>, std::vector> { + Result>> operator()(jni::JNIEnv& env, const std::vector& value) const; }; template -struct Converter::value>> { - Result operator()(jni::JNIEnv& env, const T& value) const { - return convert(env, Enum::toString(value)); +struct Converter>, T, typename std::enable_if_t::value>> { + Result>> operator()(jni::JNIEnv& env, const T& value) const { + return convert>, std::string>(env, Enum::toString(value)); } }; -// Java -> C++ - -template <> -struct Converter { - Result 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 32c304b909..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 #include @@ -6,7 +7,6 @@ #include #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) { + const jni::String& accessToken, + const jni::String& _cachePath, + const jni::Object& assetManager) { // Create a core default file source fileSource = std::make_unique( jni::Make(_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 FileSource::getAccessToken(jni::JNIEnv& env) { return jni::Make(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(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(env, url)); } -void FileSource::setResourceTransform(jni::JNIEnv& env, jni::Object transformCallback) { +void FileSource::setResourceTransform(jni::JNIEnv& env, const jni::Object& transformCallback) { if (transformCallback) { + auto global = jni::NewGlobal(env, transformCallback); resourceTransform = std::make_unique>(*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(transformCallback.NewGlobalRef(env).release().Get(), GenericGlobalRefDeleter())] + [callback = std::make_shared(std::move(global))] (mbgl::Resource::Kind kind, const std::string&& url_) { android::UniqueEnv _env = android::AttachEnv(); - return FileSource::ResourceTransformCallback::onURL(*_env, jni::Object(*callback), int(kind), url_); + return FileSource::ResourceTransformCallback::onURL(*_env, *callback, int(kind), url_); }); fileSource->setResourceTransform(resourceTransform->self()); } else { @@ -92,13 +93,13 @@ jni::jboolean FileSource::isResumed(jni::JNIEnv&) { return (jboolean) false; } -FileSource* FileSource::getNativePeer(jni::JNIEnv& env, jni::Object jFileSource) { - static auto javaClass = jni::Class::Singleton(env); +FileSource* FileSource::getNativePeer(jni::JNIEnv& env, const jni::Object& jFileSource) { + static auto& javaClass = jni::Class::Singleton(env); static auto field = javaClass.GetField(env, "nativePtr"); return reinterpret_cast(jFileSource.Get(env, field)); } -mbgl::DefaultFileSource& FileSource::getDefaultFileSource(jni::JNIEnv& env, jni::Object jFileSource) { +mbgl::DefaultFileSource& FileSource::getDefaultFileSource(jni::JNIEnv& env, const jni::Object& jFileSource) { FileSource* fileSource = FileSource::getNativePeer(env, jFileSource); assert(fileSource != nullptr); return *fileSource->fileSource; @@ -110,14 +111,14 @@ void FileSource::registerNative(jni::JNIEnv& env) { // https://developer.android.com/training/articles/perf-jni#faq_FindClass jni::Class::Singleton(env); - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( env, javaClass, "nativePtr", - std::make_unique>, + jni::MakePeer&>, "initialize", "finalize", METHOD(&FileSource::getAccessToken, "getAccessToken"), @@ -133,13 +134,13 @@ void FileSource::registerNative(jni::JNIEnv& env) { // FileSource::ResourceTransformCallback // -std::string FileSource::ResourceTransformCallback::onURL(jni::JNIEnv& env, jni::Object callback, int kind, std::string url_) { - static auto javaClass = jni::Class::Singleton(env); +std::string FileSource::ResourceTransformCallback::onURL(jni::JNIEnv& env, const jni::Object& callback, int kind, std::string url_) { + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod(env, "onURL"); return jni::Make(env, - *jni::SeizeLocal(env, callback.Call(env, method, kind, - *jni::SeizeLocal(env, jni::Make(env, url_))))); + callback.Call(env, method, kind, + jni::Make(env, url_))); } } // namespace android diff --git a/platform/android/src/file_source.hpp b/platform/android/src/file_source.hpp index f1b11c754c..572ac647b7 100644 --- a/platform/android/src/file_source.hpp +++ b/platform/android/src/file_source.hpp @@ -24,20 +24,20 @@ public: struct ResourceTransformCallback { static constexpr auto Name() { return "com/mapbox/mapboxsdk/storage/FileSource$ResourceTransformCallback"; } - static std::string onURL(jni::JNIEnv&, jni::Object, int, std::string); + static std::string onURL(jni::JNIEnv&, const jni::Object&, int, std::string); }; - FileSource(jni::JNIEnv&, jni::String, jni::String, jni::Object); + FileSource(jni::JNIEnv&, const jni::String&, const jni::String&, const jni::Object&); ~FileSource(); - jni::String getAccessToken(jni::JNIEnv&); + jni::Local 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); + void setResourceTransform(jni::JNIEnv&, const jni::Object&); void resume(jni::JNIEnv&); @@ -45,9 +45,9 @@ public: jni::jboolean isResumed(jni::JNIEnv&); - static FileSource* getNativePeer(jni::JNIEnv&, jni::Object); + static FileSource* getNativePeer(jni::JNIEnv&, const jni::Object&); - static mbgl::DefaultFileSource& getDefaultFileSource(jni::JNIEnv&, jni::Object); + static mbgl::DefaultFileSource& getDefaultFileSource(jni::JNIEnv&, const jni::Object&); static void registerNative(jni::JNIEnv&); diff --git a/platform/android/src/geojson/feature.cpp b/platform/android/src/geojson/feature.cpp index 809ac42ef7..e79c238864 100644 --- a/platform/android/src/geojson/feature.cpp +++ b/platform/android/src/geojson/feature.cpp @@ -8,18 +8,18 @@ namespace geojson { using namespace gson; -mbgl::Feature Feature::convert(jni::JNIEnv& env, jni::Object jFeature) { - static auto javaClass = jni::Class::Singleton(env); +mbgl::Feature Feature::convert(jni::JNIEnv& env, const jni::Object& jFeature) { + static auto& javaClass = jni::Class::Singleton(env); static auto id = javaClass.GetMethod(env, "id"); static auto geometry = javaClass.GetMethod ()>(env, "geometry"); static auto properties = javaClass.GetMethod ()>(env, "properties"); - auto jId = jni::SeizeLocal(env, jFeature.Call(env, id)); + auto jId = jFeature.Call(env, id); return mbgl::Feature { - Geometry::convert(env, *jni::SeizeLocal(env, jFeature.Call(env, geometry))), - JsonObject::convert(env, *jni::SeizeLocal(env, jFeature.Call(env, properties))), - jId ? std::experimental::optional(jni::Make(env, *jId)) + Geometry::convert(env, jFeature.Call(env, geometry)), + JsonObject::convert(env, jFeature.Call(env, properties)), + jId ? std::experimental::optional(jni::Make(env, jId)) : std::experimental::nullopt }; } @@ -43,21 +43,21 @@ public: } }; -jni::Object convertFeature(jni::JNIEnv& env, const mbgl::Feature& value) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local> convertFeature(jni::JNIEnv& env, const mbgl::Feature& value) { + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetStaticMethod (jni::Object, jni::Object, jni::String)>(env, "fromGeometry"); return javaClass.Call(env, method, - *jni::SeizeLocal(env, Geometry::New(env, value.geometry)), - *jni::SeizeLocal(env, JsonObject::New(env, value.properties)), - *jni::SeizeLocal(env, jni::Make(env, value.id ? value.id.value().match(FeatureIdVisitor()) : ""))); + Geometry::New(env, value.geometry), + JsonObject::New(env, value.properties), + jni::Make(env, value.id ? value.id.value().match(FeatureIdVisitor()) : "")); } -jni::Array> Feature::convert(jni::JNIEnv& env, const std::vector& value) { +jni::Local>> Feature::convert(jni::JNIEnv& env, const std::vector& value) { auto features = jni::Array>::New(env, value.size()); for (size_t i = 0; i < value.size(); i = i + 1) { - features.Set(env, i, *jni::SeizeLocal(env, convertFeature(env, value.at(i)))); + features.Set(env, i, convertFeature(env, value.at(i))); } return features; diff --git a/platform/android/src/geojson/feature.hpp b/platform/android/src/geojson/feature.hpp index fba4815e0c..fdf5d977ba 100644 --- a/platform/android/src/geojson/feature.hpp +++ b/platform/android/src/geojson/feature.hpp @@ -8,12 +8,12 @@ namespace mbgl { namespace android { namespace geojson { -class Feature : public jni::ObjectTag { +class Feature { public: static constexpr auto Name() { return "com/mapbox/geojson/Feature"; }; - static mbgl::Feature convert(jni::JNIEnv&, jni::Object); - static jni::Array> convert(jni::JNIEnv&, const std::vector&); + static mbgl::Feature convert(jni::JNIEnv&, const jni::Object&); + static jni::Local>> convert(jni::JNIEnv&, const std::vector&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/feature_collection.cpp b/platform/android/src/geojson/feature_collection.cpp index c2825e037b..f90d5226b7 100644 --- a/platform/android/src/geojson/feature_collection.cpp +++ b/platform/android/src/geojson/feature_collection.cpp @@ -6,24 +6,24 @@ namespace mbgl { namespace android { namespace geojson { -mbgl::FeatureCollection FeatureCollection::convert(jni::JNIEnv& env, jni::Object jCollection) { +mbgl::FeatureCollection FeatureCollection::convert(jni::JNIEnv& env, const jni::Object& jCollection) { auto collection = mbgl::FeatureCollection(); if (jCollection) { - auto jFeatureList = jni::SeizeLocal(env, FeatureCollection::features(env, jCollection)); - auto jFeatures = jni::SeizeLocal(env, java::util::List::toArray(env, *jFeatureList)); - auto size = size_t(jFeatures->Length(env)); + auto jFeatureList = FeatureCollection::features(env, jCollection); + auto jFeatures = java::util::List::toArray(env, jFeatureList); + auto size = size_t(jFeatures.Length(env)); collection.reserve(size); for (size_t i = 0; i < size; i++) { - collection.push_back(Feature::convert(env, *jni::SeizeLocal(env, jFeatures->Get(env, i)))); + collection.push_back(Feature::convert(env, jFeatures.Get(env, i))); } } return collection; } -jni::Object FeatureCollection::features(jni::JNIEnv& env, jni::Object jCollection) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local> FeatureCollection::features(jni::JNIEnv& env, const jni::Object& jCollection) { + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod ()>(env, "features"); return jCollection.Call(env, method); } diff --git a/platform/android/src/geojson/feature_collection.hpp b/platform/android/src/geojson/feature_collection.hpp index 1b45cca5de..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 -#include #include @@ -11,13 +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); + static mbgl::FeatureCollection convert(jni::JNIEnv&, const jni::Object&); - static jni::Object features(jni::JNIEnv&, jni::Object); + static jni::Local> features(jni::JNIEnv&, const jni::Object&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/geometry.cpp b/platform/android/src/geojson/geometry.cpp index 4262b4ee69..2356af780a 100644 --- a/platform/android/src/geojson/geometry.cpp +++ b/platform/android/src/geojson/geometry.cpp @@ -22,65 +22,65 @@ public: jni::JNIEnv& env; - jni::Object operator()(const mbgl::Point &geometry) const { + jni::Local> operator()(const mbgl::Point &geometry) const { return Point::New(env, geometry); } - jni::Object operator()(const mbgl::LineString &geometry) const { + jni::Local> operator()(const mbgl::LineString &geometry) const { return LineString::New(env, geometry); } - jni::Object operator()(const mbgl::MultiLineString &geometry) const { + jni::Local> operator()(const mbgl::MultiLineString &geometry) const { return MultiLineString::New(env, geometry); } - jni::Object operator()(const mbgl::MultiPoint &geometry) const { + jni::Local> operator()(const mbgl::MultiPoint &geometry) const { return MultiPoint::New(env, geometry); } - jni::Object operator()(const mbgl::Polygon &geometry) const { + jni::Local> operator()(const mbgl::Polygon &geometry) const { return Polygon::New(env, geometry); } - jni::Object operator()(const mbgl::MultiPolygon &geometry) const { + jni::Local> operator()(const mbgl::MultiPolygon &geometry) const { return MultiPolygon::New(env, geometry); } - jni::Object operator()(const mapbox::geometry::geometry_collection &geometry) const { + jni::Local> operator()(const mapbox::geometry::geometry_collection &geometry) const { return GeometryCollection::New(env, geometry); } }; -jni::Object Geometry::New(jni::JNIEnv& env, mbgl::Geometry geometry) { +jni::Local> Geometry::New(jni::JNIEnv& env, mbgl::Geometry geometry) { GeometryEvaluator evaluator { env } ; return mbgl::Geometry::visit(geometry, evaluator); } -mbgl::Geometry Geometry::convert(jni::JNIEnv &env, jni::Object jGeometry) { +mbgl::Geometry Geometry::convert(jni::JNIEnv &env, const jni::Object& jGeometry) { auto type = Geometry::getType(env, jGeometry); if (type == Point::Type()) { - return { Point::convert(env, jni::Object(jGeometry.Get())) }; + return { Point::convert(env, jni::Cast(env, jni::Class::Singleton(env), jGeometry)) }; } else if (type == MultiPoint::Type()) { - return { MultiPoint::convert(env, jni::Object(jGeometry.Get())) }; + return { MultiPoint::convert(env, jni::Cast(env, jni::Class::Singleton(env), jGeometry)) }; } else if (type == LineString::Type()) { - return { LineString::convert(env, jni::Object(jGeometry.Get())) }; + return { LineString::convert(env, jni::Cast(env, jni::Class::Singleton(env), jGeometry)) }; } else if (type == MultiLineString::Type()) { - return { MultiLineString::convert(env, jni::Object(jGeometry.Get())) }; + return { MultiLineString::convert(env, jni::Cast(env, jni::Class::Singleton(env), jGeometry)) }; } else if (type == Polygon::Type()) { - return { Polygon::convert(env, jni::Object(jGeometry.Get())) }; + return { Polygon::convert(env, jni::Cast(env, jni::Class::Singleton(env), jGeometry)) }; } else if (type == MultiPolygon::Type()) { - return { MultiPolygon::convert(env, jni::Object(jGeometry.Get())) }; + return { MultiPolygon::convert(env, jni::Cast(env, jni::Class::Singleton(env), jGeometry)) }; } else if (type == GeometryCollection::Type()) { - return { GeometryCollection::convert(env, jni::Object(jGeometry.Get())) }; + return { GeometryCollection::convert(env, jni::Cast(env, jni::Class::Singleton(env), jGeometry)) }; } throw std::runtime_error(std::string {"Unsupported GeoJSON type: " } + type); } -std::string Geometry::getType(jni::JNIEnv &env, jni::Object jGeometry) { - static auto javaClass = jni::Class::Singleton(env); +std::string Geometry::getType(jni::JNIEnv &env, const jni::Object& jGeometry) { + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod(env, "type"); - return jni::Make(env, *jni::SeizeLocal(env, jGeometry.Call(env, method))); + return jni::Make(env, jGeometry.Call(env, method)); } void Geometry::registerNative(jni::JNIEnv &env) { diff --git a/platform/android/src/geojson/geometry.hpp b/platform/android/src/geojson/geometry.hpp index 836c3bd5a0..4bf55c858b 100644 --- a/platform/android/src/geojson/geometry.hpp +++ b/platform/android/src/geojson/geometry.hpp @@ -14,11 +14,11 @@ class Geometry { public: static constexpr auto Name() { return "com/mapbox/geojson/Geometry"; }; - static jni::Object New(jni::JNIEnv&, mbgl::Geometry); + static jni::Local> New(jni::JNIEnv&, mbgl::Geometry); - static mbgl::Geometry convert(jni::JNIEnv&, jni::Object); + static mbgl::Geometry convert(jni::JNIEnv&, const jni::Object&); - static std::string getType(jni::JNIEnv&, jni::Object); + static std::string getType(jni::JNIEnv&, const jni::Object&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/geometry_collection.cpp b/platform/android/src/geojson/geometry_collection.cpp index ad0af71214..cca909126d 100644 --- a/platform/android/src/geojson/geometry_collection.cpp +++ b/platform/android/src/geojson/geometry_collection.cpp @@ -5,36 +5,34 @@ namespace mbgl { namespace android { namespace geojson { -jni::Object GeometryCollection::New(jni::JNIEnv& env, const mapbox::geometry::geometry_collection& collection) { +jni::Local> GeometryCollection::New(jni::JNIEnv& env, const mapbox::geometry::geometry_collection& collection) { // Create an array of geometries - auto jarray = jni::SeizeLocal(env, jni::Array>::New(env, collection.size())); + auto jarray = jni::Array>::New(env, collection.size()); for (size_t i = 0; i < collection.size(); i++) { - jarray->Set(env, i, *jni::SeizeLocal(env, Geometry::New(env, collection.at(i)))); + jarray.Set(env, i, Geometry::New(env, collection.at(i))); } // create the GeometryCollection - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetStaticMethod (jni::Object)>(env, "fromGeometries"); - return javaClass.Call(env, method, *jni::SeizeLocal(env, java::util::Arrays::asList(env, *jarray))); + return javaClass.Call(env, method, java::util::Arrays::asList(env, jarray)); } -mapbox::geometry::geometry_collection GeometryCollection::convert(jni::JNIEnv &env, jni::Object jCollection) { +mapbox::geometry::geometry_collection GeometryCollection::convert(jni::JNIEnv &env, const jni::Object& jCollection) { // Get geometries - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); static auto getGeometries = javaClass.GetMethod ()>(env, "geometries"); // Turn into array - auto jarray = jni::SeizeLocal(env, - java::util::List::toArray(env, - *jni::SeizeLocal(env, jCollection.Call(env, getGeometries)))); + auto jarray = java::util::List::toArray(env, jCollection.Call(env, getGeometries)); // Convert each geometry mapbox::geometry::geometry_collection collection{}; - auto size = jarray->Length(env); + auto size = jarray.Length(env); for (jni::jsize i = 0; i < size; i++) { - collection.push_back(Geometry::convert(env, *jni::SeizeLocal(env, jarray->Get(env, i)))); + collection.push_back(Geometry::convert(env, jarray.Get(env, i))); } return collection; diff --git a/platform/android/src/geojson/geometry_collection.hpp b/platform/android/src/geojson/geometry_collection.hpp index a301d86933..9f02ac848d 100644 --- a/platform/android/src/geojson/geometry_collection.hpp +++ b/platform/android/src/geojson/geometry_collection.hpp @@ -8,15 +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 New(jni::JNIEnv&, const mapbox::geometry::geometry_collection&); + static jni::Local> New(jni::JNIEnv&, const mapbox::geometry::geometry_collection&); - static mapbox::geometry::geometry_collection convert(jni::JNIEnv&, jni::Object); + static mapbox::geometry::geometry_collection convert(jni::JNIEnv&, const jni::Object&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/line_string.cpp b/platform/android/src/geojson/line_string.cpp index 5a18a02bb7..ae1345c958 100644 --- a/platform/android/src/geojson/line_string.cpp +++ b/platform/android/src/geojson/line_string.cpp @@ -7,42 +7,41 @@ namespace mbgl { namespace android { namespace geojson { -jni::Object LineString::New(jni::JNIEnv& env, const mbgl::LineString& lineString) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local> LineString::New(jni::JNIEnv& env, const mbgl::LineString& lineString) { + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetStaticMethod(jni::Object)>(env, "fromLngLats"); - return javaClass.Call(env, method, - *jni::SeizeLocal(env, asPointsList(env, lineString))); + return javaClass.Call(env, method, asPointsList(env, lineString)); } -mapbox::geojson::line_string LineString::convert(jni::JNIEnv &env, jni::Object jLineString) { +mapbox::geojson::line_string LineString::convert(jni::JNIEnv &env, const jni::Object& jLineString) { mapbox::geojson::line_string lineString; if (jLineString) { - lineString = LineString::convert(env, *jni::SeizeLocal(env, LineString::coordinates(env, jLineString))); + lineString = LineString::convert(env, LineString::coordinates(env, jLineString)); } return lineString; } -mapbox::geojson::line_string LineString::convert(jni::JNIEnv &env, jni::Object*/> jPointList) { +mapbox::geojson::line_string LineString::convert(jni::JNIEnv &env, const jni::Object*/>& jPointList) { mapbox::geojson::line_string lineString; if (jPointList) { - auto jPointArray = jni::SeizeLocal(env, java::util::List::toArray(env, jPointList)); - auto size = jPointArray->Length(env); + auto jPointArray = java::util::List::toArray(env, jPointList); + auto size = jPointArray.Length(env); lineString.reserve(size); for (std::size_t i = 0; i < size; i++) { - lineString.push_back(Point::convert(env, *jni::SeizeLocal(env, jPointArray->Get(env, i)))); + lineString.push_back(Point::convert(env, jPointArray.Get(env, i))); } } return lineString; } -jni::Object LineString::coordinates(jni::JNIEnv &env, jni::Object jLineString) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local> LineString::coordinates(jni::JNIEnv &env, const jni::Object& jLineString) { + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod ()>(env, "coordinates"); return jLineString.Call(env, method); } diff --git a/platform/android/src/geojson/line_string.hpp b/platform/android/src/geojson/line_string.hpp index 4df9349185..906d809fa8 100644 --- a/platform/android/src/geojson/line_string.hpp +++ b/platform/android/src/geojson/line_string.hpp @@ -14,19 +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 New(jni::JNIEnv&, const mbgl::LineString&); + static jni::Local> New(jni::JNIEnv&, const mbgl::LineString&); - static mapbox::geojson::line_string convert(jni::JNIEnv&, jni::Object); + static mapbox::geojson::line_string convert(jni::JNIEnv&, const jni::Object&); - static mapbox::geojson::line_string convert(jni::JNIEnv&, jni::Object*/>); + static mapbox::geojson::line_string convert(jni::JNIEnv&, const jni::Object*/>&); - static jni::Object coordinates(jni::JNIEnv&, jni::Object); + static jni::Local> coordinates(jni::JNIEnv&, const jni::Object&); 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 0a0974062c..1aaf53c01f 100644 --- a/platform/android/src/geojson/multi_line_string.cpp +++ b/platform/android/src/geojson/multi_line_string.cpp @@ -7,44 +7,42 @@ namespace mbgl { namespace android { namespace geojson { -jni::Object MultiLineString::New(jni::JNIEnv& env, const mbgl::MultiLineString& multiLineString) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local> MultiLineString::New(jni::JNIEnv& env, const mbgl::MultiLineString& multiLineString) { + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetStaticMethod (jni::Object)>(env, "fromLngLats"); - return javaClass.Call(env, method, - *jni::SeizeLocal(env, asPointsListsList(env, multiLineString))); + return javaClass.Call(env, method, asPointsListsList(env, multiLineString)); } -mapbox::geojson::multi_line_string MultiLineString::convert(jni::JNIEnv &env, jni::Object jMultiLineString) { +mapbox::geojson::multi_line_string MultiLineString::convert(jni::JNIEnv &env, const jni::Object& jMultiLineString) { mapbox::geojson::multi_line_string multiLineString; if (jMultiLineString) { - multiLineString = MultiLineString::convert(env, - *jni::SeizeLocal(env, MultiLineString::coordinates(env, jMultiLineString))); + multiLineString = MultiLineString::convert(env, MultiLineString::coordinates(env, jMultiLineString)); } return multiLineString; } -mapbox::geojson::multi_line_string MultiLineString::convert(jni::JNIEnv &env, jni::Object>*/> jPointListsList) { +mapbox::geojson::multi_line_string MultiLineString::convert(jni::JNIEnv &env, const jni::Object>*/>& jPointListsList) { mapbox::geojson::multi_line_string multiLineString; if (jPointListsList) { - auto jPositionListsArray = jni::SeizeLocal(env, java::util::List::toArray(env, jPointListsList)); + auto jPositionListsArray = java::util::List::toArray(env, jPointListsList); - auto size = jPositionListsArray->Length(env); + auto size = jPositionListsArray.Length(env); multiLineString.reserve(size); for (std::size_t i = 0; i < size; i++) { - multiLineString.push_back(LineString::convert(env, *jni::SeizeLocal(env, jPositionListsArray->Get(env, i)))); + multiLineString.push_back(LineString::convert(env, jPositionListsArray.Get(env, i))); } } return multiLineString; } -jni::Object MultiLineString::coordinates(jni::JNIEnv &env, jni::Object jLineString) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local> MultiLineString::coordinates(jni::JNIEnv &env, const jni::Object& jLineString) { + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod ()>(env, "coordinates"); return jLineString.Call(env, method); } diff --git a/platform/android/src/geojson/multi_line_string.hpp b/platform/android/src/geojson/multi_line_string.hpp index c66aadaf03..65ce43bd1f 100644 --- a/platform/android/src/geojson/multi_line_string.hpp +++ b/platform/android/src/geojson/multi_line_string.hpp @@ -12,19 +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 New(jni::JNIEnv&, const mbgl::MultiLineString&); + static jni::Local> New(jni::JNIEnv&, const mbgl::MultiLineString&); - static mapbox::geojson::multi_line_string convert(jni::JNIEnv&, jni::Object); + static mapbox::geojson::multi_line_string convert(jni::JNIEnv&, const jni::Object&); - static mapbox::geojson::multi_line_string convert(jni::JNIEnv&, jni::Object>*/>); + static mapbox::geojson::multi_line_string convert(jni::JNIEnv&, const jni::Object>*/>&); - static jni::Object coordinates(jni::JNIEnv&, jni::Object); + static jni::Local> coordinates(jni::JNIEnv&, const jni::Object&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/multi_point.cpp b/platform/android/src/geojson/multi_point.cpp index 5f51058f38..d530ef721f 100644 --- a/platform/android/src/geojson/multi_point.cpp +++ b/platform/android/src/geojson/multi_point.cpp @@ -8,26 +8,26 @@ namespace mbgl { namespace android { namespace geojson { -jni::Object MultiPoint::New(JNIEnv& env, const mbgl::MultiPoint& multiPoint) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local> MultiPoint::New(JNIEnv& env, const mbgl::MultiPoint& multiPoint) { + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetStaticMethod(jni::Object)>(env, "fromLngLats"); - return javaClass.Call(env, method, *jni::SeizeLocal(env, asPointsList(env, multiPoint))); + return javaClass.Call(env, method, asPointsList(env, multiPoint)); } -mapbox::geojson::multi_point MultiPoint::convert(jni::JNIEnv &env, jni::Object jMultiPoint) { +mapbox::geojson::multi_point MultiPoint::convert(jni::JNIEnv& env, const jni::Object& jMultiPoint) { mapbox::geojson::multi_point multiPoint; if (jMultiPoint) { multiPoint = convertExplicit( - LineString::convert(env, *jni::SeizeLocal(env, MultiPoint::coordinates(env, jMultiPoint)))); + LineString::convert(env, MultiPoint::coordinates(env, jMultiPoint))); } return multiPoint; } -jni::Object MultiPoint::coordinates(jni::JNIEnv &env, jni::Object jMultiPoint) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local> MultiPoint::coordinates(jni::JNIEnv& env, const jni::Object& jMultiPoint) { + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod ()>(env, "coordinates"); return jMultiPoint.Call(env, method); } diff --git a/platform/android/src/geojson/multi_point.hpp b/platform/android/src/geojson/multi_point.hpp index 0df16bfd6a..a3ca49b731 100644 --- a/platform/android/src/geojson/multi_point.hpp +++ b/platform/android/src/geojson/multi_point.hpp @@ -13,17 +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 New(jni::JNIEnv&, const mbgl::MultiPoint&); + static jni::Local> New(jni::JNIEnv&, const mbgl::MultiPoint&); - static mapbox::geojson::multi_point convert(jni::JNIEnv&, jni::Object); + static mapbox::geojson::multi_point convert(jni::JNIEnv&, const jni::Object&); - static jni::Object coordinates(jni::JNIEnv&, jni::Object); + static jni::Local> coordinates(jni::JNIEnv&, const jni::Object&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/multi_polygon.cpp b/platform/android/src/geojson/multi_polygon.cpp index 109ac714c3..3c5c3ec338 100644 --- a/platform/android/src/geojson/multi_polygon.cpp +++ b/platform/android/src/geojson/multi_polygon.cpp @@ -7,41 +7,39 @@ namespace mbgl { namespace android { namespace geojson { -jni::Object MultiPolygon::New(JNIEnv& env, const mbgl::MultiPolygon& multiPolygon) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local> MultiPolygon::New(JNIEnv& env, const mbgl::MultiPolygon& multiPolygon) { + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetStaticMethod (jni::Object)>(env, "fromLngLats"); - auto jarray = jni::SeizeLocal(env, - jni::Array>::New(env, multiPolygon.size())); + auto jarray = jni::Array>::New(env, multiPolygon.size()); for (size_t i = 0; i < multiPolygon.size(); i++) { - jarray->Set(env, i, *jni::SeizeLocal(env, asPointsListsList(env, multiPolygon.at(i)))); + jarray.Set(env, i, asPointsListsList(env, multiPolygon.at(i))); } - return javaClass.Call(env, method, - *jni::SeizeLocal(env, java::util::Arrays::asList(env, *jarray))); + return javaClass.Call(env, method, java::util::Arrays::asList(env, jarray)); } -mapbox::geojson::multi_polygon MultiPolygon::convert(jni::JNIEnv &env, jni::Object jMultiPolygon) { +mapbox::geojson::multi_polygon MultiPolygon::convert(jni::JNIEnv& env, const jni::Object& jMultiPolygon) { mapbox::geojson::multi_polygon multiPolygon; if (jMultiPolygon) { - auto jPointListsListList = jni::SeizeLocal(env, MultiPolygon::coordinates(env, jMultiPolygon)); - auto jPointListsListArray = jni::SeizeLocal(env, java::util::List::toArray(env, *jPointListsListList)); + auto jPointListsListList = MultiPolygon::coordinates(env, jMultiPolygon); + auto jPointListsListArray = java::util::List::toArray(env, jPointListsListList); - auto size = jPointListsListArray->Length(env); + auto size = jPointListsListArray.Length(env); multiPolygon.reserve(size); for (size_t i = 0; i < size; i++) { - multiPolygon.push_back(Polygon::convert(env, *jni::SeizeLocal(env, jPointListsListArray->Get(env, i)))); + multiPolygon.push_back(Polygon::convert(env, jPointListsListArray.Get(env, i))); } } return multiPolygon; } -jni::Object MultiPolygon::coordinates(jni::JNIEnv &env, jni::Object jPolygon) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local> MultiPolygon::coordinates(jni::JNIEnv& env, const jni::Object& jPolygon) { + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod ()>(env, "coordinates"); return jPolygon.Call(env, method); } diff --git a/platform/android/src/geojson/multi_polygon.hpp b/platform/android/src/geojson/multi_polygon.hpp index 3477e989ea..fd7b08016d 100644 --- a/platform/android/src/geojson/multi_polygon.hpp +++ b/platform/android/src/geojson/multi_polygon.hpp @@ -12,17 +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 New(jni::JNIEnv&, const mbgl::MultiPolygon&); + static jni::Local> New(jni::JNIEnv&, const mbgl::MultiPolygon&); - static mapbox::geojson::multi_polygon convert(jni::JNIEnv&, jni::Object); + static mapbox::geojson::multi_polygon convert(jni::JNIEnv&, const jni::Object&); - static jni::Object coordinates(jni::JNIEnv&, jni::Object); + static jni::Local> coordinates(jni::JNIEnv&, const jni::Object&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/point.cpp b/platform/android/src/geojson/point.cpp index 7fcc183dc1..2000447c0f 100644 --- a/platform/android/src/geojson/point.cpp +++ b/platform/android/src/geojson/point.cpp @@ -4,14 +4,14 @@ namespace mbgl { namespace android { namespace geojson { -jni::Object Point::New(jni::JNIEnv& env, const mbgl::Point& point) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local> Point::New(jni::JNIEnv& env, const mbgl::Point& point) { + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetStaticMethod (jni::jdouble, jni::jdouble)>(env, "fromLngLat"); return javaClass.Call(env, method, point.x, point.y); } -mbgl::Point Point::convert(jni::JNIEnv &env, jni::Object jPoint) { - static auto javaClass = jni::Class::Singleton(env); +mbgl::Point Point::convert(jni::JNIEnv &env, const jni::Object& jPoint) { + static auto& javaClass = jni::Class::Singleton(env); static auto longitude = javaClass.GetMethod(env, "longitude"); static auto latitude = javaClass.GetMethod(env, "latitude"); diff --git a/platform/android/src/geojson/point.hpp b/platform/android/src/geojson/point.hpp index d5cc7780f3..b5d71ecae1 100644 --- a/platform/android/src/geojson/point.hpp +++ b/platform/android/src/geojson/point.hpp @@ -10,13 +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 New(jni::JNIEnv&, const mbgl::Point&); - static mbgl::Point convert(jni::JNIEnv&, jni::Object); + static jni::Local> New(jni::JNIEnv&, const mbgl::Point&); + static mbgl::Point convert(jni::JNIEnv&, const jni::Object&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geojson/polygon.cpp b/platform/android/src/geojson/polygon.cpp index add843e294..4437d134a8 100644 --- a/platform/android/src/geojson/polygon.cpp +++ b/platform/android/src/geojson/polygon.cpp @@ -8,24 +8,24 @@ namespace mbgl { namespace android { namespace geojson { -jni::Object Polygon::New(jni::JNIEnv& env, const mbgl::Polygon& polygon) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local> Polygon::New(jni::JNIEnv& env, const mbgl::Polygon& polygon) { + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetStaticMethod (jni::Object)>(env, "fromLngLats"); - return javaClass.Call(env, method, *jni::SeizeLocal(env, asPointsListsList(env, polygon))); + return javaClass.Call(env, method, asPointsListsList(env, polygon)); } -mapbox::geojson::polygon Polygon::convert(jni::JNIEnv &env, jni::Object jPolygon) { +mapbox::geojson::polygon Polygon::convert(jni::JNIEnv &env, const jni::Object& jPolygon) { mapbox::geojson::polygon polygon; if (jPolygon) { - polygon = Polygon::convert(env, *jni::SeizeLocal(env, Polygon::coordinates(env, jPolygon))); + polygon = Polygon::convert(env, Polygon::coordinates(env, jPolygon)); } return polygon; } -mapbox::geojson::polygon Polygon::convert(jni::JNIEnv &env, jni::Object>*/> jPointListsList) { +mapbox::geojson::polygon Polygon::convert(jni::JNIEnv &env, const jni::Object>*/>& jPointListsList) { mapbox::geojson::polygon polygon; if (jPointListsList) { @@ -40,8 +40,8 @@ mapbox::geojson::polygon Polygon::convert(jni::JNIEnv &env, jni::Object Polygon::coordinates(jni::JNIEnv &env, jni::Object jPolygon) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local> Polygon::coordinates(jni::JNIEnv &env, const jni::Object& jPolygon) { + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod ()>(env, "coordinates"); return jPolygon.Call(env, method); } diff --git a/platform/android/src/geojson/polygon.hpp b/platform/android/src/geojson/polygon.hpp index adfa60df4d..8e1761feda 100644 --- a/platform/android/src/geojson/polygon.hpp +++ b/platform/android/src/geojson/polygon.hpp @@ -13,19 +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 New(jni::JNIEnv&, const mbgl::Polygon&); + static jni::Local> New(jni::JNIEnv&, const mbgl::Polygon&); - static mapbox::geojson::polygon convert(jni::JNIEnv &, jni::Object); + static mapbox::geojson::polygon convert(jni::JNIEnv &, const jni::Object&); - static mapbox::geojson::polygon convert(jni::JNIEnv&, jni::Object>*/>); + static mapbox::geojson::polygon convert(jni::JNIEnv&, const jni::Object>*/>&); - static jni::Object coordinates(jni::JNIEnv&, jni::Object); + static jni::Local> coordinates(jni::JNIEnv&, const jni::Object&); static void registerNative(jni::JNIEnv &); }; diff --git a/platform/android/src/geojson/util.hpp b/platform/android/src/geojson/util.hpp index e889931c56..59154516fa 100644 --- a/platform/android/src/geojson/util.hpp +++ b/platform/android/src/geojson/util.hpp @@ -23,28 +23,28 @@ To convertExplicit(From&& src) { * Geometry -> List */ template -static jni::Object asPointsList(jni::JNIEnv& env, const T& pointsList) { - auto jarray = jni::SeizeLocal(env, jni::Array>::New(env, pointsList.size())); +static jni::Local> asPointsList(jni::JNIEnv& env, const T& pointsList) { + auto jarray = jni::Array>::New(env, pointsList.size()); for (jni::jsize i = 0; i < pointsList.size(); i++) { - jarray->Set(env, i, *jni::SeizeLocal(env, Point::New(env, pointsList.at(i)))); + jarray.Set(env, i, Point::New(env, pointsList.at(i))); } - return java::util::Arrays::asList(env, *jarray); + return java::util::Arrays::asList(env, jarray); } /** * Geometry -> List> */ template -static jni::Object asPointsListsList(JNIEnv& env, SHAPE value) { - auto jarray = jni::SeizeLocal(env, jni::Array>::New(env, value.size())); +static jni::Local> asPointsListsList(JNIEnv& env, const SHAPE& value) { + auto jarray = jni::Array>::New(env, value.size()); for (size_t i = 0; i < value.size(); i++) { - jarray->Set(env, i, *jni::SeizeLocal(env, asPointsList(env, value[i]))); + jarray.Set(env, i, asPointsList(env, value[i])); } - return java::util::Arrays::asList(env, *jarray); + 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 135755d67e..5d8313cb2a 100644 --- a/platform/android/src/geometry/lat_lng.cpp +++ b/platform/android/src/geometry/lat_lng.cpp @@ -3,20 +3,20 @@ namespace mbgl { namespace android { -jni::Object LatLng::New(jni::JNIEnv& env, const mbgl::LatLng& latLng) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local> LatLng::New(jni::JNIEnv& env, const mbgl::LatLng& latLng) { + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); return javaClass.New(env, constructor, latLng.latitude(), latLng.longitude()); } -mbgl::Point LatLng::getGeometry(jni::JNIEnv& env, jni::Object latLng) { - static auto javaClass = jni::Class::Singleton(env); +mbgl::Point LatLng::getGeometry(jni::JNIEnv& env, const jni::Object& latLng) { + static auto& javaClass = jni::Class::Singleton(env); static auto latitudeField = javaClass.GetField(env, "latitude"); static auto longitudeField = javaClass.GetField(env, "longitude"); return mbgl::Point(latLng.Get(env, longitudeField), latLng.Get(env, latitudeField)); } -mbgl::LatLng LatLng::getLatLng(jni::JNIEnv& env, jni::Object latLng) { +mbgl::LatLng LatLng::getLatLng(jni::JNIEnv& env, const jni::Object& latLng) { auto point = LatLng::getGeometry(env, latLng); return mbgl::LatLng(point.y, point.x); } diff --git a/platform/android/src/geometry/lat_lng.hpp b/platform/android/src/geometry/lat_lng.hpp index 4431f1c739..30b7db1ef3 100644 --- a/platform/android/src/geometry/lat_lng.hpp +++ b/platform/android/src/geometry/lat_lng.hpp @@ -14,11 +14,11 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/geometry/LatLng"; }; - static jni::Object New(jni::JNIEnv&, const mbgl::LatLng&); + static jni::Local> New(jni::JNIEnv&, const mbgl::LatLng&); - static mbgl::Point getGeometry(jni::JNIEnv&, jni::Object); + static mbgl::Point getGeometry(jni::JNIEnv&, const jni::Object&); - static mbgl::LatLng getLatLng(jni::JNIEnv&, jni::Object); + static mbgl::LatLng getLatLng(jni::JNIEnv&, const jni::Object&); 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 583120cb68..d76ff5b365 100644 --- a/platform/android/src/geometry/lat_lng_bounds.cpp +++ b/platform/android/src/geometry/lat_lng_bounds.cpp @@ -3,14 +3,14 @@ namespace mbgl { namespace android { -jni::Object LatLngBounds::New(jni::JNIEnv& env, mbgl::LatLngBounds bounds) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local> LatLngBounds::New(jni::JNIEnv& env, mbgl::LatLngBounds bounds) { + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); return javaClass.New(env, constructor, bounds.north(), bounds.east(), bounds.south(), bounds.west()); } -mbgl::LatLngBounds LatLngBounds::getLatLngBounds(jni::JNIEnv& env, jni::Object bounds) { - static auto javaClass = jni::Class::Singleton(env); +mbgl::LatLngBounds LatLngBounds::getLatLngBounds(jni::JNIEnv& env, const jni::Object& bounds) { + static auto& javaClass = jni::Class::Singleton(env); static auto swLatField = javaClass.GetField(env, "latitudeSouth"); static auto swLonField = javaClass.GetField(env, "longitudeWest"); static auto neLatField = javaClass.GetField(env, "latitudeNorth"); diff --git a/platform/android/src/geometry/lat_lng_bounds.hpp b/platform/android/src/geometry/lat_lng_bounds.hpp index 751e0babda..d51026711d 100644 --- a/platform/android/src/geometry/lat_lng_bounds.hpp +++ b/platform/android/src/geometry/lat_lng_bounds.hpp @@ -14,9 +14,9 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/geometry/LatLngBounds"; }; - static jni::Object New(jni::JNIEnv&, mbgl::LatLngBounds); + static jni::Local> New(jni::JNIEnv&, mbgl::LatLngBounds); - static mbgl::LatLngBounds getLatLngBounds(jni::JNIEnv&, jni::Object); + static mbgl::LatLngBounds getLatLngBounds(jni::JNIEnv&, const jni::Object&); 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 5530a22903..1a1e49048b 100644 --- a/platform/android/src/geometry/lat_lng_quad.cpp +++ b/platform/android/src/geometry/lat_lng_quad.cpp @@ -4,8 +4,8 @@ namespace mbgl { namespace android { -jni::Object LatLngQuad::New(jni::JNIEnv& env, std::array coordinates) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local> LatLngQuad::New(jni::JNIEnv& env, std::array coordinates) { + static auto& javaClass = jni::Class::Singleton(env); static auto quadConstructor = javaClass.GetConstructor, jni::Object, jni::Object, jni::Object>(env); return javaClass.New(env, quadConstructor, LatLng::New(env, coordinates[0]), @@ -14,8 +14,8 @@ jni::Object LatLngQuad::New(jni::JNIEnv& env, std::array LatLngQuad::getLatLngArray(jni::JNIEnv& env, jni::Object quad) { - static auto javaClass = jni::Class::Singleton(env); +std::array LatLngQuad::getLatLngArray(jni::JNIEnv& env, const jni::Object& quad) { + static auto& javaClass = jni::Class::Singleton(env); static auto topLeftField = javaClass.GetField >(env, "topLeft"); static auto topRightField = javaClass.GetField >(env, "topRight"); static auto bottomRightField = javaClass.GetField >(env, "bottomRight"); diff --git a/platform/android/src/geometry/lat_lng_quad.hpp b/platform/android/src/geometry/lat_lng_quad.hpp index ca1430ffbc..f6560b57ba 100644 --- a/platform/android/src/geometry/lat_lng_quad.hpp +++ b/platform/android/src/geometry/lat_lng_quad.hpp @@ -15,9 +15,9 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/geometry/LatLngQuad"; }; - static jni::Object New(jni::JNIEnv&, std::array); + static jni::Local> New(jni::JNIEnv&, std::array); - static std::array getLatLngArray(jni::JNIEnv&, jni::Object); + static std::array getLatLngArray(jni::JNIEnv&, const jni::Object&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/geometry/projected_meters.cpp b/platform/android/src/geometry/projected_meters.cpp index 4dfd7b57b2..e079de0062 100644 --- a/platform/android/src/geometry/projected_meters.cpp +++ b/platform/android/src/geometry/projected_meters.cpp @@ -3,8 +3,8 @@ namespace mbgl { namespace android { -jni::Object ProjectedMeters::New(jni::JNIEnv& env, double northing, double easting) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local> ProjectedMeters::New(jni::JNIEnv& env, double northing, double easting) { + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); return javaClass.New(env, constructor, northing, easting); } diff --git a/platform/android/src/geometry/projected_meters.hpp b/platform/android/src/geometry/projected_meters.hpp index 5279e6bef2..baad1efc81 100644 --- a/platform/android/src/geometry/projected_meters.hpp +++ b/platform/android/src/geometry/projected_meters.hpp @@ -12,7 +12,7 @@ class ProjectedMeters : private mbgl::util::noncopyable { public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/geometry/ProjectedMeters"; }; - static jni::Object New(jni::JNIEnv&, double, double); + static jni::Local> New(jni::JNIEnv&, double, double); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/graphics/pointf.cpp b/platform/android/src/graphics/pointf.cpp index eceb65b07a..2fc762d6e9 100644 --- a/platform/android/src/graphics/pointf.cpp +++ b/platform/android/src/graphics/pointf.cpp @@ -4,14 +4,14 @@ namespace mbgl { namespace android { -jni::Object PointF::New(jni::JNIEnv& env, float x, float y) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local> PointF::New(jni::JNIEnv& env, float x, float y) { + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); return javaClass.New(env, constructor, x, y); } -mbgl::ScreenCoordinate PointF::getScreenCoordinate(jni::JNIEnv& env, jni::Object point) { - static auto javaClass = jni::Class::Singleton(env); +mbgl::ScreenCoordinate PointF::getScreenCoordinate(jni::JNIEnv& env, const jni::Object& point) { + static auto& javaClass = jni::Class::Singleton(env); static auto xField = javaClass.GetField(env, "x"); static auto yField = javaClass.GetField(env, "y"); return mbgl::ScreenCoordinate{point.Get(env, xField), point.Get(env, yField)}; diff --git a/platform/android/src/graphics/pointf.hpp b/platform/android/src/graphics/pointf.hpp index 27bd49138f..899468b8e3 100644 --- a/platform/android/src/graphics/pointf.hpp +++ b/platform/android/src/graphics/pointf.hpp @@ -12,9 +12,9 @@ public: static constexpr auto Name() { return "android/graphics/PointF"; }; - static jni::Object New(jni::JNIEnv&, float, float); + static jni::Local> New(jni::JNIEnv&, float, float); - static mbgl::ScreenCoordinate getScreenCoordinate(jni::JNIEnv&, jni::Object); + static mbgl::ScreenCoordinate getScreenCoordinate(jni::JNIEnv&, const jni::Object&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/graphics/rectf.cpp b/platform/android/src/graphics/rectf.cpp index 9f05728b4c..8f418da037 100644 --- a/platform/android/src/graphics/rectf.cpp +++ b/platform/android/src/graphics/rectf.cpp @@ -3,26 +3,26 @@ namespace mbgl { namespace android { -float RectF::getLeft(jni::JNIEnv& env, jni::Object rectf) { - static auto javaClass = jni::Class::Singleton(env); +float RectF::getLeft(jni::JNIEnv& env, const jni::Object& rectf) { + static auto& javaClass = jni::Class::Singleton(env); static auto field = javaClass.GetField(env, "left"); return rectf.Get(env, field); } -float RectF::getTop(jni::JNIEnv& env, jni::Object rectf) { - static auto javaClass = jni::Class::Singleton(env); +float RectF::getTop(jni::JNIEnv& env, const jni::Object& rectf) { + static auto& javaClass = jni::Class::Singleton(env); static auto field = javaClass.GetField(env, "top"); return rectf.Get(env, field); } -float RectF::getRight(jni::JNIEnv& env, jni::Object rectf) { - static auto javaClass = jni::Class::Singleton(env); +float RectF::getRight(jni::JNIEnv& env, const jni::Object& rectf) { + static auto& javaClass = jni::Class::Singleton(env); static auto field = javaClass.GetField(env, "right"); return rectf.Get(env, field); } -float RectF::getBottom(jni::JNIEnv& env, jni::Object rectf) { - static auto javaClass = jni::Class::Singleton(env); +float RectF::getBottom(jni::JNIEnv& env, const jni::Object& rectf) { + static auto& javaClass = jni::Class::Singleton(env); static auto field = javaClass.GetField(env, "bottom"); return rectf.Get(env, field); } diff --git a/platform/android/src/graphics/rectf.hpp b/platform/android/src/graphics/rectf.hpp index db836e78ba..ba611f2262 100644 --- a/platform/android/src/graphics/rectf.hpp +++ b/platform/android/src/graphics/rectf.hpp @@ -12,13 +12,13 @@ public: static constexpr auto Name() { return "android/graphics/RectF"; }; - static float getLeft(jni::JNIEnv&, jni::Object); + static float getLeft(jni::JNIEnv&, const jni::Object&); - static float getTop(jni::JNIEnv&, jni::Object); + static float getTop(jni::JNIEnv&, const jni::Object&); - static float getRight(jni::JNIEnv&, jni::Object); + static float getRight(jni::JNIEnv&, const jni::Object&); - static float getBottom(jni::JNIEnv&, jni::Object); + static float getBottom(jni::JNIEnv&, const jni::Object&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/gson/json_array.cpp b/platform/android/src/gson/json_array.cpp index b5fb85e5d9..8ffa658b76 100644 --- a/platform/android/src/gson/json_array.cpp +++ b/platform/android/src/gson/json_array.cpp @@ -5,25 +5,25 @@ namespace mbgl { namespace android { namespace gson { -jni::Object JsonArray::New(jni::JNIEnv& env, const std::vector& values){ - static auto javaClass = jni::Class::Singleton(env); +jni::Local> JsonArray::New(jni::JNIEnv& env, const std::vector& values){ + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); static auto addMethod = javaClass.GetMethod)>(env, "add"); auto jsonArray = javaClass.New(env, constructor); for (const auto &v : values) { - jsonArray.Call(env, addMethod, *jni::SeizeLocal(env, JsonElement::New(env, v))); + jsonArray.Call(env, addMethod, JsonElement::New(env, v)); } return jsonArray; } -std::vector JsonArray::convert(jni::JNIEnv& env, const jni::Object jsonArray) { +std::vector JsonArray::convert(jni::JNIEnv& env, const jni::Object& jsonArray) { std::vector values; if (jsonArray) { - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); static auto getMethod = javaClass.GetMethod (jni::jint)>(env, "get"); static auto sizeMethod = javaClass.GetMethod(env, "size"); @@ -31,9 +31,9 @@ std::vector JsonArray::convert(jni::JNIEnv& env, const jni::Object< values.reserve(uint(size)); for (int i = 0; i < size; i++) { - auto entry = jni::SeizeLocal(env, jsonArray.Call(env, getMethod, i)); - if (*entry) { - values.push_back(JsonElement::convert(env, *entry)); + auto entry = jsonArray.Call(env, getMethod, i); + if (entry) { + values.push_back(JsonElement::convert(env, entry)); } } } diff --git a/platform/android/src/gson/json_array.hpp b/platform/android/src/gson/json_array.hpp index b41596819f..24d5d3d291 100644 --- a/platform/android/src/gson/json_array.hpp +++ b/platform/android/src/gson/json_array.hpp @@ -8,12 +8,13 @@ namespace mbgl { namespace android { namespace gson { -class JsonArray : public JsonElement { +class JsonArray { public: + using SuperTag = JsonElement; static constexpr auto Name() { return "com/google/gson/JsonArray"; }; - static jni::Object New(jni::JNIEnv&, const std::vector&); - static std::vector convert(JNIEnv&, jni::Object); + static jni::Local> New(jni::JNIEnv&, const std::vector&); + static std::vector convert(JNIEnv&, const jni::Object&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/gson/json_element.cpp b/platform/android/src/gson/json_element.cpp index 28cb368386..7c9a34c03c 100644 --- a/platform/android/src/gson/json_element.cpp +++ b/platform/android/src/gson/json_element.cpp @@ -7,35 +7,30 @@ namespace mbgl { namespace android { namespace gson { -jni::Object JsonElement::New(jni::JNIEnv& env, const mbgl::Value& value) { - static auto primitive = jni::Class::Singleton(env); +jni::Local> JsonElement::New(jni::JNIEnv& env, const mbgl::Value& value) { + static auto& primitive = jni::Class::Singleton(env); static auto stringConstructor = primitive.GetConstructor(env); static auto numberConstructor = primitive.GetConstructor(env); static auto booleanConstructor = primitive.GetConstructor(env); return value.match( [&] (const mbgl::NullValue&) { - return jni::Object(); + return jni::Local>(); }, [&] (const std::string& value) { - return primitive.New(env, stringConstructor, - *jni::SeizeLocal(env, jni::Make(env, value))); + return primitive.New(env, stringConstructor, jni::Make(env, value)); }, [&] (const double value) { - return primitive.New(env, numberConstructor, - *jni::SeizeLocal(env, jni::Number(jni::Box(env, value)))); + return primitive.New(env, numberConstructor, jni::Box(env, value)); }, [&] (const int64_t value) { - return primitive.New(env, numberConstructor, - *jni::SeizeLocal(env, jni::Number(jni::Box(env, value)))); + return primitive.New(env, numberConstructor, jni::Box(env, value)); }, [&] (const uint64_t value) { - return primitive.New(env, numberConstructor, - *jni::SeizeLocal(env, jni::Number(jni::Box(env, int64_t(value))))); // TODO: should use BigInteger + return primitive.New(env, numberConstructor, jni::Box(env, int64_t(value))); // TODO: should use BigInteger }, [&] (const bool value) { - return primitive.New(env, booleanConstructor, - *jni::SeizeLocal(env, jni::Box(env, value ? jni::jni_true : jni::jni_false))); + return primitive.New(env, booleanConstructor, jni::Box(env, value ? jni::jni_true : jni::jni_false)); }, [&] (const std::vector& values) { return JsonArray::New(env, values); @@ -46,17 +41,17 @@ jni::Object JsonElement::New(jni::JNIEnv& env, const mbgl::Value& v ); } -mbgl::Value JsonElement::convert(jni::JNIEnv &env, jni::Object jsonElement) { +mbgl::Value JsonElement::convert(jni::JNIEnv &env, const jni::Object& jsonElement) { if (!jsonElement) { return mbgl::NullValue(); } - static auto elementClass = jni::Class::Singleton(env); + static auto& elementClass = jni::Class::Singleton(env); static auto isJsonObject = elementClass.GetMethod(env, "isJsonObject"); static auto isJsonArray = elementClass.GetMethod(env, "isJsonArray"); static auto isJsonPrimitive = elementClass.GetMethod(env, "isJsonPrimitive"); - static auto primitiveClass = jni::Class::Singleton(env); + static auto& primitiveClass = jni::Class::Singleton(env); static auto isBoolean = primitiveClass.GetMethod(env, "isBoolean"); static auto isString = primitiveClass.GetMethod(env, "isString"); static auto isNumber = primitiveClass.GetMethod(env, "isNumber"); @@ -71,7 +66,7 @@ mbgl::Value JsonElement::convert(jni::JNIEnv &env, jni::Object json } 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(env, *jni::SeizeLocal(env, primitive.Call(env, getAsString))); + return jni::Make(env, primitive.Call(env, getAsString)); } else { return mbgl::NullValue(); } diff --git a/platform/android/src/gson/json_element.hpp b/platform/android/src/gson/json_element.hpp index 384459dc41..e3b8a0268d 100644 --- a/platform/android/src/gson/json_element.hpp +++ b/platform/android/src/gson/json_element.hpp @@ -8,12 +8,13 @@ namespace mbgl { namespace android { namespace gson { -class JsonElement : public jni::ObjectTag { +class JsonElement { public: + using SuperTag = jni::ObjectTag; static constexpr auto Name() { return "com/google/gson/JsonElement"; }; - static jni::Object New(jni::JNIEnv&, const mbgl::Value&); - static mbgl::Value convert(JNIEnv&, jni::Object); + static jni::Local> New(jni::JNIEnv&, const mbgl::Value&); + static mbgl::Value convert(JNIEnv&, const jni::Object&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/gson/json_object.cpp b/platform/android/src/gson/json_object.cpp index 5dcb07642f..10d244ee48 100644 --- a/platform/android/src/gson/json_object.cpp +++ b/platform/android/src/gson/json_object.cpp @@ -9,48 +9,46 @@ namespace android { namespace gson { -jni::Object JsonObject::New(jni::JNIEnv& env, const mbgl::PropertyMap& values) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local> JsonObject::New(jni::JNIEnv& env, const mbgl::PropertyMap& values) { + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); static auto addMethod = javaClass.GetMethod)>(env, "add"); - jni::Object jsonObject = javaClass.New(env, constructor); + auto jsonObject = javaClass.New(env, constructor); for (auto &item : values) { jsonObject.Call(env, addMethod, - *jni::SeizeLocal(env, jni::Make(env, item.first)), - *jni::SeizeLocal(env, JsonElement::New(env, item.second))); + jni::Make(env, item.first), + JsonElement::New(env, item.second)); } return jsonObject; } template // void (jni::String, jni::Object) -static void iterateEntrySet(jni::JNIEnv& env, jni::Object jsonObject, F callback) { +static void iterateEntrySet(jni::JNIEnv& env, const jni::Object& jsonObject, F callback) { // Get Set> - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod ()>(env, "entrySet"); - auto entryArray = - jni::SeizeLocal(env, java::util::Set::toArray(env, - *jni::SeizeLocal(env, jsonObject.Call(env, method)))); + auto entryArray = java::util::Set::toArray(env, jsonObject.Call(env, method)); - size_t size = entryArray->Length(env); + size_t size = entryArray.Length(env); for (size_t i = 0; i < size; i++) { - auto entry = jni::SeizeLocal(env, entryArray->Get(env, i)); + auto entry = entryArray.Get(env, i); if (entry) { callback( - *jni::SeizeLocal(env, java::util::Map::Entry::getKey(env, *entry)), - *jni::SeizeLocal(env, java::util::Map::Entry::getValue(env, *entry))); + java::util::Map::Entry::getKey(env, entry), + java::util::Map::Entry::getValue(env, entry)); } } } -mbgl::PropertyMap JsonObject::convert(jni::JNIEnv &env, jni::Object jsonObject) { +mbgl::PropertyMap JsonObject::convert(jni::JNIEnv& env, const jni::Object& jsonObject) { mbgl::PropertyMap map; if (jsonObject) { - iterateEntrySet(env, jsonObject, [&map, &env](jni::String jId, jni::Object jsonElement) { + iterateEntrySet(env, jsonObject, [&map, &env](const jni::String& jId, const jni::Object& jsonElement) { map[jni::Make(env, jId)] = JsonElement::convert(env, jsonElement); }); } diff --git a/platform/android/src/gson/json_object.hpp b/platform/android/src/gson/json_object.hpp index 256161f0d9..b8916f8ae1 100644 --- a/platform/android/src/gson/json_object.hpp +++ b/platform/android/src/gson/json_object.hpp @@ -8,12 +8,13 @@ namespace mbgl { namespace android { namespace gson { -class JsonObject : public JsonElement { +class JsonObject { public: + using SuperTag = JsonElement; static constexpr auto Name() { return "com/google/gson/JsonObject"; }; - static jni::Object New(jni::JNIEnv&, const mbgl::PropertyMap&); - static mbgl::PropertyMap convert(JNIEnv&, jni::Object); + static jni::Local> New(jni::JNIEnv&, const mbgl::PropertyMap&); + static mbgl::PropertyMap convert(JNIEnv&, const jni::Object&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/gson/json_primitive.hpp b/platform/android/src/gson/json_primitive.hpp index fb3eefc855..36f138d902 100644 --- a/platform/android/src/gson/json_primitive.hpp +++ b/platform/android/src/gson/json_primitive.hpp @@ -8,8 +8,9 @@ namespace mbgl { namespace android { namespace gson { -class JsonPrimitive : public JsonElement { +class JsonPrimitive { public: + using SuperTag = JsonElement; static constexpr auto Name() { return "com/google/gson/JsonPrimitive"; }; static void registerNative(jni::JNIEnv&); diff --git a/platform/android/src/http_file_source.cpp b/platform/android/src/http_file_source.cpp index 6b359aab8c..e1b3493f0f 100644 --- a/platform/android/src/http_file_source.cpp +++ b/platform/android/src/http_file_source.cpp @@ -25,12 +25,12 @@ 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 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& body); jni::Global> javaRequest; @@ -54,7 +54,7 @@ private: namespace android { void RegisterNativeHTTPRequest(jni::JNIEnv& env) { - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) @@ -79,31 +79,32 @@ HTTPRequest::HTTPRequest(jni::JNIEnv& env, const Resource& resource_, FileSource jni::UniqueLocalFrame frame = jni::PushLocalFrame(env, 10); - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); - javaRequest = javaClass.New(env, constructor, - reinterpret_cast(this), - jni::Make(env, resource.url), - jni::Make(env, etagStr), - jni::Make(env, modifiedStr)).NewGlobalRef(env); + javaRequest = jni::NewGlobal(env, + javaClass.New(env, constructor, + reinterpret_cast(this), + jni::Make(env, resource.url), + jni::Make(env, etagStr), + jni::Make(env, modifiedStr))); } HTTPRequest::~HTTPRequest() { android::UniqueEnv env = android::AttachEnv(); - static auto javaClass = jni::Class::Singleton(*env); + static auto& javaClass = jni::Class::Singleton(*env); static auto cancel = javaClass.GetMethod(*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 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& body) { using Error = Response::Error; @@ -158,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(env, message); using Error = Response::Error; diff --git a/platform/android/src/image.cpp b/platform/android/src/image.cpp index a85e9aeaa2..31515ff16f 100644 --- a/platform/android/src/image.cpp +++ b/platform/android/src/image.cpp @@ -11,12 +11,11 @@ namespace mbgl { PremultipliedImage decodeImage(const std::string& string) { auto env{ android::AttachEnv() }; - auto array = jni::SeizeLocal(*env, jni::Array::New(*env, string.size())); - jni::SetArrayRegion(*env, **array, 0, string.size(), + auto array = jni::Array::New(*env, string.size()); + jni::SetArrayRegion(*env, *array, 0, string.size(), reinterpret_cast(string.data())); - return android::Bitmap::GetImage(*env, - *jni::SeizeLocal(*env, android::BitmapFactory::DecodeByteArray(*env, *array, 0, string.size()))); + return android::Bitmap::GetImage(*env, android::BitmapFactory::DecodeByteArray(*env, array, 0, string.size())); } } // namespace mbgl diff --git a/platform/android/src/java/util.hpp b/platform/android/src/java/util.hpp index 808f14be15..9b0c01459e 100644 --- a/platform/android/src/java/util.hpp +++ b/platform/android/src/java/util.hpp @@ -14,10 +14,11 @@ public: static constexpr auto Name() { return "java/util/List"; }; template - static jni::Array> toArray(jni::JNIEnv& env, jni::Object list) { - static auto javaClass = jni::Class::Singleton(env); + static jni::Local>> toArray(jni::JNIEnv& env, const jni::Object& list) { + static auto& javaClass = jni::Class::Singleton(env); static auto toArray = javaClass.GetMethod> ()>(env, "toArray"); - return (jni::Array>) list.Call(env, toArray); + + return jni::Local>>(env, list.Call(env, toArray).release()); }; }; @@ -26,10 +27,12 @@ public: static constexpr auto Name() { return "java/util/Arrays"; }; template - static jni::Object asList(jni::JNIEnv& env, jni::Array> array) { - static auto javaClass = jni::Class::Singleton(env); + static jni::Local> asList(jni::JNIEnv& env, const jni::Array>& array) { + static auto& javaClass = jni::Class::Singleton(env); static auto asList = javaClass.GetStaticMethod(jni::Array>)>(env, "asList"); - return javaClass.Call(env, asList, (jni::Array>) array); + + auto typeErasedArray = jni::Local>>(env, jni::NewLocal(env, array).release()); + return javaClass.Call(env, asList, typeErasedArray); } }; @@ -38,10 +41,11 @@ public: static constexpr auto Name() { return "java/util/Set"; }; template - static jni::Array> toArray(jni::JNIEnv& env, jni::Object list) { - static auto javaClass = jni::Class::Singleton(env); + static jni::Local>> toArray(jni::JNIEnv& env, const jni::Object& list) { + static auto& javaClass = jni::Class::Singleton(env); static auto toArray = javaClass.GetMethod> ()>(env, "toArray"); - return (jni::Array>) list.Call(env, toArray); + + return jni::Local>>(env, list.Call(env, toArray).release()); }; }; @@ -54,15 +58,15 @@ public: static constexpr auto Name() { return "java/util/Map$Entry"; }; template - static jni::Object getKey(jni::JNIEnv& env, jni::Object entry) { - static auto javaClass = jni::Class::Singleton(env); + static jni::Local> getKey(jni::JNIEnv& env, const jni::Object& entry) { + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod ()>(env, "getKey"); return jni::Cast(env, jni::Class::Singleton(env), entry.Call(env, method)); } template - static jni::Object getValue(jni::JNIEnv& env, jni::Object entry) { - static auto javaClass = jni::Class::Singleton(env); + static jni::Local> getValue(jni::JNIEnv& env, const jni::Object& entry) { + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod ()>(env, "getValue"); return jni::Cast(env, jni::Class::Singleton(env), entry.Call(env, method)); } 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 b865ee9f8b..0000000000 --- a/platform/android/src/jni/generic_global_ref_deleter.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#include - -#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) { - AttachEnv()->DeleteGlobalRef(jni::Unwrap(p)); - } - } -}; - -struct GenericWeakGlobalRefDeleter { - void operator()(jni::jobject* p) const { - if (p) { - AttachEnv()->DeleteWeakGlobalRef(jni::Unwrap(p)); - } - } -}; - -template < class T > -using GenericGlobal = jni::UniquePointerlike< T, GenericGlobalRefDeleter >; - -template < class T > -using GenericWeak = jni::UniquePointerlike< T, GenericWeakGlobalRefDeleter >; - -template < class T > -GenericGlobal SeizeGenericGlobal(T&& t) { - return GenericGlobal(std::move(t), GenericGlobalRefDeleter()); -}; - -template < class T > -GenericWeak SeizeGenericWeak(T&& t) { - return GenericWeak(std::move(t), GenericWeakGlobalRefDeleter()); -}; - -} // namespace android -} // namespace mbgl diff --git a/platform/android/src/logger.cpp b/platform/android/src/logger.cpp index ddc4d84525..f5d78cc83c 100644 --- a/platform/android/src/logger.cpp +++ b/platform/android/src/logger.cpp @@ -9,24 +9,24 @@ void Logger::registerNative(jni::JNIEnv& env) { } void Logger::log(jni::JNIEnv& env, EventSeverity severity, const std::string &msg) { - static auto _class = jni::Class::Singleton(env); + static auto& _class = jni::Class::Singleton(env); - auto tag = jni::SeizeLocal(env, jni::Make(env, "Mbgl")); - auto message = jni::SeizeLocal(env, jni::Make(env, msg)); + auto tag = jni::Make(env, "Mbgl"); + auto message = jni::Make(env, msg); using Signature = void(jni::String, jni::String); if (severity == EventSeverity::Debug) { auto static debug = _class.GetStaticMethod(env, "d"); - _class.Call(env, debug, *tag, *message); + _class.Call(env, debug, tag, message); } else if (severity == EventSeverity::Info) { auto static info = _class.GetStaticMethod(env, "i"); - _class.Call(env, info, *tag, *message); + _class.Call(env, info, tag, message); } else if(severity == EventSeverity::Warning) { auto static warning = _class.GetStaticMethod(env, "w"); - _class.Call(env, warning, *tag, *message); + _class.Call(env, warning, tag, message); } else { auto static error = _class.GetStaticMethod(env, "e"); - _class.Call(env, error, *tag, *message); + _class.Call(env, error, tag, message); } } diff --git a/platform/android/src/map/camera_position.cpp b/platform/android/src/map/camera_position.cpp index 5700341d65..3caf4ea2f3 100644 --- a/platform/android/src/map/camera_position.cpp +++ b/platform/android/src/map/camera_position.cpp @@ -4,8 +4,8 @@ namespace mbgl { namespace android { -jni::Object CameraPosition::New(jni::JNIEnv &env, mbgl::CameraOptions options) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local> CameraPosition::New(jni::JNIEnv &env, mbgl::CameraOptions options) { + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor, double, double, double>(env); // wrap LatLng values coming from core @@ -28,14 +28,14 @@ jni::Object CameraPosition::New(jni::JNIEnv &env, mbgl::CameraOp 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 position) { - static auto javaClass = jni::Class::Singleton(env); +mbgl::CameraOptions CameraPosition::getCameraOptions(jni::JNIEnv& env, const jni::Object& position) { + static auto& javaClass = jni::Class::Singleton(env); static auto bearing = javaClass.GetField(env, "bearing"); static auto target = javaClass.GetField>(env, "target"); static auto tilt = javaClass.GetField(env, "tilt"); static auto zoom = javaClass.GetField(env, "zoom"); - auto center = LatLng::getLatLng(env, *jni::SeizeLocal(env, position.Get(env, target))); + auto center = LatLng::getLatLng(env, position.Get(env, target)); return mbgl::CameraOptions { center, diff --git a/platform/android/src/map/camera_position.hpp b/platform/android/src/map/camera_position.hpp index d577811915..7579f9fed1 100644 --- a/platform/android/src/map/camera_position.hpp +++ b/platform/android/src/map/camera_position.hpp @@ -12,9 +12,9 @@ class CameraPosition : private mbgl::util::noncopyable { public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/camera/CameraPosition"; }; - static jni::Object New(jni::JNIEnv&, mbgl::CameraOptions); + static jni::Local> New(jni::JNIEnv&, mbgl::CameraOptions); - static mbgl::CameraOptions getCameraOptions(jni::JNIEnv&, jni::Object); + static mbgl::CameraOptions getCameraOptions(jni::JNIEnv&, const jni::Object&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/map/image.cpp b/platform/android/src/map/image.cpp index ee3c7012a7..a91cc938ed 100644 --- a/platform/android/src/map/image.cpp +++ b/platform/android/src/map/image.cpp @@ -5,8 +5,8 @@ namespace mbgl { namespace android { -mbgl::style::Image Image::getImage(jni::JNIEnv& env, jni::Object image) { - static auto javaClass = jni::Class::Singleton(env); +mbgl::style::Image Image::getImage(jni::JNIEnv& env, const jni::Object& image) { + static auto& javaClass = jni::Class::Singleton(env); static auto widthField = javaClass.GetField(env, "width"); static auto heightField = javaClass.GetField(env, "height"); static auto pixelRatioField = javaClass.GetField(env, "pixelRatio"); @@ -17,19 +17,19 @@ mbgl::style::Image Image::getImage(jni::JNIEnv& env, jni::Object image) { auto height = image.Get(env, heightField); auto width = image.Get(env, widthField); auto pixelRatio = image.Get(env, pixelRatioField); - auto pixels = jni::SeizeLocal(env, image.Get(env, bufferField)); - auto name = jni::Make(env, *jni::SeizeLocal(env, image.Get(env, nameField))); + auto pixels = image.Get(env, bufferField); + auto name = jni::Make(env, image.Get(env, nameField)); auto sdf = (bool) image.Get(env, sdfField); - jni::NullCheck(env, pixels->Get()); - std::size_t size = pixels->Length(env); + jni::NullCheck(env, pixels.get()); + std::size_t size = pixels.Length(env); mbgl::PremultipliedImage premultipliedImage({ static_cast(width), static_cast(height) }); if (premultipliedImage.bytes() != uint32_t(size)) { throw mbgl::util::SpriteImageException("Sprite image pixel count mismatch"); } - jni::GetArrayRegion(env, **pixels, 0, size, reinterpret_cast(premultipliedImage.data.get())); + jni::GetArrayRegion(env, *pixels, 0, size, reinterpret_cast(premultipliedImage.data.get())); return mbgl::style::Image {name, std::move(premultipliedImage), pixelRatio, sdf}; } diff --git a/platform/android/src/map/image.hpp b/platform/android/src/map/image.hpp index 17ed4cbef8..7549bc646a 100644 --- a/platform/android/src/map/image.hpp +++ b/platform/android/src/map/image.hpp @@ -12,7 +12,7 @@ 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); + static mbgl::style::Image getImage(jni::JNIEnv&, const jni::Object&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/map_renderer.cpp b/platform/android/src/map_renderer.cpp index 1f8c82ac05..13790c4544 100644 --- a/platform/android/src/map_renderer.cpp +++ b/platform/android/src/map_renderer.cpp @@ -14,15 +14,17 @@ namespace mbgl { namespace android { -MapRenderer::MapRenderer(jni::JNIEnv& _env, jni::Object obj, - jni::Object _fileSource, jni::jfloat pixelRatio_, - jni::String programCacheDir_, - jni::String localIdeographFontFamily_) - : javaPeer(SeizeGenericWeak(obj.NewWeakGlobalRef(_env).release())) +MapRenderer::MapRenderer(jni::JNIEnv& _env, + const jni::Object& obj, + const jni::Object& _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(_env, programCacheDir_)) - , localIdeographFontFamily(localIdeographFontFamily_ == nullptr ? optional{} : jni::Make(_env, localIdeographFontFamily_ )) + , localIdeographFontFamily(localIdeographFontFamily_ ? jni::Make(_env, localIdeographFontFamily_) : optional{}) , threadPool(sharedThreadPool()) , mailbox(std::make_shared(*this)) { } @@ -53,10 +55,10 @@ void MapRenderer::schedule(std::weak_ptr scheduled) { auto peer = runnable->peer(); // Queue the event on the Java Peer - static auto javaClass = jni::Class::Singleton(*_env); + static auto& javaClass = jni::Class::Singleton(*_env); static auto queueEvent = javaClass.GetMethod)>(*_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(); @@ -64,9 +66,9 @@ void MapRenderer::schedule(std::weak_ptr scheduled) { void MapRenderer::requestRender() { android::UniqueEnv _env = android::AttachEnv(); - static auto javaClass = jni::Class::Singleton(*_env); + static auto& javaClass = jni::Class::Singleton(*_env); static auto onInvalidate = javaClass.GetMethod(*_env, "requestRender"); - javaPeer->Call(*_env, onInvalidate); + javaPeer.get(*_env).Call(*_env, onInvalidate); } void MapRenderer::update(std::shared_ptr params) { @@ -184,13 +186,13 @@ void MapRenderer::onSurfaceChanged(JNIEnv&, jint width, jint height) { void MapRenderer::registerNative(jni::JNIEnv& env) { // Lookup the class - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer(env, javaClass, "nativePtr", - std::make_unique, jni::Object, jni::jfloat, jni::String, jni::String>, + jni::MakePeer&, const jni::Object&, jni::jfloat, const jni::String&, const jni::String&>, "nativeInitialize", "finalize", METHOD(&MapRenderer::render, "nativeRender"), METHOD(&MapRenderer::onSurfaceCreated, @@ -199,8 +201,8 @@ void MapRenderer::registerNative(jni::JNIEnv& env) { "nativeOnSurfaceChanged")); } -MapRenderer& MapRenderer::getNativePeer(JNIEnv& env, jni::Object jObject) { - static auto javaClass = jni::Class::Singleton(env); +MapRenderer& MapRenderer::getNativePeer(JNIEnv& env, const jni::Object& jObject) { + static auto& javaClass = jni::Class::Singleton(env); static auto field = javaClass.GetField(env, "nativePtr"); MapRenderer* mapRenderer = reinterpret_cast(jObject.Get(env, field)); assert(mapRenderer != nullptr); diff --git a/platform/android/src/map_renderer.hpp b/platform/android/src/map_renderer.hpp index 6fcf2fee71..d60447e0ec 100644 --- a/platform/android/src/map_renderer.hpp +++ b/platform/android/src/map_renderer.hpp @@ -9,8 +9,6 @@ #include #include -#include "jni/generic_global_ref_deleter.hpp" - namespace mbgl { template @@ -40,14 +38,14 @@ public: static void registerNative(jni::JNIEnv&); - static MapRenderer& getNativePeer(JNIEnv&, jni::Object); + static MapRenderer& getNativePeer(JNIEnv&, const jni::Object&); MapRenderer(jni::JNIEnv& _env, - jni::Object, - jni::Object, + const jni::Object&, + const jni::Object&, jni::jfloat pixelRatio, - jni::String programCacheDir, - jni::String localIdeographFontFamily); + const jni::String& programCacheDir, + const jni::String& localIdeographFontFamily); ~MapRenderer() override; @@ -97,7 +95,7 @@ private: void onSurfaceChanged(JNIEnv&, jint width, jint height); private: - GenericWeak> javaPeer; + jni::WeakReference, 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 1bfccebd2d..77c3aa301d 100644 --- a/platform/android/src/map_renderer_runnable.cpp +++ b/platform/android/src/map_renderer_runnable.cpp @@ -12,10 +12,10 @@ MapRendererRunnable::MapRendererRunnable(jni::JNIEnv& env, std::weak_ptr::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); auto instance = javaClass.New(env, constructor, reinterpret_cast(this)); - javaPeer = instance.NewGlobalRef(env); + javaPeer = jni::NewGlobal(env, instance); } MapRendererRunnable::~MapRendererRunnable() = default; @@ -32,7 +32,7 @@ jni::Global> MapRendererRunnable::peer() { void MapRendererRunnable::registerNative(jni::JNIEnv& env) { // Lookup the class - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp index d396e00b47..25605e09e4 100755 --- a/platform/android/src/native_map_view.cpp +++ b/platform/android/src/native_map_view.cpp @@ -57,11 +57,11 @@ namespace mbgl { namespace android { NativeMapView::NativeMapView(jni::JNIEnv& _env, - jni::Object _obj, - jni::Object jFileSource, - jni::Object jMapRenderer, + const jni::Object& _obj, + const jni::Object& jFileSource, + const jni::Object& jMapRenderer, jni::jfloat _pixelRatio) - : javaPeer(_obj.NewWeakGlobalRef(_env)) + : javaPeer(_env, _obj) , mapRenderer(MapRenderer::getNativePeer(_env, jMapRenderer)) , pixelRatio(_pixelRatio) , threadPool(sharedThreadPool()) { @@ -103,9 +103,9 @@ void NativeMapView::notifyMapChange(mbgl::MapChange change) { assert(vm != nullptr); android::UniqueEnv _env = android::AttachEnv(); - static auto javaClass = jni::Class::Singleton(*_env); + static auto& javaClass = jni::Class::Singleton(*_env); static auto onMapChanged = javaClass.GetMethod(*_env, "onMapChanged"); - javaPeer->Call(*_env, onMapChanged, (int) change); + javaPeer.get(*_env).Call(*_env, onMapChanged, (int) change); } void NativeMapView::onCameraWillChange(MapObserver::CameraChangeMode mode) { @@ -180,23 +180,23 @@ void NativeMapView::resizeView(jni::JNIEnv&, int w, int h) { map->setSize({ static_cast(width), static_cast(height) }); } -jni::String NativeMapView::getStyleUrl(jni::JNIEnv& env) { +jni::Local NativeMapView::getStyleUrl(jni::JNIEnv& env) { return jni::Make(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(env, url)); } -jni::String NativeMapView::getStyleJson(jni::JNIEnv& env) { +jni::Local NativeMapView::getStyleJson(jni::JNIEnv& env) { return jni::Make(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(env, json)); } -void NativeMapView::setLatLngBounds(jni::JNIEnv& env, jni::Object jBounds) { +void NativeMapView::setLatLngBounds(jni::JNIEnv& env, const jni::Object& jBounds) { if (jBounds) { map->setLatLngBounds(mbgl::android::LatLngBounds::getLatLngBounds(env, jBounds)); } else { @@ -281,7 +281,7 @@ void NativeMapView::flyTo(jni::JNIEnv&, jni::jdouble angle, jni::jdouble latitud map->flyTo(cameraOptions, animationOptions); } -jni::Object NativeMapView::getLatLng(JNIEnv& env) { +jni::Local> NativeMapView::getLatLng(JNIEnv& env) { return LatLng::New(env, map->getLatLng(insets)); } @@ -289,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 NativeMapView::getCameraForLatLngBounds(jni::JNIEnv& env, jni::Object jBounds, double top, double left, double bottom, double right, double bearing, double tilt) { +jni::Local> NativeMapView::getCameraForLatLngBounds(jni::JNIEnv& env, const jni::Object& 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 NativeMapView::getCameraForGeometry(jni::JNIEnv& env, jni::Object jGeometry, double top, double left, double bottom, double right, double bearing, double tilt) { +jni::Local> NativeMapView::getCameraForGeometry(jni::JNIEnv& env, const jni::Object& 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)); @@ -369,7 +369,7 @@ void NativeMapView::resetNorth(jni::JNIEnv&) { map->resetNorth(); } -void NativeMapView::setVisibleCoordinateBounds(JNIEnv& env, jni::Array> coordinates, jni::Object padding, jdouble direction, jni::jlong duration) { +void NativeMapView::setVisibleCoordinateBounds(JNIEnv& env, const jni::Array>& coordinates, const jni::Object& padding, jdouble direction, jni::jlong duration) { NullCheck(env, &coordinates); std::size_t count = coordinates.Length(env); @@ -377,7 +377,7 @@ void NativeMapView::setVisibleCoordinateBounds(JNIEnv& env, jni::Array::Singleton(*_env); + static auto& javaClass = jni::Class::Singleton(*_env); static auto onSnapshotReady = javaClass.GetMethod)>(*_env, "onSnapshotReady"); - javaPeer->Call(*_env, onSnapshotReady, bitmap); + javaPeer.get(*_env).Call(*_env, onSnapshotReady, bitmap); }); } -jni::Object NativeMapView::getCameraPosition(jni::JNIEnv& env) { +jni::Local> 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(lon, lat), iconId }); } -jni::Array NativeMapView::addMarkers(jni::JNIEnv& env, jni::Array> jmarkers) { +jni::Local> NativeMapView::addMarkers(jni::JNIEnv& env, const jni::Array>& jmarkers) { jni::NullCheck(env, &jmarkers); std::size_t len = jmarkers.Length(env); @@ -436,10 +436,10 @@ jni::Array NativeMapView::addMarkers(jni::JNIEnv& env, jni::ArrayaddAnnotation(mbgl::SymbolAnnotation { - Marker::getPosition(env, *marker), - Marker::getIconId(env, *marker) + Marker::getPosition(env, marker), + Marker::getIconId(env, marker) })); } @@ -477,25 +477,25 @@ jni::jdouble NativeMapView::getMetersPerPixelAtLatitude(JNIEnv&, jni::jdouble la return mbgl::Projection::getMetersPerPixelAtLatitude(lat, zoom); } -jni::Object NativeMapView::projectedMetersForLatLng(JNIEnv& env, jni::jdouble latitude, jni::jdouble longitude) { +jni::Local> 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 NativeMapView::latLngForProjectedMeters(JNIEnv& env, jdouble northing, jdouble easting) { +jni::Local> NativeMapView::latLngForProjectedMeters(JNIEnv& env, jdouble northing, jdouble easting) { return LatLng::New(env, mbgl::Projection::latLngForProjectedMeters(mbgl::ProjectedMeters(northing, easting))); } -jni::Object NativeMapView::pixelForLatLng(JNIEnv& env, jdouble latitude, jdouble longitude) { +jni::Local> NativeMapView::pixelForLatLng(JNIEnv& env, jdouble latitude, jdouble longitude) { mbgl::ScreenCoordinate pixel = map->pixelForLatLng(mbgl::LatLng(latitude, longitude)); return PointF::New(env, static_cast(pixel.x), static_cast(pixel.y)); } -jni::Object NativeMapView::latLngForPixel(JNIEnv& env, jfloat x, jfloat y) { +jni::Local> NativeMapView::latLngForPixel(JNIEnv& env, jfloat x, jfloat y) { return LatLng::New(env, map->latLngForPixel(mbgl::ScreenCoordinate(x, y))); } -jni::Array NativeMapView::addPolylines(JNIEnv& env, jni::Array> polylines) { +jni::Local> NativeMapView::addPolylines(JNIEnv& env, const jni::Array>& polylines) { NullCheck(env, &polylines); std::size_t len = polylines.Length(env); @@ -503,7 +503,7 @@ jni::Array NativeMapView::addPolylines(JNIEnv& env, jni::ArrayaddAnnotation(annotation)); } @@ -514,7 +514,7 @@ jni::Array NativeMapView::addPolylines(JNIEnv& env, jni::Array NativeMapView::addPolygons(JNIEnv& env, jni::Array> polygons) { +jni::Local> NativeMapView::addPolygons(JNIEnv& env, const jni::Array>& polygons) { NullCheck(env, &polygons); std::size_t len = polygons.Length(env); @@ -522,7 +522,7 @@ jni::Array NativeMapView::addPolygons(JNIEnv& env, jni::ArrayaddAnnotation(annotation)); } @@ -533,18 +533,18 @@ jni::Array NativeMapView::addPolygons(JNIEnv& env, jni::Array polyline) { +void NativeMapView::updatePolyline(JNIEnv& env, jlong polylineId, const jni::Object& 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) { +void NativeMapView::updatePolygon(JNIEnv& env, jlong polygonId, const jni::Object& polygon) { mbgl::FillAnnotation annotation = Polygon::toAnnotation(env, polygon); map->updateAnnotation(polygonId, annotation); } -void NativeMapView::removeAnnotations(JNIEnv& env, jni::Array ids) { +void NativeMapView::removeAnnotations(JNIEnv& env, const jni::Array& ids) { NullCheck(env, &ids); std::size_t len = ids.Length(env); auto elements = jni::GetArrayElements(env, *ids); @@ -558,7 +558,7 @@ void NativeMapView::removeAnnotations(JNIEnv& env, jni::Array ids) { } } -void NativeMapView::addAnnotationIcon(JNIEnv& env, jni::String symbol, jint w, jint h, jfloat scale, jni::Array jpixels) { +void NativeMapView::addAnnotationIcon(JNIEnv& env, const jni::String& symbol, jint w, jint h, jfloat scale, const jni::Array& jpixels) { const std::string symbolName = jni::Make(env, symbol); NullCheck(env, &jpixels); @@ -574,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(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(env, symbolName)); } @@ -605,7 +605,7 @@ void NativeMapView::setTransitionDelay(JNIEnv&, jlong delay) { map->getStyle().setTransitionOptions(transitionOptions); } -jni::Array NativeMapView::queryPointAnnotations(JNIEnv& env, jni::Object rect) { +jni::Local> NativeMapView::queryPointAnnotations(JNIEnv& env, const jni::Object& rect) { using namespace mbgl::style; using namespace mbgl::style::conversion; @@ -626,7 +626,7 @@ jni::Array NativeMapView::queryPointAnnotations(JNIEnv& env, jni::Object< return result; } -jni::Array NativeMapView::queryShapeAnnotations(JNIEnv &env, jni::Object rect) { +jni::Local> NativeMapView::queryShapeAnnotations(JNIEnv& env, const jni::Object& rect) { using namespace mbgl::style; using namespace mbgl::style::conversion; @@ -646,31 +646,31 @@ jni::Array NativeMapView::queryShapeAnnotations(JNIEnv &env, jni::Object< return result; } -jni::Array> NativeMapView::queryRenderedFeaturesForPoint(JNIEnv& env, jni::jfloat x, jni::jfloat y, - jni::Array layerIds, - jni::Array> jfilter) { +jni::Local>> NativeMapView::queryRenderedFeaturesForPoint(JNIEnv& env, jni::jfloat x, jni::jfloat y, + const jni::Array& layerIds, + const jni::Array>& jfilter) { using namespace mbgl::android::conversion; using namespace mbgl::android::geojson; mbgl::optional> layers; - if (layerIds != nullptr && layerIds.Length(env) > 0) { + if (layerIds && layerIds.Length(env) > 0) { layers = android::conversion::toVector(env, layerIds); } mapbox::geometry::point point = {x, y}; return Feature::convert( env, - rendererFrontend->queryRenderedFeatures(point, { layers, toFilter(env, jni::SeizeLocal(env, std::move(jfilter))) })); + rendererFrontend->queryRenderedFeatures(point, { layers, toFilter(env, jfilter) })); } -jni::Array> NativeMapView::queryRenderedFeaturesForBox(JNIEnv& env, jni::jfloat left, jni::jfloat top, - jni::jfloat right, jni::jfloat bottom, jni::Array layerIds, - jni::Array> jfilter) { +jni::Local>> NativeMapView::queryRenderedFeaturesForBox(JNIEnv& env, jni::jfloat left, jni::jfloat top, + jni::jfloat right, jni::jfloat bottom, const jni::Array& layerIds, + const jni::Array>& jfilter) { using namespace mbgl::android::conversion; using namespace mbgl::android::geojson; mbgl::optional> layers; - if (layerIds != nullptr && layerIds.Length(env) > 0) { + if (layerIds && layerIds.Length(env) > 0) { layers = toVector(env, layerIds); } mapbox::geometry::box box = { @@ -680,48 +680,48 @@ jni::Array> NativeMapView::queryRenderedFeaturesFo return Feature::convert( env, - rendererFrontend->queryRenderedFeatures(box, { layers, toFilter(env, jni::SeizeLocal(env, std::move(jfilter))) })); + rendererFrontend->queryRenderedFeatures(box, { layers, toFilter(env, jfilter) })); } -jni::Object NativeMapView::getLight(JNIEnv& env) { +jni::Local> NativeMapView::getLight(JNIEnv& env) { mbgl::style::Light* light = map->getStyle().getLight(); if (light) { - return jni::Object(Light::createJavaLightPeer(env, *map, *light)); + return Light::createJavaLightPeer(env, *map, *light); } else { - return jni::Object(); + return jni::Local>(); } } -jni::Array> NativeMapView::getLayers(JNIEnv& env) { +jni::Local>> NativeMapView::getLayers(JNIEnv& env) { // Get the core layers std::vector layers = map->getStyle().getLayers(); // Convert - jni::Array> jLayers = jni::Array>::New(env, layers.size()); + auto jLayers = jni::Array>::New(env, layers.size()); int index = 0; for (auto layer : layers) { - jLayers.Set(env, index, *jni::SeizeLocal(env, jni::Object(createJavaLayerPeer(env, *map, *layer)))); + jLayers.Set(env, index, createJavaLayerPeer(env, *map, *layer)); index++; } return jLayers; } -jni::Object NativeMapView::getLayer(JNIEnv& env, jni::String layerId) { +jni::Local> NativeMapView::getLayer(JNIEnv& env, const jni::String& layerId) { // Find the layer mbgl::style::Layer* coreLayer = map->getStyle().getLayer(jni::Make(env, layerId)); if (!coreLayer) { mbgl::Log::Debug(mbgl::Event::JNI, "No layer found"); - return jni::Object(); + return jni::Local>(); } // Create and return the layer's native peer - return jni::Object(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(nativeLayerPtr); @@ -732,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(nativeLayerPtr); @@ -795,33 +795,33 @@ void NativeMapView::addLayerAt(JNIEnv& env, jlong nativeLayerPtr, jni::jint inde /** * Remove by layer id. */ -jni::Object NativeMapView::removeLayerById(JNIEnv& env, jni::String id) { +jni::Local> NativeMapView::removeLayerById(JNIEnv& env, const jni::String& id) { std::unique_ptr coreLayer = map->getStyle().removeLayer(jni::Make(env, id)); if (coreLayer) { - return jni::Object(createJavaLayerPeer(env, *map, std::move(coreLayer))); + return createJavaLayerPeer(env, *map, std::move(coreLayer)); } else { - return jni::Object(); + return jni::Local>(); } } /** * Remove layer at index. */ -jni::Object NativeMapView::removeLayerAt(JNIEnv& env, jni::jint index) { +jni::Local> 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(); + return jni::Local>(); } std::unique_ptr coreLayer = map->getStyle().removeLayer(layers.at(index)->getID()); if (coreLayer) { - return jni::Object(createJavaLayerPeer(env, *map, std::move(coreLayer))); + return createJavaLayerPeer(env, *map, std::move(coreLayer)); } else { - return jni::Object(); + return jni::Local>(); } } @@ -838,12 +838,12 @@ void NativeMapView::removeLayer(JNIEnv&, jlong layerPtr) { } } -jni::Array> NativeMapView::getSources(JNIEnv& env) { +jni::Local>> NativeMapView::getSources(JNIEnv& env) { // Get the core sources std::vector sources = map->getStyle().getSources(); // Convert - jni::Array> jSources = jni::Array>::New(env, sources.size()); + auto jSources = jni::Array>::New(env, sources.size()); int index = 0; for (auto source : sources) { jSources.Set(env, index, Source::peerForCoreSource(env, *source, *rendererFrontend)); @@ -853,19 +853,19 @@ jni::Array> NativeMapView::getSources(JNIEnv& env) { return jSources; } -jni::Object NativeMapView::getSource(JNIEnv& env, jni::String sourceId) { +jni::Local> NativeMapView::getSource(JNIEnv& env, const jni::String& sourceId) { // Find the source mbgl::style::Source* coreSource = map->getStyle().getSource(jni::Make(env, sourceId)); if (!coreSource) { mbgl::Log::Debug(mbgl::Event::JNI, "No source found"); - return jni::Object(); + return jni::Local>(); } // 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 obj, jlong sourcePtr) { +void NativeMapView::addSource(JNIEnv& env, const jni::Object& obj, jlong sourcePtr) { assert(sourcePtr != 0); Source *source = reinterpret_cast(sourcePtr); @@ -876,7 +876,7 @@ void NativeMapView::addSource(JNIEnv& env, jni::Object obj, jlong source } } -void NativeMapView::removeSource(JNIEnv& env, jni::Object obj, jlong sourcePtr) { +void NativeMapView::removeSource(JNIEnv& env, const jni::Object& obj, jlong sourcePtr) { assert(sourcePtr != 0); mbgl::android::Source *source = reinterpret_cast(sourcePtr); @@ -885,7 +885,7 @@ void NativeMapView::removeSource(JNIEnv& env, jni::Object obj, jlong sou } } -void NativeMapView::addImage(JNIEnv& env, jni::String name, jni::Object bitmap, jni::jfloat scale, jni::jboolean sdf) { +void NativeMapView::addImage(JNIEnv& env, const jni::String& name, const jni::Object& bitmap, jni::jfloat scale, jni::jboolean sdf) { jni::NullCheck(env, &bitmap); mbgl::PremultipliedImage premultipliedImage = Bitmap::GetImage(env, bitmap); @@ -897,26 +897,26 @@ void NativeMapView::addImage(JNIEnv& env, jni::String name, jni::Object ); } -void NativeMapView::addImages(JNIEnv& env, jni::Array> jimages) { +void NativeMapView::addImages(JNIEnv& env, const jni::Array>& jimages) { jni::NullCheck(env, &jimages); std::size_t len = jimages.Length(env); for (std::size_t i = 0; i < len; i++) { - auto image = mbgl::android::Image::getImage(env, *jni::SeizeLocal(env, jimages.Get(env, i))); + auto image = mbgl::android::Image::getImage(env, jimages.Get(env, i)); map->getStyle().addImage(std::make_unique(image)); } } -void NativeMapView::removeImage(JNIEnv& env, jni::String name) { +void NativeMapView::removeImage(JNIEnv& env, const jni::String& name) { map->getStyle().removeImage(jni::Make(env, name)); } -jni::Object NativeMapView::getImage(JNIEnv& env, jni::String name) { +jni::Local> NativeMapView::getImage(JNIEnv& env, const jni::String& name) { const mbgl::style::Image *image = map->getStyle().getImage(jni::Make(env, name)); if (image) { return Bitmap::CreateBitmap(env, image->getImage()); } else { - return jni::Object(); + return jni::Local>(); } } @@ -936,13 +936,13 @@ mbgl::Map& NativeMapView::getMap() { void NativeMapView::registerNative(jni::JNIEnv& env) { // Lookup the class - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer(env, javaClass, "nativePtr", - std::make_unique, jni::Object, jni::Object, jni::jfloat>, + jni::MakePeer&, const jni::Object&, const jni::Object&, 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 d398b39bf7..969833a25b 100755 --- a/platform/android/src/native_map_view.hpp +++ b/platform/android/src/native_map_view.hpp @@ -48,9 +48,9 @@ public: static void registerNative(jni::JNIEnv&); NativeMapView(jni::JNIEnv&, - jni::Object, - jni::Object, - jni::Object, + const jni::Object&, + const jni::Object&, + const jni::Object&, jni::jfloat pixelRatio); virtual ~NativeMapView(); @@ -76,15 +76,15 @@ public: void resizeView(jni::JNIEnv&, int, int); - jni::String getStyleUrl(jni::JNIEnv&); + jni::Local getStyleUrl(jni::JNIEnv&); - void setStyleUrl(jni::JNIEnv&, jni::String); + void setStyleUrl(jni::JNIEnv&, const jni::String&); - jni::String getStyleJson(jni::JNIEnv&); + jni::Local getStyleJson(jni::JNIEnv&); - void setStyleJson(jni::JNIEnv&, jni::String); + void setStyleJson(jni::JNIEnv&, const jni::String&); - void setLatLngBounds(jni::JNIEnv&, jni::Object); + void setLatLngBounds(jni::JNIEnv&, const jni::Object&); void cancelTransitions(jni::JNIEnv&); @@ -98,13 +98,13 @@ public: void flyTo(jni::JNIEnv&, jni::jdouble, jni::jdouble, jni::jdouble, jni::jlong, jni::jdouble, jni::jdouble); - jni::Object getLatLng(JNIEnv&); + jni::Local> getLatLng(JNIEnv&); void setLatLng(jni::JNIEnv&, jni::jdouble, jni::jdouble, jni::jlong); - jni::Object getCameraForLatLngBounds(jni::JNIEnv&, jni::Object, double top, double left, double bottom, double right, double bearing, double tilt); + jni::Local> getCameraForLatLngBounds(jni::JNIEnv&, const jni::Object&, double top, double left, double bottom, double right, double bearing, double tilt); - jni::Object getCameraForGeometry(jni::JNIEnv&, jni::Object, double top, double left, double bottom, double right, double bearing, double tilt); + jni::Local> getCameraForGeometry(jni::JNIEnv&, const jni::Object&, double top, double left, double bottom, double right, double bearing, double tilt); void setReachability(jni::JNIEnv&, jni::jboolean); @@ -138,17 +138,17 @@ public: void resetNorth(jni::JNIEnv&); - void setVisibleCoordinateBounds(JNIEnv&, jni::Array>, jni::Object, jni::jdouble, jni::jlong); + void setVisibleCoordinateBounds(JNIEnv&, const jni::Array>&, const jni::Object&, jni::jdouble, jni::jlong); void setContentPadding(JNIEnv&, double, double, double, double); void scheduleSnapshot(jni::JNIEnv&); - jni::Object getCameraPosition(jni::JNIEnv&); + jni::Local> 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 addMarkers(jni::JNIEnv&, jni::Array>); + jni::Local> addMarkers(jni::JNIEnv&, const jni::Array>&); void onLowMemory(JNIEnv& env); @@ -162,29 +162,29 @@ public: jni::jdouble getMetersPerPixelAtLatitude(JNIEnv&, jni::jdouble, jni::jdouble); - jni::Object projectedMetersForLatLng(JNIEnv&, jni::jdouble, jni::jdouble); + jni::Local> projectedMetersForLatLng(JNIEnv&, jni::jdouble, jni::jdouble); - jni::Object pixelForLatLng(JNIEnv&, jdouble, jdouble); + jni::Local> pixelForLatLng(JNIEnv&, jdouble, jdouble); - jni::Object latLngForProjectedMeters(JNIEnv&, jdouble, jdouble); + jni::Local> latLngForProjectedMeters(JNIEnv&, jdouble, jdouble); - jni::Object latLngForPixel(JNIEnv&, jfloat, jfloat); + jni::Local> latLngForPixel(JNIEnv&, jfloat, jfloat); - jni::Array addPolylines(JNIEnv&, jni::Array>); + jni::Local> addPolylines(JNIEnv&, const jni::Array>&); - jni::Array addPolygons(JNIEnv&, jni::Array>); + jni::Local> addPolygons(JNIEnv&, const jni::Array>&); - void updatePolyline(JNIEnv&, jlong, jni::Object); + void updatePolyline(JNIEnv&, jlong, const jni::Object&); - void updatePolygon(JNIEnv&, jlong, jni::Object); + void updatePolygon(JNIEnv&, jlong, const jni::Object&); - void removeAnnotations(JNIEnv&, jni::Array); + void removeAnnotations(JNIEnv&, const jni::Array&); - void addAnnotationIcon(JNIEnv&, jni::String, jint, jint, jfloat, jni::Array); + void addAnnotationIcon(JNIEnv&, const jni::String&, jint, jint, jfloat, const jni::Array&); - 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&); @@ -194,53 +194,53 @@ public: void setTransitionDelay(JNIEnv&, jni::jlong); - jni::Array queryPointAnnotations(JNIEnv&, jni::Object); + jni::Local> queryPointAnnotations(JNIEnv&, const jni::Object&); - jni::Array queryShapeAnnotations(JNIEnv&, jni::Object); + jni::Local> queryShapeAnnotations(JNIEnv&, const jni::Object&); - jni::Array> queryRenderedFeaturesForPoint(JNIEnv&, jni::jfloat, jni::jfloat, - jni::Array, - jni::Array> jfilter); + jni::Local>> queryRenderedFeaturesForPoint(JNIEnv&, jni::jfloat, jni::jfloat, + const jni::Array&, + const jni::Array>& jfilter); - jni::Array> queryRenderedFeaturesForBox(JNIEnv&, jni::jfloat, jni::jfloat, jni::jfloat, - jni::jfloat, jni::Array, - jni::Array> jfilter); + jni::Local>> queryRenderedFeaturesForBox(JNIEnv&, jni::jfloat, jni::jfloat, jni::jfloat, + jni::jfloat, const jni::Array&, + const jni::Array>& jfilter); - jni::Object getLight(JNIEnv&); + jni::Local> getLight(JNIEnv&); - jni::Array> getLayers(JNIEnv&); + jni::Local>> getLayers(JNIEnv&); - jni::Object getLayer(JNIEnv&, jni::String); + jni::Local> 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 removeLayerById(JNIEnv&, jni::String); + jni::Local> removeLayerById(JNIEnv&, const jni::String&); - jni::Object removeLayerAt(JNIEnv&, jni::jint); + jni::Local> removeLayerAt(JNIEnv&, jni::jint); void removeLayer(JNIEnv&, jlong); - jni::Array> getSources(JNIEnv&); + jni::Local>> getSources(JNIEnv&); - jni::Object getSource(JNIEnv&, jni::String); + jni::Local> getSource(JNIEnv&, const jni::String&); - void addSource(JNIEnv&, jni::Object, jlong nativePtr); + void addSource(JNIEnv&, const jni::Object&, jlong nativePtr); - jni::Object removeSourceById(JNIEnv&, jni::String); + jni::Local> removeSourceById(JNIEnv&, const jni::String&); - void removeSource(JNIEnv&, jni::Object, jlong nativePtr); + void removeSource(JNIEnv&, const jni::Object&, jlong nativePtr); - void addImage(JNIEnv&, jni::String, jni::Object bitmap, jni::jfloat, jni::jboolean); + void addImage(JNIEnv&, const jni::String&, const jni::Object& bitmap, jni::jfloat, jni::jboolean); - void addImages(JNIEnv&, jni::Array>); + void addImages(JNIEnv&, const jni::Array>&); - void removeImage(JNIEnv&, jni::String); + void removeImage(JNIEnv&, const jni::String&); - jni::Object getImage(JNIEnv&, jni::String); + jni::Local> getImage(JNIEnv&, const jni::String&); void setPrefetchesTiles(JNIEnv&, jni::jboolean); @@ -252,7 +252,7 @@ private: std::unique_ptr rendererFrontend; JavaVM *vm = nullptr; - jni::Weak> javaPeer; + jni::WeakReference> javaPeer; MapRenderer& mapRenderer; diff --git a/platform/android/src/offline/offline_manager.cpp b/platform/android/src/offline/offline_manager.cpp index 263f7b9d8b..b27af8bdae 100644 --- a/platform/android/src/offline/offline_manager.cpp +++ b/platform/android/src/offline/offline_manager.cpp @@ -3,14 +3,13 @@ #include #include "../attach_env.hpp" -#include "../jni/generic_global_ref_deleter.hpp" namespace mbgl { namespace android { // OfflineManager // -OfflineManager::OfflineManager(jni::JNIEnv& env, jni::Object jFileSource) +OfflineManager::OfflineManager(jni::JNIEnv& env, const jni::Object& 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 jFileSource_, jni::Object callback_) { - // list regions +void OfflineManager::listOfflineRegions(jni::JNIEnv& env_, const jni::Object& jFileSource_, const jni::Object& callback_) { + auto globalCallback = jni::NewGlobal(env_, callback_); + auto globalFilesource = jni::NewGlobal(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(callback_.NewGlobalRef(env_).release().Get(), GenericGlobalRefDeleter()), - jFileSource = std::shared_ptr(jFileSource_.NewGlobalRef(env_).release().Get(), GenericGlobalRefDeleter()) + callback = std::make_shared(std::move(globalCallback)), + jFileSource = std::make_shared(std::move(globalFilesource)) ](mbgl::expected regions) mutable { // Reattach, the callback comes from a different thread @@ -33,20 +34,19 @@ void OfflineManager::listOfflineRegions(jni::JNIEnv& env_, jni::Object(*jFileSource), - jni::Object(*callback), std::move(*regions)); + *env, *jFileSource, *callback, std::move(*regions)); } else { OfflineManager::ListOfflineRegionsCallback::onError( - *env, jni::Object(*callback), regions.error()); + *env, *callback, regions.error()); } }); } void OfflineManager::createOfflineRegion(jni::JNIEnv& env_, - jni::Object jFileSource_, - jni::Object definition_, - jni::Array metadata_, - jni::Object callback_) { + const jni::Object& jFileSource_, + const jni::Object& definition_, + const jni::Array& metadata_, + const jni::Object& 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(env_, callback_); + auto globalFilesource = jni::NewGlobal(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(callback_.NewGlobalRef(env_).release().Get(), GenericGlobalRefDeleter()), - jFileSource = std::shared_ptr(jFileSource_.NewGlobalRef(env_).release().Get(), GenericGlobalRefDeleter()) + callback = std::make_shared(std::move(globalCallback)), + jFileSource = std::make_shared(std::move(globalFilesource)) ](mbgl::expected region) mutable { // Reattach, the callback comes from a different thread @@ -67,12 +70,11 @@ void OfflineManager::createOfflineRegion(jni::JNIEnv& env_, if (region) { OfflineManager::CreateOfflineRegionCallback::onCreate( - *env, - jni::Object(*jFileSource), - jni::Object(*callback), std::move(*region) + *env, *jFileSource, *callback, std::move(*region) ); } else { - OfflineManager::CreateOfflineRegionCallback::onError(*env, jni::Object(*callback), region.error()); + OfflineManager::CreateOfflineRegionCallback::onError( + *env, *callback, region.error()); } }); } @@ -81,12 +83,12 @@ void OfflineManager::registerNative(jni::JNIEnv& env) { jni::Class::Singleton(env); jni::Class::Singleton(env); - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) jni::RegisterNativePeer( env, javaClass, "nativePtr", - std::make_unique>, + jni::MakePeer&>, "initialize", "finalize", METHOD(&OfflineManager::setOfflineMapboxTileCountLimit, "setOfflineMapboxTileCountLimit"), @@ -97,53 +99,50 @@ void OfflineManager::registerNative(jni::JNIEnv& env) { // OfflineManager::ListOfflineRegionsCallback // void OfflineManager::ListOfflineRegionsCallback::onError(jni::JNIEnv& env, - jni::Object callback, + const jni::Object& callback, std::exception_ptr error) { - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod(env, "onError"); - callback.Call(env, method, - *jni::SeizeLocal(env, jni::Make(env, mbgl::util::toString(error)))); + callback.Call(env, method, jni::Make(env, mbgl::util::toString(error))); } void OfflineManager::ListOfflineRegionsCallback::onList(jni::JNIEnv& env, - jni::Object jFileSource, - jni::Object callback, + const jni::Object& jFileSource, + const jni::Object& callback, mbgl::optional> regions) { - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod>)>(env, "onList"); std::size_t index = 0; - auto jregions = jni::SeizeLocal(env, jni::Array>::New(env, regions->size())); + auto jregions = jni::Array>::New(env, regions->size()); for (auto& region : *regions) { - jregions->Set(env, index, *jni::SeizeLocal(env, OfflineRegion::New(env, jFileSource, std::move(region)))); + jregions.Set(env, index, OfflineRegion::New(env, jFileSource, std::move(region))); index++; } - callback.Call(env, method, *jregions); + callback.Call(env, method, jregions); } // OfflineManager::CreateOfflineRegionCallback // void OfflineManager::CreateOfflineRegionCallback::onError(jni::JNIEnv& env, - jni::Object callback, + const jni::Object& callback, std::exception_ptr error) { - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod(env, "onError"); - callback.Call(env, method, - *jni::SeizeLocal(env, jni::Make(env, mbgl::util::toString(error)))); + callback.Call(env, method, jni::Make(env, mbgl::util::toString(error))); } void OfflineManager::CreateOfflineRegionCallback::onCreate(jni::JNIEnv& env, - jni::Object jFileSource, - jni::Object callback, + const jni::Object& jFileSource, + const jni::Object& callback, mbgl::optional region) { - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod)>(env, "onCreate"); - callback.Call(env, method, - *jni::SeizeLocal(env, OfflineRegion::New(env, jFileSource, std::move(*region)))); + 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 43f5045c71..21ca5ca9c1 100644 --- a/platform/android/src/offline/offline_manager.hpp +++ b/platform/android/src/offline/offline_manager.hpp @@ -20,11 +20,11 @@ public: public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineManager$ListOfflineRegionsCallback";} - static void onError(jni::JNIEnv&, jni::Object, std::exception_ptr); + static void onError(jni::JNIEnv&, const jni::Object&, std::exception_ptr); static void onList(jni::JNIEnv&, - jni::Object, - jni::Object, + const jni::Object&, + const jni::Object&, mbgl::optional>); }; @@ -32,11 +32,11 @@ public: public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineManager$CreateOfflineRegionCallback"; } - static void onError(jni::JNIEnv&, jni::Object, std::exception_ptr); + static void onError(jni::JNIEnv&, const jni::Object&, std::exception_ptr); static void onCreate(jni::JNIEnv&, - jni::Object, - jni::Object, + const jni::Object&, + const jni::Object&, mbgl::optional); }; @@ -44,18 +44,18 @@ public: static void registerNative(jni::JNIEnv&); - OfflineManager(jni::JNIEnv&, jni::Object); + OfflineManager(jni::JNIEnv&, const jni::Object&); ~OfflineManager(); void setOfflineMapboxTileCountLimit(jni::JNIEnv&, jni::jlong limit); - void listOfflineRegions(jni::JNIEnv&, jni::Object, jni::Object callback); + void listOfflineRegions(jni::JNIEnv&, const jni::Object&, const jni::Object& callback); void createOfflineRegion(jni::JNIEnv&, - jni::Object jFileSource_, - jni::Object definition, - jni::Array metadata, - jni::Object callback); + const jni::Object& jFileSource_, + const jni::Object& definition, + const jni::Array& metadata, + const jni::Object& callback); private: mbgl::DefaultFileSource& fileSource; diff --git a/platform/android/src/offline/offline_region.cpp b/platform/android/src/offline/offline_region.cpp index 949377e221..1cd73a7c76 100644 --- a/platform/android/src/offline/offline_region.cpp +++ b/platform/android/src/offline/offline_region.cpp @@ -7,71 +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 jFileSource) +OfflineRegion::OfflineRegion(jni::JNIEnv& env, jni::jlong offlineRegionPtr, const jni::Object& jFileSource) : region(reinterpret_cast(offlineRegionPtr)), fileSource(mbgl::android::FileSource::getDefaultFileSource(env, jFileSource)) {} OfflineRegion::~OfflineRegion() {} -void OfflineRegion::setOfflineRegionObserver(jni::JNIEnv& env_, jni::Object callback) { +void OfflineRegion::setOfflineRegionObserver(jni::JNIEnv& env_, const jni::Object& callback) { // Define the observer class Observer : public mbgl::OfflineRegionObserver { public: - Observer(jni::Global>&& 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::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(); - static auto javaClass = jni::Class::Singleton(*env); + static auto& javaClass = jni::Class::Singleton(*env); static auto method = javaClass.GetMethod)>(*env, "onStatusChanged"); - callback.Call(*env, method, - *jni::SeizeLocal(*env, OfflineRegionStatus::New(*env, status))); + 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(); - static auto javaClass = jni::Class::Singleton(*env); + static auto& javaClass = jni::Class::Singleton(*env); static auto method = javaClass.GetMethod)>(*env, "onError"); - callback.Call(*env, method, - *jni::SeizeLocal(*env, OfflineRegionError::New(*env, error))); + 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(); - static auto javaClass = jni::Class::Singleton(*env); + static auto& javaClass = jni::Class::Singleton(*env); static auto method = javaClass.GetMethod(*env, "mapboxTileCountLimitExceeded"); callback.Call(*env, method, jlong(limit)); } - jni::Object callback; + jni::Global, jni::EnvAttachingDeleter> callback; }; // Set the observer - fileSource.setOfflineRegionObserver(*region, std::make_unique(callback.NewGlobalRef(env_))); + fileSource.setOfflineRegionObserver(*region, std::make_unique(jni::NewGlobal(env_, callback))); } void OfflineRegion::setOfflineRegionDownloadState(jni::JNIEnv&, jni::jint jState) { @@ -92,85 +83,84 @@ void OfflineRegion::setOfflineRegionDownloadState(jni::JNIEnv&, jni::jint jState fileSource.setOfflineRegionDownloadState(*region, state); } -void OfflineRegion::getOfflineRegionStatus(jni::JNIEnv& env_, jni::Object callback_) { +void OfflineRegion::getOfflineRegionStatus(jni::JNIEnv& env_, const jni::Object& callback_) { + auto globalCallback = jni::NewGlobal(env_, callback_); fileSource.getOfflineRegionStatus(*region, [ //Ensure the object is not gc'd in the meanwhile - callback = std::shared_ptr(callback_.NewGlobalRef(env_).release().Get(), GenericGlobalRefDeleter()) + callback = std::make_shared(std::move(globalCallback)) ](mbgl::expected status) mutable { // Reattach, the callback comes from a different thread android::UniqueEnv env = android::AttachEnv(); if (status) { - OfflineRegionStatusCallback::onStatus(*env, jni::Object(*callback), std::move(*status)); + OfflineRegionStatusCallback::onStatus(*env, *callback, std::move(*status)); } else { - OfflineRegionStatusCallback::onError(*env, jni::Object(*callback), status.error()); + OfflineRegionStatusCallback::onError(*env, *callback, status.error()); } }); } -void OfflineRegion::deleteOfflineRegion(jni::JNIEnv& env_, jni::Object callback_) { - // Delete +void OfflineRegion::deleteOfflineRegion(jni::JNIEnv& env_, const jni::Object& callback_) { + auto globalCallback = jni::NewGlobal(env_, callback_); + fileSource.deleteOfflineRegion(std::move(*region), [ //Ensure the object is not gc'd in the meanwhile - callback = std::shared_ptr(callback_.NewGlobalRef(env_).release().Get(), GenericGlobalRefDeleter()) + callback = std::make_shared(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(*callback), error); + OfflineRegionDeleteCallback::onError(*env, *callback, error); } else { - OfflineRegionDeleteCallback::onDelete(*env, jni::Object(*callback)); + OfflineRegionDeleteCallback::onDelete(*env, *callback); } }); } -void OfflineRegion::updateOfflineRegionMetadata(jni::JNIEnv& env_, jni::Array jMetadata, jni::Object callback_) { - - // Convert +void OfflineRegion::updateOfflineRegionMetadata(jni::JNIEnv& env_, const jni::Array& jMetadata, const jni::Object& callback_) { auto metadata = OfflineRegion::metadata(env_, jMetadata); + auto globalCallback = jni::NewGlobal(env_, callback_); fileSource.updateOfflineMetadata(region->getID(), metadata, [ //Ensure the object is not gc'd in the meanwhile - callback = std::shared_ptr(callback_.NewGlobalRef(env_).release().Get(), GenericGlobalRefDeleter()) + callback = std::make_shared(std::move(globalCallback)) ](mbgl::expected data) mutable { // Reattach, the callback comes from a different thread android::UniqueEnv env = android::AttachEnv(); if (data) { - OfflineRegionUpdateMetadataCallback::onUpdate(*env, jni::Object(*callback), std::move(*data)); + OfflineRegionUpdateMetadataCallback::onUpdate(*env, *callback, std::move(*data)); } else { - OfflineRegionUpdateMetadataCallback::onError(*env, jni::Object(*callback), data.error()); + OfflineRegionUpdateMetadataCallback::onError(*env, *callback, data.error()); } }); } -jni::Object OfflineRegion::New(jni::JNIEnv& env, jni::Object jFileSource, mbgl::OfflineRegion region) { +jni::Local> OfflineRegion::New(jni::JNIEnv& env, const jni::Object& jFileSource, mbgl::OfflineRegion region) { // Definition - auto definition = jni::SeizeLocal(env, region.getDefinition().match( + auto definition = region.getDefinition().match( [&](const mbgl::OfflineTilePyramidRegionDefinition def) { - return jni::Object( - *OfflineTilePyramidRegionDefinition::New(env, def)); + return OfflineTilePyramidRegionDefinition::New(env, def); }, [&](const mbgl::OfflineGeometryRegionDefinition def) { - return jni::Object( - *OfflineGeometryRegionDefinition::New(env, def)); - })); + return OfflineGeometryRegionDefinition::New(env, def); + }); // Create region java object - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor, jni::jlong, jni::Object, jni::Array>(env); return javaClass.New(env, constructor, reinterpret_cast(new mbgl::OfflineRegion(std::move(region))), //Copy a region to the heap jFileSource, jni::jlong(region.getID()), - *definition, - *jni::SeizeLocal(env, OfflineRegion::metadata(env, region.getMetadata()))); + definition, + OfflineRegion::metadata(env, region.getMetadata())); } -jni::Array OfflineRegion::metadata(jni::JNIEnv& env, mbgl::OfflineRegionMetadata metadata_) { +jni::Local> OfflineRegion::metadata(jni::JNIEnv& env, mbgl::OfflineRegionMetadata metadata_) { std::vector convertedMetadata(metadata_.begin(), metadata_.end()); std::size_t length = static_cast(convertedMetadata.size()); auto metadata = jni::Array::New(env, length); @@ -178,7 +168,7 @@ jni::Array OfflineRegion::metadata(jni::JNIEnv& env, mbgl::OfflineRe return metadata; } -mbgl::OfflineRegionMetadata OfflineRegion::metadata(jni::JNIEnv& env, jni::Array metadata_) { +mbgl::OfflineRegionMetadata OfflineRegion::metadata(jni::JNIEnv& env, const jni::Array& metadata_) { std::size_t length = metadata_.Length(env); auto metadata_tmp = std::vector(); metadata_tmp.resize(length); @@ -193,12 +183,12 @@ void OfflineRegion::registerNative(jni::JNIEnv& env) { jni::Class::Singleton(env); jni::Class::Singleton(env); - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) jni::RegisterNativePeer( env, javaClass, "nativePtr", - std::make_unique>, + jni::MakePeer&>, "initialize", "finalize", METHOD(&OfflineRegion::setOfflineRegionObserver, "setOfflineRegionObserver"), @@ -214,40 +204,37 @@ void OfflineRegion::registerNative(jni::JNIEnv& env) { // OfflineRegionStatusCallback // void OfflineRegion::OfflineRegionStatusCallback::onError(jni::JNIEnv& env, - jni::Object callback, + const jni::Object& callback, std::exception_ptr error) { - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod(env, "onError"); - callback.Call(env, method, - *jni::SeizeLocal(env, jni::Make(env, mbgl::util::toString(error)))); + callback.Call(env, method, jni::Make(env, mbgl::util::toString(error))); } void OfflineRegion::OfflineRegionStatusCallback::onStatus(jni::JNIEnv& env, - jni::Object callback, + const jni::Object& callback, mbgl::optional status) { - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod)>(env, "onStatus"); - callback.Call(env, method, - *jni::SeizeLocal(env, OfflineRegionStatus::New(env, std::move(*status)))); + callback.Call(env, method, OfflineRegionStatus::New(env, std::move(*status))); } // OfflineRegionDeleteCallback // void OfflineRegion::OfflineRegionDeleteCallback::onError(jni::JNIEnv& env, - jni::Object callback, + const jni::Object& callback, std::exception_ptr error) { - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod(env, "onError"); - callback.Call(env, method, - *jni::SeizeLocal(env, jni::Make(env, mbgl::util::toString(error)))); + callback.Call(env, method, jni::Make(env, mbgl::util::toString(error))); } -void OfflineRegion::OfflineRegionDeleteCallback::onDelete(jni::JNIEnv& env, jni::Object callback) { +void OfflineRegion::OfflineRegionDeleteCallback::onDelete(jni::JNIEnv& env, const jni::Object& callback) { // Trigger callback - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod(env, "onDelete"); callback.Call(env, method); @@ -256,23 +243,21 @@ void OfflineRegion::OfflineRegionDeleteCallback::onDelete(jni::JNIEnv& env, jni: // OfflineRegionUpdateMetadataCallback // void OfflineRegion::OfflineRegionUpdateMetadataCallback::onError(jni::JNIEnv& env, - jni::Object callback, + const jni::Object& callback, std::exception_ptr error) { - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod(env, "onError"); - callback.Call(env, method, - *jni::SeizeLocal(env, jni::Make(env, mbgl::util::toString(error)))); + callback.Call(env, method, jni::Make(env, mbgl::util::toString(error))); } void OfflineRegion::OfflineRegionUpdateMetadataCallback::onUpdate(jni::JNIEnv& env, - jni::Object callback, + const jni::Object& callback, mbgl::optional metadata) { - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod)>(env, "onUpdate"); - callback.Call(env, method, - *jni::SeizeLocal(env, OfflineRegion::metadata(env, std::move(*metadata)))); + 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 11aecb82a9..49fa0c8ff8 100644 --- a/platform/android/src/offline/offline_region.hpp +++ b/platform/android/src/offline/offline_region.hpp @@ -21,10 +21,10 @@ public: public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegion$OfflineRegionStatusCallback"; }; - static void onError(jni::JNIEnv&, jni::Object, std::exception_ptr); + static void onError(jni::JNIEnv&, const jni::Object&, std::exception_ptr); static void onStatus(jni::JNIEnv&, - jni::Object, + const jni::Object&, mbgl::optional); }; @@ -32,43 +32,43 @@ public: public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegion$OfflineRegionDeleteCallback"; }; - static void onError(jni::JNIEnv&, jni::Object, std::exception_ptr); + static void onError(jni::JNIEnv&, const jni::Object&, std::exception_ptr); - static void onDelete(jni::JNIEnv&, jni::Object); + static void onDelete(jni::JNIEnv&, const jni::Object&); }; class OfflineRegionUpdateMetadataCallback { public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegion$OfflineRegionUpdateMetadataCallback"; }; - static void onError(jni::JNIEnv&, jni::Object, std::exception_ptr); + static void onError(jni::JNIEnv&, const jni::Object&, std::exception_ptr); static void onUpdate(jni::JNIEnv&, - jni::Object, + const jni::Object&, mbgl::optional); }; static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegion"; }; - OfflineRegion(jni::JNIEnv&, jni::jlong, jni::Object); + OfflineRegion(jni::JNIEnv&, jni::jlong, const jni::Object&); ~OfflineRegion(); - void setOfflineRegionObserver(jni::JNIEnv&, jni::Object); + void setOfflineRegionObserver(jni::JNIEnv&, const jni::Object&); void setOfflineRegionDownloadState(jni::JNIEnv&, jni::jint); - void getOfflineRegionStatus(jni::JNIEnv&, jni::Object); + void getOfflineRegionStatus(jni::JNIEnv&, const jni::Object&); - void deleteOfflineRegion(jni::JNIEnv&, jni::Object); + void deleteOfflineRegion(jni::JNIEnv&, const jni::Object&); - void updateOfflineRegionMetadata(jni::JNIEnv&, jni::Array, jni::Object); + void updateOfflineRegionMetadata(jni::JNIEnv&, const jni::Array&, const jni::Object&); - static jni::Object New(jni::JNIEnv&, jni::Object, mbgl::OfflineRegion); + static jni::Local> New(jni::JNIEnv&, const jni::Object&, mbgl::OfflineRegion); - static jni::Array metadata(jni::JNIEnv&, mbgl::OfflineRegionMetadata); + static jni::Local> metadata(jni::JNIEnv&, mbgl::OfflineRegionMetadata); - static mbgl::OfflineRegionMetadata metadata(jni::JNIEnv&, jni::Array); + static mbgl::OfflineRegionMetadata metadata(jni::JNIEnv&, const jni::Array&); 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 2a69181f5b..23e5b7466b 100644 --- a/platform/android/src/offline/offline_region_definition.cpp +++ b/platform/android/src/offline/offline_region_definition.cpp @@ -15,11 +15,11 @@ void OfflineRegionDefinition::registerNative(jni::JNIEnv& env) { } mbgl::OfflineRegionDefinition OfflineRegionDefinition::getDefinition(JNIEnv& env, - jni::Object jDefinition) { + const jni::Object& jDefinition) { if (jDefinition.IsInstanceOf(env, jni::Class::Singleton(env))) { - return OfflineTilePyramidRegionDefinition::getDefinition(env, jni::Object(*jDefinition)); + return OfflineTilePyramidRegionDefinition::getDefinition(env, jni::Cast(env, jni::Class::Singleton(env), jDefinition)); } else if (jDefinition.IsInstanceOf(env, jni::Class::Singleton(env))) { - return OfflineGeometryRegionDefinition::getDefinition(env, jni::Object(*jDefinition)); + return OfflineGeometryRegionDefinition::getDefinition(env, jni::Cast(env, jni::Class::Singleton(env), jDefinition)); } throw std::runtime_error("Unknown offline region definition java class"); @@ -27,21 +27,21 @@ mbgl::OfflineRegionDefinition OfflineRegionDefinition::getDefinition(JNIEnv& env // OfflineTilePyramidRegionDefinition // -jni::Object OfflineTilePyramidRegionDefinition::New(jni::JNIEnv& env, const mbgl::OfflineTilePyramidRegionDefinition& definition) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local> OfflineTilePyramidRegionDefinition::New(jni::JNIEnv& env, const mbgl::OfflineTilePyramidRegionDefinition& definition) { + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor, jni::jdouble, jni::jdouble, jni::jfloat>(env); return javaClass.New(env, constructor, - *jni::SeizeLocal(env, jni::Make(env, definition.styleURL)), - *jni::SeizeLocal(env, LatLngBounds::New(env, definition.bounds)), + jni::Make(env, definition.styleURL), + LatLngBounds::New(env, definition.bounds), definition.minZoom, definition.maxZoom, definition.pixelRatio); } -mbgl::OfflineTilePyramidRegionDefinition OfflineTilePyramidRegionDefinition::getDefinition(jni::JNIEnv& env, jni::Object jDefinition) { +mbgl::OfflineTilePyramidRegionDefinition OfflineTilePyramidRegionDefinition::getDefinition(jni::JNIEnv& env, const jni::Object& jDefinition) { // Field references - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); static auto styleURLF = javaClass.GetField(env, "styleURL"); static auto boundsF = javaClass.GetField>(env, "bounds"); static auto minZoomF = javaClass.GetField(env, "minZoom"); @@ -49,8 +49,8 @@ mbgl::OfflineTilePyramidRegionDefinition OfflineTilePyramidRegionDefinition::get static auto pixelRatioF = javaClass.GetField(env, "pixelRatio"); return mbgl::OfflineTilePyramidRegionDefinition( - jni::Make(env, *jni::SeizeLocal(env, jDefinition.Get(env, styleURLF))), - LatLngBounds::getLatLngBounds(env, *jni::SeizeLocal(env, jDefinition.Get(env, boundsF))), + jni::Make(env, jDefinition.Get(env, styleURLF)), + LatLngBounds::getLatLngBounds(env, jDefinition.Get(env, boundsF)), jDefinition.Get(env, minZoomF), jDefinition.Get(env, maxZoomF), jDefinition.Get(env, pixelRatioF) @@ -63,21 +63,21 @@ void OfflineTilePyramidRegionDefinition::registerNative(jni::JNIEnv& env) { // OfflineGeometryRegionDefinition // -jni::Object OfflineGeometryRegionDefinition::New(jni::JNIEnv& env, const mbgl::OfflineGeometryRegionDefinition& definition) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local> OfflineGeometryRegionDefinition::New(jni::JNIEnv& env, const mbgl::OfflineGeometryRegionDefinition& definition) { + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor, jni::jdouble, jni::jdouble, jni::jfloat>(env); return javaClass.New(env, constructor, - *jni::SeizeLocal(env, jni::Make(env, definition.styleURL)), - *jni::SeizeLocal(env, geojson::Geometry::New(env, definition.geometry)), + jni::Make(env, definition.styleURL), + geojson::Geometry::New(env, definition.geometry), definition.minZoom, definition.maxZoom, definition.pixelRatio); } -mbgl::OfflineGeometryRegionDefinition OfflineGeometryRegionDefinition::getDefinition(jni::JNIEnv& env, jni::Object jDefinition) { +mbgl::OfflineGeometryRegionDefinition OfflineGeometryRegionDefinition::getDefinition(jni::JNIEnv& env, const jni::Object& jDefinition) { // Field references - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); static auto styleURLF = javaClass.GetField(env, "styleURL"); static auto geometryF = javaClass.GetField>(env, "geometry"); static auto minZoomF = javaClass.GetField(env, "minZoom"); @@ -85,8 +85,8 @@ mbgl::OfflineGeometryRegionDefinition OfflineGeometryRegionDefinition::getDefini static auto pixelRatioF = javaClass.GetField(env, "pixelRatio"); return mbgl::OfflineGeometryRegionDefinition( - jni::Make(env, *jni::SeizeLocal(env, jDefinition.Get(env, styleURLF))), - geojson::Geometry::convert(env, *jni::SeizeLocal(env, jDefinition.Get(env, geometryF))), + jni::Make(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) diff --git a/platform/android/src/offline/offline_region_definition.hpp b/platform/android/src/offline/offline_region_definition.hpp index 853cc833bf..827fac0a80 100644 --- a/platform/android/src/offline/offline_region_definition.hpp +++ b/platform/android/src/offline/offline_region_definition.hpp @@ -12,27 +12,29 @@ public: static void registerNative(jni::JNIEnv&); - static mbgl::OfflineRegionDefinition getDefinition(JNIEnv& env, jni::Object jDefinition); + static mbgl::OfflineRegionDefinition getDefinition(JNIEnv& env, const jni::Object& jDefinition); }; -class OfflineTilePyramidRegionDefinition: public OfflineRegionDefinition { +class OfflineTilePyramidRegionDefinition { public: + using SuperTag = OfflineRegionDefinition; static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineTilePyramidRegionDefinition"; }; - static jni::Object New(jni::JNIEnv&, const mbgl::OfflineTilePyramidRegionDefinition&); + static jni::Local> New(jni::JNIEnv&, const mbgl::OfflineTilePyramidRegionDefinition&); - static mbgl::OfflineTilePyramidRegionDefinition getDefinition(jni::JNIEnv&, jni::Object); + static mbgl::OfflineTilePyramidRegionDefinition getDefinition(jni::JNIEnv&, const jni::Object&); 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 New(jni::JNIEnv&, const mbgl::OfflineGeometryRegionDefinition&); + static jni::Local> New(jni::JNIEnv&, const mbgl::OfflineGeometryRegionDefinition&); - static mbgl::OfflineGeometryRegionDefinition getDefinition(jni::JNIEnv&, jni::Object); + static mbgl::OfflineGeometryRegionDefinition getDefinition(jni::JNIEnv&, const jni::Object&); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/offline/offline_region_error.cpp b/platform/android/src/offline/offline_region_error.cpp index 02432757d4..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::New(jni::JNIEnv& env, mbgl::Response::Error error) { +jni::Local> OfflineRegionError::New(jni::JNIEnv& env, mbgl::Response::Error error) { // Handle the value of reason independently of the underlying int value std::string reason; @@ -28,12 +28,12 @@ jni::Object OfflineRegionError::New(jni::JNIEnv& env, mbgl:: break; } - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); return javaClass.New(env, constructor, - *jni::SeizeLocal(env, jni::Make(env, reason)), - *jni::SeizeLocal(env, jni::Make(env, error.message))); + jni::Make(env, reason), + jni::Make(env, error.message)); } void OfflineRegionError::registerNative(jni::JNIEnv& env) { diff --git a/platform/android/src/offline/offline_region_error.hpp b/platform/android/src/offline/offline_region_error.hpp index c51f08a745..151e05ab19 100644 --- a/platform/android/src/offline/offline_region_error.hpp +++ b/platform/android/src/offline/offline_region_error.hpp @@ -10,7 +10,7 @@ class OfflineRegionError { public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegionError"; }; - static jni::Object New(jni::JNIEnv&, mbgl::Response::Error); + static jni::Local> 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 0a415bdb5f..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::New(jni::JNIEnv& env, mbgl::OfflineRegionStatus status) { +jni::Local> OfflineRegionStatus::New(jni::JNIEnv& env, mbgl::OfflineRegionStatus status) { // Convert to jint jint downloadState; @@ -17,7 +17,7 @@ jni::Object OfflineRegionStatus::New(jni::JNIEnv& env, mbgl } // Create java object - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); return javaClass.New(env, constructor, downloadState, diff --git a/platform/android/src/offline/offline_region_status.hpp b/platform/android/src/offline/offline_region_status.hpp index 9f638e1093..9ef48ec357 100644 --- a/platform/android/src/offline/offline_region_status.hpp +++ b/platform/android/src/offline/offline_region_status.hpp @@ -10,7 +10,7 @@ class OfflineRegionStatus { public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegionStatus"; }; - static jni::Object New(jni::JNIEnv&, mbgl::OfflineRegionStatus status); + static jni::Local> 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 d626ae68b7..1650f72dc7 100644 --- a/platform/android/src/snapshotter/map_snapshot.cpp +++ b/platform/android/src/snapshotter/map_snapshot.cpp @@ -16,18 +16,18 @@ MapSnapshot::MapSnapshot(float pixelRatio_, MapSnapshot::PointForFn pointForFn_, MapSnapshot::~MapSnapshot() = default; -jni::Object MapSnapshot::pixelForLatLng(jni::JNIEnv& env, jni::Object jLatLng) { +jni::Local> MapSnapshot::pixelForLatLng(jni::JNIEnv& env, jni::Object& jLatLng) { ScreenCoordinate point = pointForFn(LatLng::getLatLng(env, jLatLng)); return PointF::New(env, point.x * pixelRatio, point.y * pixelRatio); } -jni::Object MapSnapshot::latLngForPixel(jni::JNIEnv& env, jni::ObjectjPoint) { +jni::Local> MapSnapshot::latLngForPixel(jni::JNIEnv& env, jni::Object& jPoint) { return LatLng::New(env, latLngForFn(PointF::getScreenCoordinate(env, jPoint))); } // Static methods // -jni::Object MapSnapshot::New(JNIEnv& env, +jni::Local> MapSnapshot::New(JNIEnv& env, PremultipliedImage&& image, float pixelRatio, std::vector attributions, @@ -38,7 +38,7 @@ jni::Object MapSnapshot::New(JNIEnv& env, auto bitmap = Bitmap::CreateBitmap(env, std::move(image)); // Create the Mapsnapshot peers - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor, jni::Array, jni::jboolean>(env); auto nativePeer = std::make_unique(pixelRatio, pointForFn, latLngForFn); return javaClass.New(env, constructor, reinterpret_cast(nativePeer.release()), bitmap, conversion::toArray(env, attributions), (jni::jboolean) showLogo); @@ -46,7 +46,7 @@ jni::Object MapSnapshot::New(JNIEnv& env, void MapSnapshot::registerNative(jni::JNIEnv& env) { // Lookup the class - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) diff --git a/platform/android/src/snapshotter/map_snapshot.hpp b/platform/android/src/snapshotter/map_snapshot.hpp index 3cd293b621..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 New(JNIEnv& env, + static jni::Local> New(JNIEnv& env, PremultipliedImage&& image, float pixelRatio, std::vector attributions, @@ -35,8 +35,8 @@ public: MapSnapshot(float pixelRatio, PointForFn, LatLngForFn); ~MapSnapshot(); - jni::Object pixelForLatLng(jni::JNIEnv&, jni::Object); - jni::Object latLngForPixel(jni::JNIEnv&, jni::Object); + jni::Local> pixelForLatLng(jni::JNIEnv&, jni::Object&); + jni::Local> latLngForPixel(jni::JNIEnv&, jni::Object&); private: float pixelRatio; diff --git a/platform/android/src/snapshotter/map_snapshotter.cpp b/platform/android/src/snapshotter/map_snapshotter.cpp index 4df0749aa0..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 _obj, - jni::Object _jFileSource, + const jni::Object& _obj, + const jni::Object& _jFileSource, jni::jfloat _pixelRatio, jni::jint width, jni::jint height, - jni::String styleURL, - jni::String styleJSON, - jni::Object region, - jni::Object position, + const jni::String& styleURL, + const jni::String& styleJSON, + const jni::Object& region, + const jni::Object& position, jni::jboolean _showLogo, - jni::String _programCacheDir) - : javaPeer(SeizeGenericWeak(_obj.NewWeakGlobalRef(_env).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 attributions, mbgl::MapSnapshotter::PointForFn pointForFn, mbgl::MapSnapshotter::LatLngForFn latLngForFn) { MBGL_VERIFY_THREAD(tid); android::UniqueEnv _env = android::AttachEnv(); - static auto javaClass = jni::Class::Singleton(*_env); + static auto& javaClass = jni::Class::Singleton(*_env); if (err) { // error handler callback static auto onSnapshotFailed = javaClass.GetMethod(*_env, "onSnapshotFailed"); - javaPeer->Call(*_env, onSnapshotFailed, - *jni::SeizeLocal(*_env, jni::Make(*_env, util::toString(err)))); + javaPeer.get(*_env).Call(*_env, onSnapshotFailed, jni::Make(*_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)>(*_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(env, styleURL)); } -void MapSnapshotter::setStyleJson(JNIEnv& env, jni::String styleJSON) { +void MapSnapshotter::setStyleJson(JNIEnv& env, const jni::String& styleJSON) { snapshotter->setStyleJSON(jni::Make(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 position) { +void MapSnapshotter::setCameraPosition(JNIEnv& env, const jni::Object& position) { auto options = CameraPosition::getCameraOptions(env, position); snapshotter->setCameraOptions(options); } -void MapSnapshotter::setRegion(JNIEnv& env, jni::Object region) { +void MapSnapshotter::setRegion(JNIEnv& env, const jni::Object& region) { snapshotter->setRegion(LatLngBounds::getLatLngBounds(env, region)); } @@ -151,13 +150,13 @@ void MapSnapshotter::deactivateFilesource(JNIEnv& env) { void MapSnapshotter::registerNative(jni::JNIEnv& env) { // Lookup the class - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer(env, javaClass, "nativePtr", - std::make_unique, jni::Object, jni::jfloat, jni::jint, jni::jint, jni::String, jni::String, jni::Object, jni::Object, jni::jboolean, jni::String>, + jni::MakePeer&, const jni::Object&, jni::jfloat, jni::jint, jni::jint, const jni::String&, const jni::String&, const jni::Object&, const jni::Object&, 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 05a27256aa..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 -#include "../jni/generic_global_ref_deleter.hpp" #include @@ -26,29 +25,29 @@ public: static void registerNative(jni::JNIEnv&); MapSnapshotter(jni::JNIEnv&, - jni::Object, - jni::Object, + const jni::Object&, + const jni::Object&, jni::jfloat pixelRatio, jni::jint width, jni::jint height, - jni::String styleURL, - jni::String styleJSON, - jni::Object region, - jni::Object position, + const jni::String& styleURL, + const jni::String& styleJSON, + const jni::Object& region, + const jni::Object& 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 position); + void setCameraPosition(JNIEnv&, const jni::Object& position); - void setRegion(JNIEnv&, jni::Object region); + void setRegion(JNIEnv&, const jni::Object& region); void start(JNIEnv&); @@ -58,7 +57,7 @@ private: MBGL_STORE_THREAD(tid); JavaVM *vm = nullptr; - GenericWeak> javaPeer; + jni::WeakReference, jni::EnvAttachingDeleter> javaPeer; float pixelRatio; bool showLogo; diff --git a/platform/android/src/style/conversion/filter.cpp b/platform/android/src/style/conversion/filter.cpp index 44b5a71aa3..d15e2747ac 100644 --- a/platform/android/src/style/conversion/filter.cpp +++ b/platform/android/src/style/conversion/filter.cpp @@ -8,11 +8,11 @@ namespace mbgl { namespace android { namespace conversion { -optional toFilter(jni::JNIEnv& env, jni::Local>> jfilter) { +optional toFilter(jni::JNIEnv& env, const jni::Array>& jfilter) { mbgl::optional filter; if (jfilter) { mbgl::style::conversion::Error error; - auto converted = mbgl::style::conversion::convert(Value(env, std::move(jfilter)), error); + auto converted = mbgl::style::conversion::convert(Value(env, jfilter), error); if (!converted) { mbgl::Log::Error(mbgl::Event::JNI, "Error converting filter: " + error.message); } diff --git a/platform/android/src/style/conversion/filter.hpp b/platform/android/src/style/conversion/filter.hpp index f638a853a1..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 toFilter(jni::JNIEnv&, jni::Local>>); +optional toFilter(jni::JNIEnv&, const jni::Array>&); } // 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> Converter, mbgl::style::Position>::operator()(jni::JNIEnv &env, const mbgl::style::Position &value) const { +Result>> Converter>, mbgl::style::Position>::operator()(jni::JNIEnv &env, const mbgl::style::Position &value) const { std::array 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, mbgl::style::Position> { - Result> operator()(jni::JNIEnv &env, const mbgl::style::Position &value) const; +struct Converter>, mbgl::style::Position> { + Result>> 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 -struct Converter, mbgl::style::PropertyExpression> { - Result> operator()(jni::JNIEnv& env, const mbgl::style::PropertyExpression& value) const { +struct Converter>, mbgl::style::PropertyExpression> { + Result>> operator()(jni::JNIEnv& env, const mbgl::style::PropertyExpression& 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> operator()(const mbgl::style::Undefined) const { + return jni::Local>(env, nullptr); } - jni::jobject* operator()(const T& value) const { - return *convert(env, value); + jni::Local> operator()(const T& value) const { + return std::move(*convert>>(env, value)); } - jni::jobject* operator()(const mbgl::style::PropertyExpression& value) const { - return *convert>(env, value); + jni::Local> operator()(const mbgl::style::PropertyExpression& value) const { + return std::move(*convert>>(env, value)); } private: @@ -39,8 +39,8 @@ private: * Convert core property values to java */ template -struct Converter> { - Result operator()(jni::JNIEnv& env, const mbgl::style::PropertyValue& value) const { +struct Converter>, mbgl::style::PropertyValue> { + Result>> operator()(jni::JNIEnv& env, const mbgl::style::PropertyValue& value) const { PropertyValueEvaluator evaluator(env); return value.evaluate(evaluator); } @@ -50,10 +50,10 @@ struct Converter> { * Convert core heat map color property value to java */ template <> -struct Converter { - Result operator()(jni::JNIEnv& env, const mbgl::style::ColorRampPropertyValue& value) const { +struct Converter>, mbgl::style::ColorRampPropertyValue> { + Result>> operator()(jni::JNIEnv& env, const mbgl::style::ColorRampPropertyValue& value) const { PropertyValueEvaluator evaluator(env); - return *convert(env, value.evaluate(evaluator)); + return std::move(*convert>>(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> Converter, mbgl::style::TransitionOptions>::operator()(jni::JNIEnv& env, const mbgl::style::TransitionOptions& value) const { +Result>> Converter>, mbgl::style::TransitionOptions>::operator()(jni::JNIEnv& env, const mbgl::style::TransitionOptions& value) const { return TransitionOptions::fromTransitionOptions(env, std::chrono::duration_cast(value.duration.value_or(mbgl::Duration::zero())).count(), std::chrono::duration_cast(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, mbgl::style::TransitionOptions> { - Result> operator()(jni::JNIEnv&, const mbgl::style::TransitionOptions&) const; +struct Converter>, mbgl::style::TransitionOptions> { + Result>> 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 00c348b232..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(jni::Make(env, layerId))) { } @@ -35,16 +35,15 @@ namespace android { // Property getters - jni::Object BackgroundLayer::getBackgroundColor(jni::JNIEnv& env) { + jni::Local> BackgroundLayer::getBackgroundColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->BackgroundLayer::getBackgroundColor()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->BackgroundLayer::getBackgroundColor())); } - jni::Object BackgroundLayer::getBackgroundColorTransition(jni::JNIEnv& env) { + jni::Local> BackgroundLayer::getBackgroundColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->BackgroundLayer::getBackgroundColorTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void BackgroundLayer::setBackgroundColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -54,16 +53,15 @@ namespace android { layer.as()->BackgroundLayer::setBackgroundColorTransition(options); } - jni::Object BackgroundLayer::getBackgroundPattern(jni::JNIEnv& env) { + jni::Local> BackgroundLayer::getBackgroundPattern(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->BackgroundLayer::getBackgroundPattern()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->BackgroundLayer::getBackgroundPattern())); } - jni::Object BackgroundLayer::getBackgroundPatternTransition(jni::JNIEnv& env) { + jni::Local> BackgroundLayer::getBackgroundPatternTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->BackgroundLayer::getBackgroundPatternTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void BackgroundLayer::setBackgroundPatternTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -73,16 +71,15 @@ namespace android { layer.as()->BackgroundLayer::setBackgroundPatternTransition(options); } - jni::Object BackgroundLayer::getBackgroundOpacity(jni::JNIEnv& env) { + jni::Local> BackgroundLayer::getBackgroundOpacity(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->BackgroundLayer::getBackgroundOpacity()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->BackgroundLayer::getBackgroundOpacity())); } - jni::Object BackgroundLayer::getBackgroundOpacityTransition(jni::JNIEnv& env) { + jni::Local> BackgroundLayer::getBackgroundOpacityTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->BackgroundLayer::getBackgroundOpacityTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void BackgroundLayer::setBackgroundOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -93,22 +90,22 @@ namespace android { } - jni::jobject* BackgroundLayer::createJavaPeer(jni::JNIEnv& env) { - static auto javaClass = jni::Class::Singleton(env); + jni::Local> BackgroundLayer::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); return javaClass.New(env, constructor, reinterpret_cast(this)); } void BackgroundLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( env, javaClass, "nativePtr", - std::make_unique, + jni::MakePeer, "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 3b7f03ddb6..78cd5659fd 100644 --- a/platform/android/src/style/layers/background_layer.hpp +++ b/platform/android/src/style/layers/background_layer.hpp @@ -12,12 +12,12 @@ namespace android { class BackgroundLayer : public Layer { public: - + using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/BackgroundLayer"; }; static void registerNative(jni::JNIEnv&); - BackgroundLayer(jni::JNIEnv&, jni::String); + BackgroundLayer(jni::JNIEnv&, jni::String&); BackgroundLayer(mbgl::Map&, mbgl::style::BackgroundLayer&); @@ -27,18 +27,18 @@ public: // Properties - jni::Object getBackgroundColor(jni::JNIEnv&); + jni::Local> getBackgroundColor(jni::JNIEnv&); void setBackgroundColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getBackgroundColorTransition(jni::JNIEnv&); + jni::Local> getBackgroundColorTransition(jni::JNIEnv&); - jni::Object getBackgroundPattern(jni::JNIEnv&); + jni::Local> getBackgroundPattern(jni::JNIEnv&); void setBackgroundPatternTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getBackgroundPatternTransition(jni::JNIEnv&); + jni::Local> getBackgroundPatternTransition(jni::JNIEnv&); - jni::Object getBackgroundOpacity(jni::JNIEnv&); + jni::Local> getBackgroundOpacity(jni::JNIEnv&); void setBackgroundOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getBackgroundOpacityTransition(jni::JNIEnv&); - jni::jobject* createJavaPeer(jni::JNIEnv&); + jni::Local> getBackgroundOpacityTransition(jni::JNIEnv&); + jni::Local> 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 47a492dd43..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(jni::Make(env, layerId), jni::Make(env, sourceId))) { } @@ -35,16 +35,15 @@ namespace android { // Property getters - jni::Object CircleLayer::getCircleRadius(jni::JNIEnv& env) { + jni::Local> CircleLayer::getCircleRadius(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->CircleLayer::getCircleRadius()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->CircleLayer::getCircleRadius())); } - jni::Object CircleLayer::getCircleRadiusTransition(jni::JNIEnv& env) { + jni::Local> CircleLayer::getCircleRadiusTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->CircleLayer::getCircleRadiusTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void CircleLayer::setCircleRadiusTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -54,16 +53,15 @@ namespace android { layer.as()->CircleLayer::setCircleRadiusTransition(options); } - jni::Object CircleLayer::getCircleColor(jni::JNIEnv& env) { + jni::Local> CircleLayer::getCircleColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->CircleLayer::getCircleColor()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->CircleLayer::getCircleColor())); } - jni::Object CircleLayer::getCircleColorTransition(jni::JNIEnv& env) { + jni::Local> CircleLayer::getCircleColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->CircleLayer::getCircleColorTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void CircleLayer::setCircleColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -73,16 +71,15 @@ namespace android { layer.as()->CircleLayer::setCircleColorTransition(options); } - jni::Object CircleLayer::getCircleBlur(jni::JNIEnv& env) { + jni::Local> CircleLayer::getCircleBlur(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->CircleLayer::getCircleBlur()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->CircleLayer::getCircleBlur())); } - jni::Object CircleLayer::getCircleBlurTransition(jni::JNIEnv& env) { + jni::Local> CircleLayer::getCircleBlurTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->CircleLayer::getCircleBlurTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void CircleLayer::setCircleBlurTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -92,16 +89,15 @@ namespace android { layer.as()->CircleLayer::setCircleBlurTransition(options); } - jni::Object CircleLayer::getCircleOpacity(jni::JNIEnv& env) { + jni::Local> CircleLayer::getCircleOpacity(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->CircleLayer::getCircleOpacity()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->CircleLayer::getCircleOpacity())); } - jni::Object CircleLayer::getCircleOpacityTransition(jni::JNIEnv& env) { + jni::Local> CircleLayer::getCircleOpacityTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->CircleLayer::getCircleOpacityTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void CircleLayer::setCircleOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -111,16 +107,15 @@ namespace android { layer.as()->CircleLayer::setCircleOpacityTransition(options); } - jni::Object CircleLayer::getCircleTranslate(jni::JNIEnv& env) { + jni::Local> CircleLayer::getCircleTranslate(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->CircleLayer::getCircleTranslate()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->CircleLayer::getCircleTranslate())); } - jni::Object CircleLayer::getCircleTranslateTransition(jni::JNIEnv& env) { + jni::Local> CircleLayer::getCircleTranslateTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->CircleLayer::getCircleTranslateTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void CircleLayer::setCircleTranslateTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -130,34 +125,30 @@ namespace android { layer.as()->CircleLayer::setCircleTranslateTransition(options); } - jni::Object CircleLayer::getCircleTranslateAnchor(jni::JNIEnv& env) { + jni::Local> CircleLayer::getCircleTranslateAnchor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->CircleLayer::getCircleTranslateAnchor()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->CircleLayer::getCircleTranslateAnchor())); } - jni::Object CircleLayer::getCirclePitchScale(jni::JNIEnv& env) { + jni::Local> CircleLayer::getCirclePitchScale(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->CircleLayer::getCirclePitchScale()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->CircleLayer::getCirclePitchScale())); } - jni::Object CircleLayer::getCirclePitchAlignment(jni::JNIEnv& env) { + jni::Local> CircleLayer::getCirclePitchAlignment(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->CircleLayer::getCirclePitchAlignment()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->CircleLayer::getCirclePitchAlignment())); } - jni::Object CircleLayer::getCircleStrokeWidth(jni::JNIEnv& env) { + jni::Local> CircleLayer::getCircleStrokeWidth(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->CircleLayer::getCircleStrokeWidth()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->CircleLayer::getCircleStrokeWidth())); } - jni::Object CircleLayer::getCircleStrokeWidthTransition(jni::JNIEnv& env) { + jni::Local> CircleLayer::getCircleStrokeWidthTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->CircleLayer::getCircleStrokeWidthTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void CircleLayer::setCircleStrokeWidthTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -167,16 +158,15 @@ namespace android { layer.as()->CircleLayer::setCircleStrokeWidthTransition(options); } - jni::Object CircleLayer::getCircleStrokeColor(jni::JNIEnv& env) { + jni::Local> CircleLayer::getCircleStrokeColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->CircleLayer::getCircleStrokeColor()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->CircleLayer::getCircleStrokeColor())); } - jni::Object CircleLayer::getCircleStrokeColorTransition(jni::JNIEnv& env) { + jni::Local> CircleLayer::getCircleStrokeColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->CircleLayer::getCircleStrokeColorTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void CircleLayer::setCircleStrokeColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -186,16 +176,15 @@ namespace android { layer.as()->CircleLayer::setCircleStrokeColorTransition(options); } - jni::Object CircleLayer::getCircleStrokeOpacity(jni::JNIEnv& env) { + jni::Local> CircleLayer::getCircleStrokeOpacity(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->CircleLayer::getCircleStrokeOpacity()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->CircleLayer::getCircleStrokeOpacity())); } - jni::Object CircleLayer::getCircleStrokeOpacityTransition(jni::JNIEnv& env) { + jni::Local> CircleLayer::getCircleStrokeOpacityTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->CircleLayer::getCircleStrokeOpacityTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void CircleLayer::setCircleStrokeOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -206,22 +195,22 @@ namespace android { } - jni::jobject* CircleLayer::createJavaPeer(jni::JNIEnv& env) { - static auto javaClass = jni::Class::Singleton(env); + jni::Local> CircleLayer::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); return javaClass.New(env, constructor, reinterpret_cast(this)); } void CircleLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( env, javaClass, "nativePtr", - std::make_unique, + jni::MakePeer, "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 03063b1fc1..0ff34094e1 100644 --- a/platform/android/src/style/layers/circle_layer.hpp +++ b/platform/android/src/style/layers/circle_layer.hpp @@ -12,12 +12,12 @@ namespace android { class CircleLayer : public Layer { public: - + using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/CircleLayer"; }; 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&); @@ -27,44 +27,44 @@ public: // Properties - jni::Object getCircleRadius(jni::JNIEnv&); + jni::Local> getCircleRadius(jni::JNIEnv&); void setCircleRadiusTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getCircleRadiusTransition(jni::JNIEnv&); + jni::Local> getCircleRadiusTransition(jni::JNIEnv&); - jni::Object getCircleColor(jni::JNIEnv&); + jni::Local> getCircleColor(jni::JNIEnv&); void setCircleColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getCircleColorTransition(jni::JNIEnv&); + jni::Local> getCircleColorTransition(jni::JNIEnv&); - jni::Object getCircleBlur(jni::JNIEnv&); + jni::Local> getCircleBlur(jni::JNIEnv&); void setCircleBlurTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getCircleBlurTransition(jni::JNIEnv&); + jni::Local> getCircleBlurTransition(jni::JNIEnv&); - jni::Object getCircleOpacity(jni::JNIEnv&); + jni::Local> getCircleOpacity(jni::JNIEnv&); void setCircleOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getCircleOpacityTransition(jni::JNIEnv&); + jni::Local> getCircleOpacityTransition(jni::JNIEnv&); - jni::Object getCircleTranslate(jni::JNIEnv&); + jni::Local> getCircleTranslate(jni::JNIEnv&); void setCircleTranslateTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getCircleTranslateTransition(jni::JNIEnv&); + jni::Local> getCircleTranslateTransition(jni::JNIEnv&); - jni::Object getCircleTranslateAnchor(jni::JNIEnv&); + jni::Local> getCircleTranslateAnchor(jni::JNIEnv&); - jni::Object getCirclePitchScale(jni::JNIEnv&); + jni::Local> getCirclePitchScale(jni::JNIEnv&); - jni::Object getCirclePitchAlignment(jni::JNIEnv&); + jni::Local> getCirclePitchAlignment(jni::JNIEnv&); - jni::Object getCircleStrokeWidth(jni::JNIEnv&); + jni::Local> getCircleStrokeWidth(jni::JNIEnv&); void setCircleStrokeWidthTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getCircleStrokeWidthTransition(jni::JNIEnv&); + jni::Local> getCircleStrokeWidthTransition(jni::JNIEnv&); - jni::Object getCircleStrokeColor(jni::JNIEnv&); + jni::Local> getCircleStrokeColor(jni::JNIEnv&); void setCircleStrokeColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getCircleStrokeColorTransition(jni::JNIEnv&); + jni::Local> getCircleStrokeColorTransition(jni::JNIEnv&); - jni::Object getCircleStrokeOpacity(jni::JNIEnv&); + jni::Local> getCircleStrokeOpacity(jni::JNIEnv&); void setCircleStrokeOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getCircleStrokeOpacityTransition(jni::JNIEnv&); - jni::jobject* createJavaPeer(jni::JNIEnv&); + jni::Local> getCircleStrokeOpacityTransition(jni::JNIEnv&); + jni::Local> 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 c0dcc24f06..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( jni::Make(env, layerId), std::unique_ptr(reinterpret_cast(host))) @@ -33,22 +33,22 @@ namespace android { } } - jni::jobject* CustomLayer::createJavaPeer(jni::JNIEnv& env) { - static auto javaClass = jni::Class::Singleton(env); + jni::Local> CustomLayer::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); return javaClass.New(env, constructor, reinterpret_cast(this)); } void CustomLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( env, javaClass, "nativePtr", - std::make_unique, + jni::MakePeer, "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 75e1957717..950fcef9c1 100644 --- a/platform/android/src/style/layers/custom_layer.hpp +++ b/platform/android/src/style/layers/custom_layer.hpp @@ -9,18 +9,19 @@ namespace android { class CustomLayer : public Layer { public: + using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/CustomLayer"; }; 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); ~CustomLayer(); void update(jni::JNIEnv&); - jni::jobject* createJavaPeer(jni::JNIEnv&); + jni::Local> 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 6c6a0bef5a..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(jni::Make(env, layerId), jni::Make(env, sourceId))) { } @@ -35,16 +35,15 @@ namespace android { // Property getters - jni::Object FillExtrusionLayer::getFillExtrusionOpacity(jni::JNIEnv& env) { + jni::Local> FillExtrusionLayer::getFillExtrusionOpacity(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->FillExtrusionLayer::getFillExtrusionOpacity()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->FillExtrusionLayer::getFillExtrusionOpacity())); } - jni::Object FillExtrusionLayer::getFillExtrusionOpacityTransition(jni::JNIEnv& env) { + jni::Local> FillExtrusionLayer::getFillExtrusionOpacityTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->FillExtrusionLayer::getFillExtrusionOpacityTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void FillExtrusionLayer::setFillExtrusionOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -54,16 +53,15 @@ namespace android { layer.as()->FillExtrusionLayer::setFillExtrusionOpacityTransition(options); } - jni::Object FillExtrusionLayer::getFillExtrusionColor(jni::JNIEnv& env) { + jni::Local> FillExtrusionLayer::getFillExtrusionColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->FillExtrusionLayer::getFillExtrusionColor()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->FillExtrusionLayer::getFillExtrusionColor())); } - jni::Object FillExtrusionLayer::getFillExtrusionColorTransition(jni::JNIEnv& env) { + jni::Local> FillExtrusionLayer::getFillExtrusionColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->FillExtrusionLayer::getFillExtrusionColorTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void FillExtrusionLayer::setFillExtrusionColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -73,16 +71,15 @@ namespace android { layer.as()->FillExtrusionLayer::setFillExtrusionColorTransition(options); } - jni::Object FillExtrusionLayer::getFillExtrusionTranslate(jni::JNIEnv& env) { + jni::Local> FillExtrusionLayer::getFillExtrusionTranslate(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->FillExtrusionLayer::getFillExtrusionTranslate()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->FillExtrusionLayer::getFillExtrusionTranslate())); } - jni::Object FillExtrusionLayer::getFillExtrusionTranslateTransition(jni::JNIEnv& env) { + jni::Local> FillExtrusionLayer::getFillExtrusionTranslateTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->FillExtrusionLayer::getFillExtrusionTranslateTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void FillExtrusionLayer::setFillExtrusionTranslateTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -92,22 +89,20 @@ namespace android { layer.as()->FillExtrusionLayer::setFillExtrusionTranslateTransition(options); } - jni::Object FillExtrusionLayer::getFillExtrusionTranslateAnchor(jni::JNIEnv& env) { + jni::Local> FillExtrusionLayer::getFillExtrusionTranslateAnchor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->FillExtrusionLayer::getFillExtrusionTranslateAnchor()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->FillExtrusionLayer::getFillExtrusionTranslateAnchor())); } - jni::Object FillExtrusionLayer::getFillExtrusionPattern(jni::JNIEnv& env) { + jni::Local> FillExtrusionLayer::getFillExtrusionPattern(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->FillExtrusionLayer::getFillExtrusionPattern()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->FillExtrusionLayer::getFillExtrusionPattern())); } - jni::Object FillExtrusionLayer::getFillExtrusionPatternTransition(jni::JNIEnv& env) { + jni::Local> FillExtrusionLayer::getFillExtrusionPatternTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->FillExtrusionLayer::getFillExtrusionPatternTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void FillExtrusionLayer::setFillExtrusionPatternTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -117,16 +112,15 @@ namespace android { layer.as()->FillExtrusionLayer::setFillExtrusionPatternTransition(options); } - jni::Object FillExtrusionLayer::getFillExtrusionHeight(jni::JNIEnv& env) { + jni::Local> FillExtrusionLayer::getFillExtrusionHeight(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->FillExtrusionLayer::getFillExtrusionHeight()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->FillExtrusionLayer::getFillExtrusionHeight())); } - jni::Object FillExtrusionLayer::getFillExtrusionHeightTransition(jni::JNIEnv& env) { + jni::Local> FillExtrusionLayer::getFillExtrusionHeightTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->FillExtrusionLayer::getFillExtrusionHeightTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void FillExtrusionLayer::setFillExtrusionHeightTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -136,16 +130,15 @@ namespace android { layer.as()->FillExtrusionLayer::setFillExtrusionHeightTransition(options); } - jni::Object FillExtrusionLayer::getFillExtrusionBase(jni::JNIEnv& env) { + jni::Local> FillExtrusionLayer::getFillExtrusionBase(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->FillExtrusionLayer::getFillExtrusionBase()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->FillExtrusionLayer::getFillExtrusionBase())); } - jni::Object FillExtrusionLayer::getFillExtrusionBaseTransition(jni::JNIEnv& env) { + jni::Local> FillExtrusionLayer::getFillExtrusionBaseTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->FillExtrusionLayer::getFillExtrusionBaseTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void FillExtrusionLayer::setFillExtrusionBaseTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -156,22 +149,22 @@ namespace android { } - jni::jobject* FillExtrusionLayer::createJavaPeer(jni::JNIEnv& env) { - static auto javaClass = jni::Class::Singleton(env); + jni::Local> FillExtrusionLayer::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); return javaClass.New(env, constructor, reinterpret_cast(this)); } void FillExtrusionLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( env, javaClass, "nativePtr", - std::make_unique, + jni::MakePeer, "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 233c3cc334..abc30b5845 100644 --- a/platform/android/src/style/layers/fill_extrusion_layer.hpp +++ b/platform/android/src/style/layers/fill_extrusion_layer.hpp @@ -12,12 +12,12 @@ namespace android { class FillExtrusionLayer : public Layer { public: - + using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/FillExtrusionLayer"; }; 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&); @@ -27,32 +27,32 @@ public: // Properties - jni::Object getFillExtrusionOpacity(jni::JNIEnv&); + jni::Local> getFillExtrusionOpacity(jni::JNIEnv&); void setFillExtrusionOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getFillExtrusionOpacityTransition(jni::JNIEnv&); + jni::Local> getFillExtrusionOpacityTransition(jni::JNIEnv&); - jni::Object getFillExtrusionColor(jni::JNIEnv&); + jni::Local> getFillExtrusionColor(jni::JNIEnv&); void setFillExtrusionColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getFillExtrusionColorTransition(jni::JNIEnv&); + jni::Local> getFillExtrusionColorTransition(jni::JNIEnv&); - jni::Object getFillExtrusionTranslate(jni::JNIEnv&); + jni::Local> getFillExtrusionTranslate(jni::JNIEnv&); void setFillExtrusionTranslateTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getFillExtrusionTranslateTransition(jni::JNIEnv&); + jni::Local> getFillExtrusionTranslateTransition(jni::JNIEnv&); - jni::Object getFillExtrusionTranslateAnchor(jni::JNIEnv&); + jni::Local> getFillExtrusionTranslateAnchor(jni::JNIEnv&); - jni::Object getFillExtrusionPattern(jni::JNIEnv&); + jni::Local> getFillExtrusionPattern(jni::JNIEnv&); void setFillExtrusionPatternTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getFillExtrusionPatternTransition(jni::JNIEnv&); + jni::Local> getFillExtrusionPatternTransition(jni::JNIEnv&); - jni::Object getFillExtrusionHeight(jni::JNIEnv&); + jni::Local> getFillExtrusionHeight(jni::JNIEnv&); void setFillExtrusionHeightTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getFillExtrusionHeightTransition(jni::JNIEnv&); + jni::Local> getFillExtrusionHeightTransition(jni::JNIEnv&); - jni::Object getFillExtrusionBase(jni::JNIEnv&); + jni::Local> getFillExtrusionBase(jni::JNIEnv&); void setFillExtrusionBaseTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getFillExtrusionBaseTransition(jni::JNIEnv&); - jni::jobject* createJavaPeer(jni::JNIEnv&); + jni::Local> getFillExtrusionBaseTransition(jni::JNIEnv&); + jni::Local> 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 5182c546c8..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(jni::Make(env, layerId), jni::Make(env, sourceId))) { } @@ -35,22 +35,20 @@ namespace android { // Property getters - jni::Object FillLayer::getFillAntialias(jni::JNIEnv& env) { + jni::Local> FillLayer::getFillAntialias(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->FillLayer::getFillAntialias()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->FillLayer::getFillAntialias())); } - jni::Object FillLayer::getFillOpacity(jni::JNIEnv& env) { + jni::Local> FillLayer::getFillOpacity(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->FillLayer::getFillOpacity()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->FillLayer::getFillOpacity())); } - jni::Object FillLayer::getFillOpacityTransition(jni::JNIEnv& env) { + jni::Local> FillLayer::getFillOpacityTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->FillLayer::getFillOpacityTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void FillLayer::setFillOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -60,16 +58,15 @@ namespace android { layer.as()->FillLayer::setFillOpacityTransition(options); } - jni::Object FillLayer::getFillColor(jni::JNIEnv& env) { + jni::Local> FillLayer::getFillColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->FillLayer::getFillColor()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->FillLayer::getFillColor())); } - jni::Object FillLayer::getFillColorTransition(jni::JNIEnv& env) { + jni::Local> FillLayer::getFillColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->FillLayer::getFillColorTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void FillLayer::setFillColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -79,16 +76,15 @@ namespace android { layer.as()->FillLayer::setFillColorTransition(options); } - jni::Object FillLayer::getFillOutlineColor(jni::JNIEnv& env) { + jni::Local> FillLayer::getFillOutlineColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->FillLayer::getFillOutlineColor()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->FillLayer::getFillOutlineColor())); } - jni::Object FillLayer::getFillOutlineColorTransition(jni::JNIEnv& env) { + jni::Local> FillLayer::getFillOutlineColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->FillLayer::getFillOutlineColorTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void FillLayer::setFillOutlineColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -98,16 +94,15 @@ namespace android { layer.as()->FillLayer::setFillOutlineColorTransition(options); } - jni::Object FillLayer::getFillTranslate(jni::JNIEnv& env) { + jni::Local> FillLayer::getFillTranslate(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->FillLayer::getFillTranslate()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->FillLayer::getFillTranslate())); } - jni::Object FillLayer::getFillTranslateTransition(jni::JNIEnv& env) { + jni::Local> FillLayer::getFillTranslateTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->FillLayer::getFillTranslateTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void FillLayer::setFillTranslateTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -117,22 +112,20 @@ namespace android { layer.as()->FillLayer::setFillTranslateTransition(options); } - jni::Object FillLayer::getFillTranslateAnchor(jni::JNIEnv& env) { + jni::Local> FillLayer::getFillTranslateAnchor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->FillLayer::getFillTranslateAnchor()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->FillLayer::getFillTranslateAnchor())); } - jni::Object FillLayer::getFillPattern(jni::JNIEnv& env) { + jni::Local> FillLayer::getFillPattern(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->FillLayer::getFillPattern()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->FillLayer::getFillPattern())); } - jni::Object FillLayer::getFillPatternTransition(jni::JNIEnv& env) { + jni::Local> FillLayer::getFillPatternTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->FillLayer::getFillPatternTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void FillLayer::setFillPatternTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -143,22 +136,22 @@ namespace android { } - jni::jobject* FillLayer::createJavaPeer(jni::JNIEnv& env) { - static auto javaClass = jni::Class::Singleton(env); + jni::Local> FillLayer::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); return javaClass.New(env, constructor, reinterpret_cast(this)); } void FillLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( env, javaClass, "nativePtr", - std::make_unique, + jni::MakePeer, "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 db1fee1667..ea96320570 100644 --- a/platform/android/src/style/layers/fill_layer.hpp +++ b/platform/android/src/style/layers/fill_layer.hpp @@ -12,12 +12,12 @@ namespace android { class FillLayer : public Layer { public: - + using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/FillLayer"; }; 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&); @@ -27,30 +27,30 @@ public: // Properties - jni::Object getFillAntialias(jni::JNIEnv&); + jni::Local> getFillAntialias(jni::JNIEnv&); - jni::Object getFillOpacity(jni::JNIEnv&); + jni::Local> getFillOpacity(jni::JNIEnv&); void setFillOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getFillOpacityTransition(jni::JNIEnv&); + jni::Local> getFillOpacityTransition(jni::JNIEnv&); - jni::Object getFillColor(jni::JNIEnv&); + jni::Local> getFillColor(jni::JNIEnv&); void setFillColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getFillColorTransition(jni::JNIEnv&); + jni::Local> getFillColorTransition(jni::JNIEnv&); - jni::Object getFillOutlineColor(jni::JNIEnv&); + jni::Local> getFillOutlineColor(jni::JNIEnv&); void setFillOutlineColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getFillOutlineColorTransition(jni::JNIEnv&); + jni::Local> getFillOutlineColorTransition(jni::JNIEnv&); - jni::Object getFillTranslate(jni::JNIEnv&); + jni::Local> getFillTranslate(jni::JNIEnv&); void setFillTranslateTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getFillTranslateTransition(jni::JNIEnv&); + jni::Local> getFillTranslateTransition(jni::JNIEnv&); - jni::Object getFillTranslateAnchor(jni::JNIEnv&); + jni::Local> getFillTranslateAnchor(jni::JNIEnv&); - jni::Object getFillPattern(jni::JNIEnv&); + jni::Local> getFillPattern(jni::JNIEnv&); void setFillPatternTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getFillPatternTransition(jni::JNIEnv&); - jni::jobject* createJavaPeer(jni::JNIEnv&); + jni::Local> getFillPatternTransition(jni::JNIEnv&); + jni::Local> 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 e83d92873f..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(jni::Make(env, layerId), jni::Make(env, sourceId))) { } @@ -35,16 +35,15 @@ namespace android { // Property getters - jni::Object HeatmapLayer::getHeatmapRadius(jni::JNIEnv& env) { + jni::Local> HeatmapLayer::getHeatmapRadius(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->HeatmapLayer::getHeatmapRadius()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->HeatmapLayer::getHeatmapRadius())); } - jni::Object HeatmapLayer::getHeatmapRadiusTransition(jni::JNIEnv& env) { + jni::Local> HeatmapLayer::getHeatmapRadiusTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->HeatmapLayer::getHeatmapRadiusTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void HeatmapLayer::setHeatmapRadiusTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -54,22 +53,20 @@ namespace android { layer.as()->HeatmapLayer::setHeatmapRadiusTransition(options); } - jni::Object HeatmapLayer::getHeatmapWeight(jni::JNIEnv& env) { + jni::Local> HeatmapLayer::getHeatmapWeight(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->HeatmapLayer::getHeatmapWeight()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->HeatmapLayer::getHeatmapWeight())); } - jni::Object HeatmapLayer::getHeatmapIntensity(jni::JNIEnv& env) { + jni::Local> HeatmapLayer::getHeatmapIntensity(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->HeatmapLayer::getHeatmapIntensity()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->HeatmapLayer::getHeatmapIntensity())); } - jni::Object HeatmapLayer::getHeatmapIntensityTransition(jni::JNIEnv& env) { + jni::Local> HeatmapLayer::getHeatmapIntensityTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->HeatmapLayer::getHeatmapIntensityTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void HeatmapLayer::setHeatmapIntensityTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -79,26 +76,24 @@ namespace android { layer.as()->HeatmapLayer::setHeatmapIntensityTransition(options); } - jni::Object HeatmapLayer::getHeatmapColor(jni::JNIEnv& env) { + jni::Local> HeatmapLayer::getHeatmapColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; auto propertyValue = layer.as()->HeatmapLayer::getHeatmapColor(); if (propertyValue.isUndefined()) { propertyValue = layer.as()->HeatmapLayer::getDefaultHeatmapColor(); } - Result converted = convert(env, propertyValue); - return jni::Object(*converted); + return std::move(*convert>>(env, propertyValue)); } - jni::Object HeatmapLayer::getHeatmapOpacity(jni::JNIEnv& env) { + jni::Local> HeatmapLayer::getHeatmapOpacity(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->HeatmapLayer::getHeatmapOpacity()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->HeatmapLayer::getHeatmapOpacity())); } - jni::Object HeatmapLayer::getHeatmapOpacityTransition(jni::JNIEnv& env) { + jni::Local> HeatmapLayer::getHeatmapOpacityTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->HeatmapLayer::getHeatmapOpacityTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void HeatmapLayer::setHeatmapOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -109,22 +104,22 @@ namespace android { } - jni::jobject* HeatmapLayer::createJavaPeer(jni::JNIEnv& env) { - static auto javaClass = jni::Class::Singleton(env); + jni::Local> HeatmapLayer::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); return javaClass.New(env, constructor, reinterpret_cast(this)); } void HeatmapLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( env, javaClass, "nativePtr", - std::make_unique, + jni::MakePeer, "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 00ab27d854..2976e6c482 100644 --- a/platform/android/src/style/layers/heatmap_layer.hpp +++ b/platform/android/src/style/layers/heatmap_layer.hpp @@ -12,12 +12,12 @@ namespace android { class HeatmapLayer : public Layer { public: - + using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/HeatmapLayer"; }; 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&); @@ -27,22 +27,22 @@ public: // Properties - jni::Object getHeatmapRadius(jni::JNIEnv&); + jni::Local> getHeatmapRadius(jni::JNIEnv&); void setHeatmapRadiusTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getHeatmapRadiusTransition(jni::JNIEnv&); + jni::Local> getHeatmapRadiusTransition(jni::JNIEnv&); - jni::Object getHeatmapWeight(jni::JNIEnv&); + jni::Local> getHeatmapWeight(jni::JNIEnv&); - jni::Object getHeatmapIntensity(jni::JNIEnv&); + jni::Local> getHeatmapIntensity(jni::JNIEnv&); void setHeatmapIntensityTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getHeatmapIntensityTransition(jni::JNIEnv&); + jni::Local> getHeatmapIntensityTransition(jni::JNIEnv&); - jni::Object getHeatmapColor(jni::JNIEnv&); + jni::Local> getHeatmapColor(jni::JNIEnv&); - jni::Object getHeatmapOpacity(jni::JNIEnv&); + jni::Local> getHeatmapOpacity(jni::JNIEnv&); void setHeatmapOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getHeatmapOpacityTransition(jni::JNIEnv&); - jni::jobject* createJavaPeer(jni::JNIEnv&); + jni::Local> getHeatmapOpacityTransition(jni::JNIEnv&); + jni::Local> 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 b6409b3b3e..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(jni::Make(env, layerId), jni::Make(env, sourceId))) { } @@ -35,28 +35,25 @@ namespace android { // Property getters - jni::Object HillshadeLayer::getHillshadeIlluminationDirection(jni::JNIEnv& env) { + jni::Local> HillshadeLayer::getHillshadeIlluminationDirection(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->HillshadeLayer::getHillshadeIlluminationDirection()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->HillshadeLayer::getHillshadeIlluminationDirection())); } - jni::Object HillshadeLayer::getHillshadeIlluminationAnchor(jni::JNIEnv& env) { + jni::Local> HillshadeLayer::getHillshadeIlluminationAnchor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->HillshadeLayer::getHillshadeIlluminationAnchor()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->HillshadeLayer::getHillshadeIlluminationAnchor())); } - jni::Object HillshadeLayer::getHillshadeExaggeration(jni::JNIEnv& env) { + jni::Local> HillshadeLayer::getHillshadeExaggeration(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->HillshadeLayer::getHillshadeExaggeration()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->HillshadeLayer::getHillshadeExaggeration())); } - jni::Object HillshadeLayer::getHillshadeExaggerationTransition(jni::JNIEnv& env) { + jni::Local> HillshadeLayer::getHillshadeExaggerationTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->HillshadeLayer::getHillshadeExaggerationTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void HillshadeLayer::setHillshadeExaggerationTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -66,16 +63,15 @@ namespace android { layer.as()->HillshadeLayer::setHillshadeExaggerationTransition(options); } - jni::Object HillshadeLayer::getHillshadeShadowColor(jni::JNIEnv& env) { + jni::Local> HillshadeLayer::getHillshadeShadowColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->HillshadeLayer::getHillshadeShadowColor()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->HillshadeLayer::getHillshadeShadowColor())); } - jni::Object HillshadeLayer::getHillshadeShadowColorTransition(jni::JNIEnv& env) { + jni::Local> HillshadeLayer::getHillshadeShadowColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->HillshadeLayer::getHillshadeShadowColorTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void HillshadeLayer::setHillshadeShadowColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -85,16 +81,15 @@ namespace android { layer.as()->HillshadeLayer::setHillshadeShadowColorTransition(options); } - jni::Object HillshadeLayer::getHillshadeHighlightColor(jni::JNIEnv& env) { + jni::Local> HillshadeLayer::getHillshadeHighlightColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->HillshadeLayer::getHillshadeHighlightColor()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->HillshadeLayer::getHillshadeHighlightColor())); } - jni::Object HillshadeLayer::getHillshadeHighlightColorTransition(jni::JNIEnv& env) { + jni::Local> HillshadeLayer::getHillshadeHighlightColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->HillshadeLayer::getHillshadeHighlightColorTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void HillshadeLayer::setHillshadeHighlightColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -104,16 +99,15 @@ namespace android { layer.as()->HillshadeLayer::setHillshadeHighlightColorTransition(options); } - jni::Object HillshadeLayer::getHillshadeAccentColor(jni::JNIEnv& env) { + jni::Local> HillshadeLayer::getHillshadeAccentColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->HillshadeLayer::getHillshadeAccentColor()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->HillshadeLayer::getHillshadeAccentColor())); } - jni::Object HillshadeLayer::getHillshadeAccentColorTransition(jni::JNIEnv& env) { + jni::Local> HillshadeLayer::getHillshadeAccentColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->HillshadeLayer::getHillshadeAccentColorTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void HillshadeLayer::setHillshadeAccentColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -124,22 +118,22 @@ namespace android { } - jni::jobject* HillshadeLayer::createJavaPeer(jni::JNIEnv& env) { - static auto javaClass = jni::Class::Singleton(env); + jni::Local> HillshadeLayer::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); return javaClass.New(env, constructor, reinterpret_cast(this)); } void HillshadeLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( env, javaClass, "nativePtr", - std::make_unique, + jni::MakePeer, "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 f824698058..9ca0e33cfd 100644 --- a/platform/android/src/style/layers/hillshade_layer.hpp +++ b/platform/android/src/style/layers/hillshade_layer.hpp @@ -12,12 +12,12 @@ namespace android { class HillshadeLayer : public Layer { public: - + using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/HillshadeLayer"; }; 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&); @@ -27,26 +27,26 @@ public: // Properties - jni::Object getHillshadeIlluminationDirection(jni::JNIEnv&); + jni::Local> getHillshadeIlluminationDirection(jni::JNIEnv&); - jni::Object getHillshadeIlluminationAnchor(jni::JNIEnv&); + jni::Local> getHillshadeIlluminationAnchor(jni::JNIEnv&); - jni::Object getHillshadeExaggeration(jni::JNIEnv&); + jni::Local> getHillshadeExaggeration(jni::JNIEnv&); void setHillshadeExaggerationTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getHillshadeExaggerationTransition(jni::JNIEnv&); + jni::Local> getHillshadeExaggerationTransition(jni::JNIEnv&); - jni::Object getHillshadeShadowColor(jni::JNIEnv&); + jni::Local> getHillshadeShadowColor(jni::JNIEnv&); void setHillshadeShadowColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getHillshadeShadowColorTransition(jni::JNIEnv&); + jni::Local> getHillshadeShadowColorTransition(jni::JNIEnv&); - jni::Object getHillshadeHighlightColor(jni::JNIEnv&); + jni::Local> getHillshadeHighlightColor(jni::JNIEnv&); void setHillshadeHighlightColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getHillshadeHighlightColorTransition(jni::JNIEnv&); + jni::Local> getHillshadeHighlightColorTransition(jni::JNIEnv&); - jni::Object getHillshadeAccentColor(jni::JNIEnv&); + jni::Local> getHillshadeAccentColor(jni::JNIEnv&); void setHillshadeAccentColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getHillshadeAccentColorTransition(jni::JNIEnv&); - jni::jobject* createJavaPeer(jni::JNIEnv&); + jni::Local> getHillshadeAccentColorTransition(jni::JNIEnv&); + jni::Local> createJavaPeer(jni::JNIEnv&); }; // class HillshadeLayer diff --git a/platform/android/src/style/layers/layer.cpp b/platform/android/src/style/layers/layer.cpp index fe4fb9aeb6..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 Layer::getId(jni::JNIEnv& env) { return jni::Make(env, layer.getID()); } @@ -91,18 +91,18 @@ 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 error = layer.setLayoutProperty(jni::Make(env, jname), Value(env, jni::SeizeLocal(env, std::move(jvalue)))); + optional error = layer.setLayoutProperty(jni::Make(env, jname), Value(env, jvalue)); if (error) { mbgl::Log::Error(mbgl::Event::JNI, "Error setting property: " + jni::Make(env, jname) + " " + error->message); return; } } - 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 error = layer.setPaintProperty(jni::Make(env, jname), Value(env, jni::SeizeLocal(env, std::move(jvalue)))); + optional error = layer.setPaintProperty(jni::Make(env, jname), Value(env, jvalue)); if (error) { mbgl::Log::Error(mbgl::Event::JNI, "Error setting property: " + jni::Make(env, jname) + " " + error->message); return; @@ -123,12 +123,12 @@ namespace android { } }; - void Layer::setFilter(jni::JNIEnv& env, jni::Array> jfilter) { + void Layer::setFilter(jni::JNIEnv& env, const jni::Array>& jfilter) { using namespace mbgl::style; using namespace mbgl::style::conversion; Error error; - optional converted = convert(Value(env, jni::SeizeLocal(env, std::move(jfilter))), error); + optional converted = convert(Value(env, jfilter), error); if (!converted) { mbgl::Log::Error(mbgl::Event::JNI, "Error setting filter: " + error.message); return; @@ -154,7 +154,7 @@ namespace android { } }; - jni::Object Layer::getFilter(jni::JNIEnv& env) { + jni::Local> 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(); + return jni::Local>(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(env, sourceLayer)}); } @@ -202,7 +202,7 @@ namespace android { } }; - jni::String Layer::getSourceLayer(jni::JNIEnv& env) { + jni::Local Layer::getSourceLayer(jni::JNIEnv& env) { return jni::Make(env, layer.accept(GetSourceLayerEvaluator())); } @@ -221,7 +221,7 @@ namespace android { } }; - jni::String Layer::getSourceId(jni::JNIEnv& env) { + jni::Local Layer::getSourceId(jni::JNIEnv& env) { return jni::Make(env, layer.accept(GetSourceIdEvaluator())); } @@ -241,14 +241,14 @@ namespace android { layer.setMaxZoom(zoom); } - jni::Object Layer::getVisibility(jni::JNIEnv& env) { + jni::Local> Layer::getVisibility(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - return jni::Object(*convert(env, layer.getVisibility())); + return std::move(*convert>>(env, layer.getVisibility())); } void Layer::registerNative(jni::JNIEnv& env) { // Lookup the class - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) diff --git a/platform/android/src/style/layers/layer.cpp.ejs b/platform/android/src/style/layers/layer.cpp.ejs index 7dbb031b25..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_uniqueLayer>(jni::Make(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_uniqueLayer>(jni::Make(env, layerId), jni::Make(env, sourceId))) { <% } -%> } @@ -49,29 +49,27 @@ namespace android { <% for (const property of properties) { -%> <% if (property.name != 'heatmap-color') { -%> - jni::Object <%- camelize(type) %>Layer::get<%- camelize(property.name) %>(jni::JNIEnv& env) { + jni::Local> <%- camelize(type) %>Layer::get<%- camelize(property.name) %>(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.asLayer>()-><%- camelize(type) %>Layer::get<%- camelize(property.name) %>()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.asLayer>()-><%- camelize(type) %>Layer::get<%- camelize(property.name) %>())); } <% } else { -%> - jni::Object HeatmapLayer::getHeatmapColor(jni::JNIEnv& env) { + jni::Local> HeatmapLayer::getHeatmapColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; auto propertyValue = layer.as()->HeatmapLayer::getHeatmapColor(); if (propertyValue.isUndefined()) { propertyValue = layer.as()->HeatmapLayer::getDefaultHeatmapColor(); } - Result converted = convert(env, propertyValue); - return jni::Object(*converted); + return std::move(*convert>>(env, propertyValue)); } <% } -%> <% if (property.transition) { -%> - jni::Object <%- camelize(type) %>Layer::get<%- camelize(property.name) %>Transition(jni::JNIEnv& env) { + jni::Local> <%- camelize(type) %>Layer::get<%- camelize(property.name) %>Transition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.asLayer>()-><%- camelize(type) %>Layer::get<%- camelize(property.name) %>Transition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void <%- camelize(type) %>Layer::set<%- camelize(property.name) %>Transition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -84,15 +82,15 @@ namespace android { <% } -%> <% } -%> - jni::jobject* <%- camelize(type) %>Layer::createJavaPeer(jni::JNIEnv& env) { - static auto javaClass = jni::Class<<%- camelize(type) %>Layer>::Singleton(env); + jni::Local> <%- camelize(type) %>Layer::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class<<%- camelize(type) %>Layer>::Singleton(env); static auto constructor = javaClass.GetConstructor(env); return javaClass.New(env, constructor, reinterpret_cast(this)); } void <%- camelize(type) %>Layer::registerNative(jni::JNIEnv& env) { // Lookup the class - static auto javaClass = jni::Class<<%- camelize(type) %>Layer>::Singleton(env); + static auto& javaClass = jni::Class<<%- camelize(type) %>Layer>::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) @@ -100,9 +98,9 @@ namespace android { jni::RegisterNativePeer<<%- camelize(type) %>Layer>( 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 8112dd18d6..cee1b5a64e 100644 --- a/platform/android/src/style/layers/layer.hpp +++ b/platform/android/src/style/layers/layer.hpp @@ -36,7 +36,7 @@ public: virtual ~Layer(); - virtual jni::jobject* createJavaPeer(jni::JNIEnv&) = 0; + virtual jni::Local> createJavaPeer(jni::JNIEnv&) = 0; /** * Set core layer (ie return ownership after remove) @@ -45,15 +45,15 @@ public: void addToMap(mbgl::Map&, mbgl::optional); - jni::String getId(jni::JNIEnv&); + jni::Local getId(jni::JNIEnv&); - jni::String getSourceId(jni::JNIEnv&); + jni::Local 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 @@ -67,17 +67,17 @@ public: /* common properties, but not shared by all */ - void setFilter(jni::JNIEnv&, jni::Array>); + void setFilter(jni::JNIEnv&, const jni::Array>&); - jni::Object getFilter(jni::JNIEnv&); + jni::Local> getFilter(jni::JNIEnv&); - void setSourceLayer(jni::JNIEnv&, jni::String); + void setSourceLayer(jni::JNIEnv&, const jni::String&); - jni::String getSourceLayer(jni::JNIEnv&); + jni::Local getSourceLayer(jni::JNIEnv&); // Property getters - jni::Object getVisibility(jni::JNIEnv&); + jni::Local> 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 dd599d71df..5ceab0dcfa 100644 --- a/platform/android/src/style/layers/layer.hpp.ejs +++ b/platform/android/src/style/layers/layer.hpp.ejs @@ -16,15 +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 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&); @@ -36,13 +36,13 @@ public: // Properties <% for (const property of properties) { -%> - jni::Object get<%- camelize(property.name) %>(jni::JNIEnv&); + jni::Local> get<%- camelize(property.name) %>(jni::JNIEnv&); <% if (property.transition) { -%> void set<%- camelize(property.name) %>Transition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object get<%- camelize(property.name) %>Transition(jni::JNIEnv&); + jni::Local> get<%- camelize(property.name) %>Transition(jni::JNIEnv&); <% } -%> <% } -%> - jni::jobject* createJavaPeer(jni::JNIEnv&); + jni::Local> 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 return layer ? layer : new UnknownLayer(map, std::move(coreLayer)); } -jni::jobject* createJavaLayerPeer(jni::JNIEnv& env, Map& map, style::Layer& coreLayer) { +jni::Local> createJavaLayerPeer(jni::JNIEnv& env, Map& map, style::Layer& coreLayer) { std::unique_ptr peerLayer = std::unique_ptr(initializeLayerPeer(map, coreLayer)); - jni::jobject* result = peerLayer->createJavaPeer(env); + jni::Local> result = peerLayer->createJavaPeer(env); peerLayer.release(); return result; } -jni::jobject* createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr coreLayer) { +jni::Local> createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr coreLayer) { std::unique_ptr peerLayer = std::unique_ptr(initializeLayerPeer(map, std::move(coreLayer))); - jni::jobject* result = peerLayer->createJavaPeer(env); + jni::Local> 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> createJavaLayerPeer(jni::JNIEnv&, mbgl::Map&, mbgl::style::Layer&); /** * Create an owning peer */ -jni::jobject* createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr); +jni::Local> createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr); 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 2656bd9c09..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(jni::Make(env, layerId), jni::Make(env, sourceId))) { } @@ -35,40 +35,35 @@ namespace android { // Property getters - jni::Object LineLayer::getLineCap(jni::JNIEnv& env) { + jni::Local> LineLayer::getLineCap(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->LineLayer::getLineCap()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->LineLayer::getLineCap())); } - jni::Object LineLayer::getLineJoin(jni::JNIEnv& env) { + jni::Local> LineLayer::getLineJoin(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->LineLayer::getLineJoin()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->LineLayer::getLineJoin())); } - jni::Object LineLayer::getLineMiterLimit(jni::JNIEnv& env) { + jni::Local> LineLayer::getLineMiterLimit(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->LineLayer::getLineMiterLimit()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->LineLayer::getLineMiterLimit())); } - jni::Object LineLayer::getLineRoundLimit(jni::JNIEnv& env) { + jni::Local> LineLayer::getLineRoundLimit(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->LineLayer::getLineRoundLimit()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->LineLayer::getLineRoundLimit())); } - jni::Object LineLayer::getLineOpacity(jni::JNIEnv& env) { + jni::Local> LineLayer::getLineOpacity(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->LineLayer::getLineOpacity()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->LineLayer::getLineOpacity())); } - jni::Object LineLayer::getLineOpacityTransition(jni::JNIEnv& env) { + jni::Local> LineLayer::getLineOpacityTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->LineLayer::getLineOpacityTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void LineLayer::setLineOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -78,16 +73,15 @@ namespace android { layer.as()->LineLayer::setLineOpacityTransition(options); } - jni::Object LineLayer::getLineColor(jni::JNIEnv& env) { + jni::Local> LineLayer::getLineColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->LineLayer::getLineColor()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->LineLayer::getLineColor())); } - jni::Object LineLayer::getLineColorTransition(jni::JNIEnv& env) { + jni::Local> LineLayer::getLineColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->LineLayer::getLineColorTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void LineLayer::setLineColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -97,16 +91,15 @@ namespace android { layer.as()->LineLayer::setLineColorTransition(options); } - jni::Object LineLayer::getLineTranslate(jni::JNIEnv& env) { + jni::Local> LineLayer::getLineTranslate(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->LineLayer::getLineTranslate()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->LineLayer::getLineTranslate())); } - jni::Object LineLayer::getLineTranslateTransition(jni::JNIEnv& env) { + jni::Local> LineLayer::getLineTranslateTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->LineLayer::getLineTranslateTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void LineLayer::setLineTranslateTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -116,22 +109,20 @@ namespace android { layer.as()->LineLayer::setLineTranslateTransition(options); } - jni::Object LineLayer::getLineTranslateAnchor(jni::JNIEnv& env) { + jni::Local> LineLayer::getLineTranslateAnchor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->LineLayer::getLineTranslateAnchor()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->LineLayer::getLineTranslateAnchor())); } - jni::Object LineLayer::getLineWidth(jni::JNIEnv& env) { + jni::Local> LineLayer::getLineWidth(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->LineLayer::getLineWidth()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->LineLayer::getLineWidth())); } - jni::Object LineLayer::getLineWidthTransition(jni::JNIEnv& env) { + jni::Local> LineLayer::getLineWidthTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->LineLayer::getLineWidthTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void LineLayer::setLineWidthTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -141,16 +132,15 @@ namespace android { layer.as()->LineLayer::setLineWidthTransition(options); } - jni::Object LineLayer::getLineGapWidth(jni::JNIEnv& env) { + jni::Local> LineLayer::getLineGapWidth(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->LineLayer::getLineGapWidth()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->LineLayer::getLineGapWidth())); } - jni::Object LineLayer::getLineGapWidthTransition(jni::JNIEnv& env) { + jni::Local> LineLayer::getLineGapWidthTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->LineLayer::getLineGapWidthTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void LineLayer::setLineGapWidthTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -160,16 +150,15 @@ namespace android { layer.as()->LineLayer::setLineGapWidthTransition(options); } - jni::Object LineLayer::getLineOffset(jni::JNIEnv& env) { + jni::Local> LineLayer::getLineOffset(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->LineLayer::getLineOffset()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->LineLayer::getLineOffset())); } - jni::Object LineLayer::getLineOffsetTransition(jni::JNIEnv& env) { + jni::Local> LineLayer::getLineOffsetTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->LineLayer::getLineOffsetTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void LineLayer::setLineOffsetTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -179,16 +168,15 @@ namespace android { layer.as()->LineLayer::setLineOffsetTransition(options); } - jni::Object LineLayer::getLineBlur(jni::JNIEnv& env) { + jni::Local> LineLayer::getLineBlur(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->LineLayer::getLineBlur()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->LineLayer::getLineBlur())); } - jni::Object LineLayer::getLineBlurTransition(jni::JNIEnv& env) { + jni::Local> LineLayer::getLineBlurTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->LineLayer::getLineBlurTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void LineLayer::setLineBlurTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -198,16 +186,15 @@ namespace android { layer.as()->LineLayer::setLineBlurTransition(options); } - jni::Object LineLayer::getLineDasharray(jni::JNIEnv& env) { + jni::Local> LineLayer::getLineDasharray(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->LineLayer::getLineDasharray()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->LineLayer::getLineDasharray())); } - jni::Object LineLayer::getLineDasharrayTransition(jni::JNIEnv& env) { + jni::Local> LineLayer::getLineDasharrayTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->LineLayer::getLineDasharrayTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void LineLayer::setLineDasharrayTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -217,16 +204,15 @@ namespace android { layer.as()->LineLayer::setLineDasharrayTransition(options); } - jni::Object LineLayer::getLinePattern(jni::JNIEnv& env) { + jni::Local> LineLayer::getLinePattern(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->LineLayer::getLinePattern()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->LineLayer::getLinePattern())); } - jni::Object LineLayer::getLinePatternTransition(jni::JNIEnv& env) { + jni::Local> LineLayer::getLinePatternTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->LineLayer::getLinePatternTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void LineLayer::setLinePatternTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -236,29 +222,28 @@ namespace android { layer.as()->LineLayer::setLinePatternTransition(options); } - jni::Object LineLayer::getLineGradient(jni::JNIEnv& env) { + jni::Local> LineLayer::getLineGradient(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->LineLayer::getLineGradient()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->LineLayer::getLineGradient())); } - jni::jobject* LineLayer::createJavaPeer(jni::JNIEnv& env) { - static auto javaClass = jni::Class::Singleton(env); + jni::Local> LineLayer::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); return javaClass.New(env, constructor, reinterpret_cast(this)); } void LineLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( env, javaClass, "nativePtr", - std::make_unique, + jni::MakePeer, "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 4d1e759c1b..01be481958 100644 --- a/platform/android/src/style/layers/line_layer.hpp +++ b/platform/android/src/style/layers/line_layer.hpp @@ -12,12 +12,12 @@ namespace android { class LineLayer : public Layer { public: - + using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/LineLayer"; }; 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&); @@ -27,54 +27,54 @@ public: // Properties - jni::Object getLineCap(jni::JNIEnv&); + jni::Local> getLineCap(jni::JNIEnv&); - jni::Object getLineJoin(jni::JNIEnv&); + jni::Local> getLineJoin(jni::JNIEnv&); - jni::Object getLineMiterLimit(jni::JNIEnv&); + jni::Local> getLineMiterLimit(jni::JNIEnv&); - jni::Object getLineRoundLimit(jni::JNIEnv&); + jni::Local> getLineRoundLimit(jni::JNIEnv&); - jni::Object getLineOpacity(jni::JNIEnv&); + jni::Local> getLineOpacity(jni::JNIEnv&); void setLineOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getLineOpacityTransition(jni::JNIEnv&); + jni::Local> getLineOpacityTransition(jni::JNIEnv&); - jni::Object getLineColor(jni::JNIEnv&); + jni::Local> getLineColor(jni::JNIEnv&); void setLineColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getLineColorTransition(jni::JNIEnv&); + jni::Local> getLineColorTransition(jni::JNIEnv&); - jni::Object getLineTranslate(jni::JNIEnv&); + jni::Local> getLineTranslate(jni::JNIEnv&); void setLineTranslateTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getLineTranslateTransition(jni::JNIEnv&); + jni::Local> getLineTranslateTransition(jni::JNIEnv&); - jni::Object getLineTranslateAnchor(jni::JNIEnv&); + jni::Local> getLineTranslateAnchor(jni::JNIEnv&); - jni::Object getLineWidth(jni::JNIEnv&); + jni::Local> getLineWidth(jni::JNIEnv&); void setLineWidthTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getLineWidthTransition(jni::JNIEnv&); + jni::Local> getLineWidthTransition(jni::JNIEnv&); - jni::Object getLineGapWidth(jni::JNIEnv&); + jni::Local> getLineGapWidth(jni::JNIEnv&); void setLineGapWidthTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getLineGapWidthTransition(jni::JNIEnv&); + jni::Local> getLineGapWidthTransition(jni::JNIEnv&); - jni::Object getLineOffset(jni::JNIEnv&); + jni::Local> getLineOffset(jni::JNIEnv&); void setLineOffsetTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getLineOffsetTransition(jni::JNIEnv&); + jni::Local> getLineOffsetTransition(jni::JNIEnv&); - jni::Object getLineBlur(jni::JNIEnv&); + jni::Local> getLineBlur(jni::JNIEnv&); void setLineBlurTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getLineBlurTransition(jni::JNIEnv&); + jni::Local> getLineBlurTransition(jni::JNIEnv&); - jni::Object getLineDasharray(jni::JNIEnv&); + jni::Local> getLineDasharray(jni::JNIEnv&); void setLineDasharrayTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getLineDasharrayTransition(jni::JNIEnv&); + jni::Local> getLineDasharrayTransition(jni::JNIEnv&); - jni::Object getLinePattern(jni::JNIEnv&); + jni::Local> getLinePattern(jni::JNIEnv&); void setLinePatternTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getLinePatternTransition(jni::JNIEnv&); + jni::Local> getLinePatternTransition(jni::JNIEnv&); - jni::Object getLineGradient(jni::JNIEnv&); - jni::jobject* createJavaPeer(jni::JNIEnv&); + jni::Local> getLineGradient(jni::JNIEnv&); + jni::Local> 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 c52891b662..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(jni::Make(env, layerId), jni::Make(env, sourceId))) { } @@ -35,16 +35,15 @@ namespace android { // Property getters - jni::Object RasterLayer::getRasterOpacity(jni::JNIEnv& env) { + jni::Local> RasterLayer::getRasterOpacity(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->RasterLayer::getRasterOpacity()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->RasterLayer::getRasterOpacity())); } - jni::Object RasterLayer::getRasterOpacityTransition(jni::JNIEnv& env) { + jni::Local> RasterLayer::getRasterOpacityTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->RasterLayer::getRasterOpacityTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void RasterLayer::setRasterOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -54,16 +53,15 @@ namespace android { layer.as()->RasterLayer::setRasterOpacityTransition(options); } - jni::Object RasterLayer::getRasterHueRotate(jni::JNIEnv& env) { + jni::Local> RasterLayer::getRasterHueRotate(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->RasterLayer::getRasterHueRotate()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->RasterLayer::getRasterHueRotate())); } - jni::Object RasterLayer::getRasterHueRotateTransition(jni::JNIEnv& env) { + jni::Local> RasterLayer::getRasterHueRotateTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->RasterLayer::getRasterHueRotateTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void RasterLayer::setRasterHueRotateTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -73,16 +71,15 @@ namespace android { layer.as()->RasterLayer::setRasterHueRotateTransition(options); } - jni::Object RasterLayer::getRasterBrightnessMin(jni::JNIEnv& env) { + jni::Local> RasterLayer::getRasterBrightnessMin(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->RasterLayer::getRasterBrightnessMin()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->RasterLayer::getRasterBrightnessMin())); } - jni::Object RasterLayer::getRasterBrightnessMinTransition(jni::JNIEnv& env) { + jni::Local> RasterLayer::getRasterBrightnessMinTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->RasterLayer::getRasterBrightnessMinTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void RasterLayer::setRasterBrightnessMinTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -92,16 +89,15 @@ namespace android { layer.as()->RasterLayer::setRasterBrightnessMinTransition(options); } - jni::Object RasterLayer::getRasterBrightnessMax(jni::JNIEnv& env) { + jni::Local> RasterLayer::getRasterBrightnessMax(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->RasterLayer::getRasterBrightnessMax()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->RasterLayer::getRasterBrightnessMax())); } - jni::Object RasterLayer::getRasterBrightnessMaxTransition(jni::JNIEnv& env) { + jni::Local> RasterLayer::getRasterBrightnessMaxTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->RasterLayer::getRasterBrightnessMaxTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void RasterLayer::setRasterBrightnessMaxTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -111,16 +107,15 @@ namespace android { layer.as()->RasterLayer::setRasterBrightnessMaxTransition(options); } - jni::Object RasterLayer::getRasterSaturation(jni::JNIEnv& env) { + jni::Local> RasterLayer::getRasterSaturation(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->RasterLayer::getRasterSaturation()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->RasterLayer::getRasterSaturation())); } - jni::Object RasterLayer::getRasterSaturationTransition(jni::JNIEnv& env) { + jni::Local> RasterLayer::getRasterSaturationTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->RasterLayer::getRasterSaturationTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void RasterLayer::setRasterSaturationTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -130,16 +125,15 @@ namespace android { layer.as()->RasterLayer::setRasterSaturationTransition(options); } - jni::Object RasterLayer::getRasterContrast(jni::JNIEnv& env) { + jni::Local> RasterLayer::getRasterContrast(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->RasterLayer::getRasterContrast()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->RasterLayer::getRasterContrast())); } - jni::Object RasterLayer::getRasterContrastTransition(jni::JNIEnv& env) { + jni::Local> RasterLayer::getRasterContrastTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->RasterLayer::getRasterContrastTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void RasterLayer::setRasterContrastTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -149,35 +143,33 @@ namespace android { layer.as()->RasterLayer::setRasterContrastTransition(options); } - jni::Object RasterLayer::getRasterResampling(jni::JNIEnv& env) { + jni::Local> RasterLayer::getRasterResampling(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->RasterLayer::getRasterResampling()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->RasterLayer::getRasterResampling())); } - jni::Object RasterLayer::getRasterFadeDuration(jni::JNIEnv& env) { + jni::Local> RasterLayer::getRasterFadeDuration(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->RasterLayer::getRasterFadeDuration()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->RasterLayer::getRasterFadeDuration())); } - jni::jobject* RasterLayer::createJavaPeer(jni::JNIEnv& env) { - static auto javaClass = jni::Class::Singleton(env); + jni::Local> RasterLayer::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); return javaClass.New(env, constructor, reinterpret_cast(this)); } void RasterLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( env, javaClass, "nativePtr", - std::make_unique, + jni::MakePeer, "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 4e268c36e5..40cc47634e 100644 --- a/platform/android/src/style/layers/raster_layer.hpp +++ b/platform/android/src/style/layers/raster_layer.hpp @@ -12,12 +12,12 @@ namespace android { class RasterLayer : public Layer { public: - + using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/RasterLayer"; }; 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&); @@ -27,34 +27,34 @@ public: // Properties - jni::Object getRasterOpacity(jni::JNIEnv&); + jni::Local> getRasterOpacity(jni::JNIEnv&); void setRasterOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getRasterOpacityTransition(jni::JNIEnv&); + jni::Local> getRasterOpacityTransition(jni::JNIEnv&); - jni::Object getRasterHueRotate(jni::JNIEnv&); + jni::Local> getRasterHueRotate(jni::JNIEnv&); void setRasterHueRotateTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getRasterHueRotateTransition(jni::JNIEnv&); + jni::Local> getRasterHueRotateTransition(jni::JNIEnv&); - jni::Object getRasterBrightnessMin(jni::JNIEnv&); + jni::Local> getRasterBrightnessMin(jni::JNIEnv&); void setRasterBrightnessMinTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getRasterBrightnessMinTransition(jni::JNIEnv&); + jni::Local> getRasterBrightnessMinTransition(jni::JNIEnv&); - jni::Object getRasterBrightnessMax(jni::JNIEnv&); + jni::Local> getRasterBrightnessMax(jni::JNIEnv&); void setRasterBrightnessMaxTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getRasterBrightnessMaxTransition(jni::JNIEnv&); + jni::Local> getRasterBrightnessMaxTransition(jni::JNIEnv&); - jni::Object getRasterSaturation(jni::JNIEnv&); + jni::Local> getRasterSaturation(jni::JNIEnv&); void setRasterSaturationTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getRasterSaturationTransition(jni::JNIEnv&); + jni::Local> getRasterSaturationTransition(jni::JNIEnv&); - jni::Object getRasterContrast(jni::JNIEnv&); + jni::Local> getRasterContrast(jni::JNIEnv&); void setRasterContrastTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getRasterContrastTransition(jni::JNIEnv&); + jni::Local> getRasterContrastTransition(jni::JNIEnv&); - jni::Object getRasterResampling(jni::JNIEnv&); + jni::Local> getRasterResampling(jni::JNIEnv&); - jni::Object getRasterFadeDuration(jni::JNIEnv&); - jni::jobject* createJavaPeer(jni::JNIEnv&); + jni::Local> getRasterFadeDuration(jni::JNIEnv&); + jni::Local> 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 953c73e221..a0f37c91d2 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(jni::Make(env, layerId), jni::Make(env, sourceId))) { } @@ -35,232 +35,195 @@ namespace android { // Property getters - jni::Object SymbolLayer::getSymbolPlacement(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getSymbolPlacement(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getSymbolPlacement()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getSymbolPlacement())); } - jni::Object SymbolLayer::getSymbolSpacing(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getSymbolSpacing(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getSymbolSpacing()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getSymbolSpacing())); } - jni::Object SymbolLayer::getSymbolAvoidEdges(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getSymbolAvoidEdges(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getSymbolAvoidEdges()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getSymbolAvoidEdges())); } - jni::Object SymbolLayer::getIconAllowOverlap(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getIconAllowOverlap(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getIconAllowOverlap()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getIconAllowOverlap())); } - jni::Object SymbolLayer::getIconIgnorePlacement(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getIconIgnorePlacement(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getIconIgnorePlacement()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getIconIgnorePlacement())); } - jni::Object SymbolLayer::getIconOptional(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getIconOptional(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getIconOptional()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getIconOptional())); } - jni::Object SymbolLayer::getIconRotationAlignment(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getIconRotationAlignment(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getIconRotationAlignment()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getIconRotationAlignment())); } - jni::Object SymbolLayer::getIconSize(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getIconSize(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getIconSize()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getIconSize())); } - jni::Object SymbolLayer::getIconTextFit(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getIconTextFit(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getIconTextFit()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getIconTextFit())); } - jni::Object SymbolLayer::getIconTextFitPadding(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getIconTextFitPadding(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getIconTextFitPadding()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getIconTextFitPadding())); } - jni::Object SymbolLayer::getIconImage(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getIconImage(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getIconImage()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getIconImage())); } - jni::Object SymbolLayer::getIconRotate(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getIconRotate(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getIconRotate()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getIconRotate())); } - jni::Object SymbolLayer::getIconPadding(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getIconPadding(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getIconPadding()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getIconPadding())); } - jni::Object SymbolLayer::getIconKeepUpright(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getIconKeepUpright(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getIconKeepUpright()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getIconKeepUpright())); } - jni::Object SymbolLayer::getIconOffset(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getIconOffset(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getIconOffset()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getIconOffset())); } - jni::Object SymbolLayer::getIconAnchor(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getIconAnchor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getIconAnchor()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getIconAnchor())); } - jni::Object SymbolLayer::getIconPitchAlignment(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getIconPitchAlignment(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getIconPitchAlignment()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getIconPitchAlignment())); } - jni::Object SymbolLayer::getTextPitchAlignment(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextPitchAlignment(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getTextPitchAlignment()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getTextPitchAlignment())); } - jni::Object SymbolLayer::getTextRotationAlignment(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextRotationAlignment(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getTextRotationAlignment()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getTextRotationAlignment())); } - jni::Object SymbolLayer::getTextField(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextField(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getTextField()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getTextField())); } - jni::Object SymbolLayer::getTextFont(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextFont(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getTextFont()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getTextFont())); } - jni::Object SymbolLayer::getTextSize(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextSize(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getTextSize()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getTextSize())); } - jni::Object SymbolLayer::getTextMaxWidth(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextMaxWidth(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getTextMaxWidth()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getTextMaxWidth())); } - jni::Object SymbolLayer::getTextLineHeight(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextLineHeight(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getTextLineHeight()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getTextLineHeight())); } - jni::Object SymbolLayer::getTextLetterSpacing(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextLetterSpacing(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getTextLetterSpacing()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getTextLetterSpacing())); } - jni::Object SymbolLayer::getTextJustify(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextJustify(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getTextJustify()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getTextJustify())); } - jni::Object SymbolLayer::getTextAnchor(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextAnchor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getTextAnchor()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getTextAnchor())); } - jni::Object SymbolLayer::getTextMaxAngle(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextMaxAngle(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getTextMaxAngle()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getTextMaxAngle())); } - jni::Object SymbolLayer::getTextRotate(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextRotate(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getTextRotate()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getTextRotate())); } - jni::Object SymbolLayer::getTextPadding(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextPadding(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getTextPadding()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getTextPadding())); } - jni::Object SymbolLayer::getTextKeepUpright(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextKeepUpright(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getTextKeepUpright()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getTextKeepUpright())); } - jni::Object SymbolLayer::getTextTransform(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextTransform(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getTextTransform()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getTextTransform())); } - jni::Object SymbolLayer::getTextOffset(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextOffset(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getTextOffset()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getTextOffset())); } - jni::Object SymbolLayer::getTextAllowOverlap(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextAllowOverlap(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getTextAllowOverlap()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getTextAllowOverlap())); } - jni::Object SymbolLayer::getTextIgnorePlacement(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextIgnorePlacement(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getTextIgnorePlacement()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getTextIgnorePlacement())); } - jni::Object SymbolLayer::getTextOptional(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextOptional(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getTextOptional()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getTextOptional())); } - jni::Object SymbolLayer::getIconOpacity(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getIconOpacity(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getIconOpacity()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getIconOpacity())); } - jni::Object SymbolLayer::getIconOpacityTransition(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getIconOpacityTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->SymbolLayer::getIconOpacityTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void SymbolLayer::setIconOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -270,16 +233,15 @@ namespace android { layer.as()->SymbolLayer::setIconOpacityTransition(options); } - jni::Object SymbolLayer::getIconColor(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getIconColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getIconColor()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getIconColor())); } - jni::Object SymbolLayer::getIconColorTransition(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getIconColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->SymbolLayer::getIconColorTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void SymbolLayer::setIconColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -289,16 +251,15 @@ namespace android { layer.as()->SymbolLayer::setIconColorTransition(options); } - jni::Object SymbolLayer::getIconHaloColor(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getIconHaloColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getIconHaloColor()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getIconHaloColor())); } - jni::Object SymbolLayer::getIconHaloColorTransition(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getIconHaloColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->SymbolLayer::getIconHaloColorTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void SymbolLayer::setIconHaloColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -308,16 +269,15 @@ namespace android { layer.as()->SymbolLayer::setIconHaloColorTransition(options); } - jni::Object SymbolLayer::getIconHaloWidth(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getIconHaloWidth(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getIconHaloWidth()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getIconHaloWidth())); } - jni::Object SymbolLayer::getIconHaloWidthTransition(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getIconHaloWidthTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->SymbolLayer::getIconHaloWidthTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void SymbolLayer::setIconHaloWidthTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -327,16 +287,15 @@ namespace android { layer.as()->SymbolLayer::setIconHaloWidthTransition(options); } - jni::Object SymbolLayer::getIconHaloBlur(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getIconHaloBlur(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getIconHaloBlur()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getIconHaloBlur())); } - jni::Object SymbolLayer::getIconHaloBlurTransition(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getIconHaloBlurTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->SymbolLayer::getIconHaloBlurTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void SymbolLayer::setIconHaloBlurTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -346,16 +305,15 @@ namespace android { layer.as()->SymbolLayer::setIconHaloBlurTransition(options); } - jni::Object SymbolLayer::getIconTranslate(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getIconTranslate(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getIconTranslate()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getIconTranslate())); } - jni::Object SymbolLayer::getIconTranslateTransition(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getIconTranslateTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->SymbolLayer::getIconTranslateTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void SymbolLayer::setIconTranslateTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -365,22 +323,20 @@ namespace android { layer.as()->SymbolLayer::setIconTranslateTransition(options); } - jni::Object SymbolLayer::getIconTranslateAnchor(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getIconTranslateAnchor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getIconTranslateAnchor()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getIconTranslateAnchor())); } - jni::Object SymbolLayer::getTextOpacity(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextOpacity(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getTextOpacity()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getTextOpacity())); } - jni::Object SymbolLayer::getTextOpacityTransition(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextOpacityTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->SymbolLayer::getTextOpacityTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void SymbolLayer::setTextOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -390,16 +346,15 @@ namespace android { layer.as()->SymbolLayer::setTextOpacityTransition(options); } - jni::Object SymbolLayer::getTextColor(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getTextColor()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getTextColor())); } - jni::Object SymbolLayer::getTextColorTransition(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->SymbolLayer::getTextColorTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void SymbolLayer::setTextColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -409,16 +364,15 @@ namespace android { layer.as()->SymbolLayer::setTextColorTransition(options); } - jni::Object SymbolLayer::getTextHaloColor(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextHaloColor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getTextHaloColor()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getTextHaloColor())); } - jni::Object SymbolLayer::getTextHaloColorTransition(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextHaloColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->SymbolLayer::getTextHaloColorTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void SymbolLayer::setTextHaloColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -428,16 +382,15 @@ namespace android { layer.as()->SymbolLayer::setTextHaloColorTransition(options); } - jni::Object SymbolLayer::getTextHaloWidth(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextHaloWidth(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getTextHaloWidth()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getTextHaloWidth())); } - jni::Object SymbolLayer::getTextHaloWidthTransition(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextHaloWidthTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->SymbolLayer::getTextHaloWidthTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void SymbolLayer::setTextHaloWidthTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -447,16 +400,15 @@ namespace android { layer.as()->SymbolLayer::setTextHaloWidthTransition(options); } - jni::Object SymbolLayer::getTextHaloBlur(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextHaloBlur(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getTextHaloBlur()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getTextHaloBlur())); } - jni::Object SymbolLayer::getTextHaloBlurTransition(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextHaloBlurTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->SymbolLayer::getTextHaloBlurTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void SymbolLayer::setTextHaloBlurTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -466,16 +418,15 @@ namespace android { layer.as()->SymbolLayer::setTextHaloBlurTransition(options); } - jni::Object SymbolLayer::getTextTranslate(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextTranslate(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getTextTranslate()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getTextTranslate())); } - jni::Object SymbolLayer::getTextTranslateTransition(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextTranslateTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = layer.as()->SymbolLayer::getTextTranslateTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void SymbolLayer::setTextTranslateTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -485,29 +436,28 @@ namespace android { layer.as()->SymbolLayer::setTextTranslateTransition(options); } - jni::Object SymbolLayer::getTextTranslateAnchor(jni::JNIEnv& env) { + jni::Local> SymbolLayer::getTextTranslateAnchor(jni::JNIEnv& env) { using namespace mbgl::android::conversion; - Result converted = convert(env, layer.as()->SymbolLayer::getTextTranslateAnchor()); - return jni::Object(*converted); + return std::move(*convert>>(env, layer.as()->SymbolLayer::getTextTranslateAnchor())); } - jni::jobject* SymbolLayer::createJavaPeer(jni::JNIEnv& env) { - static auto javaClass = jni::Class::Singleton(env); + jni::Local> SymbolLayer::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); return javaClass.New(env, constructor, reinterpret_cast(this)); } void SymbolLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( env, javaClass, "nativePtr", - std::make_unique, + jni::MakePeer, "initialize", "finalize", METHOD(&SymbolLayer::getSymbolPlacement, "nativeGetSymbolPlacement"), diff --git a/platform/android/src/style/layers/symbol_layer.hpp b/platform/android/src/style/layers/symbol_layer.hpp index 3835e01bf1..206a6546c3 100644 --- a/platform/android/src/style/layers/symbol_layer.hpp +++ b/platform/android/src/style/layers/symbol_layer.hpp @@ -12,12 +12,12 @@ namespace android { class SymbolLayer : public Layer { public: - + using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/SymbolLayer"; }; 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&); @@ -27,130 +27,130 @@ public: // Properties - jni::Object getSymbolPlacement(jni::JNIEnv&); + jni::Local> getSymbolPlacement(jni::JNIEnv&); - jni::Object getSymbolSpacing(jni::JNIEnv&); + jni::Local> getSymbolSpacing(jni::JNIEnv&); - jni::Object getSymbolAvoidEdges(jni::JNIEnv&); + jni::Local> getSymbolAvoidEdges(jni::JNIEnv&); - jni::Object getIconAllowOverlap(jni::JNIEnv&); + jni::Local> getIconAllowOverlap(jni::JNIEnv&); - jni::Object getIconIgnorePlacement(jni::JNIEnv&); + jni::Local> getIconIgnorePlacement(jni::JNIEnv&); - jni::Object getIconOptional(jni::JNIEnv&); + jni::Local> getIconOptional(jni::JNIEnv&); - jni::Object getIconRotationAlignment(jni::JNIEnv&); + jni::Local> getIconRotationAlignment(jni::JNIEnv&); - jni::Object getIconSize(jni::JNIEnv&); + jni::Local> getIconSize(jni::JNIEnv&); - jni::Object getIconTextFit(jni::JNIEnv&); + jni::Local> getIconTextFit(jni::JNIEnv&); - jni::Object getIconTextFitPadding(jni::JNIEnv&); + jni::Local> getIconTextFitPadding(jni::JNIEnv&); - jni::Object getIconImage(jni::JNIEnv&); + jni::Local> getIconImage(jni::JNIEnv&); - jni::Object getIconRotate(jni::JNIEnv&); + jni::Local> getIconRotate(jni::JNIEnv&); - jni::Object getIconPadding(jni::JNIEnv&); + jni::Local> getIconPadding(jni::JNIEnv&); - jni::Object getIconKeepUpright(jni::JNIEnv&); + jni::Local> getIconKeepUpright(jni::JNIEnv&); - jni::Object getIconOffset(jni::JNIEnv&); + jni::Local> getIconOffset(jni::JNIEnv&); - jni::Object getIconAnchor(jni::JNIEnv&); + jni::Local> getIconAnchor(jni::JNIEnv&); - jni::Object getIconPitchAlignment(jni::JNIEnv&); + jni::Local> getIconPitchAlignment(jni::JNIEnv&); - jni::Object getTextPitchAlignment(jni::JNIEnv&); + jni::Local> getTextPitchAlignment(jni::JNIEnv&); - jni::Object getTextRotationAlignment(jni::JNIEnv&); + jni::Local> getTextRotationAlignment(jni::JNIEnv&); - jni::Object getTextField(jni::JNIEnv&); + jni::Local> getTextField(jni::JNIEnv&); - jni::Object getTextFont(jni::JNIEnv&); + jni::Local> getTextFont(jni::JNIEnv&); - jni::Object getTextSize(jni::JNIEnv&); + jni::Local> getTextSize(jni::JNIEnv&); - jni::Object getTextMaxWidth(jni::JNIEnv&); + jni::Local> getTextMaxWidth(jni::JNIEnv&); - jni::Object getTextLineHeight(jni::JNIEnv&); + jni::Local> getTextLineHeight(jni::JNIEnv&); - jni::Object getTextLetterSpacing(jni::JNIEnv&); + jni::Local> getTextLetterSpacing(jni::JNIEnv&); - jni::Object getTextJustify(jni::JNIEnv&); + jni::Local> getTextJustify(jni::JNIEnv&); - jni::Object getTextAnchor(jni::JNIEnv&); + jni::Local> getTextAnchor(jni::JNIEnv&); - jni::Object getTextMaxAngle(jni::JNIEnv&); + jni::Local> getTextMaxAngle(jni::JNIEnv&); - jni::Object getTextRotate(jni::JNIEnv&); + jni::Local> getTextRotate(jni::JNIEnv&); - jni::Object getTextPadding(jni::JNIEnv&); + jni::Local> getTextPadding(jni::JNIEnv&); - jni::Object getTextKeepUpright(jni::JNIEnv&); + jni::Local> getTextKeepUpright(jni::JNIEnv&); - jni::Object getTextTransform(jni::JNIEnv&); + jni::Local> getTextTransform(jni::JNIEnv&); - jni::Object getTextOffset(jni::JNIEnv&); + jni::Local> getTextOffset(jni::JNIEnv&); - jni::Object getTextAllowOverlap(jni::JNIEnv&); + jni::Local> getTextAllowOverlap(jni::JNIEnv&); - jni::Object getTextIgnorePlacement(jni::JNIEnv&); + jni::Local> getTextIgnorePlacement(jni::JNIEnv&); - jni::Object getTextOptional(jni::JNIEnv&); + jni::Local> getTextOptional(jni::JNIEnv&); - jni::Object getIconOpacity(jni::JNIEnv&); + jni::Local> getIconOpacity(jni::JNIEnv&); void setIconOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getIconOpacityTransition(jni::JNIEnv&); + jni::Local> getIconOpacityTransition(jni::JNIEnv&); - jni::Object getIconColor(jni::JNIEnv&); + jni::Local> getIconColor(jni::JNIEnv&); void setIconColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getIconColorTransition(jni::JNIEnv&); + jni::Local> getIconColorTransition(jni::JNIEnv&); - jni::Object getIconHaloColor(jni::JNIEnv&); + jni::Local> getIconHaloColor(jni::JNIEnv&); void setIconHaloColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getIconHaloColorTransition(jni::JNIEnv&); + jni::Local> getIconHaloColorTransition(jni::JNIEnv&); - jni::Object getIconHaloWidth(jni::JNIEnv&); + jni::Local> getIconHaloWidth(jni::JNIEnv&); void setIconHaloWidthTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getIconHaloWidthTransition(jni::JNIEnv&); + jni::Local> getIconHaloWidthTransition(jni::JNIEnv&); - jni::Object getIconHaloBlur(jni::JNIEnv&); + jni::Local> getIconHaloBlur(jni::JNIEnv&); void setIconHaloBlurTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getIconHaloBlurTransition(jni::JNIEnv&); + jni::Local> getIconHaloBlurTransition(jni::JNIEnv&); - jni::Object getIconTranslate(jni::JNIEnv&); + jni::Local> getIconTranslate(jni::JNIEnv&); void setIconTranslateTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getIconTranslateTransition(jni::JNIEnv&); + jni::Local> getIconTranslateTransition(jni::JNIEnv&); - jni::Object getIconTranslateAnchor(jni::JNIEnv&); + jni::Local> getIconTranslateAnchor(jni::JNIEnv&); - jni::Object getTextOpacity(jni::JNIEnv&); + jni::Local> getTextOpacity(jni::JNIEnv&); void setTextOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getTextOpacityTransition(jni::JNIEnv&); + jni::Local> getTextOpacityTransition(jni::JNIEnv&); - jni::Object getTextColor(jni::JNIEnv&); + jni::Local> getTextColor(jni::JNIEnv&); void setTextColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getTextColorTransition(jni::JNIEnv&); + jni::Local> getTextColorTransition(jni::JNIEnv&); - jni::Object getTextHaloColor(jni::JNIEnv&); + jni::Local> getTextHaloColor(jni::JNIEnv&); void setTextHaloColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getTextHaloColorTransition(jni::JNIEnv&); + jni::Local> getTextHaloColorTransition(jni::JNIEnv&); - jni::Object getTextHaloWidth(jni::JNIEnv&); + jni::Local> getTextHaloWidth(jni::JNIEnv&); void setTextHaloWidthTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getTextHaloWidthTransition(jni::JNIEnv&); + jni::Local> getTextHaloWidthTransition(jni::JNIEnv&); - jni::Object getTextHaloBlur(jni::JNIEnv&); + jni::Local> getTextHaloBlur(jni::JNIEnv&); void setTextHaloBlurTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getTextHaloBlurTransition(jni::JNIEnv&); + jni::Local> getTextHaloBlurTransition(jni::JNIEnv&); - jni::Object getTextTranslate(jni::JNIEnv&); + jni::Local> getTextTranslate(jni::JNIEnv&); void setTextTranslateTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getTextTranslateTransition(jni::JNIEnv&); + jni::Local> getTextTranslateTransition(jni::JNIEnv&); - jni::Object getTextTranslateAnchor(jni::JNIEnv&); - jni::jobject* createJavaPeer(jni::JNIEnv&); + jni::Local> getTextTranslateAnchor(jni::JNIEnv&); + jni::Local> 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 9f877e4896..5c770012bd 100644 --- a/platform/android/src/style/layers/unknown_layer.cpp +++ b/platform/android/src/style/layers/unknown_layer.cpp @@ -22,15 +22,15 @@ namespace android { : Layer(map, std::move(coreLayer)) { } - jni::jobject* UnknownLayer::createJavaPeer(jni::JNIEnv& env) { - static auto javaClass = jni::Class::Singleton(env); + jni::Local> UnknownLayer::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); return javaClass.New(env, constructor, reinterpret_cast(this)); } void UnknownLayer::registerNative(jni::JNIEnv& env) { // Lookup the class - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) diff --git a/platform/android/src/style/layers/unknown_layer.hpp b/platform/android/src/style/layers/unknown_layer.hpp index 0610c843f1..692e2f5db4 100644 --- a/platform/android/src/style/layers/unknown_layer.hpp +++ b/platform/android/src/style/layers/unknown_layer.hpp @@ -9,7 +9,7 @@ namespace android { class UnknownLayer : public Layer { public: - + using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/UnknownLayer"; }; static void registerNative(jni::JNIEnv&); @@ -20,7 +20,7 @@ public: ~UnknownLayer() = default; - jni::jobject* createJavaPeer(jni::JNIEnv&); + jni::Local> createJavaPeer(jni::JNIEnv&); }; // class UnknownLayer diff --git a/platform/android/src/style/light.cpp b/platform/android/src/style/light.cpp index 64afb89204..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 #include "light.hpp" #include "conversion/transition_options.hpp" @@ -16,20 +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> Light::createJavaLightPeer(jni::JNIEnv& env, Map& map, mbgl::style::Light& coreLight) { std::unique_ptr peerLight = std::unique_ptr(initializeLightPeer(map, coreLight)); - jni::jobject* result = peerLight->createJavaPeer(env); + auto result = peerLight->createJavaPeer(env); peerLight.release(); return result; } -jni::jobject* Light::createJavaPeer(jni::JNIEnv& env) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local> Light::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); return javaClass.New(env, constructor, reinterpret_cast(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(env, property); if (anchorStr.compare("map") == 0) { light.setAnchor(LightAnchorType::Map); @@ -38,7 +36,7 @@ void Light::setAnchor(jni::JNIEnv& env, jni::String property) { } } -jni::String Light::getAnchor(jni::JNIEnv& env) { +jni::Local Light::getAnchor(jni::JNIEnv& env) { auto anchorType = light.getAnchor(); if (anchorType == LightAnchorType::Map) { return jni::Make(env, "map"); @@ -47,22 +45,22 @@ jni::String Light::getAnchor(jni::JNIEnv& env) { } } -void Light::setPosition(jni::JNIEnv& env, jni::Object jposition) { +void Light::setPosition(jni::JNIEnv& env, const jni::Object& jposition) { using namespace mbgl::android::conversion; auto position = *convert(env, jposition); light.setPosition(position); } -jni::Object Light::getPosition(jni::JNIEnv& env) { +jni::Local> Light::getPosition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::Position position = light.getPosition().asConstant(); - return *convert>(env, position); + return std::move(*convert>>(env, position)); } -jni::Object Light::getPositionTransition(jni::JNIEnv& env) { +jni::Local> Light::getPositionTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = light.getPositionTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void Light::setPositionTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -72,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(env, property)); if (color) { light.setColor(color.value()); } } -jni::String Light::getColor(jni::JNIEnv &env) { +jni::Local Light::getColor(jni::JNIEnv &env) { auto color = light.getColor().asConstant(); return jni::Make(env, color.stringify()); } -jni::Object Light::getColorTransition(jni::JNIEnv& env) { +jni::Local> Light::getColorTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = light.getColorTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void Light::setColorTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -105,10 +103,10 @@ jni::jfloat Light::getIntensity(jni::JNIEnv&) { return light.getIntensity().asConstant(); } -jni::Object Light::getIntensityTransition(jni::JNIEnv& env) { +jni::Local> Light::getIntensityTransition(jni::JNIEnv& env) { using namespace mbgl::android::conversion; mbgl::style::TransitionOptions options = light.getIntensityTransition(); - return *convert>(env, options); + return std::move(*convert>>(env, options)); } void Light::setIntensityTransition(jni::JNIEnv&, jlong duration, jlong delay) { @@ -120,7 +118,7 @@ void Light::setIntensityTransition(jni::JNIEnv&, jlong duration, jlong delay) { void Light::registerNative(jni::JNIEnv& env) { // Lookup the class - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer diff --git a/platform/android/src/style/light.cpp.ejs b/platform/android/src/style/light.cpp.ejs deleted file mode 100644 index f18dc57a4f..0000000000 --- a/platform/android/src/style/light.cpp.ejs +++ /dev/null @@ -1,122 +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 -#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 peerLight = std::unique_ptr(initializeLightPeer(map, coreLight)); - jni::jobject* result = peerLight->createJavaPeer(env); - peerLight.release(); - return result; -} - -jni::jobject* Light::createJavaPeer(jni::JNIEnv& env) { - static auto javaClass = jni::Class::Singleton(env); - static auto constructor = javaClass.GetConstructor(env); - return javaClass.New(env, constructor, reinterpret_cast(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>(env, jposition); - light.set<%- camelize(property.name) %>(<%- property.name %>); -} - -jni::Object 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>>(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(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(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(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(env, "map"); - } else { - return jni::Make(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 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>(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 - static auto javaClass = jni::Class::Singleton(env); - -#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) - // Register the peer - jni::RegisterNativePeer(env, 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 @@ -21,29 +19,27 @@ public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/light/Light"; }; - static jni::Class javaClass; - static void registerNative(jni::JNIEnv&); - static jni::jobject* createJavaLightPeer(jni::JNIEnv&, mbgl::Map&, mbgl::style::Light&); + static jni::Local> 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); - jni::Object getPosition(jni::JNIEnv&); + void setAnchor(jni::JNIEnv&, const jni::String&); + jni::Local getAnchor(jni::JNIEnv&); + void setPosition(jni::JNIEnv&, const jni::Object&); + jni::Local> getPosition(jni::JNIEnv&); void setPositionTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getPositionTransition(jni::JNIEnv&); - void setColor(jni::JNIEnv&, jni::String); - jni::String getColor(jni::JNIEnv&); + jni::Local> getPositionTransition(jni::JNIEnv&); + void setColor(jni::JNIEnv&, const jni::String&); + jni::Local getColor(jni::JNIEnv&); void setColorTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getColorTransition(jni::JNIEnv&); + jni::Local> getColorTransition(jni::JNIEnv&); void setIntensity(jni::JNIEnv&, jni::jfloat); jni::jfloat getIntensity(jni::JNIEnv&); void setIntensityTransition(jni::JNIEnv&, jlong duration, jlong delay); - jni::Object getIntensityTransition(jni::JNIEnv&); - jni::jobject* createJavaPeer(jni::JNIEnv&); + jni::Local> getIntensityTransition(jni::JNIEnv&); + jni::Local> 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 - -#include -#include -#include "transition_options.hpp" -#include "position.hpp" -#include -#include - -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 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); - 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 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 c6918a2e9a..20a0c47dff 100644 --- a/platform/android/src/style/position.cpp +++ b/platform/android/src/style/position.cpp @@ -3,8 +3,8 @@ namespace mbgl { namespace android { -jni::Object Position::fromPosition(jni::JNIEnv& env, jfloat radialCoordinate, jfloat azimuthalAngle, jfloat polarAngle) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local> Position::fromPosition(jni::JNIEnv& env, jfloat radialCoordinate, jfloat azimuthalAngle, jfloat polarAngle) { + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetStaticMethod (jfloat, jfloat, jfloat)>(env, "fromPosition"); return javaClass.Call(env, method, radialCoordinate, azimuthalAngle, polarAngle); } @@ -13,20 +13,20 @@ void Position::registerNative(jni::JNIEnv& env) { jni::Class::Singleton(env); } -float Position::getRadialCoordinate(jni::JNIEnv& env, jni::Object position){ - static auto javaClass = jni::Class::Singleton(env); +float Position::getRadialCoordinate(jni::JNIEnv& env, const jni::Object& position) { + static auto& javaClass = jni::Class::Singleton(env); static auto field = javaClass.GetField(env, "radialCoordinate"); return position.Get(env, field); } -float Position::getAzimuthalAngle(jni::JNIEnv& env, jni::Object position){ - static auto javaClass = jni::Class::Singleton(env); +float Position::getAzimuthalAngle(jni::JNIEnv& env, const jni::Object& position) { + static auto& javaClass = jni::Class::Singleton(env); static auto field = javaClass.GetField(env, "azimuthalAngle"); return position.Get(env, field); } -float Position::getPolarAngle(jni::JNIEnv& env, jni::Object position){ - static auto javaClass = jni::Class::Singleton(env); +float Position::getPolarAngle(jni::JNIEnv& env, const jni::Object& position) { + static auto& javaClass = jni::Class::Singleton(env); static auto field = javaClass.GetField(env, "polarAngle"); return position.Get(env, field); } diff --git a/platform/android/src/style/position.hpp b/platform/android/src/style/position.hpp index 4f3738da9f..eb4f5ac674 100644 --- a/platform/android/src/style/position.hpp +++ b/platform/android/src/style/position.hpp @@ -11,13 +11,13 @@ class Position : private mbgl::util::noncopyable { public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/light/Position"; }; - static jni::Object fromPosition(jni::JNIEnv&, jfloat, jfloat, jfloat); + static jni::Local> fromPosition(jni::JNIEnv&, jfloat, jfloat, jfloat); static void registerNative(jni::JNIEnv&); - static float getRadialCoordinate(jni::JNIEnv&, jni::Object); - static float getAzimuthalAngle(jni::JNIEnv&, jni::Object); - static float getPolarAngle(jni::JNIEnv&, jni::Object); + static float getRadialCoordinate(jni::JNIEnv&, const jni::Object&); + static float getAzimuthalAngle(jni::JNIEnv&, const jni::Object&); + static float getPolarAngle(jni::JNIEnv&, const jni::Object&); }; } // namespace android diff --git a/platform/android/src/style/sources/custom_geometry_source.cpp b/platform/android/src/style/sources/custom_geometry_source.cpp index 9012948b0b..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 @@ -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::Local> options, + const jni::Object<>& options, style::TileFunction fetchFn, style::TileFunction cancelFn) { using namespace mbgl::style::conversion; @@ -29,7 +30,7 @@ namespace android { return style::CustomGeometrySource::Options(); } Error error; - optional result = convert(Value(env, std::move(options)), error); + optional result = convert(Value(env, options), error); if (!result) { throw std::logic_error(error.message); } @@ -39,11 +40,11 @@ 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( jni::Make(env, sourceId), - convertCustomGeometrySourceOptions(env, jni::SeizeLocal(env, std::move(options)), + convertCustomGeometrySourceOptions(env, options, std::bind(&CustomGeometrySource::fetchTile, this, std::placeholders::_1), std::bind(&CustomGeometrySource::cancelTile, this, std::placeholders::_1)))) { } @@ -61,48 +62,48 @@ namespace android { void CustomGeometrySource::fetchTile (const mbgl::CanonicalTileID& tileID) { android::UniqueEnv _env = android::AttachEnv(); - static auto javaClass = jni::Class::Singleton(*_env); + static auto& javaClass = jni::Class::Singleton(*_env); static auto fetchTile = javaClass.GetMethod(*_env, "fetchTile"); assert(javaPeer); - auto peer = jni::Cast(*_env, javaClass, *javaPeer); + 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::Singleton(*_env); + static auto& javaClass = jni::Class::Singleton(*_env); static auto cancelTile = javaClass.GetMethod(*_env, "cancelTile"); assert(javaPeer); - auto peer = jni::Cast(*_env, javaClass, *javaPeer); + 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::Singleton(*_env); + static auto& javaClass = jni::Class::Singleton(*_env); static auto startThreads = javaClass.GetMethod(*_env, "startThreads"); assert(javaPeer); - auto peer = jni::Cast(*_env, javaClass, *javaPeer); + auto peer = jni::Cast(*_env, javaClass, javaPeer); peer.Call(*_env, startThreads); } void CustomGeometrySource::releaseThreads() { android::UniqueEnv _env = android::AttachEnv(); - static auto javaClass = jni::Class::Singleton(*_env); + static auto& javaClass = jni::Class::Singleton(*_env); static auto releaseThreads = javaClass.GetMethod(*_env, "releaseThreads"); assert(javaPeer); - auto peer = jni::Cast(*_env, javaClass, *javaPeer); + auto peer = jni::Cast(*_env, javaClass, javaPeer); peer.Call(*_env, releaseThreads); }; @@ -111,12 +112,12 @@ namespace android { jni::jint y) { android::UniqueEnv _env = android::AttachEnv(); - static auto javaClass = jni::Class::Singleton(*_env); + static auto& javaClass = jni::Class::Singleton(*_env); static auto isCancelled = javaClass.GetMethod(*_env, "isCancelled"); assert(javaPeer); - auto peer = jni::Cast(*_env, javaClass, *javaPeer); + auto peer = jni::Cast(*_env, javaClass, javaPeer); return peer.Call(*_env, isCancelled, z, x, y); }; @@ -124,7 +125,7 @@ namespace android { jni::jint z, jni::jint x, jni::jint y, - jni::Object jFeatures) { + const jni::Object& jFeatures) { using namespace mbgl::android::geojson; // Convert the jni object @@ -140,36 +141,35 @@ namespace android { source.as()->CustomGeometrySource::invalidateTile(CanonicalTileID(z, x, y)); } - void CustomGeometrySource::invalidateBounds(jni::JNIEnv& env, jni::Object jBounds) { + void CustomGeometrySource::invalidateBounds(jni::JNIEnv& env, const jni::Object& jBounds) { auto bounds = LatLngBounds::getLatLngBounds(env, jBounds); source.as()->CustomGeometrySource::invalidateRegion(bounds); } - jni::Array> CustomGeometrySource::querySourceFeatures(jni::JNIEnv& env, - jni::Array> jfilter) { + jni::Local>> CustomGeometrySource::querySourceFeatures(jni::JNIEnv& env, + const jni::Array>& jfilter) { using namespace mbgl::android::conversion; using namespace mbgl::android::geojson; std::vector features; if (rendererFrontend) { - features = rendererFrontend->querySourceFeatures(source.getID(), - { {}, toFilter(env, jni::SeizeLocal(env, std::move(jfilter))) }); + features = rendererFrontend->querySourceFeatures(source.getID(), { {}, toFilter(env, jfilter) }); } return Feature::convert(env, features); } - jni::Object CustomGeometrySource::createJavaPeer(jni::JNIEnv& env) { - static auto javaClass = jni::Class::Singleton(env); + jni::Local> CustomGeometrySource::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); - return jni::Object(javaClass.New(env, constructor, reinterpret_cast(this)).Get()); + return javaClass.New(env, constructor, reinterpret_cast(this)); } - void CustomGeometrySource::addToMap(JNIEnv& env, jni::Object obj, mbgl::Map& map, AndroidRendererFrontend& frontend) { + void CustomGeometrySource::addToMap(JNIEnv& env, const jni::Object& obj, mbgl::Map& map, AndroidRendererFrontend& frontend) { Source::addToMap(env, obj, map, frontend); startThreads(); } - bool CustomGeometrySource::removeFromMap(JNIEnv& env, jni::Object source, mbgl::Map& map) { + bool CustomGeometrySource::removeFromMap(JNIEnv& env, const jni::Object& source, mbgl::Map& map) { bool successfullyRemoved = Source::removeFromMap(env, source, map); if (successfullyRemoved) { releaseThreads(); @@ -179,14 +179,14 @@ namespace android { void CustomGeometrySource::registerNative(jni::JNIEnv& env) { // Lookup the class - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( env, javaClass, "nativePtr", - std::make_unique>, + jni::MakePeer&>, "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 ecfadd659c..52e4027dd8 100644 --- a/platform/android/src/style/sources/custom_geometry_source.hpp +++ b/platform/android/src/style/sources/custom_geometry_source.hpp @@ -15,17 +15,17 @@ namespace android { class CustomGeometrySource : public Source { public: - + using SuperTag = Source; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/CustomGeometrySource"; }; 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, mbgl::Map&) override; - void addToMap(JNIEnv&, jni::Object, mbgl::Map&, AndroidRendererFrontend&) override; + bool removeFromMap(JNIEnv&, const jni::Object&, mbgl::Map&) override; + void addToMap(JNIEnv&, const jni::Object&, mbgl::Map&, AndroidRendererFrontend&) override; void fetchTile(const mbgl::CanonicalTileID& tileID); void cancelTile(const mbgl::CanonicalTileID& tileID); @@ -34,15 +34,15 @@ public: void releaseThreads(); private: - void setTileData(jni::JNIEnv& env, jni::jint z, jni::jint x, jni::jint y, jni::Object jf); + void setTileData(jni::JNIEnv& env, jni::jint z, jni::jint x, jni::jint y, const jni::Object& jf); void invalidateTile(jni::JNIEnv& env, jni::jint z, jni::jint x, jni::jint y); - void invalidateBounds(jni::JNIEnv& env, jni::Object bounds); + void invalidateBounds(jni::JNIEnv& env, const jni::Object& bounds); - jni::Array> querySourceFeatures(jni::JNIEnv&, - jni::Array> ); + jni::Local>> querySourceFeatures(jni::JNIEnv&, + const jni::Array>& ); - jni::Object createJavaPeer(jni::JNIEnv&); + jni::Local> 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 943cc48386..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 @@ -29,24 +30,24 @@ 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::Local> 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 result = convert( - mbgl::android::Value(env, std::move(options)), error); + 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( jni::Make(env, sourceId), - convertGeoJSONOptions(env, jni::SeizeLocal(env, std::move(options))))) + convertGeoJSONOptions(env, options))) , threadPool(sharedThreadPool()) , converter(std::make_unique>(*threadPool)) { } @@ -61,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 json = std::make_shared(jni::Make(env, jString)); @@ -72,54 +73,54 @@ namespace android { setAsync(converterFn); } - void GeoJSONSource::setFeatureCollection(jni::JNIEnv& env, jni::Object jFeatures) { + void GeoJSONSource::setFeatureCollection(jni::JNIEnv& env, const jni::Object& jFeatures) { setCollectionAsync(env, jFeatures); } - void GeoJSONSource::setFeature(jni::JNIEnv& env, jni::Object jFeature) { + void GeoJSONSource::setFeature(jni::JNIEnv& env, const jni::Object& jFeature) { setCollectionAsync(env, jFeature); } - void GeoJSONSource::setGeometry(jni::JNIEnv& env, jni::Object jGeometry) { + void GeoJSONSource::setGeometry(jni::JNIEnv& env, const jni::Object& 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()->GeoJSONSource::setURL(jni::Make(env, url)); } - jni::String GeoJSONSource::getURL(jni::JNIEnv& env) { + jni::Local GeoJSONSource::getURL(jni::JNIEnv& env) { optional url = source.as()->GeoJSONSource::getURL(); - return url ? jni::Make(env, *url) : jni::String(); + return url ? jni::Make(env, *url) : jni::Local(); } - jni::Array> GeoJSONSource::querySourceFeatures(jni::JNIEnv& env, - jni::Array> jfilter) { + jni::Local>> GeoJSONSource::querySourceFeatures(jni::JNIEnv& env, + const jni::Array>& jfilter) { using namespace mbgl::android::conversion; using namespace mbgl::android::geojson; std::vector features; if (rendererFrontend) { features = rendererFrontend->querySourceFeatures(source.getID(), - { {}, toFilter(env, jni::SeizeLocal(env, std::move(jfilter))) }); + { {}, toFilter(env, jfilter) }); } return Feature::convert(env, features); } - jni::Object GeoJSONSource::createJavaPeer(jni::JNIEnv& env) { - static auto javaClass = jni::Class::Singleton(env); + jni::Local> GeoJSONSource::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); - return jni::Object(javaClass.New(env, constructor, reinterpret_cast(this)).Get()); + return javaClass.New(env, constructor, reinterpret_cast(this)); } template - void GeoJSONSource::setCollectionAsync(jni::JNIEnv& env, jni::Object jObject) { - - std::shared_ptr object = std::shared_ptr(jObject.NewGlobalRef(env).release().Get(), GenericGlobalRefDeleter()); + void GeoJSONSource::setCollectionAsync(jni::JNIEnv& env, const jni::Object& jObject) { + auto global = jni::NewGlobal(env, jObject); + auto object = std::make_shared(std::move(global)); Update::Converter converterFn = [this, object](ActorRef _callback) { - converter->self().invoke(&FeatureConverter::convertObject, jni::Object(*object), _callback); + converter->self().invoke(&FeatureConverter::convertObject, object, _callback); }; setAsync(converterFn); @@ -159,14 +160,14 @@ namespace android { void GeoJSONSource::registerNative(jni::JNIEnv& env) { // Lookup the class - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( env, javaClass, "nativePtr", - std::make_unique>, + jni::MakePeer&>, "initialize", "finalize", METHOD(&GeoJSONSource::setGeoJSONString, "nativeSetGeoJsonString"), @@ -196,13 +197,13 @@ namespace android { callback.invoke(&Callback::operator(), *converted); } - template - void FeatureConverter::convertObject(jni::Object jObject, ActorRef callback) { + template + void FeatureConverter::convertObject(std::shared_ptr, jni::EnvAttachingDeleter>> jObject, ActorRef 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 eb28e2470b..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, ActorRef); template - void convertObject(jni::Object, ActorRef); + void convertObject(std::shared_ptr, jni::EnvAttachingDeleter>>, ActorRef); }; struct Update { @@ -30,34 +30,35 @@ struct Update { class GeoJSONSource : public Source { public: + using SuperTag = Source; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/GeoJsonSource"; }; 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(); private: - void setGeoJSONString(jni::JNIEnv&, jni::String); - void setFeatureCollection(jni::JNIEnv&, jni::Object); - void setFeature(jni::JNIEnv&, jni::Object); - void setGeometry(jni::JNIEnv&, jni::Object); - void setURL(jni::JNIEnv&, jni::String); + void setGeoJSONString(jni::JNIEnv&, const jni::String&); + void setFeatureCollection(jni::JNIEnv&, const jni::Object&); + void setFeature(jni::JNIEnv&, const jni::Object&); + void setGeometry(jni::JNIEnv&, const jni::Object&); + void setURL(jni::JNIEnv&, const jni::String&); - jni::Array> querySourceFeatures(jni::JNIEnv&, - jni::Array>); + jni::Local>> querySourceFeatures(jni::JNIEnv&, + const jni::Array>&); - jni::String getURL(jni::JNIEnv&); + jni::Local getURL(jni::JNIEnv&); - jni::Object createJavaPeer(jni::JNIEnv&); + jni::Local> createJavaPeer(jni::JNIEnv&); std::unique_ptr awaitingUpdate; std::unique_ptr update; std::shared_ptr threadPool; std::unique_ptr> converter; template - void setCollectionAsync(jni::JNIEnv&, jni::Object); + void setCollectionAsync(jni::JNIEnv&, const jni::Object&); 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 343b7439c8..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 coordinatesObject) + ImageSource::ImageSource(jni::JNIEnv& env, const jni::String& sourceId, const jni::Object& coordinatesObject) : Source(env, std::make_unique( jni::Make(env, sourceId), LatLngQuad::getLatLngArray(env, coordinatesObject) @@ -31,41 +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()->ImageSource::setURL(jni::Make(env, url)); } - jni::String ImageSource::getURL(jni::JNIEnv& env) { + jni::Local ImageSource::getURL(jni::JNIEnv& env) { optional url = source.as()->ImageSource::getURL(); - return url ? jni::Make(env, *url) : jni::String(); + return url ? jni::Make(env, *url) : jni::Local(); } - void ImageSource::setImage(jni::JNIEnv& env, jni::Object bitmap) { + void ImageSource::setImage(jni::JNIEnv& env, const jni::Object& bitmap) { source.as()->setImage(Bitmap::GetImage(env, bitmap)); } - void ImageSource::setCoordinates(jni::JNIEnv& env, jni::Object coordinatesObject) { + void ImageSource::setCoordinates(jni::JNIEnv& env, const jni::Object& coordinatesObject) { source.as()->setCoordinates( LatLngQuad::getLatLngArray(env, coordinatesObject)); } - jni::Object ImageSource::createJavaPeer(jni::JNIEnv& env) { - static auto javaClass = jni::Class::Singleton(env); + jni::Local> ImageSource::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); - return jni::Object(javaClass.New(env, constructor, reinterpret_cast(this)).Get()); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void ImageSource::registerNative(jni::JNIEnv& env) { // Lookup the class - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( env, javaClass, "nativePtr", - std::make_unique>, + jni::MakePeer&>, "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 b09d4f8c95..6c359bf0ee 100644 --- a/platform/android/src/style/sources/image_source.hpp +++ b/platform/android/src/style/sources/image_source.hpp @@ -12,26 +12,26 @@ class Bitmap; class ImageSource : public Source { public: - + using SuperTag = Source; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/ImageSource"; }; static void registerNative(jni::JNIEnv&); - ImageSource(jni::JNIEnv&, jni::String, jni::Object); + ImageSource(jni::JNIEnv&, const jni::String&, const jni::Object&); 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 getURL(jni::JNIEnv&); - void setImage(jni::JNIEnv&, jni::Object); + void setImage(jni::JNIEnv&, const jni::Object&); - void setCoordinates(jni::JNIEnv&, jni::Object); + void setCoordinates(jni::JNIEnv&, const jni::Object&); private: - jni::Object createJavaPeer(jni::JNIEnv&); + jni::Local> 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 73d04f27c1..f60526a9b7 100644 --- a/platform/android/src/style/sources/raster_dem_source.cpp +++ b/platform/android/src/style/sources/raster_dem_source.cpp @@ -12,12 +12,12 @@ 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( jni::Make(env, sourceId), - convertURLOrTileset(Value(env, jni::SeizeLocal(env, std::move(urlOrTileSet)))), + convertURLOrTileset(Value(env, urlOrTileSet)), tileSize ) ) { @@ -31,27 +31,27 @@ namespace android { RasterDEMSource::~RasterDEMSource() = default; - jni::String RasterDEMSource::getURL(jni::JNIEnv& env) { + jni::Local RasterDEMSource::getURL(jni::JNIEnv& env) { optional url = source.as()->RasterDEMSource::getURL(); - return url ? jni::Make(env, *url) : jni::String(); + return url ? jni::Make(env, *url) : jni::Local(); } - jni::Object RasterDEMSource::createJavaPeer(jni::JNIEnv& env) { - static auto javaClass = jni::Class::Singleton(env); + jni::Local> RasterDEMSource::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); - return jni::Object(javaClass.New(env, constructor, reinterpret_cast(this)).Get()); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void RasterDEMSource::registerNative(jni::JNIEnv& env) { // Lookup the class - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( env, javaClass, "nativePtr", - std::make_unique, jni::jint>, + jni::MakePeer&, 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 25d9fe90cd..0b31c4ecd3 100644 --- a/platform/android/src/style/sources/raster_dem_source.hpp +++ b/platform/android/src/style/sources/raster_dem_source.hpp @@ -9,18 +9,19 @@ namespace android { class RasterDEMSource : public Source { public: + using SuperTag = Source; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/RasterDemSource"; }; 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 getURL(jni::JNIEnv&); private: - jni::Object createJavaPeer(jni::JNIEnv&); + jni::Local> 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 4eef41c8b1..535f899c99 100644 --- a/platform/android/src/style/sources/raster_source.cpp +++ b/platform/android/src/style/sources/raster_source.cpp @@ -11,12 +11,12 @@ 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( jni::Make(env, sourceId), - convertURLOrTileset(Value(env, jni::SeizeLocal(env, std::move(urlOrTileSet)))), + convertURLOrTileset(Value(env, urlOrTileSet)), tileSize ) ) { @@ -30,27 +30,27 @@ namespace android { RasterSource::~RasterSource() = default; - jni::String RasterSource::getURL(jni::JNIEnv& env) { + jni::Local RasterSource::getURL(jni::JNIEnv& env) { optional url = source.as()->RasterSource::getURL(); - return url ? jni::Make(env, *url) : jni::String(); + return url ? jni::Make(env, *url) : jni::Local(); } - jni::Object RasterSource::createJavaPeer(jni::JNIEnv& env) { - static auto javaClass = jni::Class::Singleton(env); + jni::Local> RasterSource::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); - return jni::Object(javaClass.New(env, constructor, reinterpret_cast(this)).Get()); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void RasterSource::registerNative(jni::JNIEnv& env) { // Lookup the class - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( env, javaClass, "nativePtr", - std::make_unique, jni::jint>, + jni::MakePeer&, 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 888d9f601d..08648f79aa 100644 --- a/platform/android/src/style/sources/raster_source.hpp +++ b/platform/android/src/style/sources/raster_source.hpp @@ -9,18 +9,19 @@ namespace android { class RasterSource : public Source { public: + using SuperTag = Source; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/RasterSource"; }; 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 getURL(jni::JNIEnv&); private: - jni::Object createJavaPeer(jni::JNIEnv&); + jni::Local> createJavaPeer(jni::JNIEnv&); }; // class RasterSource diff --git a/platform/android/src/style/sources/source.cpp b/platform/android/src/style/sources/source.cpp index c7968786ec..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 @@ -47,16 +48,16 @@ namespace android { } } - jni::Object Source::peerForCoreSource(jni::JNIEnv& env, mbgl::style::Source& coreSource, AndroidRendererFrontend& frontend) { + const jni::Object& 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>()->javaPeer; + return coreSource.peer.get>()->javaPeer; } - Source::Source(jni::JNIEnv& env, mbgl::style::Source& coreSource, jni::Object obj, AndroidRendererFrontend& frontend) + Source::Source(jni::JNIEnv& env, mbgl::style::Source& coreSource, const jni::Object& obj, AndroidRendererFrontend& frontend) : source(coreSource) - , javaPeer(obj.NewGlobalRef(env)) + , javaPeer(jni::NewGlobal(env, obj)) , rendererFrontend(&frontend) { } @@ -76,23 +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::Singleton(*env); + static auto& javaClass = jni::Class::Singleton(*env); static auto nativePtrField = javaClass.GetField(*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 Source::getId(jni::JNIEnv& env) { return jni::Make(env, source.getID()); } - jni::String Source::getAttribution(jni::JNIEnv& env) { + jni::Local Source::getAttribution(jni::JNIEnv& env) { auto attribution = source.getAttribution(); return attribution ? jni::Make(env, attribution.value()) : jni::Make(env,""); } - void Source::addToMap(JNIEnv& env, jni::Object obj, mbgl::Map& map, AndroidRendererFrontend& frontend) { + void Source::addToMap(JNIEnv& env, const jni::Object& 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"); @@ -105,12 +106,12 @@ namespace android { source.peer = std::unique_ptr(this); // Add strong reference to java source - javaPeer = obj.NewGlobalRef(env); + javaPeer = jni::NewGlobal(env, obj); rendererFrontend = &frontend; } - bool Source::removeFromMap(JNIEnv&, jni::Object, mbgl::Map& map) { + bool Source::removeFromMap(JNIEnv&, const jni::Object&, mbgl::Map& map) { // Cannot remove if not attached yet if (ownedSource) { throw std::runtime_error("Cannot remove detached source"); @@ -143,7 +144,7 @@ namespace android { void Source::registerNative(jni::JNIEnv& env) { // Lookup the class - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) diff --git a/platform/android/src/style/sources/source.hpp b/platform/android/src/style/sources/source.hpp index 492be8dfec..93b706425a 100644 --- a/platform/android/src/style/sources/source.hpp +++ b/platform/android/src/style/sources/source.hpp @@ -19,12 +19,12 @@ public: static void registerNative(jni::JNIEnv&); - static jni::Object peerForCoreSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&); + static const jni::Object& 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, AndroidRendererFrontend&); + Source(jni::JNIEnv&, mbgl::style::Source&, const jni::Object&, AndroidRendererFrontend&); /* * Called when a Java object is created for a new core source that does not belong to a map. @@ -33,15 +33,15 @@ public: virtual ~Source(); - virtual void addToMap(JNIEnv&, jni::Object, mbgl::Map&, AndroidRendererFrontend&); + virtual void addToMap(JNIEnv&, const jni::Object&, mbgl::Map&, AndroidRendererFrontend&); - virtual bool removeFromMap(JNIEnv&, jni::Object, mbgl::Map&); + virtual bool removeFromMap(JNIEnv&, const jni::Object&, mbgl::Map&); void releaseJavaPeer(); - jni::String getId(jni::JNIEnv&); + jni::Local getId(jni::JNIEnv&); - jni::String getAttribution(jni::JNIEnv&); + jni::Local getAttribution(jni::JNIEnv&); protected: // Set on newly created sources until added to the map. diff --git a/platform/android/src/style/sources/unknown_source.cpp b/platform/android/src/style/sources/unknown_source.cpp index 8e91798392..b5285a5f9f 100644 --- a/platform/android/src/style/sources/unknown_source.cpp +++ b/platform/android/src/style/sources/unknown_source.cpp @@ -18,15 +18,15 @@ namespace android { : Source(env, coreSource, createJavaPeer(env), frontend) { } - jni::Object UnknownSource::createJavaPeer(jni::JNIEnv& env) { - static auto javaClass = jni::Class::Singleton(env); + jni::Local> UnknownSource::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); - return jni::Object(javaClass.New(env, constructor, reinterpret_cast(this)).Get()); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void UnknownSource::registerNative(jni::JNIEnv& env) { // Lookup the class - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) diff --git a/platform/android/src/style/sources/unknown_source.hpp b/platform/android/src/style/sources/unknown_source.hpp index 855aea7c63..f042e2042c 100644 --- a/platform/android/src/style/sources/unknown_source.hpp +++ b/platform/android/src/style/sources/unknown_source.hpp @@ -9,7 +9,7 @@ namespace android { class UnknownSource : public Source { public: - + using SuperTag = Source; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/UnknownSource"; }; static void registerNative(jni::JNIEnv&); @@ -19,7 +19,7 @@ public: ~UnknownSource() = default; private: - jni::Object createJavaPeer(jni::JNIEnv&); + jni::Local> 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 48eb4ca51c..e46fc1a94e 100644 --- a/platform/android/src/style/sources/vector_source.cpp +++ b/platform/android/src/style/sources/vector_source.cpp @@ -20,12 +20,12 @@ 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( jni::Make(env, sourceId), - convertURLOrTileset(Value(env, jni::SeizeLocal(env, std::move(urlOrTileSet)))) + convertURLOrTileset(Value(env, urlOrTileSet)) ) ) { } @@ -38,41 +38,41 @@ namespace android { VectorSource::~VectorSource() = default; - jni::String VectorSource::getURL(jni::JNIEnv& env) { + jni::Local VectorSource::getURL(jni::JNIEnv& env) { optional url = source.as()->VectorSource::getURL(); - return url ? jni::Make(env, *url) : jni::String(); + return url ? jni::Make(env, *url) : jni::Local(); } - jni::Array> VectorSource::querySourceFeatures(jni::JNIEnv& env, - jni::Array jSourceLayerIds, - jni::Array> jfilter) { + jni::Local>> VectorSource::querySourceFeatures(jni::JNIEnv& env, + const jni::Array& jSourceLayerIds, + const jni::Array>& jfilter) { using namespace mbgl::android::conversion; using namespace mbgl::android::geojson; std::vector features; if (rendererFrontend) { features = rendererFrontend->querySourceFeatures(source.getID(), - { toVector(env, jSourceLayerIds), toFilter(env, jni::SeizeLocal(env, std::move(jfilter))) }); + { toVector(env, jSourceLayerIds), toFilter(env, jfilter) }); } return Feature::convert(env, features); } - jni::Object VectorSource::createJavaPeer(jni::JNIEnv& env) { - static auto javaClass = jni::Class::Singleton(env); + jni::Local> VectorSource::createJavaPeer(jni::JNIEnv& env) { + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); - return jni::Object(javaClass.New(env, constructor, reinterpret_cast(this)).Get()); + return javaClass.New(env, constructor, reinterpret_cast(this)); } void VectorSource::registerNative(jni::JNIEnv& env) { // Lookup the class - static auto javaClass = jni::Class::Singleton(env); + static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( env, javaClass, "nativePtr", - std::make_unique>, + jni::MakePeer&>, "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 587a4be208..4cb46c6c62 100644 --- a/platform/android/src/style/sources/vector_source.hpp +++ b/platform/android/src/style/sources/vector_source.hpp @@ -10,21 +10,22 @@ namespace android { class VectorSource : public Source { public: + using SuperTag = Source; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/VectorSource"; }; 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(); private: - jni::Array> querySourceFeatures(jni::JNIEnv&, jni::Array, - jni::Array> jfilter); + jni::Local>> querySourceFeatures(jni::JNIEnv&, const jni::Array&, + const jni::Array>& jfilter); - jni::String getURL(jni::JNIEnv&); + jni::Local getURL(jni::JNIEnv&); - jni::Object createJavaPeer(jni::JNIEnv&); + jni::Local> createJavaPeer(jni::JNIEnv&); }; // class VectorSource diff --git a/platform/android/src/style/transition_options.cpp b/platform/android/src/style/transition_options.cpp index 84bd909125..b908c37089 100644 --- a/platform/android/src/style/transition_options.cpp +++ b/platform/android/src/style/transition_options.cpp @@ -3,8 +3,8 @@ namespace mbgl { namespace android { -jni::Object TransitionOptions::fromTransitionOptions(jni::JNIEnv& env, jlong duration, jlong delay) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local> TransitionOptions::fromTransitionOptions(jni::JNIEnv& env, jlong duration, jlong delay) { + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetStaticMethod (jlong, jlong)>(env, "fromTransitionOptions"); return javaClass.Call(env, method, duration, delay); } diff --git a/platform/android/src/style/transition_options.hpp b/platform/android/src/style/transition_options.hpp index 83276ca1d8..0bac43fa16 100644 --- a/platform/android/src/style/transition_options.hpp +++ b/platform/android/src/style/transition_options.hpp @@ -11,7 +11,7 @@ class TransitionOptions : private mbgl::util::noncopyable { public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/TransitionOptions"; }; - static jni::Object fromTransitionOptions(jni::JNIEnv&, jlong duration, jlong offset); + static jni::Local> fromTransitionOptions(jni::JNIEnv&, jlong duration, jlong offset); static void registerNative(jni::JNIEnv&); }; diff --git a/platform/android/src/style/value.cpp b/platform/android/src/style/value.cpp index 6cdf134931..f916909687 100644 --- a/platform/android/src/style/value.cpp +++ b/platform/android/src/style/value.cpp @@ -10,64 +10,67 @@ namespace android { : 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; } bool Value::isArray() const { - return jni::IsInstanceOf(env, value->Get(), *java::ObjectArray::jclass); + return jni::IsInstanceOf(env, value.get(), *java::ObjectArray::jclass); } 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 { - return jni::IsInstanceOf(env, value->Get(), *java::String::jclass); + return jni::IsInstanceOf(env, value.get(), *java::String::jclass); } bool Value::isBool() const { - return jni::IsInstanceOf(env, value->Get(), *java::Boolean::jclass); + return jni::IsInstanceOf(env, value.get(), *java::Boolean::jclass); } bool Value::isNumber() const { - return jni::IsInstanceOf(env, value->Get(), *java::Number::jclass); + return jni::IsInstanceOf(env, value.get(), *java::Number::jclass); } std::string Value::toString() const { - jni::jstring* string = reinterpret_cast(value->Get()); - return jni::Make(env, jni::String(string)); + return jni::Make(env, jni::Cast(env, jni::Class::Singleton(env), value)); } float Value::toFloat() const { - return jni::CallMethod(env, value->Get(), *java::Number::floatValueMethodId); + return jni::CallMethod(env, value.get(), *java::Number::floatValueMethodId); } double Value::toDouble() const { - return jni::CallMethod(env, value->Get(), *java::Number::doubleValueMethodId); + return jni::CallMethod(env, value.get(), *java::Number::doubleValueMethodId); } long Value::toLong() const { - return jni::CallMethod(env, value->Get(), *java::Number::longValueMethodId); + return jni::CallMethod(env, value.get(), *java::Number::longValueMethodId); } bool Value::toBool() const { - return jni::CallMethod(env, value->Get(), *java::Boolean::booleanValueMethodId); + return jni::CallMethod(env, value.get(), *java::Boolean::booleanValueMethodId); } Value Value::get(const char* key) const { - jni::jobject* member = jni::CallMethod(env, value->Get(), *java::Map::getMethodId, jni::Make(env, std::string(key)).Get()); - return Value(env, jni::SeizeLocal(env, jni::Object<>(member))); + jni::jobject* member = jni::CallMethod(env, value.get(), *java::Map::getMethodId, jni::Make(env, std::string(key)).get()); + return Value(env, jni::Local>(env, member)); } int Value::getLength() const { - auto array = (jni::jarray*) value->Get(); + auto array = (jni::jarray*) value.get(); return jni::GetArrayLength(env, *array); } Value Value::get(const int index) const { - auto array = (jni::jarray*) value->Get(); - return Value(env, jni::SeizeLocal(env, jni::Object<>(jni::GetObjectArrayElement(env, *array, index)))); + auto array = (jni::jarray*) value.get(); + return Value(env, jni::Local>(env, jni::GetObjectArrayElement(env, *array, index))); } } } diff --git a/platform/android/src/style/value.hpp b/platform/android/src/style/value.hpp index bd1c552be0..b3e665e57b 100644 --- a/platform/android/src/style/value.hpp +++ b/platform/android/src/style/value.hpp @@ -10,6 +10,7 @@ namespace android { class Value { public: Value(jni::JNIEnv&, jni::Local>); + Value(jni::JNIEnv&, const jni::Object<>&); Value(Value&&) = default; Value& operator=(Value&&) = default; 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

, jni::Array args) { + static void runAllTests(jni::JNIEnv& env, const jni::Object
&, const jni::Array& 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
::Find(env), + jni::RegisterNatives(env, *jni::Class
::Find(env), jni::MakeNativeMethod("runAllTests")); return JNI_VERSION_1_6; diff --git a/platform/android/src/text/collator.cpp b/platform/android/src/text/collator.cpp index 86e72a1dac..04da53832a 100644 --- a/platform/android/src/text/collator.cpp +++ b/platform/android/src/text/collator.cpp @@ -16,20 +16,20 @@ void Collator::registerNative(jni::JNIEnv& env) { jni::Class::Singleton(env); } -jni::Object Collator::getInstance(jni::JNIEnv& env, jni::Object locale) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local> Collator::getInstance(jni::JNIEnv& env, const jni::Object& locale) { + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetStaticMethod (jni::Object)>(env, "getInstance"); return javaClass.Call(env, method, locale); } -void Collator::setStrength(jni::JNIEnv& env, jni::Object collator, jni::jint strength) { - static auto javaClass = jni::Class::Singleton(env); +void Collator::setStrength(jni::JNIEnv& env, const jni::Object& collator, jni::jint strength) { + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod(env, "setStrength"); collator.Call(env, method, strength); } -jni::jint Collator::compare(jni::JNIEnv& env, jni::Object collator, jni::String lhs, jni::String rhs) { - static auto javaClass = jni::Class::Singleton(env); +jni::jint Collator::compare(jni::JNIEnv& env, const jni::Object& collator, const jni::String& lhs, const jni::String& rhs) { + static auto& javaClass = jni::Class::Singleton(env); auto static method = javaClass.GetMethod(env, "compare"); return collator.Call(env, method, lhs, rhs); } @@ -54,32 +54,32 @@ jni::String Locale::toLanguageTag(jni::JNIEnv& env, jni::Object locale) } */ -jni::String Locale::getLanguage(jni::JNIEnv& env, jni::Object locale) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local Locale::getLanguage(jni::JNIEnv& env, const jni::Object& locale) { + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod(env, "getLanguage"); return locale.Call(env, method); } -jni::String Locale::getCountry(jni::JNIEnv& env, jni::Object locale) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local Locale::getCountry(jni::JNIEnv& env, const jni::Object& locale) { + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod(env, "getCountry"); return locale.Call(env, method); } -jni::Object Locale::getDefault(jni::JNIEnv& env) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local> Locale::getDefault(jni::JNIEnv& env) { + static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetStaticMethod ()>(env, "getDefault"); return javaClass.Call(env, method); } -jni::Object Locale::New(jni::JNIEnv& env, jni::String language) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local> Locale::New(jni::JNIEnv& env, const jni::String& language) { + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); return javaClass.New(env, constructor, language); } -jni::Object Locale::New(jni::JNIEnv& env, jni::String language, jni::String region) { - static auto javaClass = jni::Class::Singleton(env); +jni::Local> Locale::New(jni::JNIEnv& env, const jni::String& language, const jni::String& region) { + static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); return javaClass.New(env, constructor, language, region); } @@ -98,26 +98,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(*env, *(languageTag.language))) - .NewGlobalRef(*env); + locale = jni::NewGlobal(*env, + android::Locale::New(*env, jni::Make(*env, *languageTag.language))); } else { - locale = android::Locale::New(*env, - jni::Make(*env, *(languageTag.language)), - jni::Make(*env, *(languageTag.region))) - .NewGlobalRef(*env); + locale = jni::NewGlobal(*env, + android::Locale::New(*env, jni::Make(*env, *languageTag.language), + jni::Make(*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*/); } } @@ -135,23 +134,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::Local jlhs = jni::SeizeLocal(*env, jni::Make(*env, useUnaccent ? + jni::Local jlhs = jni::Make(*env, useUnaccent ? platform::unaccent(lhs) : - lhs)); - jni::Local jrhs = jni::SeizeLocal(*env, jni::Make(*env, useUnaccent ? + lhs); + jni::Local jrhs = jni::Make(*env, useUnaccent ? platform::unaccent(rhs) : - rhs)); + rhs); - jni::jint result = android::Collator::compare(*env, *collator, *jlhs, *jrhs); + jni::jint result = android::Collator::compare(*env, collator, jlhs, jrhs); return result; } std::string resolvedLocale() const { - std::string language = jni::Make(*env, - *jni::SeizeLocal(*env, android::Locale::getLanguage(*env, *locale))); - std::string region = jni::Make(*env, - *jni::SeizeLocal(*env, android::Locale::getCountry(*env, *locale))); + std::string language = jni::Make(*env, android::Locale::getLanguage(*env, locale)); + std::string region = jni::Make(*env, android::Locale::getCountry(*env, locale)); optional resultLanguage; if (!language.empty()) resultLanguage = language; diff --git a/platform/android/src/text/collator_jni.hpp b/platform/android/src/text/collator_jni.hpp index 30fb6a4369..e5e82c34fd 100644 --- a/platform/android/src/text/collator_jni.hpp +++ b/platform/android/src/text/collator_jni.hpp @@ -24,12 +24,12 @@ public: static jni::Object forLanguageTag(jni::JNIEnv&, jni::String); static jni::String toLanguageTag(jni::JNIEnv&, jni::Object); */ - static jni::Object getDefault(jni::JNIEnv&); - static jni::String getLanguage(jni::JNIEnv&, jni::Object); - static jni::String getCountry(jni::JNIEnv&, jni::Object); + static jni::Local> getDefault(jni::JNIEnv&); + static jni::Local getLanguage(jni::JNIEnv&, const jni::Object&); + static jni::Local getCountry(jni::JNIEnv&, const jni::Object&); - static jni::Object New(jni::JNIEnv&, jni::String); - static jni::Object New(jni::JNIEnv&, jni::String, jni::String); + static jni::Local> New(jni::JNIEnv&, const jni::String&); + static jni::Local> New(jni::JNIEnv&, const jni::String&, const jni::String&); static void registerNative(jni::JNIEnv&); @@ -39,11 +39,11 @@ class Collator { public: static constexpr auto Name() { return "java/text/Collator"; }; - static jni::Object getInstance(jni::JNIEnv&, jni::Object); + static jni::Local> getInstance(jni::JNIEnv&, const jni::Object&); - static void setStrength(jni::JNIEnv&, jni::Object, jni::jint); + static void setStrength(jni::JNIEnv&, const jni::Object&, jni::jint); - static jni::jint compare(jni::JNIEnv&, jni::Object, jni::String, jni::String); + static jni::jint compare(jni::JNIEnv&, const jni::Object&, const jni::String&, const jni::String&); static void registerNative(jni::JNIEnv&); diff --git a/platform/android/src/text/local_glyph_rasterizer.cpp b/platform/android/src/text/local_glyph_rasterizer.cpp index adfa0559f3..8892ee3f37 100644 --- a/platform/android/src/text/local_glyph_rasterizer.cpp +++ b/platform/android/src/text/local_glyph_rasterizer.cpp @@ -36,25 +36,24 @@ namespace android { LocalGlyphRasterizer::LocalGlyphRasterizer() { UniqueEnv env { AttachEnv() }; - static auto javaClass = jni::Class::Singleton(*env); + static auto& javaClass = jni::Class::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() }; - static auto javaClass = jni::Class::Singleton(*env); + static auto& javaClass = jni::Class::Singleton(*env); static auto drawGlyphBitmap = javaClass.GetMethod (jni::String, jni::jboolean, jni::jchar)>(*env, "drawGlyphBitmap"); - auto javaBitmap = jni::SeizeLocal(*env, - javaObject->Call(*env, drawGlyphBitmap, - *jni::SeizeLocal(*env, jni::Make(*env, fontFamily)), - static_cast(bold), - static_cast(glyphID))); - - return Bitmap::GetImage(*env, *javaBitmap); + return Bitmap::GetImage(*env, + javaObject.Call(*env, + drawGlyphBitmap, + jni::Make(*env, fontFamily), + static_cast(bold), + static_cast(glyphID))); } void LocalGlyphRasterizer::registerNative(jni::JNIEnv& env) { -- cgit v1.2.1 From 31cca05fc6a9d08d3b0028149f7ef2f2348b18e9 Mon Sep 17 00:00:00 2001 From: ryanhamley Date: Thu, 30 Aug 2018 17:18:29 -0700 Subject: Port symbol-z-order symbol layout style-spec property to Native --- include/mbgl/style/layers/symbol_layer.hpp | 4 ++ include/mbgl/style/types.hpp | 5 ++ mapbox-gl-js | 2 +- platform/android/CHANGELOG.md | 1 + .../mapbox/mapboxsdk/style/layers/Property.java | 21 ++++++++ .../mapboxsdk/style/layers/PropertyFactory.java | 20 ++++++++ .../mapbox/mapboxsdk/style/layers/SymbolLayer.java | 14 +++++ .../mapboxsdk/testapp/style/SymbolLayerTest.java | 14 +++++ platform/android/src/style/layers/symbol_layer.cpp | 6 +++ platform/android/src/style/layers/symbol_layer.hpp | 2 + .../darwin/scripts/style-spec-overrides-v8.json | 10 ++++ platform/darwin/src/MGLSymbolStyleLayer.h | 59 ++++++++++++++++++++++ platform/darwin/src/MGLSymbolStyleLayer.mm | 32 ++++++++++++ platform/darwin/test/MGLSymbolStyleLayerTests.mm | 47 +++++++++++++++++ platform/ios/CHANGELOG.md | 3 ++ platform/macos/CHANGELOG.md | 3 ++ platform/node/CHANGELOG.md | 1 + src/mbgl/layout/symbol_layout.cpp | 7 +-- src/mbgl/style/conversion/constant.cpp | 1 + src/mbgl/style/conversion/function.cpp | 2 + src/mbgl/style/conversion/property_value.cpp | 1 + src/mbgl/style/expression/value.cpp | 3 ++ src/mbgl/style/layers/symbol_layer.cpp | 35 +++++++++++++ src/mbgl/style/layers/symbol_layer_properties.hpp | 6 +++ src/mbgl/style/types.cpp | 5 ++ 25 files changed, 300 insertions(+), 4 deletions(-) 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 getSymbolAvoidEdges() const; void setSymbolAvoidEdges(PropertyValue); + static PropertyValue getDefaultSymbolZOrder(); + PropertyValue getSymbolZOrder() const; + void setSymbolZOrder(PropertyValue); + static PropertyValue getDefaultIconAllowOverlap(); PropertyValue getIconAllowOverlap() const; void setIconAllowOverlap(PropertyValue); 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/mapbox-gl-js b/mapbox-gl-js index 53e622b475..e8fd41abae 160000 --- a/mapbox-gl-js +++ b/mapbox-gl-js @@ -1 +1 @@ -Subproject commit 53e622b475b7c9cb26b98d18e3fbd61d27b183a2 +Subproject commit e8fd41abae382f39f17a561a1461db90bd2204f3 diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index 13162c0b48..8031232d43 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -3,6 +3,7 @@ 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-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/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 @@ -1764,6 +1764,26 @@ public class PropertyFactory { return new LayoutPropertyValue<>("symbol-avoid-edges", 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 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 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. * 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 @@ -170,6 +170,17 @@ public class SymbolLayer extends Layer { return (PropertyValue) new PropertyValue("symbol-avoid-edges", nativeGetSymbolAvoidEdges()); } + /** + * Get the SymbolZOrder property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue getSymbolZOrder() { + checkThread(); + return (PropertyValue) new PropertyValue("symbol-z-order", nativeGetSymbolZOrder()); + } + /** * Get the IconAllowOverlap property * @@ -1004,6 +1015,9 @@ public class SymbolLayer extends Layer { @Keep private native Object nativeGetSymbolAvoidEdges(); + @Keep + private native Object nativeGetSymbolZOrder(); + @Keep private native Object nativeGetIconAllowOverlap(); 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 @@ -159,6 +159,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(); diff --git a/platform/android/src/style/layers/symbol_layer.cpp b/platform/android/src/style/layers/symbol_layer.cpp index a0f37c91d2..f1c77c61a9 100644 --- a/platform/android/src/style/layers/symbol_layer.cpp +++ b/platform/android/src/style/layers/symbol_layer.cpp @@ -50,6 +50,11 @@ namespace android { return std::move(*convert>>(env, layer.as()->SymbolLayer::getSymbolAvoidEdges())); } + jni::Local> SymbolLayer::getSymbolZOrder(jni::JNIEnv& env) { + using namespace mbgl::android::conversion; + return std::move(*convert>>(env, layer.as()->SymbolLayer::getSymbolZOrder())); + } + jni::Local> SymbolLayer::getIconAllowOverlap(jni::JNIEnv& env) { using namespace mbgl::android::conversion; return std::move(*convert>>(env, layer.as()->SymbolLayer::getIconAllowOverlap())); @@ -463,6 +468,7 @@ namespace android { 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 206a6546c3..9887fd8fb7 100644 --- a/platform/android/src/style/layers/symbol_layer.hpp +++ b/platform/android/src/style/layers/symbol_layer.hpp @@ -33,6 +33,8 @@ public: jni::Local> getSymbolAvoidEdges(jni::JNIEnv&); + jni::Local> getSymbolZOrder(jni::JNIEnv&); + jni::Local> getIconAllowOverlap(jni::JNIEnv&); jni::Local> getIconIgnorePlacement(jni::JNIEnv&); 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 @@ -150,6 +150,26 @@ typedef NS_ENUM(NSUInteger, MGLSymbolPlacement) { MGLSymbolPlacementLineCenter, }; +/** + 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. @@ -1004,6 +1024,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. @@ -2140,6 +2186,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. 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().toExpression(propertyValue); } +- (void)setSymbolZOrder:(NSExpression *)symbolZOrder { + MGLAssertStyleLayerIsValid(); + + auto mbglValue = MGLStyleValueTransformer().toPropertyValue>(symbolZOrder, false); + self.rawLayer->setSymbolZOrder(mbglValue); +} + +- (NSExpression *)symbolZOrder { + MGLAssertStyleLayerIsValid(); + + auto propertyValue = self.rawLayer->getSymbolZOrder(); + if (propertyValue.isUndefined()) { + propertyValue = self.rawLayer->getDefaultSymbolZOrder(); + } + return MGLStyleValueTransformer().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 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( + 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/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index dc78220b48..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 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/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/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 CalculateTileDistances(const GeometryCoordinates& line, const } void SymbolLayout::createBucket(const ImagePositions&, std::unique_ptr&, std::unordered_map>& buckets, const bool firstLoad, const bool showCollisionBoxes) { - const bool mayOverlap = layout.get() || layout.get() || - layout.get() || layout.get(); + const bool zOrderByViewport = layout.get() == SymbolZOrderType::ViewportY; + const bool sortFeaturesByY = zOrderByViewport && (layout.get() || layout.get() || + layout.get() || layout.get()); - auto bucket = std::make_shared(layout, layerPaintProperties, textSize, iconSize, zoom, sdfIcons, iconsNeedLinear, mayOverlap, bucketLeaderID, std::move(symbolInstances)); + auto bucket = std::make_shared(layout, layerPaintProperties, textSize, iconSize, zoom, sdfIcons, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(symbolInstances)); for (SymbolInstance &symbolInstance : bucket->symbolInstances) { 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 Converter::operator()(const Conver template optional Converter::operator()(const Convertible&, Error&) const; template optional Converter::operator()(const Convertible&, Error&) const; template optional Converter::operator()(const Convertible&, Error&) const; +template optional Converter::operator()(const Convertible&, Error&) const; template optional Converter::operator()(const Convertible&, Error&) const; template optional Converter::operator()(const Convertible&, Error&) const; template optional Converter::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> convertFunctionToExpression(const Convertible&, Error&, bool); template optional> convertFunctionToExpression(const Convertible&, Error&, bool); +template optional> + convertFunctionToExpression(const Convertible&, Error&, bool); template optional> convertFunctionToExpression(const Convertible&, Error&, bool); template optional> 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> Converter>::o template optional> Converter>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const; template optional> Converter>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const; template optional> Converter>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const; +template optional> Converter>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const; template optional> Converter>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const; template optional> Converter>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const; template optional> Converter>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const; 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; template type::Type valueTypeToExpressionType(); template struct ValueConverter; + +template type::Type valueTypeToExpressionType(); +template struct ValueConverter; template type::Type valueTypeToExpressionType(); template struct ValueConverter; 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 value) { baseImpl = std::move(impl_); observer->onLayerChanged(*this); } +PropertyValue SymbolLayer::getDefaultSymbolZOrder() { + return SymbolZOrder::defaultValue(); +} + +PropertyValue SymbolLayer::getSymbolZOrder() const { + return impl().layout.get(); +} + +void SymbolLayer::setSymbolZOrder(PropertyValue value) { + if (value == getSymbolZOrder()) + return; + auto impl_ = mutableImpl(); + impl_->layout.get() = value; + baseImpl = std::move(impl_); + observer->onLayerChanged(*this); +} PropertyValue SymbolLayer::getDefaultIconAllowOverlap() { return IconAllowOverlap::defaultValue(); } @@ -1440,6 +1456,7 @@ optional SymbolLayer::setLayoutProperty(const std::string& name, const Co SymbolPlacement, SymbolSpacing, SymbolAvoidEdges, + SymbolZOrder, IconAllowOverlap, IconIgnorePlacement, IconOptional, @@ -1496,6 +1513,12 @@ optional 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 SymbolLayer::setLayoutProperty(const std::string& name, const Co } + if (property == Property::SymbolZOrder) { + Error error; + optional> typedValue = convert>(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> typedValue = convert>(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 { static bool defaultValue() { return false; } }; +struct SymbolZOrder : LayoutProperty { + static constexpr const char * key = "symbol-z-order"; + static SymbolZOrderType defaultValue() { return SymbolZOrderType::ViewportY; } +}; + struct IconAllowOverlap : LayoutProperty { 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" }, -- cgit v1.2.1 From 435241c3357a9c2c96035a99a9f6725b6665d8a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Thu, 6 Sep 2018 10:28:10 -0700 Subject: [macos] macOS 10.10, Xcode 8 no longer supported --- platform/macos/INSTALL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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: -- cgit v1.2.1 From e947fa0d23dc4016d44f8117622ecc036c520893 Mon Sep 17 00:00:00 2001 From: Josh Erb Date: Mon, 10 Sep 2018 12:02:22 -0400 Subject: Remove Links to Deprecated Frameworks (#12852) --- README.md | 2 -- 1 file changed, 2 deletions(-) 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. -- cgit v1.2.1 From 06ff49dfb2574fe3d12e2a3cbcd2828be525fec5 Mon Sep 17 00:00:00 2001 From: Nadia Barbosa Date: Mon, 10 Sep 2018 14:20:48 -0700 Subject: [ios, macos, docs] Move MGLShapeOfflineRegion to offline section --- platform/ios/jazzy.yml | 1 + platform/macos/jazzy.yml | 1 + 2 files changed, 2 insertions(+) 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/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 -- cgit v1.2.1 From 536652ca201ce59190ae5c41d1202372d28d6d6d Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Tue, 11 Sep 2018 12:18:26 +0300 Subject: [build] Disable implicit fallthrough warnings for sqlite3 (#12855) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sqlite3 source code has a lot of implicit fallthroughs in case statements. They are documented with comments but even though gcc provides options to use these comments to suppress the warnings, that's not always reliable. For instance, it may fail if an #ifdef follows the comment or if the comment is within a block scope used for a case. With gcc version '(Ubuntu 7.3.0-16ubuntu3) 7.3.0' I get warnings similar to the below: ../../../vendor/sqlite/src/sqlite3.c: In function ‘sqlite3_db_status’: ../../../vendor/sqlite/src/sqlite3.c:20251:10: error: this statement may fall through [-Werror=implicit-fallthrough=] op = SQLITE_DBSTATUS_CACHE_WRITE+1; So disable the implicit falltrhough warnings for that library. Note that -Wno-error=implicit-fallthrough is not used to keep the build silent since this is vendor library. --- cmake/sqlite.cmake | 1 + 1 file changed, 1 insertion(+) 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" ) -- cgit v1.2.1 From 30e570aae7d2ba5522feafb962b334ef3f35459e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=A4fer?= Date: Thu, 21 Jun 2018 14:44:00 +0200 Subject: [core] add polyfill for codecvt for STLs that don't have it yet --- CMakeLists.txt | 2 ++ cmake/codecvt.cmake | 19 +++++++++++++++++++ cmake/core.cmake | 2 ++ platform/android/config.cmake | 3 +++ platform/default/codecvt/codecvt | 30 ++++++++++++++++++++++++++++++ platform/default/utf.cpp | 16 ++-------------- 6 files changed, 58 insertions(+), 14 deletions(-) create mode 100644 cmake/codecvt.cmake create mode 100644 platform/default/codecvt/codecvt 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/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 \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/platform/android/config.cmake b/platform/android/config.cmake index d6be05095b..004912ba1a 100644 --- a/platform/android/config.cmake +++ b/platform/android/config.cmake @@ -71,6 +71,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 +87,7 @@ add_library(mapbox-gl SHARED ) target_link_libraries(mapbox-gl + PRIVATE codecvt PRIVATE mbgl-core PRIVATE mbgl-filesource ) @@ -106,6 +108,7 @@ macro(mbgl_platform_test) ) target_link_libraries(mbgl-test + PRIVATE codecvt PRIVATE mbgl-core PRIVATE mbgl-filesource ) 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 +#include + +namespace std { + +template +class wstring_convert { +public: + static_assert(std::is_same::value, "type mismatch"); + + inline std::basic_string from_bytes(const string& str) { + return boost::locale::conv::utf_to_utf(str); + } + + inline string to_bytes(const std::basic_string& str) { + return boost::locale::conv::utf_to_utf(str); + } +}; + +template +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 -#include #include - -// GCC 4.9 compatibility -#if !defined(__GNUC__) || __GNUC__ >= 5 #include -#else -#include -#endif namespace mbgl { namespace util { -std::u16string utf8_to_utf16::convert(std::string const& utf8) { -#if !defined(__GNUC__) || __GNUC__ >= 5 - std::wstring_convert, char16_t> converter; - return converter.from_bytes(utf8); -#else - return boost::locale::conv::utf_to_utf(utf8.c_str(), utf8.c_str() + utf8.size()); -#endif +std::u16string utf8_to_utf16::convert(const std::string& utf8) { + return std::wstring_convert, char16_t>().from_bytes(utf8); } } // namespace util -- cgit v1.2.1 From 4a3c4edb59b6881a30056531bc71e52295ab1cb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=A4fer?= Date: Thu, 21 Jun 2018 14:44:00 +0200 Subject: [android] add support for gnustl --- Makefile | 3 ++- cmake/mason-dependencies.cmake | 2 +- include/mbgl/math/log2.hpp | 11 ++++++++++ platform/android/MapboxGLAndroidSDK/build.gradle | 8 ++++++- platform/android/src/geojson/feature.cpp | 2 ++ platform/linux/src/headless_backend_egl.cpp | 3 ++- src/mbgl/map/map.cpp | 2 +- src/mbgl/map/transform_state.cpp | 2 +- src/mbgl/renderer/sources/render_image_source.cpp | 2 +- src/mbgl/style/expression/compound_expression.cpp | 2 +- src/mbgl/text/collision_feature.cpp | 2 +- src/mbgl/util/dtoa.hpp | 5 +++++ src/mbgl/util/tile_cover.cpp | 2 +- test/map/transform.test.cpp | 6 ++++-- test/storage/http_file_source.test.cpp | 5 +++-- test/storage/online_file_source.test.cpp | 5 +++-- test/util/dtoa.test.cpp | 26 +++++++++++------------ 17 files changed, 59 insertions(+), 29 deletions(-) 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/cmake/mason-dependencies.cmake b/cmake/mason-dependencies.cmake index 6c571db259..a143ec8ee6 100644 --- a/cmake/mason-dependencies.cmake +++ b/cmake/mason-dependencies.cmake @@ -5,7 +5,7 @@ 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.65.1 HEADER_ONLY) -mason_use(geojsonvt VERSION 6.6.0 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) 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 +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/platform/android/MapboxGLAndroidSDK/build.gradle b/platform/android/MapboxGLAndroidSDK/build.gradle index e796c35cee..d122687823 100644 --- a/platform/android/MapboxGLAndroidSDK/build.gradle +++ b/platform/android/MapboxGLAndroidSDK/build.gradle @@ -59,12 +59,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/src/geojson/feature.cpp b/platform/android/src/geojson/feature.cpp index e79c238864..f0ed097842 100644 --- a/platform/android/src/geojson/feature.cpp +++ b/platform/android/src/geojson/feature.cpp @@ -2,6 +2,8 @@ #include "geometry.hpp" #include "../gson/json_object.hpp" +#include + namespace mbgl { namespace android { namespace geojson { 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 +#include #include #include @@ -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/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& 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 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/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 initiali define("sqrt", [](double x) -> Result { return sqrt(x); }); define("log10", [](double x) -> Result { return log10(x); }); define("ln", [](double x) -> Result { return log(x); }); - define("log2", [](double x) -> Result { return log2(x); }); + define("log2", [](double x) -> Result { return util::log2(x); }); define("sin", [](double x) -> Result { return sin(x); }); define("cos", [](double x) -> Result { return cos(x); }); define("tan", [](double x) -> Result { return tan(x); }); 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(overscaling)); + const float overscalingPaddingFactor = 1 + .4 * util::log2(static_cast(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/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 +#include 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 tileCover(const Point& 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 #include +#include + 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 #include #include +#include #include using namespace mbgl; @@ -177,12 +178,12 @@ TEST(HTTPFileSource, TEST_REQUIRES_SERVER(Load)) { std::function 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 #include #include +#include #include #include @@ -240,12 +241,12 @@ TEST(OnlineFileSource, TEST_REQUIRES_SERVER(Load)) { std::function 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))); } -- cgit v1.2.1 From bc9b2249169276987af4ed91b29bf8a2fd65e15e Mon Sep 17 00:00:00 2001 From: Anand Thakker Date: Wed, 25 Jul 2018 11:00:11 -0400 Subject: [build] add android-gnustl-arm-v7 CI job --- circle.yml | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) 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: @@ -468,6 +469,86 @@ jobs: - store_artifacts: 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: -- cgit v1.2.1 From 2fccdecfb1ae720682276c0342e1c3902d8c9873 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=A4fer?= Date: Thu, 23 Aug 2018 12:15:09 +0200 Subject: [build] add script to generate a standalone version of Mapbox GL --- cmake/mason-dependencies.cmake | 2 +- cmake/mason.cmake | 4 +-- platform/android/core-files.txt | 3 ++ scripts/standalone.cmake | 18 ++++++++++ scripts/standalone.sh | 78 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 scripts/standalone.cmake create mode 100755 scripts/standalone.sh diff --git a/cmake/mason-dependencies.cmake b/cmake/mason-dependencies.cmake index a143ec8ee6..3c6a535fc8 100644 --- a/cmake/mason-dependencies.cmake +++ b/cmake/mason-dependencies.cmake @@ -21,7 +21,7 @@ mason_use(vector-tile VERSION 1.0.2 HEADER_ONLY) if(MBGL_PLATFORM STREQUAL "android") 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/platform/android/core-files.txt b/platform/android/core-files.txt index cd4028cd59..4262489056 100644 --- a/platform/android/core-files.txt +++ b/platform/android/core-files.txt @@ -213,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/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 [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 -- cgit v1.2.1 From 6e171a62a9cc07ddbb0765e3021e46ebd60313df Mon Sep 17 00:00:00 2001 From: tobrun Date: Fri, 27 Jul 2018 14:00:55 +0200 Subject: [android] - replace platform default implementation using nunicode for uppercasing an lowercasing with an Android specific String.java equivalent --- .../com/mapbox/mapboxsdk/utils/StringUtils.java | 27 ++++++++++++ .../testapp/string/UppperLowerCaseTest.java | 50 ++++++++++++++++++++++ .../activity/render/RenderTestActivity.java | 3 +- platform/android/config.cmake | 2 - platform/android/core-files.txt | 4 +- platform/android/scripts/run-render-test.py | 2 +- platform/android/src/jni.cpp | 1 + platform/android/src/string_util.cpp | 25 +++++++++++ platform/android/src/text/collator.cpp | 12 +++++- platform/android/src/text/collator_jni.hpp | 11 +++++ platform/android/src/unaccent.cpp | 18 ++++++++ 11 files changed, 148 insertions(+), 7 deletions(-) create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/StringUtils.java create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/string/UppperLowerCaseTest.java create mode 100644 platform/android/src/string_util.cpp create mode 100644 platform/android/src/unaccent.cpp 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/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 + *

+ * See core test in https://github.com/mapbox/mapbox-gl-native/blob/master/test/util/text_conversions.test.cpp + *

+ */ +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/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 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/config.cmake b/platform/android/config.cmake index 004912ba1a..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 diff --git a/platform/android/core-files.txt b/platform/android/core-files.txt index 4262489056..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 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/jni.cpp b/platform/android/src/jni.cpp index abea7f4502..e323dc83b3 100755 --- a/platform/android/src/jni.cpp +++ b/platform/android/src/jni.cpp @@ -187,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/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 +#include "attach_env.hpp" +#include + +namespace mbgl { +namespace platform { + +std::string uppercase(const std::string& str) { + auto env{ android::AttachEnv() }; + jni::Local value = jni::Make(*env, str.c_str()); + static auto toUpperCase = jni::Class::Singleton(*env).GetMethod(*env, "toUpperCase"); + auto result = value.Call(*env, toUpperCase); + return jni::Make(*env, result); +} + +std::string lowercase(const std::string& str) { + auto env{ android::AttachEnv() }; + jni::Local value = jni::Make(*env, str.c_str()); + static auto toLowerCase = jni::Class::Singleton(*env).GetMethod(*env, "toLowerCase"); + auto result = value.Call(*env, toLowerCase); + return jni::Make(*env, result); +} + +} // namespace platform +} // namespace mbgl diff --git a/platform/android/src/text/collator.cpp b/platform/android/src/text/collator.cpp index 04da53832a..381851eff2 100644 --- a/platform/android/src/text/collator.cpp +++ b/platform/android/src/text/collator.cpp @@ -30,10 +30,20 @@ void Collator::setStrength(jni::JNIEnv& env, const jni::Object& collat jni::jint Collator::compare(jni::JNIEnv& env, const jni::Object& collator, const jni::String& lhs, const jni::String& rhs) { static auto& javaClass = jni::Class::Singleton(env); - auto static method = javaClass.GetMethod(env, "compare"); + static auto method = javaClass.GetMethod(env, "compare"); return collator.Call(env, method, lhs, rhs); } +void StringUtils::registerNative(jni::JNIEnv& env) { + jni::Class::Singleton(env); +} + +jni::Local StringUtils::unaccent(jni::JNIEnv& env, const jni::String& value) { + static auto& javaClass = jni::Class::Singleton(env); + static auto method = javaClass.GetStaticMethod(env, "unaccent"); + return javaClass.Call(env, method, value); +} + void Locale::registerNative(jni::JNIEnv& env) { jni::Class::Singleton(env); } diff --git a/platform/android/src/text/collator_jni.hpp b/platform/android/src/text/collator_jni.hpp index e5e82c34fd..dd3f845662 100644 --- a/platform/android/src/text/collator_jni.hpp +++ b/platform/android/src/text/collator_jni.hpp @@ -49,5 +49,16 @@ public: static void registerNative(jni::JNIEnv&); }; + +class StringUtils { +public: + static constexpr auto Name() { return "com/mapbox/mapboxsdk/utils/StringUtils"; }; + + static jni::Local unaccent(jni::JNIEnv&, const jni::String&); + + + static void registerNative(jni::JNIEnv&); +}; + } // namespace android } // namespace mbgl 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 +#include +#include "attach_env.hpp" +#include "text/collator_jni.hpp" +#include + +namespace mbgl { +namespace platform { + +std::string unaccent(const std::string& str) { + android::UniqueEnv env = android::AttachEnv(); + jni::Local input = jni::Make(*env, str); + jni::Local unaccented = android::StringUtils::unaccent(*env, input); + return jni::Make(*env, unaccented); +} + +} // namespace platform +} // namespace mbgl -- cgit v1.2.1 From 511fca7210f8b41c37a2250e77239e4b25b41ed5 Mon Sep 17 00:00:00 2001 From: Jason Wray Date: Wed, 7 Feb 2018 16:53:33 -0500 Subject: [ios] Add fall-through single tap to iosapp --- platform/ios/app/MBXViewController.m | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) 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) -- cgit v1.2.1 From e70fe057566104b2e845533c6e58f3a8572159f9 Mon Sep 17 00:00:00 2001 From: tobrun Date: Tue, 11 Sep 2018 18:53:21 +0200 Subject: [android] - update changelog for v6.5.0 --- platform/android/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index 8031232d43..1db3140b6f 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -5,6 +5,10 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to ## 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) - MapStrictMode configuration [#12817](https://github.com/mapbox/mapbox-gl-native/pull/12817) -- cgit v1.2.1 From 5d000d090fd1d69fb902fd5b477d3bb996e3c955 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Paczos?= Date: Tue, 28 Aug 2018 17:06:21 +0200 Subject: [android] merge LocationLayerPlugin to Maps SDK --- platform/android/MapboxGLAndroidSDK/build.gradle | 8 +- .../CameraCompassBearingAnimator.java | 24 + .../locationlayer/CameraGpsBearingAnimator.java | 23 + .../locationlayer/CameraLatLngAnimator.java | 25 + .../plugins/locationlayer/CompassEngine.java | 62 + .../plugins/locationlayer/CompassListener.java | 33 + .../plugins/locationlayer/LatLngEvaluator.java | 19 + .../locationlayer/LayerAccuracyAnimator.java | 24 + .../plugins/locationlayer/LayerBitmapProvider.java | 33 + .../locationlayer/LayerCompassBearingAnimator.java | 24 + .../locationlayer/LayerFeatureProvider.java | 26 + .../locationlayer/LayerGpsBearingAnimator.java | 23 + .../plugins/locationlayer/LayerLatLngAnimator.java | 25 + .../plugins/locationlayer/LayerSourceProvider.java | 107 + .../plugins/locationlayer/LocationLayer.java | 398 + .../plugins/locationlayer/LocationLayerCamera.java | 263 + .../locationlayer/LocationLayerCompassEngine.java | 267 + .../locationlayer/LocationLayerConstants.java | 60 + .../locationlayer/LocationLayerOptions.java | 1561 + .../plugins/locationlayer/LocationLayerPlugin.java | 966 + .../locationlayer/MapboxCameraAnimatorAdapter.java | 38 + .../OnCameraMoveInvalidateListener.java | 7 + .../OnCameraTrackingChangedListener.java | 21 + .../OnLocationLayerClickListener.java | 11 + .../OnLocationLayerLongClickListener.java | 11 + .../locationlayer/OnLocationStaleListener.java | 13 + .../plugins/locationlayer/PluginAnimator.java | 92 + .../locationlayer/PluginAnimatorCoordinator.java | 375 + .../plugins/locationlayer/PluginFloatAnimator.java | 17 + .../locationlayer/PluginLatLngAnimator.java | 19 + .../plugins/locationlayer/StaleStateManager.java | 64 + .../plugins/locationlayer/TiltAnimator.java | 27 + .../mapboxsdk/plugins/locationlayer/Utils.java | 102 + .../plugins/locationlayer/ZoomAnimator.java | 29 + .../plugins/locationlayer/modes/CameraMode.java | 66 + .../plugins/locationlayer/modes/RenderMode.java | 45 + .../plugins/locationlayer/package-info.java | 4 + .../src/main/res-public/values/public.xml | 41 + .../main/res/drawable/mapbox_user_bearing_icon.xml | 10 + .../src/main/res/drawable/mapbox_user_icon.xml | 10 + .../main/res/drawable/mapbox_user_icon_shadow.xml | 19 + .../main/res/drawable/mapbox_user_icon_stale.xml | 10 + .../main/res/drawable/mapbox_user_puck_icon.xml | 17 + .../main/res/drawable/mapbox_user_stroke_icon.xml | 10 + .../src/main/res/values/attrs.xml | 46 + .../src/main/res/values/colors.xml | 3 + .../src/main/res/values/dimens.xml | 3 + .../src/main/res/values/styles.xml | 45 + .../plugins/locationlayer/CompassEngineTest.java | 64 + .../locationlayer/LocationLayerCameraTest.java | 337 + .../locationlayer/LocationLayerOptionsTest.java | 68 + .../plugins/locationlayer/LocationLayerTest.java | 466 + .../locationlayer/PluginAnimatorCoordinatorTest.kt | 284 + .../mapboxsdk/plugins/locationlayer/UtilsTest.java | 29 + .../locationlayer/LocationLayerPluginTest.kt | 1089 + .../plugins/locationlayer/LocationLayerTest.kt | 356 + .../mapboxsdk/plugins/utils/GenericPluginAction.kt | 48 + .../mapboxsdk/plugins/utils/MapboxTestingUtils.kt | 79 + .../utils/OnMapFragmentReadyIdlingResource.kt | 39 + .../plugins/utils/OnMapReadyIdlingResource.java | 63 + .../plugins/utils/PluginGenerationUtil.kt | 51 + .../plugins/utils/StyleChangeIdlingResource.kt | 46 + .../mapboxsdk/plugins/utils/TestLifecycleOwner.kt | 19 + .../src/debug/AndroidManifest.xml | 18 + .../src/debug/assets/heavy_style.json | 81857 +++++++++++++++++++ .../mapboxsdk/testapp/activity/SingleActivity.java | 62 + .../testapp/activity/SingleFragmentActivity.java | 36 + .../src/debug/res/layout/activity_single.xml | 13 + 68 files changed, 90148 insertions(+), 2 deletions(-) create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/CameraCompassBearingAnimator.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/CameraGpsBearingAnimator.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/CameraLatLngAnimator.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/CompassEngine.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/CompassListener.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LatLngEvaluator.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LayerAccuracyAnimator.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LayerBitmapProvider.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LayerCompassBearingAnimator.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LayerFeatureProvider.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LayerGpsBearingAnimator.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LayerLatLngAnimator.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LayerSourceProvider.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayer.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerCamera.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerCompassEngine.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerConstants.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerOptions.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerPlugin.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/MapboxCameraAnimatorAdapter.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnCameraMoveInvalidateListener.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnCameraTrackingChangedListener.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnLocationLayerClickListener.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnLocationLayerLongClickListener.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnLocationStaleListener.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/PluginAnimator.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/PluginAnimatorCoordinator.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/PluginFloatAnimator.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/PluginLatLngAnimator.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/StaleStateManager.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/TiltAnimator.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/Utils.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/ZoomAnimator.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/modes/CameraMode.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/modes/RenderMode.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/package-info.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_bearing_icon.xml create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_icon.xml create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_icon_shadow.xml create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_icon_stale.xml create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_puck_icon.xml create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_user_stroke_icon.xml create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/res/values/styles.xml create mode 100644 platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/plugins/locationlayer/CompassEngineTest.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerCameraTest.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerOptionsTest.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerTest.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/plugins/locationlayer/PluginAnimatorCoordinatorTest.kt create mode 100644 platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/plugins/locationlayer/UtilsTest.java create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerPluginTest.kt create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerTest.kt create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/GenericPluginAction.kt create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/MapboxTestingUtils.kt create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/OnMapFragmentReadyIdlingResource.kt create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/OnMapReadyIdlingResource.java create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/PluginGenerationUtil.kt create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/StyleChangeIdlingResource.kt create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/TestLifecycleOwner.kt create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/debug/AndroidManifest.xml create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/debug/assets/heavy_style.json create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/debug/java/com/mapbox/mapboxsdk/testapp/activity/SingleActivity.java create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/debug/java/com/mapbox/mapboxsdk/testapp/activity/SingleFragmentActivity.java create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/debug/res/layout/activity_single.xml diff --git a/platform/android/MapboxGLAndroidSDK/build.gradle b/platform/android/MapboxGLAndroidSDK/build.gradle index d122687823..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()) diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/CameraCompassBearingAnimator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/CameraCompassBearingAnimator.java new file mode 100644 index 0000000000..6d5fd9da8f --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/CameraCompassBearingAnimator.java @@ -0,0 +1,24 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +import android.animation.ValueAnimator; + +import java.util.List; + +class CameraCompassBearingAnimator extends PluginFloatAnimator { + CameraCompassBearingAnimator(Float previous, Float target, + List 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/plugins/locationlayer/CameraGpsBearingAnimator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/CameraGpsBearingAnimator.java new file mode 100644 index 0000000000..ac88a0258c --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/CameraGpsBearingAnimator.java @@ -0,0 +1,23 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +import android.animation.ValueAnimator; + +import java.util.List; + +class CameraGpsBearingAnimator extends PluginFloatAnimator { + CameraGpsBearingAnimator(Float previous, Float target, List 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/plugins/locationlayer/CameraLatLngAnimator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/CameraLatLngAnimator.java new file mode 100644 index 0000000000..6f383a480a --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/CameraLatLngAnimator.java @@ -0,0 +1,25 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +import android.animation.ValueAnimator; + +import com.mapbox.mapboxsdk.geometry.LatLng; + +import java.util.List; + +class CameraLatLngAnimator extends PluginLatLngAnimator { + CameraLatLngAnimator(LatLng previous, LatLng target, List 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/plugins/locationlayer/CompassEngine.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/CompassEngine.java new file mode 100644 index 0000000000..b4b8ea4acb --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/CompassEngine.java @@ -0,0 +1,62 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +import android.support.annotation.NonNull; + +/** + * Interface defining the source of compass heading data that is + * consumed by the {@link LocationLayerPlugin} when in compass related + * {@link com.mapbox.mapboxsdk.plugins.locationlayer.modes.RenderMode} or + * {@link com.mapbox.mapboxsdk.plugins.locationlayer.modes.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. + *

+ * An integer value which is identical to the {@code SensorManager} class constants: + *

    + *
  • {@link android.hardware.SensorManager#SENSOR_STATUS_NO_CONTACT}
  • + *
  • {@link android.hardware.SensorManager#SENSOR_STATUS_UNRELIABLE}
  • + *
  • {@link android.hardware.SensorManager#SENSOR_STATUS_ACCURACY_LOW}
  • + *
  • {@link android.hardware.SensorManager#SENSOR_STATUS_ACCURACY_MEDIUM}
  • + *
  • {@link android.hardware.SensorManager#SENSOR_STATUS_ACCURACY_HIGH}
  • + *
+ * + * @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/plugins/locationlayer/CompassListener.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/CompassListener.java new file mode 100644 index 0000000000..eabf62afa2 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/CompassListener.java @@ -0,0 +1,33 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +/** + * 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 LocationLayerPlugin#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: + *
    + *
  • {@link android.hardware.SensorManager#SENSOR_STATUS_NO_CONTACT}
  • + *
  • {@link android.hardware.SensorManager#SENSOR_STATUS_UNRELIABLE}
  • + *
  • {@link android.hardware.SensorManager#SENSOR_STATUS_ACCURACY_LOW}
  • + *
  • {@link android.hardware.SensorManager#SENSOR_STATUS_ACCURACY_MEDIUM}
  • + *
  • {@link android.hardware.SensorManager#SENSOR_STATUS_ACCURACY_HIGH}
  • + *
+ * + * @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/plugins/locationlayer/LatLngEvaluator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LatLngEvaluator.java new file mode 100644 index 0000000000..b137ea0134 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LatLngEvaluator.java @@ -0,0 +1,19 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +import android.animation.TypeEvaluator; + +import com.mapbox.mapboxsdk.geometry.LatLng; + +class LatLngEvaluator implements TypeEvaluator { + + 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/plugins/locationlayer/LayerAccuracyAnimator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LayerAccuracyAnimator.java new file mode 100644 index 0000000000..1d200f454d --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LayerAccuracyAnimator.java @@ -0,0 +1,24 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +import android.animation.ValueAnimator; + +import java.util.List; + +class LayerAccuracyAnimator extends PluginFloatAnimator { + + LayerAccuracyAnimator(Float previous, Float target, List 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/plugins/locationlayer/LayerBitmapProvider.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LayerBitmapProvider.java new file mode 100644 index 0000000000..aabf083525 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LayerBitmapProvider.java @@ -0,0 +1,33 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +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.plugins.locationlayer.Utils.generateShadow; +import static com.mapbox.mapboxsdk.plugins.locationlayer.Utils.getBitmapFromDrawable; +import static com.mapbox.mapboxsdk.plugins.locationlayer.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(LocationLayerOptions 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/plugins/locationlayer/LayerCompassBearingAnimator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LayerCompassBearingAnimator.java new file mode 100644 index 0000000000..3b3898d1e6 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LayerCompassBearingAnimator.java @@ -0,0 +1,24 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +import android.animation.ValueAnimator; + +import java.util.List; + +class LayerCompassBearingAnimator extends PluginFloatAnimator { + LayerCompassBearingAnimator(Float previous, + Float target, List 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/plugins/locationlayer/LayerFeatureProvider.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LayerFeatureProvider.java new file mode 100644 index 0000000000..9f119ef6eb --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LayerFeatureProvider.java @@ -0,0 +1,26 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +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.plugins.locationlayer.LocationLayerConstants.PROPERTY_COMPASS_BEARING; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_GPS_BEARING; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_LOCATION_STALE; + +class LayerFeatureProvider { + + @NonNull + Feature generateLocationFeature(@Nullable Feature locationFeature, LocationLayerOptions 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/plugins/locationlayer/LayerGpsBearingAnimator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LayerGpsBearingAnimator.java new file mode 100644 index 0000000000..c14ffbb935 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LayerGpsBearingAnimator.java @@ -0,0 +1,23 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +import android.animation.ValueAnimator; + +import java.util.List; + +class LayerGpsBearingAnimator extends PluginFloatAnimator { + LayerGpsBearingAnimator(Float previous, Float target, List 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/plugins/locationlayer/LayerLatLngAnimator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LayerLatLngAnimator.java new file mode 100644 index 0000000000..0ff0a46bd7 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LayerLatLngAnimator.java @@ -0,0 +1,25 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +import android.animation.ValueAnimator; + +import com.mapbox.mapboxsdk.geometry.LatLng; + +import java.util.List; + +class LayerLatLngAnimator extends PluginLatLngAnimator { + LayerLatLngAnimator(LatLng previous, LatLng target, List 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/plugins/locationlayer/LayerSourceProvider.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LayerSourceProvider.java new file mode 100644 index 0000000000..31f5b75426 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LayerSourceProvider.java @@ -0,0 +1,107 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +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.plugins.locationlayer.LocationLayerConstants.ACCURACY_LAYER; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.BACKGROUND_LAYER; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.BEARING_LAYER; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.FOREGROUND_LAYER; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.LOCATION_SOURCE; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_ACCURACY_ALPHA; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_ACCURACY_COLOR; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_ACCURACY_RADIUS; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_BACKGROUND_ICON; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_BACKGROUND_STALE_ICON; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_BEARING_ICON; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_COMPASS_BEARING; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_FOREGROUND_ICON; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_FOREGROUND_ICON_OFFSET; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_FOREGROUND_STALE_ICON; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_GPS_BEARING; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_LOCATION_STALE; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_SHADOW_ICON_OFFSET; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.SHADOW_ICON; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.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/plugins/locationlayer/LocationLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayer.java new file mode 100644 index 0000000000..0e7ce37a07 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayer.java @@ -0,0 +1,398 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +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.plugins.locationlayer.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.plugins.locationlayer.LocationLayerConstants.ACCURACY_LAYER; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.BACKGROUND_ICON; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.BACKGROUND_LAYER; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.BACKGROUND_STALE_ICON; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.BEARING_ICON; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.BEARING_LAYER; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.FOREGROUND_ICON; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.FOREGROUND_LAYER; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.FOREGROUND_STALE_ICON; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.LOCATION_SOURCE; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_ACCURACY_ALPHA; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_ACCURACY_COLOR; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_ACCURACY_RADIUS; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_BACKGROUND_ICON; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_BACKGROUND_STALE_ICON; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_BEARING_ICON; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_COMPASS_BEARING; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_FOREGROUND_ICON; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_FOREGROUND_ICON_OFFSET; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_FOREGROUND_STALE_ICON; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_GPS_BEARING; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_LOCATION_STALE; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_SHADOW_ICON_OFFSET; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.SHADOW_ICON; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.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 LocationLayer implements PluginAnimator.OnLayerAnimationsValuesChangeListener { + + @RenderMode.Mode + private int renderMode; + + private final MapboxMap mapboxMap; + private final LayerSourceProvider layerSourceProvider; + private final LayerBitmapProvider bitmapProvider; + private LocationLayerOptions options; + + private final List layerMap = new ArrayList<>(); + private Feature locationFeature; + private GeoJsonSource locationSource; + + private boolean isHidden = true; + + LocationLayer(MapboxMap mapboxMap, LayerSourceProvider layerSourceProvider, + LayerFeatureProvider featureProvider, LayerBitmapProvider bitmapProvider, + LocationLayerOptions options) { + this.mapboxMap = mapboxMap; + this.layerSourceProvider = layerSourceProvider; + this.bitmapProvider = bitmapProvider; + this.locationFeature = featureProvider.generateLocationFeature(locationFeature, options); + initializeComponents(options); + setRenderMode(RenderMode.NORMAL); + } + + void initializeComponents(LocationLayerOptions options) { + addLocationSource(); + addLayers(options.layerBelow()); + applyStyle(options); + + if (isHidden) { + hide(); + } else { + show(); + } + } + + void applyStyle(@NonNull LocationLayerOptions 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); + } + } + + 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(LocationLayerOptions 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(LocationLayerOptions options) { + mapboxMap.addImage(SHADOW_ICON, bitmapProvider.generateShadowBitmap(options)); + } + + private void styleBearing(LocationLayerOptions 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(LocationLayerOptions 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(LocationLayerOptions 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(LocationLayerOptions 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) { + // If options has stale state disabled, just return here. + if (!options.enableStaleState()) { + return; + } + 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 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/plugins/locationlayer/LocationLayerCamera.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerCamera.java new file mode 100644 index 0000000000..b59f849aa1 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerCamera.java @@ -0,0 +1,263 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +import android.content.Context; +import android.graphics.PointF; +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.maps.MapboxMap; +import com.mapbox.mapboxsdk.plugins.locationlayer.modes.CameraMode; + +import java.util.List; +import java.util.Set; + +final class LocationLayerCamera implements PluginAnimator.OnCameraAnimationsValuesChangeListener { + + @CameraMode.Mode + private int cameraMode; + + private final MapboxMap mapboxMap; + private final OnCameraTrackingChangedListener internalCameraTrackingChangedListener; + private LocationLayerOptions options; + private boolean adjustFocalPoint; + + private final MoveGestureDetector moveGestureDetector; + private final OnCameraMoveInvalidateListener onCameraMoveInvalidateListener; + + LocationLayerCamera( + Context context, + MapboxMap mapboxMap, + OnCameraTrackingChangedListener internalCameraTrackingChangedListener, + LocationLayerOptions options, + OnCameraMoveInvalidateListener onCameraMoveInvalidateListener) { + this.mapboxMap = mapboxMap; + mapboxMap.setGesturesManager( + new PluginsGesturesManager(context), true, true); + moveGestureDetector = mapboxMap.getGesturesManager().getMoveGestureDetector(); + mapboxMap.addOnMoveListener(onMoveListener); + mapboxMap.addOnRotateListener(onRotateListener); + mapboxMap.addOnFlingListener(onFlingListener); + + this.internalCameraTrackingChangedListener = internalCameraTrackingChangedListener; + this.onCameraMoveInvalidateListener = onCameraMoveInvalidateListener; + initializeOptions(options); + } + + // Package private for testing purposes + LocationLayerCamera(MapboxMap mapboxMap, + MoveGestureDetector moveGestureDetector, + OnCameraTrackingChangedListener internalCameraTrackingChangedListener, + OnCameraMoveInvalidateListener onCameraMoveInvalidateListener) { + this.mapboxMap = mapboxMap; + this.moveGestureDetector = moveGestureDetector; + this.internalCameraTrackingChangedListener = internalCameraTrackingChangedListener; + this.onCameraMoveInvalidateListener = onCameraMoveInvalidateListener; + } + + void initializeOptions(LocationLayerOptions options) { + this.options = options; + } + + 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 (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(MoveGestureDetector detector) { + if (detector.getPointersCount() > 1 + && detector.getMoveThreshold() != options.trackingMultiFingerMoveThreshold() + && isLocationTracking()) { + detector.setMoveThreshold(options.trackingMultiFingerMoveThreshold()); + interrupt = true; + } + } + + @Override + public void onMove(MoveGestureDetector detector) { + if (interrupt) { + detector.interrupt(); + return; + } + + setCameraMode(CameraMode.NONE); + } + + @Override + public void onMoveEnd(MoveGestureDetector detector) { + if (!interrupt && isLocationTracking()) { + moveGestureDetector.setMoveThreshold(options.trackingInitialMoveThreshold()); + } + interrupt = false; + } + }; + + private MapboxMap.OnRotateListener onRotateListener = new MapboxMap.OnRotateListener() { + @Override + public void onRotateBegin(RotateGestureDetector detector) { + if (isBearingTracking()) { + setCameraMode(CameraMode.NONE); + } + } + + @Override + public void onRotate(RotateGestureDetector detector) { + // no implementation + } + + @Override + public void onRotateEnd(RotateGestureDetector detector) { + // no implementation + } + }; + + private MapboxMap.OnFlingListener onFlingListener = new MapboxMap.OnFlingListener() { + @Override + public void onFling() { + setCameraMode(CameraMode.NONE); + } + }; + + private class PluginsGesturesManager extends AndroidGesturesManager { + + public PluginsGesturesManager(Context context) { + super(context); + } + + public PluginsGesturesManager(Context context, boolean applyDefaultThresholds) { + super(context, applyDefaultThresholds); + } + + public PluginsGesturesManager(Context context, Set[] exclusiveGestures) { + super(context, exclusiveGestures); + } + + public PluginsGesturesManager(Context context, List> exclusiveGestures, + boolean applyDefaultThresholds) { + super(context, exclusiveGestures, applyDefaultThresholds); + } + + @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/plugins/locationlayer/LocationLayerCompassEngine.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerCompassEngine.java new file mode 100644 index 0000000000..f05580a21f --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerCompassEngine.java @@ -0,0 +1,267 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +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 LocationLayerCompassEngine 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 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. + */ + LocationLayerCompassEngine(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 + LocationLayerConstants.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/plugins/locationlayer/LocationLayerConstants.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerConstants.java new file mode 100644 index 0000000000..b6e4f568af --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerConstants.java @@ -0,0 +1,60 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +/** + * Contains all the constants being used for the Location layer. + */ +final class LocationLayerConstants { + + // 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_ANIMATION_DURATION = 750; + + // Default animation duration for tilting while tracking. + static final long DEFAULT_TRACKING_TILT_ANIMATION_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 LocationLayerConstants() { + // Class should not be initialized + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerOptions.java new file mode 100644 index 0000000000..204cb88013 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerOptions.java @@ -0,0 +1,1561 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +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.mapboxsdk.R; +import com.mapbox.mapboxsdk.constants.MapboxConstants; + +import java.util.Arrays; + +/** + * This class exposes options for the Location Layer Plugin. The options can be set by defining a + * style in your apps style.xml file and passing in directly into the {@link LocationLayerPlugin} + * 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 LocationLayerPlugin} constructor (if it isn't initialized yet) or + * {@link LocationLayerPlugin#applyStyle(LocationLayerOptions)}. + *

+ * 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 LocationLayerOptions} class using the builder, any options neglecting to be set will + * reset to their default values. + *

+ * 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 LocationLayerPlugin#getLocationLayerOptions()} + * 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 + * layer plugin using {@link LocationLayerPlugin#applyStyle(LocationLayerOptions)}. + */ +public class LocationLayerOptions 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 = 30000; + + 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 float trackingInitialMoveThreshold; + private float trackingMultiFingerMoveThreshold; + private String layerBelow; + + public LocationLayerOptions( + 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, + 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.trackingInitialMoveThreshold = trackingInitialMoveThreshold; + this.trackingMultiFingerMoveThreshold = trackingMultiFingerMoveThreshold; + this.layerBelow = layerBelow; + } + + /** + * Construct a new Location Layer 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 LocationLayerOptions} object with the settings you defined in your style + * resource + */ + public static LocationLayerOptions createFromAttributes(@NonNull Context context, + @StyleRes int styleRes) { + + TypedArray typedArray = context.obtainStyledAttributes( + styleRes, R.styleable.mapbox_LocationLayer); + + LocationLayerOptions.Builder builder = new LocationLayerOptions.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_LocationLayer_mapbox_foregroundDrawable, -1)); + if (typedArray.hasValue(R.styleable.mapbox_LocationLayer_mapbox_foregroundTintColor)) { + builder.foregroundTintColor(typedArray.getColor( + R.styleable.mapbox_LocationLayer_mapbox_foregroundTintColor, -1)); + } + builder.backgroundDrawable(typedArray.getResourceId( + R.styleable.mapbox_LocationLayer_mapbox_backgroundDrawable, -1)); + if (typedArray.hasValue(R.styleable.mapbox_LocationLayer_mapbox_backgroundTintColor)) { + builder.backgroundTintColor(typedArray.getColor( + R.styleable.mapbox_LocationLayer_mapbox_backgroundTintColor, -1)); + } + builder.foregroundDrawableStale(typedArray.getResourceId( + R.styleable.mapbox_LocationLayer_mapbox_foregroundDrawableStale, -1)); + if (typedArray.hasValue(R.styleable.mapbox_LocationLayer_mapbox_foregroundStaleTintColor)) { + builder.foregroundStaleTintColor(typedArray.getColor( + R.styleable.mapbox_LocationLayer_mapbox_foregroundStaleTintColor, -1)); + } + builder.backgroundDrawableStale(typedArray.getResourceId( + R.styleable.mapbox_LocationLayer_mapbox_backgroundDrawableStale, -1)); + if (typedArray.hasValue(R.styleable.mapbox_LocationLayer_mapbox_backgroundStaleTintColor)) { + builder.backgroundStaleTintColor(typedArray.getColor( + R.styleable.mapbox_LocationLayer_mapbox_backgroundStaleTintColor, -1)); + } + builder.bearingDrawable(typedArray.getResourceId( + R.styleable.mapbox_LocationLayer_mapbox_bearingDrawable, -1)); + if (typedArray.hasValue(R.styleable.mapbox_LocationLayer_mapbox_bearingTintColor)) { + builder.bearingTintColor(typedArray.getColor( + R.styleable.mapbox_LocationLayer_mapbox_bearingTintColor, -1)); + } + if (typedArray.hasValue(R.styleable.mapbox_LocationLayer_mapbox_enableStaleState)) { + builder.enableStaleState(typedArray.getBoolean( + R.styleable.mapbox_LocationLayer_mapbox_enableStaleState, true)); + } + if (typedArray.hasValue(R.styleable.mapbox_LocationLayer_mapbox_staleStateTimeout)) { + builder.staleStateTimeout(typedArray.getInteger( + R.styleable.mapbox_LocationLayer_mapbox_staleStateTimeout, (int) STALE_STATE_DELAY_MS)); + } + builder.gpsDrawable(typedArray.getResourceId( + R.styleable.mapbox_LocationLayer_mapbox_gpsDrawable, -1)); + float elevation = typedArray.getDimension( + R.styleable.mapbox_LocationLayer_mapbox_elevation, 0); + builder.accuracyColor(typedArray.getColor( + R.styleable.mapbox_LocationLayer_mapbox_accuracyColor, -1)); + builder.accuracyAlpha(typedArray.getFloat( + R.styleable.mapbox_LocationLayer_mapbox_accuracyAlpha, ACCURACY_ALPHA_DEFAULT)); + builder.elevation(elevation); + + builder.trackingInitialMoveThreshold(typedArray.getDimension( + R.styleable.mapbox_LocationLayer_mapbox_trackingInitialMoveThreshold, + context.getResources().getDimension(R.dimen.mapbox_locationLayerTrackingInitialMoveThreshold))); + + builder.trackingMultiFingerMoveThreshold(typedArray.getDimension( + R.styleable.mapbox_LocationLayer_mapbox_trackingMultiFingerMoveThreshold, + context.getResources().getDimension(R.dimen.mapbox_locationLayerTrackingMultiFingerMoveThreshold))); + + builder.padding(new int[] { + typedArray.getInt(R.styleable.mapbox_LocationLayer_mapbox_iconPaddingLeft, 0), + typedArray.getInt(R.styleable.mapbox_LocationLayer_mapbox_iconPaddingTop, 0), + typedArray.getInt(R.styleable.mapbox_LocationLayer_mapbox_iconPaddingRight, 0), + typedArray.getInt(R.styleable.mapbox_LocationLayer_mapbox_iconPaddingBottom, 0), + }); + + float maxZoom + = typedArray.getFloat(R.styleable.mapbox_LocationLayer_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_LocationLayer_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_LocationLayer_mapbox_layer_below)); + + float minScale = typedArray.getFloat( + R.styleable.mapbox_LocationLayer_mapbox_minZoomIconScale, MIN_ZOOM_ICON_SCALE_DEFAULT); + float maxScale = typedArray.getFloat( + R.styleable.mapbox_LocationLayer_mapbox_maxZoomIconScale, MAX_ZOOM_ICON_SCALE_DEFAULT); + builder.minZoomIconScale(minScale); + builder.maxZoomIconScale(maxScale); + + typedArray.recycle(); + + return builder.build(); + } + + /** + * Takes the currently constructed {@link LocationLayerOptions} 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 Location Layer 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 LocationLayerOptions} 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 Location Layer builder which contains the default values defined by the style + * resource + */ + public static Builder builder(Context context) { + return LocationLayerOptions.createFromAttributes(context, + R.style.mapbox_LocationLayer).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#LocationLayer_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#LocationLayer_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#LocationLayer_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 + * plugin, will used this image in place of the provided or default mapbox_foregroundDrawableStale. + *

+ * 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. + *

+ * + * @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#LocationLayer_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 + * plugin, will used this image in place of the provided or default mapbox_foregroundDrawableStale. + *

+ * 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. + *

+ * + * @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#LocationLayer_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 + * plugin, will used this image in place of the provided or default mapbox_gpsDrawable. + *

+ * 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. + *

+ * + * @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 Layer + * Plugin layer stack. + * + * @return the drawable resource used for the foreground layer + * @attr ref R.styleable#LocationLayer_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 + * plugin, will used this image in place of the provided or default mapbox_foregroundDrawable. + *

+ * 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. + *

+ * + * @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#LocationLayer_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 + * plugin, will used this image in place of the provided or default mapbox_backgroundDrawable. + *

+ * 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. + *

+ * + * @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#LocationLayer_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 + * plugin, will used this image in place of the provided or default mapbox_bearingDrawable. + *

+ * 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. + *

+ * + * @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#LocationLayer_bearingTintColor + */ + @ColorInt + @Nullable + public Integer bearingTintColor() { + return bearingTintColor; + } + + /** + * Defines the foreground color as an integer. + * + * @return the color integer resource + * @attr ref R.styleable#LocationLayer_foregroundTintColor + */ + @ColorInt + @Nullable + public Integer foregroundTintColor() { + return foregroundTintColor; + } + + /** + * Defines the background color as an integer. + * + * @return the color integer resource + * @attr ref R.styleable#LocationLayer_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#LocationLayer_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#LocationLayer_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 layer icon + * @attr ref R.styleable#LocationLayer_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#LocationLayer_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 layer is + * considered stale + * @attr ref R.styleable#LocationLayer_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. + *

+ *

+ * 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. + *

+ * + * @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; + } + + /** + * 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 layer above to. + * + * @return layerBelow the id of the layer to add the location layer above to + */ + public String layerBelow() { + return layerBelow; + } + + @Override + public String toString() { + return "LocationLayerOptions{" + + "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 + ", " + + "trackingInitialMoveThreshold=" + trackingInitialMoveThreshold + ", " + + "trackingMultiFingerMoveThreshold=" + trackingMultiFingerMoveThreshold + ", " + + "layerBelow=" + layerBelow + + "}"; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof LocationLayerOptions) { + LocationLayerOptions that = (LocationLayerOptions) 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())) + && (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$ ^= Float.floatToIntBits(trackingInitialMoveThreshold); + h$ *= 1000003; + h$ ^= Float.floatToIntBits(trackingMultiFingerMoveThreshold); + return h$; + } + + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + @Override + public LocationLayerOptions createFromParcel(Parcel in) { + return new LocationLayerOptions( + 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.readFloat(), + in.readFloat(), + in.readString() + ); + } + + @Override + public LocationLayerOptions[] newArray(int size) { + return new LocationLayerOptions[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.writeFloat(trackingInitialMoveThreshold()); + dest.writeFloat(trackingMultiFingerMoveThreshold()); + dest.writeString(layerBelow()); + } + + @Override + public int describeContents() { + return 0; + } + + /** + * Builder class for constructing a new instance of {@link LocationLayerOptions}. + */ + public static class Builder { + + /** + * Build a new instance of this {@link LocationLayerOptions} class. + * + * @return a new instance of {@link LocationLayerOptions} + */ + public LocationLayerOptions build() { + LocationLayerOptions locationLayerOptions = autoBuild(); + if (locationLayerOptions.accuracyAlpha() < 0 || locationLayerOptions.accuracyAlpha() > 1) { + throw new IllegalArgumentException( + "Location layer accuracy alpha value must be between 0.0 and 1.0."); + } + + if (locationLayerOptions.elevation() < 0f) { + throw new IllegalArgumentException("Invalid shadow size " + + locationLayerOptions.elevation() + ". Must be >= 0"); + } + + return locationLayerOptions; + } + + 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 Float trackingInitialMoveThreshold; + private Float trackingMultiFingerMoveThreshold; + private String layerBelow; + + Builder() { + } + + private Builder(LocationLayerOptions 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.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#LocationLayer_accuracyAlpha + */ + public LocationLayerOptions.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#LocationLayer_accuracyColor + */ + public LocationLayerOptions.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#LocationLayer_backgroundDrawableStale + */ + public LocationLayerOptions.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 + * plugin, will used this image in place of the provided or default mapbox_backgroundDrawableStale. + *

+ * 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. + *

+ * + * @param backgroundStaleName String icon or maki-icon name + * @return this builder for chaining options together + */ + public LocationLayerOptions.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#LocationLayer_foregroundDrawableStale + */ + public LocationLayerOptions.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 + * plugin, will used this image in place of the provided or default mapbox_foregroundDrawableStale. + *

+ * 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. + *

+ * + * @param foregroundStaleName String icon or maki-icon name + * @return this builder for chaining options together + */ + public LocationLayerOptions.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#LocationLayer_gpsDrawable + */ + public LocationLayerOptions.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 + * plugin, will used this image in place of the provided or default mapbox_gpsDrawable. + *

+ * 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. + *

+ * + * @param gpsName String icon or maki-icon name + * @return this builder for chaining options together + */ + public LocationLayerOptions.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 Layer + * Plugin layer stack. + * + * @param foregroundDrawable the drawable resource used for the foreground layer + * @return this builder for chaining options together + * @attr ref R.styleable#LocationLayer_foregroundDrawable + */ + public LocationLayerOptions.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 + * plugin, will used this image in place of the provided or default mapbox_foregroundDrawable. + *

+ * 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. + *

+ * + * @param foregroundName String icon or maki-icon name + * @return this builder for chaining options together + */ + public LocationLayerOptions.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#LocationLayer_backgroundDrawable + */ + public LocationLayerOptions.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 + * plugin, will used this image in place of the provided or default mapbox_backgroundDrawable. + *

+ * 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. + *

+ * + * @param backgroundName String icon or maki-icon name + * @return this builder for chaining options together + */ + public LocationLayerOptions.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#LocationLayer_bearingDrawable + */ + public LocationLayerOptions.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 + * plugin, will used this image in place of the provided or default mapbox_bearingDrawable. + *

+ * 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. + *

+ * + * @param bearingName String icon or maki-icon name + * @return this builder for chaining options together + */ + public LocationLayerOptions.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#LocationLayer_bearingTintColor + */ + public LocationLayerOptions.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#LocationLayer_foregroundTintColor + */ + public LocationLayerOptions.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#LocationLayer_backgroundTintColor + */ + public LocationLayerOptions.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#LocationLayer_foregroundStaleTintColor + */ + public LocationLayerOptions.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#LocationLayer_backgroundStaleTintColor + */ + public LocationLayerOptions.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 layer icon + * @return this builder for chaining options together + * @attr ref R.styleable#LocationLayer_elevation + */ + public LocationLayerOptions.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#LocationLayer_enableStaleState + */ + public LocationLayerOptions.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 layer is + * considered stale + * @return this builder for chaining options together + * @attr ref R.styleable#LocationLayer_staleStateTimeout + */ + public LocationLayerOptions.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. + *

+ *

+ * 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. + *

+ * + * @param padding The margins for the map in pixels (left, top, right, bottom). + */ + public LocationLayerOptions.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. + *

+ * The default maximum zoomn level is 22. The upper bound for this value is 25.5. + * + * @param maxZoom The new maximum zoom level. + */ + public LocationLayerOptions.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 LocationLayerOptions.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. + *

+ * Set both this and {@link #minZoomIconScale(float)} to 1f to disable location icon scaling. + *

+ * + * @param maxZoomIconScale icon scale factor + */ + public LocationLayerOptions.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. + *

+ * Set both this and {@link #maxZoomIconScale(float)} to 1f to disable location icon scaling. + *

+ * + * @param minZoomIconScale icon scale factor + */ + public LocationLayerOptions.Builder minZoomIconScale(float minZoomIconScale) { + this.minZoomIconScale = minZoomIconScale; + return this; + } + + /** + * Sets minimum single pointer movement (map pan) in pixels required to break camera tracking. + * + * @param moveThreshold the minimum movement + */ + public LocationLayerOptions.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 LocationLayerOptions.Builder trackingMultiFingerMoveThreshold(float moveThreshold) { + this.trackingMultiFingerMoveThreshold = moveThreshold; + return this; + } + + /** + * Sets the layer id to set the location layer plugin below to. + * + * @param layerBelow the id to set the location layer plugin below to. + */ + public LocationLayerOptions.Builder layerBelow(String layerBelow) { + this.layerBelow = layerBelow; + return this; + } + + LocationLayerOptions 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.trackingInitialMoveThreshold == null) { + missing += " trackingInitialMoveThreshold"; + } + if (this.trackingMultiFingerMoveThreshold == null) { + missing += " trackingMultiFingerMoveThreshold"; + } + if (!missing.isEmpty()) { + throw new IllegalStateException("Missing required properties:" + missing); + } + return new LocationLayerOptions( + 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, + this.trackingInitialMoveThreshold, + this.trackingMultiFingerMoveThreshold, + this.layerBelow); + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerPlugin.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerPlugin.java new file mode 100644 index 0000000000..70fc2ae298 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerPlugin.java @@ -0,0 +1,966 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +import android.annotation.SuppressLint; +import android.arch.lifecycle.Lifecycle; +import android.arch.lifecycle.LifecycleObserver; +import android.arch.lifecycle.OnLifecycleEvent; +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.maps.MapView; +import com.mapbox.mapboxsdk.maps.MapView.OnMapChangedListener; +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 com.mapbox.mapboxsdk.plugins.locationlayer.modes.CameraMode; +import com.mapbox.mapboxsdk.plugins.locationlayer.modes.RenderMode; + +import java.util.concurrent.CopyOnWriteArrayList; + +import timber.log.Timber; + +import static android.Manifest.permission.ACCESS_COARSE_LOCATION; +import static android.Manifest.permission.ACCESS_FINE_LOCATION; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.DEFAULT_TRACKING_TILT_ANIMATION_DURATION; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.DEFAULT_TRACKING_ZOOM_ANIMATION_DURATION; + +/** + * The Location layer plugin provides location awareness to your mobile application. Enabling this + * plugin 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 LocationLayerOptions#gpsDrawable()}) we call the user puck. + *

+ * This plugin 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 LocationLayerPlugin#setCameraMode(int)}. + *

+ * Lastly, {@link LocationLayerPlugin#setLocationLayerEnabled(boolean)} can be used + * to disable the Location Layer but keep the instance around till the activity is destroyed. + *

+ * Using this plugin 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. + *

+ * When instantiating the plugin for the first time, the map's max/min zoom levels will be set to + * {@link LocationLayerOptions#MAX_ZOOM_DEFAULT} and {@link LocationLayerOptions#MIN_ZOOM_DEFAULT} respectively. + * You can adjust the zoom range with {@link LocationLayerOptions#maxZoom()} and {@link LocationLayerOptions#minZoom()}. + */ +public final class LocationLayerPlugin implements LifecycleObserver { + + private final MapboxMap mapboxMap; + private final MapView mapView; + private LocationLayerOptions options; + private LocationEngine locationEngine; + private CompassEngine compassEngine; + private boolean usingInternalLocationEngine; + + private LocationLayer locationLayer; + private LocationLayerCamera locationLayerCamera; + + private PluginAnimatorCoordinator pluginAnimatorCoordinator; + + /** + * 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 that the plugin is enabled and should be displaying location if Mapbox components are available and + * the lifecycle is in a resumed state. + */ + private boolean isEnabled; + + /** + * Indicated that plugin's lifecycle {@link #onStart()} method has been called or the plugin is initialized.. + * This allows Mapbox components enter started state and display data, and adds state safety for methods like + * {@link #setLocationLayerEnabled(boolean)} + *

+ * Initialized in a started state because the plugin can be instantiated after lifecycle's onStart() and + * the developer might not register the lifecycle observer but call lifecycle methods manually instead. + */ + private boolean isPluginStarted = true; + + /** + * Indicates if Mapbox components are ready to be interacted with. This can differ from {@link #isPluginStarted} + * if the Mapbox style is being reloaded. + */ + private boolean isLocationLayerStarted; + + private StaleStateManager staleStateManager; + private final CopyOnWriteArrayList onLocationStaleListeners + = new CopyOnWriteArrayList<>(); + private final CopyOnWriteArrayList onLocationLayerClickListeners + = new CopyOnWriteArrayList<>(); + private final CopyOnWriteArrayList onLocationLayerLongClickListeners + = new CopyOnWriteArrayList<>(); + private final CopyOnWriteArrayList onCameraTrackingChangedListeners + = new CopyOnWriteArrayList<>(); + + /** + * Construct a LocationLayerPlugin + *

+ * Note: This constructor will initialize and use an internal {@link LocationEngine}. + *

+ * + * @param mapView the MapView to apply the LocationLayerPlugin to + * @param mapboxMap the MapboxMap to apply the LocationLayerPlugin with + */ + public LocationLayerPlugin(@NonNull MapView mapView, @NonNull MapboxMap mapboxMap) { + this.mapboxMap = mapboxMap; + this.mapView = mapView; + options = LocationLayerOptions.createFromAttributes(mapView.getContext(), R.style.mapbox_LocationLayer); + initializeLocationEngine(); + initialize(); + } + + /** + * Construct a LocationLayerPlugin + *

+ * Note: This constructor will initialize and use an internal {@link LocationEngine}. + *

+ * + * @param mapView the MapView to apply the LocationLayerPlugin to + * @param mapboxMap the MapboxMap to apply the LocationLayerPlugin with + * @param options to customize the user location icons inside your apps + */ + public LocationLayerPlugin(@NonNull MapView mapView, @NonNull MapboxMap mapboxMap, + @NonNull LocationLayerOptions options) { + this.mapboxMap = mapboxMap; + this.mapView = mapView; + this.options = options; + initializeLocationEngine(); + initialize(); + } + + /** + * Construct a LocationLayerPlugin + *

+ * Note: This constructor will initialize and use an internal {@link LocationEngine}. + *

+ * + * @param mapView the MapView to apply the LocationLayerPlugin to + * @param mapboxMap the MapboxMap to apply the LocationLayerPlugin with + */ + public LocationLayerPlugin(@NonNull MapView mapView, @NonNull MapboxMap mapboxMap, + @StyleRes int styleRes) { + this.mapboxMap = mapboxMap; + this.mapView = mapView; + this.options = LocationLayerOptions.createFromAttributes(mapView.getContext(), styleRes); + initializeLocationEngine(); + initialize(); + } + + /** + * Construct a LocationLayerPlugin + * + * @param mapView the MapView to apply the LocationLayerPlugin to + * @param mapboxMap the MapboxMap to apply the LocationLayerPlugin with + * @param locationEngine the {@link LocationEngine} this plugin should use to update + */ + public LocationLayerPlugin(@NonNull MapView mapView, @NonNull MapboxMap mapboxMap, + @Nullable LocationEngine locationEngine) { + this(mapView, mapboxMap, locationEngine, + LocationLayerOptions.createFromAttributes(mapView.getContext(), + R.style.mapbox_LocationLayer)); + } + + /** + * Construct a LocationLayerPlugin + * + * @param mapView the MapView to apply the LocationLayerPlugin to + * @param mapboxMap the MapboxMap to apply the LocationLayerPlugin with + * @param locationEngine the {@link LocationEngine} this plugin should use to update + * @param styleRes customize the user location icons inside your apps {@code style.xml} + */ + public LocationLayerPlugin(@NonNull MapView mapView, @NonNull MapboxMap mapboxMap, + @Nullable LocationEngine locationEngine, @StyleRes int styleRes) { + this(mapView, mapboxMap, locationEngine, + LocationLayerOptions.createFromAttributes(mapView.getContext(), styleRes)); + } + + /** + * Construct a LocationLayerPlugin + * + * @param mapView the MapView to apply the LocationLayerPlugin to + * @param mapboxMap the MapboxMap to apply the LocationLayerPlugin with + * @param locationEngine the {@link LocationEngine} this plugin should use to update + * @param options to customize the user location icons inside your apps + */ + public LocationLayerPlugin(@NonNull MapView mapView, @NonNull MapboxMap mapboxMap, + @Nullable LocationEngine locationEngine, + @NonNull LocationLayerOptions options) { + this.locationEngine = locationEngine; + this.mapboxMap = mapboxMap; + this.mapView = mapView; + this.options = options; + initialize(); + } + + /** + * This method will show or hide the location icon and enable or disable the camera + * tracking the location. + * + * @param isEnabled true to show layers and enable camera, false otherwise + */ + public void setLocationLayerEnabled(boolean isEnabled) { + if (isEnabled) { + enableLocationLayerPlugin(); + } else { + disableLocationLayerPlugin(); + } + } + + /** + * 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 isLocationLayerEnabled() { + return isEnabled; + } + + /** + * Sets the camera mode, which determines how the map camera will track the rendered location. + *

+ *

    + *
  • {@link CameraMode#NONE}: No camera tracking
  • + *
  • {@link CameraMode#NONE_COMPASS}: Camera does not track location, but does track compass bearing
  • + *
  • {@link CameraMode#NONE_GPS}: Camera does not track location, but does track GPS bearing
  • + *
  • {@link CameraMode#TRACKING}: Camera tracks the user location
  • + *
  • {@link CameraMode#TRACKING_COMPASS}: Camera tracks the user location, with bearing provided by a compass
  • + *
  • {@link CameraMode#TRACKING_GPS}: Camera tracks the user location, with normalized bearing
  • + *
  • {@link CameraMode#TRACKING_GPS_NORTH}: Camera tracks the user location, with bearing always set to north
  • + *
+ * + * @param cameraMode one of the modes found in {@link CameraMode} + */ + public void setCameraMode(@CameraMode.Mode int cameraMode) { + boolean isGpsNorth = cameraMode == CameraMode.TRACKING_GPS_NORTH; + pluginAnimatorCoordinator.resetAllCameraAnimations(mapboxMap.getCameraPosition(), isGpsNorth); + locationLayerCamera.setCameraMode(cameraMode); + } + + /** + * 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 locationLayerCamera.getCameraMode(); + } + + /** + * Sets the render mode, which determines how the location updates will be rendered on the map. + *

+ *

    + *
  • {@link RenderMode#NORMAL}: Shows user location, bearing ignored
  • + *
  • {@link RenderMode#COMPASS}: Shows user location with bearing considered from compass
  • + *
  • {@link RenderMode#GPS}: Shows user location with bearing considered from location
  • + *
+ * + * @param renderMode one of the modes found in {@link RenderMode} + */ + public void setRenderMode(@RenderMode.Mode int renderMode) { + locationLayer.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 locationLayer.getRenderMode(); + } + + /** + * Returns the current location options being used. + * + * @return the current {@link LocationLayerOptions} + */ + public LocationLayerOptions getLocationLayerOptions() { + return options; + } + + /** + * Apply a new LocationLayer style with a style resource. + * + * @param styleRes a XML style overriding some or all the options + */ + public void applyStyle(@StyleRes int styleRes) { + applyStyle(LocationLayerOptions.createFromAttributes(mapView.getContext(), styleRes)); + } + + /** + * Apply a new LocationLayer style with location layer options. + * + * @param options to update the current style + */ + public void applyStyle(LocationLayerOptions options) { + this.options = options; + locationLayer.applyStyle(options); + if (!options.enableStaleState()) { + staleStateManager.onStop(); + } + 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 (!isLocationLayerStarted) { + return; + } else if (getCameraMode() == CameraMode.NONE) { + Timber.e("%s%s", + "LocationLayerPlugin#zoomWhileTracking method can only be used", + " when a camera mode other than CameraMode#NONE is engaged."); + return; + } + pluginAnimatorCoordinator.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_ANIMATION_DURATION, null); + } + + /** + * Cancels animation started by {@link #zoomWhileTracking(double, long, MapboxMap.CancelableCallback)}. + */ + public void cancelZoomWhileTrackingAnimation() { + pluginAnimatorCoordinator.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 (!isLocationLayerStarted) { + return; + } else if (getCameraMode() == CameraMode.NONE) { + Timber.e("%s%s", + "LocationLayerPlugin#tiltWhileTracking method can only be used", + " when a camera mode other than CameraMode#NONE is engaged."); + return; + } + pluginAnimatorCoordinator.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_ANIMATION_DURATION, null); + } + + /** + * Cancels animation started by {@link #tiltWhileTracking(double, long, MapboxMap.CancelableCallback)}. + */ + public void cancelTiltWhileTrackingAnimation() { + pluginAnimatorCoordinator.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. + *

+ * If {@code null} is passed in, all updates will occur through the + * {@link LocationLayerPlugin#forceLocationUpdate(Location)} method. + * + * @param locationEngine a {@link LocationEngine} this plugin 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 layer. + * + * @return the {@link LocationEngine} being used to update the user location layer + */ + @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 layer plugin. + * + * @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 layer plugin. + *

+ * 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 location layer. + * + * @param listener The location layer click listener that is invoked when the + * location layer is clicked + */ + public void addOnLocationClickListener(@NonNull OnLocationLayerClickListener listener) { + onLocationLayerClickListeners.add(listener); + } + + /** + * Removes the passed listener from the current list of location click listeners. + * + * @param listener to be removed + */ + public void removeOnLocationClickListener(@NonNull OnLocationLayerClickListener listener) { + onLocationLayerClickListeners.remove(listener); + } + + /** + * Adds a listener that gets invoked when the user long clicks the location layer. + * + * @param listener The location layer click listener that is invoked when the + * location layer is clicked + */ + public void addOnLocationLongClickListener(@NonNull OnLocationLayerLongClickListener listener) { + onLocationLayerLongClickListeners.add(listener); + } + + /** + * Removes the passed listener from the current list of location long click listeners. + * + * @param listener to be removed + */ + public void removeOnLocationLongClickListener(@NonNull OnLocationLayerLongClickListener listener) { + onLocationLayerLongClickListeners.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. + *

+ * This timeout is set by {@link LocationLayerOptions#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); + } + + /** + * You must call this method from the parent's Activity#onStart() or Fragment#onStart() + */ + @OnLifecycleEvent(Lifecycle.Event.ON_START) + public void onStart() { + if (mapView.isDestroyed()) { + Timber.e("You are calling plugins #onStart after the map was destroyed. Re-create the plugin before using it."); + return; + } + + isPluginStarted = true; + onLocationLayerStart(); + } + + /** + * You must call this method from the parent's Activity#onStop() or Fragment#onStop(). + */ + @OnLifecycleEvent(Lifecycle.Event.ON_STOP) + public void onStop() { + onLocationLayerStop(); + isPluginStarted = false; + } + + @SuppressLint("MissingPermission") + private void onLocationLayerStart() { + if (!isPluginStarted) { + return; + } + + if (!isLocationLayerStarted) { + isLocationLayerStarted = true; + if (mapboxMap != null) { + 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(locationLayerCamera.getCameraMode()); + setLastLocation(); + setLastCompassHeading(); + } + } + + private void onLocationLayerStop() { + if (!isLocationLayerStarted || !isPluginStarted) { + return; + } + + isLocationLayerStarted = false; + locationLayer.hide(); + staleStateManager.onStop(); + compassEngine.onStop(); + pluginAnimatorCoordinator.cancelAllAnimations(); + if (locationEngine != null) { + if (usingInternalLocationEngine) { + locationEngine.removeLocationUpdates(); + } + locationEngine.removeLocationEngineListener(locationEngineListener); + } + if (mapboxMap != null) { + mapboxMap.removeOnCameraMoveListener(onCameraMoveListener); + mapboxMap.removeOnCameraIdleListener(onCameraIdleListener); + } + } + + private void initialize() { + AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); + + mapView.addOnMapChangedListener(onMapChangedListener); + + mapboxMap.addOnMapClickListener(onMapClickListener); + mapboxMap.addOnMapLongClickListener(onMapLongClickListener); + + LayerSourceProvider sourceProvider = new LayerSourceProvider(); + LayerFeatureProvider featureProvider = new LayerFeatureProvider(); + LayerBitmapProvider bitmapProvider = new LayerBitmapProvider(mapView.getContext()); + locationLayer = new LocationLayer(mapboxMap, sourceProvider, featureProvider, bitmapProvider, options); + locationLayerCamera = new LocationLayerCamera( + mapView.getContext(), mapboxMap, cameraTrackingChangedListener, options, onCameraMoveInvalidateListener); + pluginAnimatorCoordinator = new PluginAnimatorCoordinator(); + pluginAnimatorCoordinator.addLayerListener(locationLayer); + pluginAnimatorCoordinator.addCameraListener(locationLayerCamera); + + Context context = mapView.getContext(); + WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + SensorManager sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); + compassEngine = new LocationLayerCompassEngine(windowManager, sensorManager); + compassEngine.addCompassListener(compassListener); + staleStateManager = new StaleStateManager(onLocationStaleListener, options.staleStateTimeout()); + + updateMapWithOptions(options); + + enableLocationLayerPlugin(); + setRenderMode(RenderMode.NORMAL); + setCameraMode(CameraMode.NONE); + } + + private void initializeLocationEngine() { + usingInternalLocationEngine = true; + locationEngine = new LocationEngineProvider(mapView.getContext()).obtainBestLocationEngineAvailable(); + locationEngine.setPriority(LocationEnginePriority.HIGH_ACCURACY); + locationEngine.setFastestInterval(1000); + locationEngine.addLocationEngineListener(locationEngineListener); + locationEngine.activate(); + } + + private void enableLocationLayerPlugin() { + isEnabled = true; + onLocationLayerStart(); + } + + private void disableLocationLayerPlugin() { + isEnabled = false; + onLocationLayerStop(); + } + + private void updateMapWithOptions(final LocationLayerOptions 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 (!isLocationLayerStarted) { + lastLocation = location; + return; + } + + if (isEnabled && isPluginStarted) { + locationLayer.show(); + } + + if (!fromLastLocation) { + staleStateManager.updateLatestLocationTime(); + } + CameraPosition currentCameraPosition = mapboxMap.getCameraPosition(); + boolean isGpsNorth = getCameraMode() == CameraMode.TRACKING_GPS_NORTH; + pluginAnimatorCoordinator.feedNewLocation(location, currentCameraPosition, isGpsNorth); + updateAccuracyRadius(location, false); + lastLocation = location; + } + + private void updateCompassHeading(float heading) { + pluginAnimatorCoordinator.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; + locationLayer.updateForegroundBearing((float) position.bearing); + locationLayer.updateForegroundOffset(position.tilt); + updateAccuracyRadius(getLastKnownLocation(), true); + return; + } + + if (position.bearing != lastCameraPosition.bearing) { + locationLayer.updateForegroundBearing((float) position.bearing); + } + if (position.tilt != lastCameraPosition.tilt) { + locationLayer.updateForegroundOffset(position.tilt); + } + if (position.zoom != lastCameraPosition.zoom) { + updateAccuracyRadius(getLastKnownLocation(), true); + } + lastCameraPosition = position; + } + + private void updateAccuracyRadius(Location location, boolean noAnimation) { + pluginAnimatorCoordinator.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 (!onLocationLayerClickListeners.isEmpty() && locationLayer.onMapClick(point)) { + for (OnLocationLayerClickListener listener : onLocationLayerClickListeners) { + listener.onLocationLayerClick(); + } + } + } + }; + + private MapboxMap.OnMapLongClickListener onMapLongClickListener = new MapboxMap.OnMapLongClickListener() { + @Override + public void onMapLongClick(@NonNull LatLng point) { + if (!onLocationLayerLongClickListeners.isEmpty() && locationLayer.onMapClick(point)) { + for (OnLocationLayerLongClickListener listener : onLocationLayerLongClickListeners) { + listener.onLocationLayerLongClick(); + } + } + } + }; + + private OnLocationStaleListener onLocationStaleListener = new OnLocationStaleListener() { + @Override + public void onStaleStateChange(boolean isStale) { + locationLayer.setLocationsStale(isStale); + + for (OnLocationStaleListener listener : onLocationStaleListeners) { + listener.onStaleStateChange(isStale); + } + } + }; + + private OnMapChangedListener onMapChangedListener = new OnMapChangedListener() { + @SuppressLint("MissingPermission") + @Override + public void onMapChanged(int change) { + if (change == MapView.WILL_START_LOADING_MAP) { + onLocationLayerStop(); + } else if (change == MapView.DID_FINISH_LOADING_STYLE) { + locationLayer.initializeComponents(options); + locationLayerCamera.initializeOptions(options); + onLocationLayerStart(); + } + } + }; + + 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 && isLocationLayerStarted && 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) { + pluginAnimatorCoordinator.cancelZoomAnimation(); + pluginAnimatorCoordinator.cancelTiltAnimation(); + for (OnCameraTrackingChangedListener listener : onCameraTrackingChangedListeners) { + listener.onCameraTrackingChanged(currentMode); + } + } + }; +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/MapboxCameraAnimatorAdapter.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/MapboxCameraAnimatorAdapter.java new file mode 100644 index 0000000000..d2381cc1e3 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/MapboxCameraAnimatorAdapter.java @@ -0,0 +1,38 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +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 + PluginFloatAnimator { + private final MapboxMap.CancelableCallback cancelableCallback; + + MapboxCameraAnimatorAdapter(Float previous, Float target, + List 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/plugins/locationlayer/OnCameraMoveInvalidateListener.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnCameraMoveInvalidateListener.java new file mode 100644 index 0000000000..3636df9f87 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnCameraMoveInvalidateListener.java @@ -0,0 +1,7 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +interface OnCameraMoveInvalidateListener { + + void onInvalidateCameraMove(); + +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnCameraTrackingChangedListener.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnCameraTrackingChangedListener.java new file mode 100644 index 0000000000..272b3c73f9 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnCameraTrackingChangedListener.java @@ -0,0 +1,21 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +import com.mapbox.mapboxsdk.plugins.locationlayer.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/plugins/locationlayer/OnLocationLayerClickListener.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnLocationLayerClickListener.java new file mode 100644 index 0000000000..83d4ce72cc --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnLocationLayerClickListener.java @@ -0,0 +1,11 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +/** + * The Location Layer Plugin 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 #onLocationLayerClick()} method + * gets invoked. + */ +public interface OnLocationLayerClickListener { + + void onLocationLayerClick(); +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnLocationLayerLongClickListener.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnLocationLayerLongClickListener.java new file mode 100644 index 0000000000..5724c9f1dc --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnLocationLayerLongClickListener.java @@ -0,0 +1,11 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +/** + * The Location Layer Plugin 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 #onLocationLayerLongClick()} method + * gets invoked. + */ +public interface OnLocationLayerLongClickListener { + + void onLocationLayerLongClick(); +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnLocationStaleListener.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnLocationStaleListener.java new file mode 100644 index 0000000000..979bed3e2a --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/OnLocationStaleListener.java @@ -0,0 +1,13 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +/** + * Listener that can be added as a callback when the last location update + * is considered stale. + *

+ * The time from the last location update that determines if a location update + * is stale or not is provided by {@link LocationLayerOptions#staleStateTimeout()}. + */ +public interface OnLocationStaleListener { + + void onStaleStateChange(boolean isStale); +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/PluginAnimator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/PluginAnimator.java new file mode 100644 index 0000000000..faa2a1ae44 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/PluginAnimator.java @@ -0,0 +1,92 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +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 plugin animators. + * + * @param Data type that will be animated. + * @param Listener of animation updates. + */ +abstract class PluginAnimator 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 updateListeners; + private final K target; + + PluginAnimator(K previous, K target, List 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/plugins/locationlayer/PluginAnimatorCoordinator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/PluginAnimatorCoordinator.java new file mode 100644 index 0000000000..2ee87a6e46 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/PluginAnimatorCoordinator.java @@ -0,0 +1,375 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +import android.animation.Animator; +import android.animation.AnimatorSet; +import android.annotation.SuppressLint; +import android.location.Location; +import android.os.SystemClock; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +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.HashMap; +import java.util.List; +import java.util.Map; + +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.ACCURACY_RADIUS_ANIMATION_DURATION; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.COMPASS_UPDATE_RATE_MS; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.MAX_ANIMATION_DURATION_MS; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.TRANSITION_ANIMATION_DURATION_MS; +import static com.mapbox.mapboxsdk.plugins.locationlayer.PluginAnimator.ANIMATOR_CAMERA_COMPASS_BEARING; +import static com.mapbox.mapboxsdk.plugins.locationlayer.PluginAnimator.ANIMATOR_CAMERA_GPS_BEARING; +import static com.mapbox.mapboxsdk.plugins.locationlayer.PluginAnimator.ANIMATOR_CAMERA_LATLNG; +import static com.mapbox.mapboxsdk.plugins.locationlayer.PluginAnimator.ANIMATOR_LAYER_ACCURACY; +import static com.mapbox.mapboxsdk.plugins.locationlayer.PluginAnimator.ANIMATOR_LAYER_COMPASS_BEARING; +import static com.mapbox.mapboxsdk.plugins.locationlayer.PluginAnimator.ANIMATOR_LAYER_GPS_BEARING; +import static com.mapbox.mapboxsdk.plugins.locationlayer.PluginAnimator.ANIMATOR_LAYER_LATLNG; +import static com.mapbox.mapboxsdk.plugins.locationlayer.PluginAnimator.ANIMATOR_TILT; +import static com.mapbox.mapboxsdk.plugins.locationlayer.PluginAnimator.ANIMATOR_ZOOM; + +final class PluginAnimatorCoordinator { + + @SuppressLint("UseSparseArrays") + final Map animatorMap = new HashMap<>(); + + final List layerListeners = new ArrayList<>(); + final List cameraListeners = new ArrayList<>(); + + private Location previousLocation; + private float previousAccuracyRadius = -1; + private float previousCompassBearing = -1; + private long locationUpdateTimestamp = -1; + + void addLayerListener(PluginAnimator.OnLayerAnimationsValuesChangeListener listener) { + layerListeners.add(listener); + } + + void removeLayerListener(PluginAnimator.OnLayerAnimationsValuesChangeListener listener) { + layerListeners.remove(listener); + } + + void addCameraListener(PluginAnimator.OnCameraAnimationsValuesChangeListener listener) { + cameraListeners.add(listener); + } + + void removeCameraListener(PluginAnimator.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; + PluginAnimator latLngAnimator = animatorMap.get(ANIMATOR_LAYER_LATLNG); + if (latLngAnimator != null) { + previousLatLng = (LatLng) latLngAnimator.getAnimatedValue(); + } else { + previousLatLng = new LatLng(previousLocation); + } + return previousLatLng; + } + + private float getPreviousLayerGpsBearing() { + LayerGpsBearingAnimator animator = (LayerGpsBearingAnimator) animatorMap.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) animatorMap.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) animatorMap.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 locationAnimators = new ArrayList<>(); + locationAnimators.add(animatorMap.get(ANIMATOR_LAYER_LATLNG)); + locationAnimators.add(animatorMap.get(ANIMATOR_LAYER_GPS_BEARING)); + locationAnimators.add(animatorMap.get(ANIMATOR_CAMERA_LATLNG)); + locationAnimators.add(animatorMap.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 compassAnimators = new ArrayList<>(); + compassAnimators.add(animatorMap.get(ANIMATOR_LAYER_COMPASS_BEARING)); + compassAnimators.add(animatorMap.get(ANIMATOR_CAMERA_COMPASS_BEARING)); + AnimatorSet compassAnimatorSet = new AnimatorSet(); + compassAnimatorSet.playTogether(compassAnimators); + compassAnimatorSet.setDuration(duration); + compassAnimatorSet.start(); + } + + private void playAccuracyAnimator(long duration) { + PluginAnimator animator = animatorMap.get(ANIMATOR_LAYER_ACCURACY); + animator.setDuration(duration); + animator.start(); + } + + private void playZoomAnimator(long duration) { + PluginAnimator animator = animatorMap.get(ANIMATOR_ZOOM); + animator.setDuration(duration); + animator.start(); + } + + private void playTiltAnimator(long duration) { + PluginAnimator animator = animatorMap.get(ANIMATOR_TILT); + animator.setDuration(duration); + animator.start(); + } + + private void playCameraLocationAnimators(long duration) { + List locationAnimators = new ArrayList<>(); + locationAnimators.add(animatorMap.get(ANIMATOR_CAMERA_LATLNG)); + locationAnimators.add(animatorMap.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) animatorMap.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) animatorMap.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) animatorMap.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(@PluginAnimator.Type int animatorType, PluginAnimator animator) { + cancelAnimator(animatorType); + animatorMap.put(animatorType, animator); + } + + void cancelZoomAnimation() { + cancelAnimator(ANIMATOR_ZOOM); + } + + void cancelTiltAnimation() { + cancelAnimator(ANIMATOR_TILT); + } + + void cancelAllAnimations() { + for (@PluginAnimator.Type int animatorType : animatorMap.keySet()) { + cancelAnimator(animatorType); + } + } + + private void cancelAnimator(@PluginAnimator.Type int animatorType) { + PluginAnimator animator = animatorMap.get(animatorType); + if (animator != null) { + animator.cancel(); + animator.removeAllUpdateListeners(); + animator.removeAllListeners(); + animatorMap.put(animatorType, null); + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/PluginFloatAnimator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/PluginFloatAnimator.java new file mode 100644 index 0000000000..f99f17cd97 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/PluginFloatAnimator.java @@ -0,0 +1,17 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +import android.animation.FloatEvaluator; +import android.animation.TypeEvaluator; + +import java.util.List; + +abstract class PluginFloatAnimator extends PluginAnimator { + PluginFloatAnimator(Float previous, Float target, List updateListeners) { + super(previous, target, updateListeners); + } + + @Override + TypeEvaluator provideEvaluator() { + return new FloatEvaluator(); + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/PluginLatLngAnimator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/PluginLatLngAnimator.java new file mode 100644 index 0000000000..29d73f8db7 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/PluginLatLngAnimator.java @@ -0,0 +1,19 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +import android.animation.TypeEvaluator; + +import com.mapbox.mapboxsdk.geometry.LatLng; + +import java.util.List; + +abstract class PluginLatLngAnimator extends PluginAnimator { + + PluginLatLngAnimator(LatLng previous, LatLng target, List updateListeners) { + super(previous, target, updateListeners); + } + + @Override + TypeEvaluator provideEvaluator() { + return new LatLngEvaluator(); + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/StaleStateManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/StaleStateManager.java new file mode 100644 index 0000000000..5c180b5c47 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/StaleStateManager.java @@ -0,0 +1,64 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +import android.os.Handler; + +/** + * Class controls the location layer stale state when the {@link android.location.Location} hasn't + * been updated in 'x' amount of time. {@link LocationLayerOptions#staleStateTimeout()} can be used to + * control the amount of time before the locations considered stale. + * {@link LocationLayerOptions#enableStaleState()} is available for disabling this behaviour. + */ +class StaleStateManager { + + private final OnLocationStaleListener innerOnLocationStaleListeners; + private final Handler handler; + private boolean isStale = true; + private long delayTime; + + StaleStateManager(OnLocationStaleListener innerListener, long delayTime) { + innerOnLocationStaleListeners = innerListener; + this.delayTime = delayTime; + handler = new Handler(); + innerOnLocationStaleListeners.onStaleStateChange(true); + } + + private Runnable staleStateRunnable = new Runnable() { + @Override + public void run() { + isStale = true; + innerOnLocationStaleListeners.onStaleStateChange(true); + } + }; + + boolean isStale() { + return isStale; + } + + void updateLatestLocationTime() { + if (isStale) { + isStale = false; + innerOnLocationStaleListeners.onStaleStateChange(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); + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/TiltAnimator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/TiltAnimator.java new file mode 100644 index 0000000000..2a12622df5 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/TiltAnimator.java @@ -0,0 +1,27 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +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 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/plugins/locationlayer/Utils.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/Utils.java new file mode 100644 index 0000000000..6a0bd94285 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/Utils.java @@ -0,0 +1,102 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +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 icon rotated degree to the new degree. + * + * @param magneticHeading the new position of the rotation + * @param previousMagneticHeading the current position of the rotation + * @return the shortest degree of rotation possible + */ + public static float shortestRotation(float magneticHeading, float previousMagneticHeading) { + double diff = previousMagneticHeading - magneticHeading; + if (diff > 180.0f) { + magneticHeading += 360.0f; + } else if (diff < -180.0f) { + magneticHeading -= 360.f; + } + return magneticHeading; + } + + 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/plugins/locationlayer/ZoomAnimator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/ZoomAnimator.java new file mode 100644 index 0000000000..a1b1d4bf81 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/ZoomAnimator.java @@ -0,0 +1,29 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +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 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/plugins/locationlayer/modes/CameraMode.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/modes/CameraMode.java new file mode 100644 index 0000000000..5edffd00bd --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/modes/CameraMode.java @@ -0,0 +1,66 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer.modes; + +import android.location.Location; +import android.support.annotation.IntDef; + +import com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerPlugin; + +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 LocationLayerPlugin}. + */ + @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/plugins/locationlayer/modes/RenderMode.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/modes/RenderMode.java new file mode 100644 index 0000000000..88db25beb7 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/modes/RenderMode.java @@ -0,0 +1,45 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer.modes; + +import android.support.annotation.IntDef; + +import com.mapbox.mapboxsdk.plugins.locationlayer.CompassEngine; +import com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerPlugin; + +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 LocationLayerPlugin#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/plugins/locationlayer/package-info.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/package-info.java new file mode 100644 index 0000000000..0dc3ea41e5 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains the Mapbox Location layer plugin. + */ +package com.mapbox.mapboxsdk.plugins.locationlayer; \ No newline at end of file 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..789ba73f1a 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + 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 @@ + + + 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 @@ + + + + + + + + \ 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 @@ + + + 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 @@ + + + + + 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 @@ + + + diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml index 053da80ade..9206899dd6 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml +++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml @@ -128,4 +128,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ #5F5F5F #7D7F80 #1E8CAB + + #4A90E2 + #A1B0C0 diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml index 00fc05cf6d..9bf77d46d9 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 @@ 0.025dp + + 25dp + 125dp 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..40bf1540ab --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/styles.xml @@ -0,0 +1,45 @@ + + + + + \ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/plugins/locationlayer/CompassEngineTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/plugins/locationlayer/CompassEngineTest.java new file mode 100644 index 0000000000..c69d2fc5fb --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/plugins/locationlayer/CompassEngineTest.java @@ -0,0 +1,64 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +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 LocationLayerCompassEngine compassEngine; + + @Mock + private WindowManager windowManager; + + @Mock + private SensorManager sensorManager; + + @Before + public void setUp() throws Exception { + compassEngine = new LocationLayerCompassEngine(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 LocationLayerCompassEngine(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 LocationLayerCompassEngine(windowManager, sensorManager); + + verify(sensorManager, times(1)).getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerCameraTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerCameraTest.java new file mode 100644 index 0000000000..c73216f5d6 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerCameraTest.java @@ -0,0 +1,337 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +import android.graphics.PointF; + +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.maps.MapboxMap; +import com.mapbox.mapboxsdk.maps.Projection; +import com.mapbox.mapboxsdk.maps.UiSettings; +import com.mapbox.mapboxsdk.plugins.locationlayer.modes.CameraMode; + +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 LocationLayerCameraTest { + + @Test + public void setCameraMode_mapTransitionsAreCancelled() { + MapboxMap mapboxMap = mock(MapboxMap.class); + LocationLayerCamera camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationLayerOptions.class)); + + camera.setCameraMode(CameraMode.TRACKING_GPS); + + verify(mapboxMap).cancelTransitions(); + } + + @Test + public void setCameraMode_gestureThresholdIsAdjusted() { + MoveGestureDetector moveGestureDetector = mock(MoveGestureDetector.class); + LocationLayerCamera camera = buildCamera(moveGestureDetector); + LocationLayerOptions options = mock(LocationLayerOptions.class); + float moveThreshold = 5f; + when(options.trackingInitialMoveThreshold()).thenReturn(moveThreshold); + camera.initializeOptions(options); + + camera.setCameraMode(CameraMode.TRACKING_GPS); + + verify(moveGestureDetector).setMoveThreshold(moveThreshold); + } + + @Test + public void setCameraMode_gestureThresholdIsResetWhenNotTracking() { + MoveGestureDetector moveGestureDetector = mock(MoveGestureDetector.class); + LocationLayerCamera camera = buildCamera(moveGestureDetector); + camera.initializeOptions(mock(LocationLayerOptions.class)); + + camera.setCameraMode(CameraMode.NONE); + + verify(moveGestureDetector).setMoveThreshold(0f); + } + + @Test + public void setCameraMode_notTrackingAdjustsFocalPoint() { + MapboxMap mapboxMap = mock(MapboxMap.class); + when(mapboxMap.getUiSettings()).thenReturn(mock(UiSettings.class)); + LocationLayerCamera camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationLayerOptions.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); + LocationLayerCamera camera = buildCamera(internalTrackingChangedListener); + camera.initializeOptions(mock(LocationLayerOptions.class)); + + camera.setCameraMode(CameraMode.TRACKING_GPS); + camera.setCameraMode(CameraMode.NONE); + + verify(internalTrackingChangedListener).onCameraTrackingDismissed(); + } + + @Test + public void setCameraMode_internalCameraTrackingChangeListenerIsCalled() { + OnCameraTrackingChangedListener internalTrackingChangedListener = mock(OnCameraTrackingChangedListener.class); + LocationLayerCamera camera = buildCamera(internalTrackingChangedListener); + camera.initializeOptions(mock(LocationLayerOptions.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)); + LocationLayerCamera camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationLayerOptions.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)); + LocationLayerCamera camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationLayerOptions.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)); + LocationLayerCamera camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationLayerOptions.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)); + LocationLayerCamera camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationLayerOptions.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)); + LocationLayerCamera camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationLayerOptions.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); + LocationLayerCamera camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationLayerOptions.class)); + 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); + LocationLayerCamera camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationLayerOptions.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); + LocationLayerCamera camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationLayerOptions.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); + LocationLayerCamera camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationLayerOptions.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); + LocationLayerCamera camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationLayerOptions.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); + LocationLayerCamera camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationLayerOptions.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); + LocationLayerCamera camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationLayerOptions.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); + LocationLayerCamera camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationLayerOptions.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); + LocationLayerCamera camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationLayerOptions.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); + LocationLayerCamera camera = buildCamera(mapboxMap); + camera.initializeOptions(mock(LocationLayerOptions.class)); + camera.setCameraMode(CameraMode.TRACKING); + float zoom = 5f; + + camera.onNewZoomValue(zoom); + + verify(mapboxMap).moveCamera(any(CameraUpdate.class)); + } + + private LocationLayerCamera 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); + return new LocationLayerCamera(mapboxMap, moveGestureDetector, + onCameraTrackingChangedListener, onCameraMoveInvalidateListener); + } + + private LocationLayerCamera 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); + return new LocationLayerCamera(mapboxMap, moveGestureDetector, + onCameraTrackingChangedListener, onCameraMoveInvalidateListener); + } + + private LocationLayerCamera buildCamera(MapboxMap mapboxMap) { + MoveGestureDetector moveGestureDetector = mock(MoveGestureDetector.class); + OnCameraTrackingChangedListener onCameraTrackingChangedListener = mock(OnCameraTrackingChangedListener.class); + OnCameraMoveInvalidateListener onCameraMoveInvalidateListener = mock(OnCameraMoveInvalidateListener.class); + return new LocationLayerCamera(mapboxMap, moveGestureDetector, + onCameraTrackingChangedListener, onCameraMoveInvalidateListener); + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerOptionsTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerOptionsTest.java new file mode 100644 index 0000000000..5062a9b9cc --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerOptionsTest.java @@ -0,0 +1,68 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +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 LocationLayerOptionsTest { + + @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_LocationLayer, R.styleable.mapbox_LocationLayer)) + .thenReturn(array); + when(array.getResourceId(R.styleable.mapbox_LocationLayer_mapbox_foregroundDrawable, -1)) + .thenReturn(R.drawable.mapbox_user_icon); + when(context.getResources()).thenReturn(resources); + } + + @Test + public void sanity() throws Exception { + LocationLayerOptions locationLayerOptions = LocationLayerOptions.builder(context) + .accuracyAlpha(0.5f) + .build(); + assertNotNull(locationLayerOptions); + } + + @Test + public void passingOutOfRangeAccuracyAlpha_throwsException() throws Exception { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Location layer accuracy alpha value must be between 0.0 and " + + "1.0."); + LocationLayerOptions.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"); + LocationLayerOptions.builder(context) + .elevation(-500) + .build(); + } +} \ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerTest.java new file mode 100644 index 0000000000..2a08855ab7 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerTest.java @@ -0,0 +1,466 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +import android.graphics.Bitmap; + +import com.google.gson.JsonElement; +import com.mapbox.geojson.Feature; +import com.mapbox.mapboxsdk.geometry.LatLng; +import com.mapbox.mapboxsdk.maps.MapboxMap; +import com.mapbox.mapboxsdk.plugins.locationlayer.modes.RenderMode; +import com.mapbox.mapboxsdk.style.layers.Layer; +import com.mapbox.mapboxsdk.style.sources.GeoJsonSource; + +import org.junit.Test; + +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.BACKGROUND_ICON; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.BACKGROUND_LAYER; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.BACKGROUND_STALE_ICON; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.BEARING_ICON; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.BEARING_LAYER; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.FOREGROUND_ICON; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.FOREGROUND_LAYER; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.FOREGROUND_STALE_ICON; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.LOCATION_SOURCE; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_ACCURACY_RADIUS; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_COMPASS_BEARING; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_FOREGROUND_ICON_OFFSET; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_GPS_BEARING; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.PROPERTY_SHADOW_ICON_OFFSET; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.SHADOW_ICON; +import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.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 LocationLayerTest { + + @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); + LocationLayerOptions options = mock(LocationLayerOptions.class); + + new LocationLayer(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); + LocationLayerOptions options = mock(LocationLayerOptions.class); + + new LocationLayer(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); + LocationLayerOptions options = mock(LocationLayerOptions.class); + + new LocationLayer(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); + LocationLayerOptions options = mock(LocationLayerOptions.class); + + new LocationLayer(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); + LocationLayerOptions options = mock(LocationLayerOptions.class); + String layerBelow = "layer-below"; + when(options.layerBelow()).thenReturn(layerBelow); + + new LocationLayer(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); + LocationLayerOptions options = mock(LocationLayerOptions.class); + + new LocationLayer(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(LocationLayerOptions.class))).thenReturn(bitmap); + LocationLayerOptions options = mock(LocationLayerOptions.class); + when(options.elevation()).thenReturn(2f); + + // Style is applied on initialization + new LocationLayer(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(LocationLayerOptions.class))).thenReturn(bitmap); + LocationLayerOptions options = mock(LocationLayerOptions.class); + when(options.elevation()).thenReturn(0f); + + new LocationLayer(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)); + LocationLayerOptions options = mock(LocationLayerOptions.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 LocationLayer(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)); + LocationLayerOptions options = mock(LocationLayerOptions.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 LocationLayer(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)); + LocationLayerOptions options = mock(LocationLayerOptions.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 LocationLayer(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)); + LocationLayerOptions options = mock(LocationLayerOptions.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 LocationLayer(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)); + LocationLayerOptions options = mock(LocationLayerOptions.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 LocationLayer(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); + LocationLayerOptions options = mock(LocationLayerOptions.class); + Feature locationFeature = mock(Feature.class); + LocationLayer layer = new LocationLayer( + 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); + LocationLayerOptions options = mock(LocationLayerOptions.class); + Feature locationFeature = mock(Feature.class); + LocationLayer layer = new LocationLayer( + 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); + LocationLayerOptions options = mock(LocationLayerOptions.class); + Feature locationFeature = mock(Feature.class); + LocationLayer layer = new LocationLayer( + 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); + LocationLayerOptions options = mock(LocationLayerOptions.class); + Feature locationFeature = mock(Feature.class); + LocationLayer layer = new LocationLayer( + 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); + LocationLayerOptions options = mock(LocationLayerOptions.class); + Feature locationFeature = mock(Feature.class); + LocationLayer layer = new LocationLayer( + 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); + LocationLayerOptions options = mock(LocationLayerOptions.class); + Feature locationFeature = mock(Feature.class); + LocationLayer layer = new LocationLayer( + 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); + LocationLayerOptions options = mock(LocationLayerOptions.class); + Feature locationFeature = mock(Feature.class); + LocationLayer layer = new LocationLayer( + 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); + LocationLayerOptions options = mock(LocationLayerOptions.class); + Feature locationFeature = mock(Feature.class); + LocationLayer layer = new LocationLayer( + 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); + LocationLayerOptions options = mock(LocationLayerOptions.class); + Feature locationFeature = mock(Feature.class); + LocationLayer layer = new LocationLayer( + 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(LocationLayerOptions options) { + LayerFeatureProvider provider = mock(LayerFeatureProvider.class); + when(provider.generateLocationFeature(null, options)).thenReturn(mock(Feature.class)); + return provider; + } + + private LayerFeatureProvider buildFeatureProvider(Feature feature, LocationLayerOptions 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/plugins/locationlayer/PluginAnimatorCoordinatorTest.kt b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/plugins/locationlayer/PluginAnimatorCoordinatorTest.kt new file mode 100644 index 0000000000..738b7b7a20 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/plugins/locationlayer/PluginAnimatorCoordinatorTest.kt @@ -0,0 +1,284 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer + +import android.location.Location +import com.mapbox.mapboxsdk.camera.CameraPosition +import com.mapbox.mapboxsdk.geometry.LatLng +import com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.DEFAULT_TRACKING_TILT_ANIMATION_DURATION +import com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.DEFAULT_TRACKING_ZOOM_ANIMATION_DURATION +import com.mapbox.mapboxsdk.plugins.locationlayer.PluginAnimator.* +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 PluginAnimatorCoordinatorTest { + + private lateinit var pluginAnimatorCoordinator: PluginAnimatorCoordinator + private val cameraPosition: CameraPosition = CameraPosition.DEFAULT + + @Before + fun setUp() { + pluginAnimatorCoordinator = PluginAnimatorCoordinator() + } + + @Test + fun feedNewLocation_animatorsAreCreated() { + pluginAnimatorCoordinator.feedNewLocation(Location(""), cameraPosition, false) + + assertTrue(pluginAnimatorCoordinator.animatorMap[ANIMATOR_CAMERA_LATLNG] != null) + assertTrue(pluginAnimatorCoordinator.animatorMap[ANIMATOR_CAMERA_GPS_BEARING] != null) + assertTrue(pluginAnimatorCoordinator.animatorMap[ANIMATOR_LAYER_LATLNG] != null) + assertTrue(pluginAnimatorCoordinator.animatorMap[ANIMATOR_LAYER_GPS_BEARING] != null) + } + + @Test + fun feedNewLocation_animatorValue() { + val location = Location("") + location.latitude = 51.0 + location.longitude = 17.0 + location.bearing = 35f + pluginAnimatorCoordinator.feedNewLocation(location, cameraPosition, false) + + val cameraLatLngTarget = pluginAnimatorCoordinator.animatorMap[ANIMATOR_CAMERA_LATLNG]?.target as LatLng + assertEquals(cameraLatLngTarget.latitude, cameraLatLngTarget.latitude) + + val layerLatLngTarget = pluginAnimatorCoordinator.animatorMap[ANIMATOR_LAYER_LATLNG]?.target as LatLng + assertEquals(layerLatLngTarget.latitude, layerLatLngTarget.latitude) + + val cameraBearingTarget = pluginAnimatorCoordinator.animatorMap[ANIMATOR_CAMERA_GPS_BEARING]?.target as Float + assertEquals(location.bearing, cameraBearingTarget) + + val layerBearingTarget = pluginAnimatorCoordinator.animatorMap[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 + pluginAnimatorCoordinator.feedNewLocation(location, cameraPosition, false) + + assertTrue(pluginAnimatorCoordinator.animatorMap[ANIMATOR_CAMERA_LATLNG] != null) + assertTrue(pluginAnimatorCoordinator.animatorMap[ANIMATOR_CAMERA_GPS_BEARING] != null) + assertTrue(pluginAnimatorCoordinator.animatorMap[ANIMATOR_LAYER_LATLNG] != null) + assertTrue(pluginAnimatorCoordinator.animatorMap[ANIMATOR_LAYER_GPS_BEARING] != null) + } + + @Test + fun feedNewLocation_isNorth_animatorValue() { + val location = Location("") + location.latitude = 51.0 + location.longitude = 17.0 + location.bearing = 35f + pluginAnimatorCoordinator.feedNewLocation(location, cameraPosition, true) + + val cameraLatLngTarget = pluginAnimatorCoordinator.animatorMap[ANIMATOR_CAMERA_LATLNG]?.target as LatLng + assertEquals(cameraLatLngTarget.latitude, cameraLatLngTarget.latitude) + + val layerLatLngTarget = pluginAnimatorCoordinator.animatorMap[ANIMATOR_LAYER_LATLNG]?.target as LatLng + assertEquals(layerLatLngTarget.latitude, layerLatLngTarget.latitude) + + val cameraBearingTarget = pluginAnimatorCoordinator.animatorMap[ANIMATOR_CAMERA_GPS_BEARING]?.target as Float + assertEquals(0f, cameraBearingTarget) + + val layerBearingTarget = pluginAnimatorCoordinator.animatorMap[ANIMATOR_LAYER_GPS_BEARING]?.target as Float + assertEquals(location.bearing, layerBearingTarget) + } + + @Test + fun feedNewCompassBearing_animatorsAreCreated() { + pluginAnimatorCoordinator.feedNewCompassBearing(77f, cameraPosition) + + assertTrue(pluginAnimatorCoordinator.animatorMap[ANIMATOR_CAMERA_COMPASS_BEARING] != null) + assertTrue(pluginAnimatorCoordinator.animatorMap[ANIMATOR_LAYER_COMPASS_BEARING] != null) + } + + @Test + fun feedNewCompassBearing_animatorValue() { + val bearing = 77f + pluginAnimatorCoordinator.feedNewCompassBearing(bearing, cameraPosition) + + val cameraBearingTarget = pluginAnimatorCoordinator.animatorMap[ANIMATOR_CAMERA_COMPASS_BEARING]?.target as Float + assertEquals(bearing, cameraBearingTarget) + + val layerBearingTarget = pluginAnimatorCoordinator.animatorMap[ANIMATOR_LAYER_COMPASS_BEARING]?.target as Float + assertEquals(bearing, layerBearingTarget) + } + + @Test + fun feedNewAccuracyRadius_animatorsCreated() { + pluginAnimatorCoordinator.feedNewAccuracyRadius(150f, false) + + assertTrue(pluginAnimatorCoordinator.animatorMap[ANIMATOR_LAYER_ACCURACY] != null) + } + + @Test + fun feedNewAccuracyRadius_animatorValue() { + val accuracy = 150f + pluginAnimatorCoordinator.feedNewAccuracyRadius(accuracy, false) + + val layerAccuracy = pluginAnimatorCoordinator.animatorMap[ANIMATOR_LAYER_ACCURACY]?.target as Float + assertEquals(layerAccuracy, accuracy) + + val animationDuration = pluginAnimatorCoordinator.animatorMap[ANIMATOR_LAYER_ACCURACY]?.duration as Long + assertEquals(LocationLayerConstants.ACCURACY_RADIUS_ANIMATION_DURATION, animationDuration) + } + + @Test + fun feedNewAccuracyRadius_noAnimation_animatorsCreated() { + pluginAnimatorCoordinator.feedNewAccuracyRadius(150f, true) + + assertTrue(pluginAnimatorCoordinator.animatorMap[ANIMATOR_LAYER_ACCURACY] != null) + } + + @Test + fun feedNewAccuracyRadius_noAnimation_animatorValue() { + val accuracy = 150f + pluginAnimatorCoordinator.feedNewAccuracyRadius(accuracy, true) + + val layerAccuracy = pluginAnimatorCoordinator.animatorMap[ANIMATOR_LAYER_ACCURACY]?.target as Float + assertEquals(layerAccuracy, accuracy) + + val animationDuration = pluginAnimatorCoordinator.animatorMap[ANIMATOR_LAYER_ACCURACY]?.duration as Long + assertEquals(0L, animationDuration) + } + + @Test + fun feedNewZoomLevel_animatorsCreated() { + pluginAnimatorCoordinator.feedNewZoomLevel( + 15.0, + cameraPosition, + DEFAULT_TRACKING_ZOOM_ANIMATION_DURATION, + null + ) + + assertTrue(pluginAnimatorCoordinator.animatorMap[ANIMATOR_ZOOM] != null) + } + + @Test + fun feedNewZoomLevel_animatorValue() { + val zoom = 15.0f + pluginAnimatorCoordinator.feedNewZoomLevel( + zoom.toDouble(), + cameraPosition, + DEFAULT_TRACKING_ZOOM_ANIMATION_DURATION, + null + ) + + val animationDuration = pluginAnimatorCoordinator.animatorMap[ANIMATOR_ZOOM]?.duration as Long + assertEquals(DEFAULT_TRACKING_ZOOM_ANIMATION_DURATION, animationDuration) + + val target = pluginAnimatorCoordinator.animatorMap[ANIMATOR_ZOOM]?.target as Float + assertEquals(zoom, target) + } + + @Test + fun feedNewTiltLevel_animatorsCreated() { + pluginAnimatorCoordinator.feedNewTilt( + 30.0, + cameraPosition, + DEFAULT_TRACKING_TILT_ANIMATION_DURATION, + null + ) + + assertTrue(pluginAnimatorCoordinator.animatorMap[ANIMATOR_TILT] != null) + } + + @Test + fun feedNewTiltLevel_animatorValue() { + val tilt = 30.0f + pluginAnimatorCoordinator.feedNewTilt( + tilt.toDouble(), + cameraPosition, + DEFAULT_TRACKING_TILT_ANIMATION_DURATION, + null + ) + + val animationDuration = pluginAnimatorCoordinator.animatorMap[ANIMATOR_TILT]?.duration as Long + assertEquals(DEFAULT_TRACKING_TILT_ANIMATION_DURATION, animationDuration) + + val target = pluginAnimatorCoordinator.animatorMap[ANIMATOR_TILT]?.target as Float + assertEquals(tilt, target) + } + + @Test + fun cancelAllAnimators() { + pluginAnimatorCoordinator.feedNewLocation(Location(""), cameraPosition, true) + pluginAnimatorCoordinator.cancelAllAnimations() + + assertTrue(pluginAnimatorCoordinator.animatorMap[ANIMATOR_CAMERA_LATLNG] == null) + } + + @Test + fun cancelZoomAnimators() { + pluginAnimatorCoordinator.feedNewZoomLevel( + 15.0, + cameraPosition, + DEFAULT_TRACKING_ZOOM_ANIMATION_DURATION, + null + ) + pluginAnimatorCoordinator.cancelZoomAnimation() + + assertTrue(pluginAnimatorCoordinator.animatorMap[ANIMATOR_ZOOM] == null) + } + + @Test + fun cancelTiltAnimation() { + pluginAnimatorCoordinator.feedNewTilt( + 30.0, + cameraPosition, + DEFAULT_TRACKING_TILT_ANIMATION_DURATION, + null + ) + + pluginAnimatorCoordinator.cancelTiltAnimation() + + assertTrue(pluginAnimatorCoordinator.animatorMap[ANIMATOR_TILT] == null) + } + + @Test + fun resetAllCameraAnimations_empty() { + pluginAnimatorCoordinator.resetAllCameraAnimations(cameraPosition, false) + assertTrue(pluginAnimatorCoordinator.animatorMap.isEmpty()) + } + + @Test + fun addLayerListener() { + val layerListener = Mockito.mock(OnLayerAnimationsValuesChangeListener::class.java) + pluginAnimatorCoordinator.addLayerListener(layerListener) + + assertTrue(pluginAnimatorCoordinator.layerListeners.contains(layerListener)) + } + + @Test + fun removeLayerListener() { + val layerListener = Mockito.mock(OnLayerAnimationsValuesChangeListener::class.java) + pluginAnimatorCoordinator.addLayerListener(layerListener) + pluginAnimatorCoordinator.removeLayerListener(layerListener) + + assertTrue(pluginAnimatorCoordinator.layerListeners.isEmpty()) + } + + @Test + fun addCameraListener() { + val cameraListener = Mockito.mock(OnCameraAnimationsValuesChangeListener::class.java) + pluginAnimatorCoordinator.addCameraListener(cameraListener) + + assertTrue(pluginAnimatorCoordinator.cameraListeners.contains(cameraListener)) + } + + @Test + fun removeCameraListener() { + val cameraListener = Mockito.mock(OnCameraAnimationsValuesChangeListener::class.java) + pluginAnimatorCoordinator.addCameraListener(cameraListener) + pluginAnimatorCoordinator.removeCameraListener(cameraListener) + + assertTrue(pluginAnimatorCoordinator.cameraListeners.isEmpty()) + } +} \ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/plugins/locationlayer/UtilsTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/plugins/locationlayer/UtilsTest.java new file mode 100644 index 0000000000..9caad6c6a1 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/plugins/locationlayer/UtilsTest.java @@ -0,0 +1,29 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer; + +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/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerPluginTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerPluginTest.kt new file mode 100644 index 0000000000..12a64850b0 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerPluginTest.kt @@ -0,0 +1,1089 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer + +import android.Manifest +import android.R +import android.arch.lifecycle.Lifecycle +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.filters.LargeTest +import android.support.test.rule.ActivityTestRule +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.CameraPosition +import com.mapbox.mapboxsdk.camera.CameraUpdateFactory +import com.mapbox.mapboxsdk.constants.Style +import com.mapbox.mapboxsdk.geometry.LatLng +import com.mapbox.mapboxsdk.maps.MapView +import com.mapbox.mapboxsdk.maps.MapboxMap +import com.mapbox.mapboxsdk.maps.MapboxMapOptions +import com.mapbox.mapboxsdk.maps.SupportMapFragment +import com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.* +import com.mapbox.mapboxsdk.plugins.locationlayer.modes.CameraMode +import com.mapbox.mapboxsdk.plugins.locationlayer.modes.RenderMode +import com.mapbox.mapboxsdk.plugins.utils.* +import com.mapbox.mapboxsdk.plugins.utils.MapboxTestingUtils.Companion.MAPBOX_HEAVY_STYLE +import com.mapbox.mapboxsdk.plugins.utils.MapboxTestingUtils.Companion.pushSourceUpdates +import com.mapbox.mapboxsdk.plugins.utils.PluginGenerationUtil.Companion.MAP_CONNECTION_DELAY +import com.mapbox.mapboxsdk.plugins.utils.PluginGenerationUtil.Companion.MAP_RENDER_DELAY +import com.mapbox.mapboxsdk.style.layers.PropertyFactory +import com.mapbox.mapboxsdk.style.sources.GeoJsonSource +import com.mapbox.mapboxsdk.testapp.activity.SingleFragmentActivity +import org.hamcrest.CoreMatchers.* +import org.junit.* +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.rules.TestName +import org.junit.runner.RunWith +import timber.log.Timber + +/** + * Test class that uses a map fragment to keep onMapReady actions isolated to within the test + */ +@RunWith(AndroidJUnit4::class) +@LargeTest +class LocationLayerPluginTest { + + @Rule + @JvmField + val activityRule = ActivityTestRule(SingleFragmentActivity::class.java, true, true) + + @Rule + @JvmField + val nameRule = TestName() + + @Rule + @JvmField + val permissionRule: GrantPermissionRule = GrantPermissionRule.grant(Manifest.permission.ACCESS_FINE_LOCATION) + + private lateinit var idlingResource: OnMapFragmentReadyIdlingResource + private lateinit var styleChangeIdlingResource: StyleChangeIdlingResource + private lateinit var fragment: SupportMapFragment + private lateinit var mapboxMap: MapboxMap + private val location: Location by lazy { + val initLocation = Location("test") + initLocation.latitude = 15.0 + initLocation.longitude = 17.0 + initLocation + } + + @Before + fun beforeTest() { + + // Create a default support map fragment and pass it into the empty activity + val options = MapboxMapOptions() + .camera(CameraPosition.Builder().zoom(2.0).build()) // to match plugins min zoom + fragment = SupportMapFragment.newInstance(options) + activityRule.activity.setFragment(fragment) + + Timber.e("@Before: ${nameRule.methodName} - register idle resource") + // If idlingResource is null, throw Kotlin exception + idlingResource = OnMapFragmentReadyIdlingResource(fragment) + styleChangeIdlingResource = StyleChangeIdlingResource() + IdlingRegistry.getInstance().register(idlingResource) + IdlingRegistry.getInstance().register(styleChangeIdlingResource) + onView(withId(R.id.content)).check(matches(isDisplayed())) + mapboxMap = idlingResource.mapboxMap + } + + @Test + fun locationLayerPlugin_initializesLocationEngineCorrectlyWhenOnesNotProvided() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + + val locationEngine = plugin.locationEngine + assertThat(locationEngine, notNullValue()) + + uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + assertThat(locationEngine?.isConnected, `is`(true)) + } + } + + executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, true)) + } + + @Test + fun locationLayerPlugin_initializesLocationEngineCorrectlyWhenOnesNotProvidedButHasOptions() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + + val locationEngine = plugin.locationEngine + val pluginOptions = plugin.locationLayerOptions + + assertThat(locationEngine, notNullValue()) + assertThat(pluginOptions, notNullValue()) + + uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + assertThat(locationEngine?.isConnected, `is`(true)) + assertThat(pluginOptions?.accuracyAlpha(), `is`(.5f)) + assertThat(pluginOptions?.accuracyColor(), `is`(Color.BLUE)) + } + } + + val options = LocationLayerOptions.builder(fragment.activity) + .staleStateTimeout(200) + .enableStaleState(false) + .accuracyAlpha(.5f) + .accuracyColor(Color.BLUE) + .build() + + executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider( + activityRule.activity, true, null, options)) + } + + @Test + fun settingMapStyleImmediatelyBeforeLoadingPlugin_doesStillLoadLayersProperly() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + + uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + + assertThat(plugin.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)) + } + } + + executePluginTest(pluginAction, object : GenericPluginAction.PluginProvider { + override fun providePlugin(mapView: MapView, mapboxMap: MapboxMap, context: Context): LocationLayerPlugin { + // changing the style just before instantiating the plugin + mapboxMap.setStyleUrl(Style.LIGHT) + val plugin = + PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, null, false) + .providePlugin(mapView, mapboxMap, context) + plugin.forceLocationUpdate(location) + return plugin + } + + override fun isPluginDataReady(plugin: LocationLayerPlugin, mapboxMap: MapboxMap): Boolean { + val source = mapboxMap.getSource(LOCATION_SOURCE) + return source != null && (source as GeoJsonSource).querySourceFeatures(null).isNotEmpty() + } + }) + } + + @Test + fun locationLayer_doesntShowUntilFirstLocationFix() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + + // Source should be present but empty + val mapView = fragment.view as MapView + assertThat(mapboxMap.queryRenderedFeatures( + RectF(0f, 0f, mapView.width.toFloat(), mapView.height.toFloat()), FOREGROUND_LAYER) + .isEmpty(), `is`(true)) + + // Force the first location update + plugin.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + + // Check if the puck is visible + assertThat(mapboxMap.queryRenderedFeatures(location, FOREGROUND_LAYER).isEmpty(), `is`(false)) + } + } + executePluginTest(pluginAction) + } + + // + // Location Layer Options + // + + @Test + fun locationLayerOptions_disablingStaleStateDoesWorkCorrectly() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + + plugin.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(200) + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + + mapboxMap.querySourceFeatures(LOCATION_SOURCE).also { + it.forEach { + assertThat(it.getBooleanProperty(PROPERTY_LOCATION_STALE), `is`(false)) + } + } + } + } + + val options = LocationLayerOptions.builder(fragment.activity) + .staleStateTimeout(200) + .enableStaleState(false) + .build() + executePluginTest(pluginAction, + PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, options)) + } + + @Test + fun locationLayerOptions_loadsForegroundBitmapFromNameOption() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + val foregroundDrawable = ContextCompat.getDrawable(context, R.drawable.ic_media_play) + mapboxMap.addImageFromDrawable("custom-foreground-bitmap", foregroundDrawable!!) + mapboxMap.addImageFromDrawable("custom-background-bitmap", foregroundDrawable) + mapboxMap.addImageFromDrawable("custom-foreground-stale-bitmap", foregroundDrawable) + mapboxMap.addImageFromDrawable("custom-background-stale-bitmap", foregroundDrawable) + mapboxMap.addImageFromDrawable("custom-bearing-bitmap", foregroundDrawable) + + plugin.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + 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"))) + } + } + + val options = LocationLayerOptions.builder(fragment.activity) + .foregroundName("custom-foreground-bitmap") + .backgroundName("custom-background-bitmap") + .foregroundStaleName("custom-foreground-stale-bitmap") + .backgroundStaleName("custom-background-stale-bitmap") + .bearingName("custom-bearing-bitmap") + .build() + executePluginTest(pluginAction, + PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, options)) + } + + @Test + fun locationLayerOptions_loadsGpsNameWithGpsRenderMode() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.renderMode = RenderMode.GPS + plugin.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + val foregroundDrawable = ContextCompat.getDrawable(context, R.drawable.ic_media_play) + mapboxMap.addImageFromDrawable("custom-foreground-bitmap", foregroundDrawable!!) + mapboxMap.addImageFromDrawable("custom-gps-bitmap", foregroundDrawable) + + val foregroundId = mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getStringProperty(PROPERTY_FOREGROUND_ICON) + assertThat(foregroundId, `is`(equalTo("custom-gps-bitmap"))) + } + } + + val options = LocationLayerOptions.builder(fragment.activity) + .foregroundName("custom-foreground-bitmap") + .gpsName("custom-gps-bitmap") + .build() + executePluginTest(pluginAction, + PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, options)) + } + + @Test + fun locationLayerOptions_customIconNameRevertsToDefault() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.renderMode = RenderMode.GPS + plugin.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + + val foregroundId = mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getStringProperty(PROPERTY_FOREGROUND_ICON) + assertThat(foregroundId, `is`(equalTo("custom-gps-bitmap"))) + + plugin.applyStyle(LocationLayerOptions.builder(fragment.activity).build()) + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + + val revertedForegroundId = mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getStringProperty(PROPERTY_FOREGROUND_ICON) + assertThat(revertedForegroundId, `is`(equalTo(FOREGROUND_ICON))) + } + } + + val options = LocationLayerOptions.builder(fragment.activity) + .foregroundName("custom-foreground-bitmap") + .gpsName("custom-gps-bitmap") + .build() + executePluginTest(pluginAction, + PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, options)) + } + + @Test + fun locationLayerOptions_customGpsIconNameChangeBackWithMode() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.renderMode = RenderMode.GPS + plugin.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + + val foregroundId = mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getStringProperty(PROPERTY_FOREGROUND_ICON) + assertThat(foregroundId, `is`(equalTo("custom-gps-bitmap"))) + + plugin.renderMode = RenderMode.NORMAL + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + + val revertedForegroundId = mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getStringProperty(PROPERTY_FOREGROUND_ICON) + assertThat(revertedForegroundId, `is`(equalTo(FOREGROUND_ICON))) + } + } + + val options = LocationLayerOptions.builder(fragment.activity) + .gpsName("custom-gps-bitmap") + .build() + executePluginTest(pluginAction, + PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, options)) + } + + @Test + fun stillStaleAfterResuming() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + val testLifecycleOwner = TestLifecycleOwner() + testLifecycleOwner.markState(Lifecycle.State.RESUMED) + testLifecycleOwner.lifecycle.addObserver(plugin) + + plugin.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(300) // engaging stale state + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + assertThat(mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getBooleanProperty(PROPERTY_LOCATION_STALE), `is`(true)) + + testLifecycleOwner.markState(Lifecycle.State.CREATED) + testLifecycleOwner.markState(Lifecycle.State.RESUMED) + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + + assertThat(mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getBooleanProperty(PROPERTY_LOCATION_STALE), `is`(true)) + assertThat(mapboxMap.isLayerVisible(ACCURACY_LAYER), `is`(false)) + } + } + val options = LocationLayerOptions.builder(fragment.activity) + .staleStateTimeout(200) + .build() + executePluginTest(pluginAction, + PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, options, false)) + } + + @Test + fun stillNotStaleAfterResuming() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + val testLifecycleOwner = TestLifecycleOwner() + testLifecycleOwner.markState(Lifecycle.State.RESUMED) + testLifecycleOwner.lifecycle.addObserver(plugin) + + plugin.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + assertThat(mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getBooleanProperty(PROPERTY_LOCATION_STALE), `is`(false)) + + testLifecycleOwner.markState(Lifecycle.State.CREATED) + testLifecycleOwner.markState(Lifecycle.State.RESUMED) + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + + assertThat(mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getBooleanProperty(PROPERTY_LOCATION_STALE), `is`(false)) + assertThat(mapboxMap.isLayerVisible(ACCURACY_LAYER), `is`(true)) + } + } + executePluginTest(pluginAction, + PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + } + + @Test + fun locationLayerOptions_accuracyRingWithColor() { + val color = Color.parseColor("#4A90E2") + val rgbaColor = PropertyFactory.colorToRgbaString(color) + + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + + // Check that the source property changes correctly + mapboxMap.querySourceFeatures(LOCATION_SOURCE).also { + it.forEach { + assertThat(it.getStringProperty(PROPERTY_ACCURACY_COLOR), `is`(equalTo(rgbaColor))) + } + } + } + } + + val options = LocationLayerOptions.builder(fragment.activity) + .accuracyColor(color) + .build() + executePluginTest(pluginAction, + PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, options)) + } + + @Test + fun forceLocationUpdate_doesMoveLocationLayerIconToCorrectPosition() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + + plugin.forceLocationUpdate(location) + + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + + val point: Point = mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].geometry() as Point + + assertThat(plugin.locationEngine, nullValue()) + assertEquals(point.latitude(), location.latitude, 0.1) + assertEquals(point.longitude(), location.longitude, 0.1) + } + } + executePluginTest(pluginAction) + } + + @Test + fun disablingPluginHidesPuck() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + + plugin.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + 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) + + plugin.isLocationLayerEnabled = false + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + assertThat(mapboxMap.querySourceFeatures(LOCATION_SOURCE).isEmpty(), `is`(true)) + } + } + executePluginTest(pluginAction) + } + + @Test + fun disablingPluginAndChangingStyleAllowsToEnableAgain() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + + plugin.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + + plugin.isLocationLayerEnabled = false + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + mapboxMap.setStyle(Style.LIGHT) + uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + plugin.isLocationLayerEnabled = true + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + assertThat(mapboxMap.isLayerVisible(FOREGROUND_LAYER), `is`(true)) + } + } + executePluginTest(pluginAction) + } + + @Test + fun lifecycle_keepsEnabledWhenStoppedAndStarted() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + val testLifecycleOwner = TestLifecycleOwner() + testLifecycleOwner.markState(Lifecycle.State.RESUMED) + testLifecycleOwner.lifecycle.addObserver(plugin) + + assertThat(plugin.isLocationLayerEnabled, `is`(true)) + testLifecycleOwner.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE) + testLifecycleOwner.handleLifecycleEvent(Lifecycle.Event.ON_STOP) + testLifecycleOwner.markState(Lifecycle.State.RESUMED) + assertThat(plugin.isLocationLayerEnabled, `is`(true)) + } + } + executePluginTest(pluginAction, + PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, null, false)) + } + + @Test + fun lifecycle_keepsDisabledWhenStoppedAndStarted() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.isLocationLayerEnabled = false + + val testLifecycleOwner = TestLifecycleOwner() + testLifecycleOwner.markState(Lifecycle.State.RESUMED) + testLifecycleOwner.lifecycle.addObserver(plugin) + + assertThat(plugin.isLocationLayerEnabled, `is`(false)) + testLifecycleOwner.markState(Lifecycle.State.CREATED) + testLifecycleOwner.markState(Lifecycle.State.RESUMED) + assertThat(plugin.isLocationLayerEnabled, `is`(false)) + } + } + executePluginTest(pluginAction, + PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, null, false)) + } + + @Test + fun lifecycle_ableToChangeStyleAfterResuming() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + + val testLifecycleOwner = TestLifecycleOwner() + testLifecycleOwner.markState(Lifecycle.State.RESUMED) + testLifecycleOwner.lifecycle.addObserver(plugin) + + testLifecycleOwner.markState(Lifecycle.State.CREATED) + testLifecycleOwner.markState(Lifecycle.State.RESUMED) + + mapboxMap.setStyle(Style.DARK) + uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + } + } + executePluginTest(pluginAction, + PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, null, false)) + } + + @Test + fun lifecycle_interruptedDuringStyleChange() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + + val testLifecycleOwner = TestLifecycleOwner() + testLifecycleOwner.markState(Lifecycle.State.RESUMED) + testLifecycleOwner.lifecycle.addObserver(plugin) + mapboxMap.setStyle(Style.DARK) + + testLifecycleOwner.markState(Lifecycle.State.CREATED) + testLifecycleOwner.markState(Lifecycle.State.RESUMED) + uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + } + } + executePluginTest(pluginAction, + PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, null, false)) + } + + @Test + fun lifecycle_forceLocationUpdateAfterStopped() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + + val testLifecycleOwner = TestLifecycleOwner() + testLifecycleOwner.markState(Lifecycle.State.RESUMED) + testLifecycleOwner.lifecycle.addObserver(plugin) + + testLifecycleOwner.markState(Lifecycle.State.CREATED) + plugin.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + + assertThat(mapboxMap.querySourceFeatures(LOCATION_SOURCE).isEmpty(), `is`(true)) + } + } + executePluginTest(pluginAction, + PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, null, false)) + } + + @Test + fun lifecycle_acceptAndReuseLocationUpdatesBeforeLayerStarted() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + + val testLifecycleOwner = TestLifecycleOwner() + testLifecycleOwner.markState(Lifecycle.State.RESUMED) + testLifecycleOwner.lifecycle.addObserver(plugin) + + testLifecycleOwner.markState(Lifecycle.State.CREATED) + plugin.forceLocationUpdate(location) + testLifecycleOwner.markState(Lifecycle.State.RESUMED) + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + + 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) + } + } + executePluginTest(pluginAction, + PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, null, false)) + } + + @Test + fun lifecycle_lifecycleChangeRightAfterStyleReload() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + + val testLifecycleOwner = TestLifecycleOwner() + testLifecycleOwner.markState(Lifecycle.State.RESUMED) + testLifecycleOwner.lifecycle.addObserver(plugin) + + plugin.forceLocationUpdate(location) + mapboxMap.setStyle(Style.LIGHT) + testLifecycleOwner.markState(Lifecycle.State.CREATED) + uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + testLifecycleOwner.markState(Lifecycle.State.RESUMED) + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + + 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)) + } + } + executePluginTest(pluginAction, + PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, null, false)) + } + + @Test + fun mapChange_settingPluginStyle() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + styleChangeIdlingResource.waitForStyle(fragment.view as MapView, mapboxMap, MAPBOX_HEAVY_STYLE) + val options = LocationLayerOptions.builder(fragment.activity) + .accuracyColor(Color.RED) + .build() + + pushSourceUpdates(styleChangeIdlingResource) { + plugin.applyStyle(options) + } + + uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + } + } + executePluginTest(pluginAction, + PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + + // Waiting for style to finish loading while pushing updates + onView(withId(R.id.content)).check(matches(isDisplayed())) + } + + @Test + fun mapChange_forcingLocation() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + styleChangeIdlingResource.waitForStyle(fragment.view as MapView, mapboxMap, MAPBOX_HEAVY_STYLE) + + pushSourceUpdates(styleChangeIdlingResource) { + plugin.forceLocationUpdate(location) + } + + uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + } + } + executePluginTest(pluginAction, + PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + + // Waiting for style to finish loading while pushing updates + onView(withId(R.id.content)).check(matches(isDisplayed())) + } + + @Test + fun mapChange_settingMapStyleBeforePluginCreation() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + val options = LocationLayerOptions.builder(fragment.activity) + .accuracyColor(Color.RED) + .build() + + pushSourceUpdates(styleChangeIdlingResource) { + plugin.forceLocationUpdate(location) + plugin.applyStyle(options) + } + } + } + + executePluginTest(pluginAction, object : GenericPluginAction.PluginProvider { + override fun providePlugin(mapView: MapView, mapboxMap: MapboxMap, context: Context): LocationLayerPlugin { + // changing the style just before instantiating the plugin + styleChangeIdlingResource.waitForStyle(mapView, mapboxMap, MAPBOX_HEAVY_STYLE) + return PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, null, false) + .providePlugin(mapView, mapboxMap, context) + } + + override fun isPluginDataReady(plugin: LocationLayerPlugin, mapboxMap: MapboxMap): Boolean { + return true + } + }) + + // Waiting for style to finish loading while pushing updates + onView(withId(R.id.content)).check(matches(isDisplayed())) + } + + @Test + fun animators_layerBearingCorrect() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.renderMode = RenderMode.GPS + location.bearing = 77f + plugin.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(1000) + assertEquals(77.0, mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getNumberProperty(PROPERTY_GPS_BEARING) as Double, 0.1) + + location.bearing = 92f + plugin.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(2000) // Waiting for the animation to finish + assertEquals(92.0, mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getNumberProperty(PROPERTY_GPS_BEARING) as Double, 0.1) + } + } + + executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + } + + @Test + fun animators_cameraLatLngBearingCorrect() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.cameraMode = CameraMode.TRACKING_GPS + location.bearing = 77f + plugin.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(1000) + 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 + plugin.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(2000) // 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) + } + } + + executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + } + + @Test + fun animators_cameraBearingCorrect() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.cameraMode = CameraMode.NONE_GPS + val latitude = mapboxMap.cameraPosition.target.latitude + val longitude = mapboxMap.cameraPosition.target.longitude + + location.bearing = 77f + plugin.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(1000) + 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 + plugin.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(2000) // Waiting for the animation to finish + assertEquals(92.0, mapboxMap.cameraPosition.bearing, 0.1) + assertEquals(latitude, mapboxMap.cameraPosition.target.latitude, 0.1) + assertEquals(longitude, mapboxMap.cameraPosition.target.longitude, 0.1) + } + } + + executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + } + + @Test + fun animators_cameraNoneCorrect() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.cameraMode = CameraMode.NONE + val latitude = mapboxMap.cameraPosition.target.latitude + val longitude = mapboxMap.cameraPosition.target.longitude + val bearing = mapboxMap.cameraPosition.bearing + + location.bearing = 77f + plugin.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(1000) + 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 + plugin.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(2000) // 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) + } + } + + executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + } + + @Test + fun animators_focalPointAdjustment() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.cameraMode = CameraMode.TRACKING + plugin.cameraMode = CameraMode.NONE + plugin.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + + assertThat(mapboxMap.uiSettings.focalPoint, nullValue()) + } + } + + executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + } + + @Test + fun animators_dontZoomWhileNotTracking() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.cameraMode = CameraMode.NONE + val zoom = mapboxMap.cameraPosition.zoom + plugin.zoomWhileTracking(10.0) + uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_ZOOM_ANIMATION_DURATION) + + assertEquals(zoom, mapboxMap.cameraPosition.zoom, 0.1) + } + } + + executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + } + + @Test + fun animators_zoomWhileTracking() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.cameraMode = CameraMode.TRACKING + plugin.zoomWhileTracking(10.0) + uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_ZOOM_ANIMATION_DURATION) + + assertEquals(10.0, mapboxMap.cameraPosition.zoom, 0.1) + } + } + + executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + } + + @Test + @Ignore + fun animators_zoomWhileTrackingCanceledOnModeChange() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.cameraMode = CameraMode.TRACKING + plugin.zoomWhileTracking(15.0) + uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_ZOOM_ANIMATION_DURATION / 2) + plugin.cameraMode = CameraMode.NONE + uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_ZOOM_ANIMATION_DURATION / 2) + + assertEquals(15.0 / 2.0, mapboxMap.cameraPosition.zoom, 3.0) + } + } + + executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + } + + @Test + fun animators_dontZoomWhileStopped() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + + val testLifecycleOwner = TestLifecycleOwner() + testLifecycleOwner.markState(Lifecycle.State.RESUMED) + testLifecycleOwner.lifecycle.addObserver(plugin) + + plugin.cameraMode = CameraMode.TRACKING + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + val zoom = mapboxMap.cameraPosition.zoom + + testLifecycleOwner.markState(Lifecycle.State.CREATED) + plugin.zoomWhileTracking(10.0) + uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_ZOOM_ANIMATION_DURATION) + + assertEquals(zoom, mapboxMap.cameraPosition.zoom, 0.1) + } + } + + executePluginTest(pluginAction, + PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, null, false)) + } + + @Test + @Ignore + fun animators_cancelZoomWhileTracking() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.cameraMode = CameraMode.TRACKING + plugin.zoomWhileTracking(15.0) + uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_ZOOM_ANIMATION_DURATION / 2) + plugin.cancelZoomWhileTrackingAnimation() + uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_ZOOM_ANIMATION_DURATION / 2) + + assertEquals(15.0 / 2.0, mapboxMap.cameraPosition.zoom, 3.0) + } + } + + executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + } + + @Test + fun animators_dontTiltWhileNotTracking() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.cameraMode = CameraMode.NONE + val tilt = mapboxMap.cameraPosition.tilt + plugin.tiltWhileTracking(30.0) + uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_TILT_ANIMATION_DURATION) + + assertEquals(tilt, mapboxMap.cameraPosition.tilt, 0.1) + } + } + + executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + } + + @Test + fun animators_tiltWhileTracking() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.cameraMode = CameraMode.TRACKING + plugin.tiltWhileTracking(30.0) + uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_TILT_ANIMATION_DURATION) + + assertEquals(30.0, mapboxMap.cameraPosition.tilt, 0.1) + } + } + + executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + } + + @Test + @Ignore + fun animators_tiltWhileTrackingCanceledOnModeChange() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.cameraMode = CameraMode.TRACKING + plugin.tiltWhileTracking(30.0) + uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_TILT_ANIMATION_DURATION / 2) + plugin.cameraMode = CameraMode.NONE + uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_TILT_ANIMATION_DURATION / 2) + + assertEquals(30.0 / 2.0, mapboxMap.cameraPosition.tilt, 3.0) + } + } + + executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + } + + @Test + fun animators_dontTiltWhileStopped() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + + val testLifecycleOwner = TestLifecycleOwner() + testLifecycleOwner.markState(Lifecycle.State.RESUMED) + testLifecycleOwner.lifecycle.addObserver(plugin) + + plugin.cameraMode = CameraMode.TRACKING + val tilt = mapboxMap.cameraPosition.tilt + + testLifecycleOwner.markState(Lifecycle.State.CREATED) + plugin.tiltWhileTracking(30.0) + uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_TILT_ANIMATION_DURATION) + + assertEquals(tilt, mapboxMap.cameraPosition.tilt, 0.1) + } + } + + executePluginTest(pluginAction, + PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, null, false)) + } + + @Test + @Ignore + fun animators_cancelTiltWhileTracking() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.cameraMode = CameraMode.TRACKING + plugin.tiltWhileTracking(30.0) + uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_TILT_ANIMATION_DURATION / 2) + plugin.cancelTiltWhileTrackingAnimation() + uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_TILT_ANIMATION_DURATION / 2) + + assertEquals(30.0 / 2.0, mapboxMap.cameraPosition.tilt, 3.0) + } + } + + executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + } + + @Test + fun cameraPositionAdjustedToTrackingModeWhenPluginEnabled() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.cameraMode = CameraMode.TRACKING_GPS + plugin.forceLocationUpdate(location) + plugin.isLocationLayerEnabled = false + mapboxMap.moveCamera(CameraUpdateFactory.newLatLng(LatLng(51.0, 17.0))) + mapboxMap.moveCamera(CameraUpdateFactory.bearingTo(90.0)) + plugin.isLocationLayerEnabled = true + uiController.loopMainThreadForAtLeast(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) + } + } + + executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + } + + @Test + fun onPluginInitialized_defaultCompassEngineIsProvided() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + assertTrue(plugin.compassEngine is LocationLayerCompassEngine) + } + } + + executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + } + + @After + fun afterTest() { + Timber.e("@After: ${nameRule.methodName} - unregister idle resource") + IdlingRegistry.getInstance().unregister(idlingResource) + IdlingRegistry.getInstance().unregister(styleChangeIdlingResource) + } + + private fun executePluginTest(listener: GenericPluginAction.OnPerformGenericPluginAction, + pluginProvider: GenericPluginAction.PluginProvider = PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) { + onView(withId(R.id.content)).perform(GenericPluginAction(fragment.view as MapView, mapboxMap, pluginProvider, listener)) + } +} \ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerTest.kt new file mode 100644 index 0000000000..121c8f2d22 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerTest.kt @@ -0,0 +1,356 @@ +package com.mapbox.mapboxsdk.plugins.locationlayer + +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.filters.LargeTest +import android.support.test.rule.ActivityTestRule +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.maps.MapboxMap +import com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.* +import com.mapbox.mapboxsdk.plugins.locationlayer.modes.RenderMode +import com.mapbox.mapboxsdk.plugins.utils.* +import com.mapbox.mapboxsdk.plugins.utils.MapboxTestingUtils.Companion.MAPBOX_HEAVY_STYLE +import com.mapbox.mapboxsdk.plugins.utils.MapboxTestingUtils.Companion.pushSourceUpdates +import com.mapbox.mapboxsdk.plugins.utils.PluginGenerationUtil.Companion.MAP_CONNECTION_DELAY +import com.mapbox.mapboxsdk.plugins.utils.PluginGenerationUtil.Companion.MAP_RENDER_DELAY +import com.mapbox.mapboxsdk.style.sources.GeoJsonSource +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.rules.TestName +import org.junit.runner.RunWith +import timber.log.Timber + +@RunWith(AndroidJUnit4::class) +@LargeTest +class LocationLayerTest { + + @Rule + @JvmField + val activityRule = ActivityTestRule(SingleActivity::class.java) + + @Rule + @JvmField + val nameRule = TestName() + + @Rule + @JvmField + val permissionRule: GrantPermissionRule = grant(Manifest.permission.ACCESS_FINE_LOCATION) + + private lateinit var idlingResource: OnMapReadyIdlingResource + private lateinit var styleChangeIdlingResource: StyleChangeIdlingResource + private lateinit var mapboxMap: MapboxMap + private val location: Location by lazy { + val initLocation = Location("test") + initLocation.latitude = 15.0 + initLocation.longitude = 17.0 + initLocation.accuracy = 2000f + initLocation + } + + @Before + fun beforeTest() { + Timber.e("@Before: ${nameRule.methodName} - register idle resource") + // If idlingResource is null, throw Kotlin exception + idlingResource = OnMapReadyIdlingResource(activityRule.activity) + styleChangeIdlingResource = StyleChangeIdlingResource() + IdlingRegistry.getInstance().register(idlingResource) + IdlingRegistry.getInstance().register(styleChangeIdlingResource) + onView(withId(android.R.id.content)).check(matches(isDisplayed())) + mapboxMap = idlingResource.mapboxMap + } + + // + // Location Source + // + + @Test + fun renderModeNormal_sourceDoesGetAdded() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.renderMode = RenderMode.NORMAL + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + assertThat(mapboxMap.getSource(LOCATION_SOURCE), notNullValue()) + } + } + executePluginTest(pluginAction) + } + + // + // Location Layers + // + + @Test + fun renderModeNormal_trackingNormalLayersDoGetAdded() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.renderMode = RenderMode.NORMAL + plugin.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + 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)) + } + } + executePluginTest(pluginAction) + } + + @Test + fun renderModeCompass_bearingLayersDoGetAdded() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.renderMode = RenderMode.COMPASS + plugin.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + 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)) + } + } + executePluginTest(pluginAction) + } + + @Test + fun renderModeGps_navigationLayersDoGetAdded() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.renderMode = RenderMode.GPS + plugin.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + 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)) + } + } + executePluginTest(pluginAction) + } + + @Test + fun dontShowPuckWhenRenderModeSetAndPluginDisabled() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.forceLocationUpdate(location) + plugin.isLocationLayerEnabled = false + plugin.renderMode = RenderMode.GPS + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + 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)) + } + } + executePluginTest(pluginAction) + } + + @Test + fun whenLocationLayerPluginDisabled_doesSetAllLayersToVisibilityNone() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.renderMode = RenderMode.NORMAL + plugin.forceLocationUpdate(location) + plugin.isLocationLayerEnabled = false + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + + // 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)) + } + } + executePluginTest(pluginAction) + } + + @Test + fun onMapChange_locationLayerLayersDoGetRedrawn() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.renderMode = RenderMode.NORMAL + plugin.forceLocationUpdate(location) + mapboxMap.setStyleUrl(Style.LIGHT) + plugin.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + + assertThat(plugin.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)) + } + } + executePluginTest(pluginAction) + } + +// +// Stale state test +// + + @Test + fun whenStyleChanged_continuesUsingStaleIcons() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.applyStyle(LocationLayerOptions.builder(context).staleStateTimeout(100).build()) + plugin.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(200) + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + + assertThat(mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getBooleanProperty(PROPERTY_LOCATION_STALE), `is`(true)) + + mapboxMap.setStyleUrl(Style.LIGHT) + uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + + assertThat(mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getBooleanProperty(PROPERTY_LOCATION_STALE), `is`(true)) + } + } + executePluginTest(pluginAction) + } + + @Test + fun whenStyleChanged_staleStateChanges() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.applyStyle(LocationLayerOptions.builder(context).staleStateTimeout(1).build()) + styleChangeIdlingResource.waitForStyle(idlingResource.mapView, mapboxMap, MAPBOX_HEAVY_STYLE) + pushSourceUpdates(styleChangeIdlingResource) { + plugin.forceLocationUpdate(location) + } + } + } + executePluginTest(pluginAction) + + // Waiting for style to finish loading while pushing updates + onView(withId(R.id.content)).check(matches(isDisplayed())) + } + + @Test + fun whenStyleChanged_layerVisibilityUpdates() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + styleChangeIdlingResource.waitForStyle(idlingResource.mapView, mapboxMap, MAPBOX_HEAVY_STYLE) + var show = true + pushSourceUpdates(styleChangeIdlingResource) { + plugin.isLocationLayerEnabled = show + show = !show + } + + uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + } + } + executePluginTest(pluginAction) + + // Waiting for style to finish loading while pushing updates + onView(withId(R.id.content)).check(matches(isDisplayed())) + } + + @Test + fun accuracy_visibleWithNewLocation() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(location), 16.0)) + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + plugin.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY + 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) + } + } + executePluginTest(pluginAction) + } + + @Test + fun accuracy_visibleWhenCameraEased() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + plugin.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + mapboxMap.easeCamera(CameraUpdateFactory.newLatLngZoom(LatLng(location), 16.0), 300) + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY + 300) + + assertEquals(Utils.calculateZoomLevelRadius(mapboxMap, location) /*meters projected to radius on zoom 16*/, + mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0] + .getNumberProperty(PROPERTY_ACCURACY_RADIUS).toFloat(), 0.1f) + } + } + executePluginTest(pluginAction) + } + + @Test + fun accuracy_visibleWhenCameraMoved() { + val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { + override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + plugin.forceLocationUpdate(location) + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(location), 16.0)) + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY + 300) + + assertEquals(Utils.calculateZoomLevelRadius(mapboxMap, location) /*meters projected to radius on zoom 16*/, + mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0] + .getNumberProperty(PROPERTY_ACCURACY_RADIUS).toFloat(), 0.1f) + } + } + executePluginTest(pluginAction) + } + + @After + fun afterTest() { + Timber.e("@After: ${nameRule.methodName} - unregister idle resource") + IdlingRegistry.getInstance().unregister(idlingResource) + IdlingRegistry.getInstance().unregister(styleChangeIdlingResource) + } + + private fun executePluginTest(listener: GenericPluginAction.OnPerformGenericPluginAction) { + onView(withId(android.R.id.content)).perform(GenericPluginAction(idlingResource.mapView, mapboxMap, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity), listener)) + } +} diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/GenericPluginAction.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/GenericPluginAction.kt new file mode 100644 index 0000000000..210f7b4758 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/GenericPluginAction.kt @@ -0,0 +1,48 @@ +package com.mapbox.mapboxsdk.plugins.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.MapView +import com.mapbox.mapboxsdk.maps.MapboxMap +import com.mapbox.mapboxsdk.plugins.utils.PluginGenerationUtil.Companion.MAP_RENDER_DELAY +import org.hamcrest.Matcher + +class GenericPluginAction(private val mapView: MapView, private val mapboxMap: MapboxMap, private val pluginProvider: PluginProvider, + private val onPerformGenericPluginAction: OnPerformGenericPluginAction) : ViewAction { + + override fun getConstraints(): Matcher { + return isDisplayed() + } + + override fun getDescription(): String { + return javaClass.simpleName + } + + override fun perform(uiController: UiController, view: View) { + val plugin = pluginProvider.providePlugin(mapView, mapboxMap, view.context) + + // ensuring that the asynchronous renderer has time to render data we want to test + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + while (!pluginProvider.isPluginDataReady(plugin, mapboxMap)) { + uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + } + + onPerformGenericPluginAction.onGenericPluginAction( + plugin, + mapboxMap, + uiController, + view.context) + } + + interface OnPerformGenericPluginAction { + fun onGenericPluginAction(plugin: T, mapboxMap: MapboxMap, uiController: UiController, context: Context) + } + + interface PluginProvider { + fun providePlugin(mapView: MapView, mapboxMap: MapboxMap, context: Context): T + fun isPluginDataReady(plugin: T, mapboxMap: MapboxMap): Boolean + } +} \ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/MapboxTestingUtils.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/MapboxTestingUtils.kt new file mode 100644 index 0000000000..b65cb3278b --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/MapboxTestingUtils.kt @@ -0,0 +1,79 @@ +package com.mapbox.mapboxsdk.plugins.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 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 { + return this.getSourceAs(sourceId)?.querySourceFeatures(null) as List +} + +fun MapboxMap.queryRenderedFeatures(location: Location, layerId: String): List { + 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)!! +} + +class MapboxTestingUtils { + companion object { + + /** + * 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/plugins/utils/OnMapFragmentReadyIdlingResource.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/OnMapFragmentReadyIdlingResource.kt new file mode 100644 index 0000000000..fa6b732770 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/OnMapFragmentReadyIdlingResource.kt @@ -0,0 +1,39 @@ +package com.mapbox.mapboxsdk.plugins.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/plugins/utils/OnMapReadyIdlingResource.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/OnMapReadyIdlingResource.java new file mode 100644 index 0000000000..f084343594 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/OnMapReadyIdlingResource.java @@ -0,0 +1,63 @@ +package com.mapbox.mapboxsdk.plugins.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/plugins/utils/PluginGenerationUtil.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/PluginGenerationUtil.kt new file mode 100644 index 0000000000..9049a28298 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/PluginGenerationUtil.kt @@ -0,0 +1,51 @@ +package com.mapbox.mapboxsdk.plugins.utils + +import android.content.Context +import android.support.v7.app.AppCompatActivity +import com.mapbox.android.core.location.LocationEngine +import com.mapbox.mapboxsdk.maps.MapView +import com.mapbox.mapboxsdk.maps.MapboxMap +import com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerOptions +import com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerPlugin + +class PluginGenerationUtil { + companion object { + fun getLocationLayerPluginProvider(activity: AppCompatActivity, + useDefaultEngine: Boolean = false, + engine: LocationEngine? = null, + options: LocationLayerOptions? = null, + registerLifecycleObserver: Boolean = true) + : GenericPluginAction.PluginProvider { + return object : GenericPluginAction.PluginProvider { + override fun providePlugin(mapView: MapView, mapboxMap: MapboxMap, context: Context): LocationLayerPlugin { + val plugin = if (useDefaultEngine) { + if (options != null) { + LocationLayerPlugin(mapView, mapboxMap, options) + } else { + LocationLayerPlugin(mapView, mapboxMap) + } + } else { + if (options != null) { + LocationLayerPlugin(mapView, mapboxMap, engine, options) + } else { + LocationLayerPlugin(mapView, mapboxMap, engine) + } + } + + if (registerLifecycleObserver) { + activity.lifecycle.addObserver(plugin) + } + + return plugin + } + + override fun isPluginDataReady(plugin: LocationLayerPlugin, mapboxMap: MapboxMap): Boolean { + return mapboxMap.getSource("mapbox-location-source") != null + } + } + } + + const val MAP_RENDER_DELAY = 250L + const val MAP_CONNECTION_DELAY = 1000L + } +} \ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/StyleChangeIdlingResource.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/StyleChangeIdlingResource.kt new file mode 100644 index 0000000000..ab2c855c65 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/StyleChangeIdlingResource.kt @@ -0,0 +1,46 @@ +package com.mapbox.mapboxsdk.plugins.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/plugins/utils/TestLifecycleOwner.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/TestLifecycleOwner.kt new file mode 100644 index 0000000000..ccb8da17a7 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/TestLifecycleOwner.kt @@ -0,0 +1,19 @@ +package com.mapbox.mapboxsdk.plugins.utils + +import android.arch.lifecycle.Lifecycle +import android.arch.lifecycle.LifecycleOwner +import android.arch.lifecycle.LifecycleRegistry + +class TestLifecycleOwner : LifecycleOwner { + private val lifecycleRegistry = LifecycleRegistry(this) + + override fun getLifecycle() = lifecycleRegistry + + fun markState(state: Lifecycle.State) { + lifecycleRegistry.markState(state) + } + + fun handleLifecycleEvent(event: Lifecycle.Event) { + lifecycleRegistry.handleLifecycleEvent(event) + } +} \ No newline at end of file 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 @@ + + + + + + + + + + + + + + + + + \ 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..3c7812f9b1 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/debug/java/com/mapbox/mapboxsdk/testapp/activity/SingleActivity.java @@ -0,0 +1,62 @@ +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); + } + + @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..d7dfcf2dd0 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/debug/res/layout/activity_single.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file -- cgit v1.2.1 From cb771f6aca2ef3cd0d1bf686139e18ce7cc0e233 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Paczos?= Date: Mon, 3 Sep 2018 15:48:32 +0200 Subject: [android] initialize LocationLayerPlugin with Map --- .../java/com/mapbox/mapboxsdk/maps/MapView.java | 23 ++- .../java/com/mapbox/mapboxsdk/maps/MapboxMap.java | 35 ++++ .../plugins/locationlayer/LocationLayerPlugin.java | 220 ++++++++++----------- 3 files changed, 153 insertions(+), 125 deletions(-) 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..76870e44d9 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.plugins.locationlayer.LocationLayerPlugin; 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)); + + // LocationLayerPlugin + mapboxMap.injectLocationLayerPlugin(new LocationLayerPlugin(context, mapboxMap)); + // inject widgets with MapboxMap attrView.setOnClickListener(new AttributionClickListener(context, mapboxMap)); @@ -1214,11 +1220,16 @@ 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) { + mapboxMap.onStartLoadingMap(); + } else if (change == DID_FINISH_LOADING_STYLE) { + if (initialLoad) { + initialLoad = false; + mapboxMap.onPreMapReady(); + onMapReady(); + mapboxMap.onPostMapReady(); + } + 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..8892aa45fe 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 @@ -43,6 +43,7 @@ import com.mapbox.mapboxsdk.constants.Style; import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.geometry.LatLngBounds; import com.mapbox.mapboxsdk.log.Logger; +import com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerPlugin; import com.mapbox.mapboxsdk.style.expressions.Expression; import com.mapbox.mapboxsdk.style.layers.Layer; import com.mapbox.mapboxsdk.style.light.Light; @@ -75,6 +76,7 @@ public final class MapboxMap { private final OnGesturesManagerInteractionListener onGesturesManagerInteractionListener; + private LocationLayerPlugin locationLayerPlugin; 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); } + locationLayerPlugin.onStart(); } /** * Called when the hosting Activity/Fragment onStop() method is called. */ void onStop() { + locationLayerPlugin.onStop(); } /** @@ -174,6 +178,20 @@ public final class MapboxMap { invalidateCameraPosition(); } + /** + * Called when the map will start loading style. + */ + void onStartLoadingMap() { + locationLayerPlugin.onStartLoadingMap(); + } + + /** + * Called the map finished loading style. + */ + void onFinishLoadingStyle() { + locationLayerPlugin.onFinishLoadingStyle(); + } + /** * Called when the region is changing or has changed. */ @@ -2283,6 +2301,23 @@ public final class MapboxMap { return nativeMapView.queryRenderedFeatures(coordinates, layerIds, filter); } + // + // LocationLayerPlugin + // + + void injectLocationLayerPlugin(LocationLayerPlugin locationLayerPlugin) { + this.locationLayerPlugin = locationLayerPlugin; + } + + /** + * Returns an object that can be used to display user's location on the Map. + * @return the location layer + */ + @NonNull + public LocationLayerPlugin getLocationLayerPlugin() { + return locationLayerPlugin; + } + // // Interfaces // diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerPlugin.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerPlugin.java index 70fc2ae298..988f01dce8 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerPlugin.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerPlugin.java @@ -1,9 +1,6 @@ package com.mapbox.mapboxsdk.plugins.locationlayer; import android.annotation.SuppressLint; -import android.arch.lifecycle.Lifecycle; -import android.arch.lifecycle.LifecycleObserver; -import android.arch.lifecycle.OnLifecycleEvent; import android.content.Context; import android.hardware.SensorManager; import android.location.Location; @@ -22,8 +19,7 @@ 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.maps.MapView; -import com.mapbox.mapboxsdk.maps.MapView.OnMapChangedListener; +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; @@ -33,8 +29,6 @@ import com.mapbox.mapboxsdk.plugins.locationlayer.modes.RenderMode; import java.util.concurrent.CopyOnWriteArrayList; -import timber.log.Timber; - import static android.Manifest.permission.ACCESS_COARSE_LOCATION; import static android.Manifest.permission.ACCESS_FINE_LOCATION; import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.DEFAULT_TRACKING_TILT_ANIMATION_DURATION; @@ -66,10 +60,10 @@ import static com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants. * {@link LocationLayerOptions#MAX_ZOOM_DEFAULT} and {@link LocationLayerOptions#MIN_ZOOM_DEFAULT} respectively. * You can adjust the zoom range with {@link LocationLayerOptions#maxZoom()} and {@link LocationLayerOptions#minZoom()}. */ -public final class LocationLayerPlugin implements LifecycleObserver { +public final class LocationLayerPlugin { + private static final String TAG = "Mbgl-LocationLayerPlugin"; private final MapboxMap mapboxMap; - private final MapView mapView; private LocationLayerOptions options; private LocationEngine locationEngine; private CompassEngine compassEngine; @@ -101,7 +95,7 @@ public final class LocationLayerPlugin implements LifecycleObserver { * Initialized in a started state because the plugin can be instantiated after lifecycle's onStart() and * the developer might not register the lifecycle observer but call lifecycle methods manually instead. */ - private boolean isPluginStarted = true; + private boolean isPluginStarted; /** * Indicates if Mapbox components are ready to be interacted with. This can differ from {@link #isPluginStarted} @@ -121,116 +115,107 @@ public final class LocationLayerPlugin implements LifecycleObserver { /** * Construct a LocationLayerPlugin - *

- * Note: This constructor will initialize and use an internal {@link LocationEngine}. - *

* - * @param mapView the MapView to apply the LocationLayerPlugin to * @param mapboxMap the MapboxMap to apply the LocationLayerPlugin with */ - public LocationLayerPlugin(@NonNull MapView mapView, @NonNull MapboxMap mapboxMap) { + public LocationLayerPlugin(@NonNull Context context, @NonNull MapboxMap mapboxMap) { this.mapboxMap = mapboxMap; - this.mapView = mapView; - options = LocationLayerOptions.createFromAttributes(mapView.getContext(), R.style.mapbox_LocationLayer); - initializeLocationEngine(); - initialize(); + options = LocationLayerOptions.createFromAttributes(context, R.style.mapbox_LocationLayer); + initialize(context); } /** - * Construct a LocationLayerPlugin + * This method will show or hide the location icon and enable or disable the camera + * tracking the location. + * + * @param isEnabled true to show layers and enable camera, false otherwise + */ + private void setLocationLayerEnabled(boolean isEnabled) { + if (isEnabled) { + enableLocationLayerPlugin(); + } else { + disableLocationLayerPlugin(); + } + } + + /** + * This method will show the location icon and enable the camera tracking the location. *

* Note: This constructor will initialize and use an internal {@link LocationEngine}. - *

* - * @param mapView the MapView to apply the LocationLayerPlugin to - * @param mapboxMap the MapboxMap to apply the LocationLayerPlugin with - * @param options to customize the user location icons inside your apps + * @param context the context */ - public LocationLayerPlugin(@NonNull MapView mapView, @NonNull MapboxMap mapboxMap, - @NonNull LocationLayerOptions options) { - this.mapboxMap = mapboxMap; - this.mapView = mapView; - this.options = options; - initializeLocationEngine(); - initialize(); + @RequiresPermission(anyOf = {ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION}) + public void activateLocationLayerPlugin(@NonNull Context context) { + activateLocationLayerPlugin(context, LocationLayerOptions.createFromAttributes(context, R.style + .mapbox_LocationLayer)); } /** - * Construct a LocationLayerPlugin + * This method will show the location icon and enable the camera tracking the location. *

* Note: This constructor will initialize and use an internal {@link LocationEngine}. - *

* - * @param mapView the MapView to apply the LocationLayerPlugin to - * @param mapboxMap the MapboxMap to apply the LocationLayerPlugin with + * @param context the context + * @param styleRes the LocationLayerPlugin style res */ - public LocationLayerPlugin(@NonNull MapView mapView, @NonNull MapboxMap mapboxMap, - @StyleRes int styleRes) { - this.mapboxMap = mapboxMap; - this.mapView = mapView; - this.options = LocationLayerOptions.createFromAttributes(mapView.getContext(), styleRes); - initializeLocationEngine(); - initialize(); + @RequiresPermission(anyOf = {ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION}) + public void activateLocationLayerPlugin(@NonNull Context context, @StyleRes int styleRes) { + activateLocationLayerPlugin(context, LocationLayerOptions.createFromAttributes(context, styleRes)); } /** - * Construct a LocationLayerPlugin + * This method will show the location icon and enable the camera tracking the location. + *

+ * Note: This constructor will initialize and use an internal {@link LocationEngine}. + *

* - * @param mapView the MapView to apply the LocationLayerPlugin to - * @param mapboxMap the MapboxMap to apply the LocationLayerPlugin with - * @param locationEngine the {@link LocationEngine} this plugin should use to update + * @param context the context + * @param options the options */ - public LocationLayerPlugin(@NonNull MapView mapView, @NonNull MapboxMap mapboxMap, - @Nullable LocationEngine locationEngine) { - this(mapView, mapboxMap, locationEngine, - LocationLayerOptions.createFromAttributes(mapView.getContext(), - R.style.mapbox_LocationLayer)); + @RequiresPermission(anyOf = {ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION}) + public void activateLocationLayerPlugin(@NonNull Context context, @NonNull LocationLayerOptions options) { + applyStyle(options); + initializeLocationEngine(context); + setLocationLayerEnabled(true); } /** - * Construct a LocationLayerPlugin + * This method will show the location icon and enable the camera tracking the location. + *

+ * Note: This constructor will initialize and use an internal {@link LocationEngine}. + *

* - * @param mapView the MapView to apply the LocationLayerPlugin to - * @param mapboxMap the MapboxMap to apply the LocationLayerPlugin with - * @param locationEngine the {@link LocationEngine} this plugin should use to update - * @param styleRes customize the user location icons inside your apps {@code style.xml} + * @param context the context + * @param locationEngine the engine, or null if you'd like to only force location updates + * @param styleRes the LocationLayerPlugin style res */ - public LocationLayerPlugin(@NonNull MapView mapView, @NonNull MapboxMap mapboxMap, - @Nullable LocationEngine locationEngine, @StyleRes int styleRes) { - this(mapView, mapboxMap, locationEngine, - LocationLayerOptions.createFromAttributes(mapView.getContext(), styleRes)); + public void activateLocationLayerPlugin(@NonNull Context context, @Nullable LocationEngine locationEngine, + @StyleRes int styleRes) { + activateLocationLayerPlugin(locationEngine, LocationLayerOptions.createFromAttributes(context, styleRes)); } /** - * Construct a LocationLayerPlugin + * This method will show the location icon and enable the camera tracking the location. + *

+ * Note: This constructor will initialize and use an internal {@link LocationEngine}. + *

* - * @param mapView the MapView to apply the LocationLayerPlugin to - * @param mapboxMap the MapboxMap to apply the LocationLayerPlugin with - * @param locationEngine the {@link LocationEngine} this plugin should use to update - * @param options to customize the user location icons inside your apps + * @param locationEngine the engine, or null if you'd like to only force location updates + * @param options the options */ - public LocationLayerPlugin(@NonNull MapView mapView, @NonNull MapboxMap mapboxMap, - @Nullable LocationEngine locationEngine, - @NonNull LocationLayerOptions options) { - this.locationEngine = locationEngine; - this.mapboxMap = mapboxMap; - this.mapView = mapView; - this.options = options; - initialize(); + public void activateLocationLayerPlugin(@Nullable LocationEngine locationEngine, + @NonNull LocationLayerOptions options) { + setLocationEngine(locationEngine); + applyStyle(options); + setLocationLayerEnabled(true); } /** - * This method will show or hide the location icon and enable or disable the camera - * tracking the location. - * - * @param isEnabled true to show layers and enable camera, false otherwise + * This method will hide the location icon and disable the camera tracking the location. */ - public void setLocationLayerEnabled(boolean isEnabled) { - if (isEnabled) { - enableLocationLayerPlugin(); - } else { - disableLocationLayerPlugin(); - } + public void deactivateLocationLayerPlugin() { + setLocationLayerEnabled(false); } /** @@ -315,8 +300,8 @@ public final class LocationLayerPlugin implements LifecycleObserver { * * @param styleRes a XML style overriding some or all the options */ - public void applyStyle(@StyleRes int styleRes) { - applyStyle(LocationLayerOptions.createFromAttributes(mapView.getContext(), styleRes)); + public void applyStyle(@NonNull Context context, @StyleRes int styleRes) { + applyStyle(LocationLayerOptions.createFromAttributes(context, styleRes)); } /** @@ -350,9 +335,9 @@ public final class LocationLayerPlugin implements LifecycleObserver { if (!isLocationLayerStarted) { return; } else if (getCameraMode() == CameraMode.NONE) { - Timber.e("%s%s", + Logger.e(TAG, String.format("%s%s", "LocationLayerPlugin#zoomWhileTracking method can only be used", - " when a camera mode other than CameraMode#NONE is engaged."); + " when a camera mode other than CameraMode#NONE is engaged.")); return; } pluginAnimatorCoordinator.feedNewZoomLevel(zoomLevel, mapboxMap.getCameraPosition(), animationDuration, callback); @@ -408,9 +393,9 @@ public final class LocationLayerPlugin implements LifecycleObserver { if (!isLocationLayerStarted) { return; } else if (getCameraMode() == CameraMode.NONE) { - Timber.e("%s%s", + Logger.e(TAG, String.format("%s%s", "LocationLayerPlugin#tiltWhileTracking method can only be used", - " when a camera mode other than CameraMode#NONE is engaged."); + " when a camera mode other than CameraMode#NONE is engaged.")); return; } pluginAnimatorCoordinator.feedNewTilt(tilt, mapboxMap.getCameraPosition(), animationDuration, callback); @@ -645,28 +630,43 @@ public final class LocationLayerPlugin implements LifecycleObserver { } /** - * You must call this method from the parent's Activity#onStart() or Fragment#onStart() + * Internal use. */ - @OnLifecycleEvent(Lifecycle.Event.ON_START) public void onStart() { - if (mapView.isDestroyed()) { - Timber.e("You are calling plugins #onStart after the map was destroyed. Re-create the plugin before using it."); + // TODO: 03.09.18 LLP when map destroyed + /*if (context.isDestroyed()) { + Logger.e("You are calling plugins #onStart after the map was destroyed. Re-create the plugin before using it."); return; - } + }*/ isPluginStarted = true; onLocationLayerStart(); } /** - * You must call this method from the parent's Activity#onStop() or Fragment#onStop(). + * Internal use. */ - @OnLifecycleEvent(Lifecycle.Event.ON_STOP) public void onStop() { onLocationLayerStop(); isPluginStarted = false; } + /** + * Internal use. + */ + public void onStartLoadingMap() { + onLocationLayerStop(); + } + + /** + * Internal use. + */ + public void onFinishLoadingStyle() { + locationLayer.initializeComponents(options); + locationLayerCamera.initializeOptions(options); + onLocationLayerStart(); + } + @SuppressLint("MissingPermission") private void onLocationLayerStart() { if (!isPluginStarted) { @@ -720,25 +720,22 @@ public final class LocationLayerPlugin implements LifecycleObserver { } } - private void initialize() { + private void initialize(@NonNull Context context) { AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); - mapView.addOnMapChangedListener(onMapChangedListener); - mapboxMap.addOnMapClickListener(onMapClickListener); mapboxMap.addOnMapLongClickListener(onMapLongClickListener); LayerSourceProvider sourceProvider = new LayerSourceProvider(); LayerFeatureProvider featureProvider = new LayerFeatureProvider(); - LayerBitmapProvider bitmapProvider = new LayerBitmapProvider(mapView.getContext()); + LayerBitmapProvider bitmapProvider = new LayerBitmapProvider(context); locationLayer = new LocationLayer(mapboxMap, sourceProvider, featureProvider, bitmapProvider, options); locationLayerCamera = new LocationLayerCamera( - mapView.getContext(), mapboxMap, cameraTrackingChangedListener, options, onCameraMoveInvalidateListener); + context, mapboxMap, cameraTrackingChangedListener, options, onCameraMoveInvalidateListener); pluginAnimatorCoordinator = new PluginAnimatorCoordinator(); pluginAnimatorCoordinator.addLayerListener(locationLayer); pluginAnimatorCoordinator.addCameraListener(locationLayerCamera); - Context context = mapView.getContext(); WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); SensorManager sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); compassEngine = new LocationLayerCompassEngine(windowManager, sensorManager); @@ -747,14 +744,13 @@ public final class LocationLayerPlugin implements LifecycleObserver { updateMapWithOptions(options); - enableLocationLayerPlugin(); setRenderMode(RenderMode.NORMAL); setCameraMode(CameraMode.NONE); } - private void initializeLocationEngine() { + private void initializeLocationEngine(@NonNull Context context) { usingInternalLocationEngine = true; - locationEngine = new LocationEngineProvider(mapView.getContext()).obtainBestLocationEngineAvailable(); + locationEngine = new LocationEngineProvider(context).obtainBestLocationEngineAvailable(); locationEngine.setPriority(LocationEnginePriority.HIGH_ACCURACY); locationEngine.setFastestInterval(1000); locationEngine.addLocationEngineListener(locationEngineListener); @@ -898,20 +894,6 @@ public final class LocationLayerPlugin implements LifecycleObserver { } }; - private OnMapChangedListener onMapChangedListener = new OnMapChangedListener() { - @SuppressLint("MissingPermission") - @Override - public void onMapChanged(int change) { - if (change == MapView.WILL_START_LOADING_MAP) { - onLocationLayerStop(); - } else if (change == MapView.DID_FINISH_LOADING_STYLE) { - locationLayer.initializeComponents(options); - locationLayerCamera.initializeOptions(options); - onLocationLayerStart(); - } - } - }; - private OnCameraMoveInvalidateListener onCameraMoveInvalidateListener = new OnCameraMoveInvalidateListener() { @Override public void onInvalidateCameraMove() { -- cgit v1.2.1 From 465316b4cef4b0d4630d855a789f5b6acef2084e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Paczos?= Date: Mon, 3 Sep 2018 21:51:43 +0200 Subject: [android] adapt LocationLayerPlugin's test suite --- .../plugins/locationlayer/LocationLayer.java | 4 - .../plugins/locationlayer/LocationLayerPlugin.java | 26 +- .../plugins/locationlayer/StaleStateManager.java | 34 +- .../locationlayer/LocationLayerPluginTest.kt | 860 +++++++++++---------- .../plugins/locationlayer/LocationLayerTest.kt | 177 ++--- .../mapboxsdk/plugins/utils/GenericPluginAction.kt | 48 -- .../plugins/utils/LocationLayerPluginAction.kt | 40 + .../mapboxsdk/plugins/utils/MapboxTestingUtils.kt | 30 +- .../plugins/utils/PluginGenerationUtil.kt | 51 -- .../mapboxsdk/plugins/utils/TestLifecycleOwner.kt | 19 - .../mapboxsdk/testapp/action/MapboxMapAction.java | 3 +- .../testapp/activity/BaseActivityTest.java | 19 +- .../mapboxsdk/testapp/activity/SingleActivity.java | 4 + .../src/debug/res/layout/activity_single.xml | 2 +- 14 files changed, 665 insertions(+), 652 deletions(-) delete mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/GenericPluginAction.kt create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/LocationLayerPluginAction.kt delete mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/PluginGenerationUtil.kt delete mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/TestLifecycleOwner.kt diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayer.java index 0e7ce37a07..67cd26d9cc 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayer.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayer.java @@ -346,10 +346,6 @@ final class LocationLayer implements PluginAnimator.OnLayerAnimationsValuesChang } void setLocationsStale(boolean isStale) { - // If options has stale state disabled, just return here. - if (!options.enableStaleState()) { - return; - } locationFeature.addBooleanProperty(PROPERTY_LOCATION_STALE, isStale); refreshSource(); if (renderMode != RenderMode.GPS) { diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerPlugin.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerPlugin.java index 988f01dce8..45a13ed58b 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerPlugin.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerPlugin.java @@ -114,7 +114,9 @@ public final class LocationLayerPlugin { = new CopyOnWriteArrayList<>(); /** - * Construct a LocationLayerPlugin + * Construct a LocationLayerPlugin. In order to display location, + * the location layer has to be activated with {@link LocationLayerPlugin#activateLocationLayerPlugin(Context)}, + * or one of the overloads. * * @param mapboxMap the MapboxMap to apply the LocationLayerPlugin with */ @@ -151,6 +153,22 @@ public final class LocationLayerPlugin { .mapbox_LocationLayer)); } + /** + * This method will show the location icon and enable the camera tracking the location. + *

+ * Note: This constructor will initialize and use an internal {@link LocationEngine}. + * + * @param context the context + */ + @RequiresPermission(anyOf = {ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION}) + public void activateLocationLayerPlugin(@NonNull Context context, boolean useDefaultLocationEngine) { + if (useDefaultLocationEngine) { + activateLocationLayerPlugin(context, R.style.mapbox_LocationLayer); + } else { + activateLocationLayerPlugin(context, null, R.style.mapbox_LocationLayer); + } + } + /** * This method will show the location icon and enable the camera tracking the location. *

@@ -312,9 +330,7 @@ public final class LocationLayerPlugin { public void applyStyle(LocationLayerOptions options) { this.options = options; locationLayer.applyStyle(options); - if (!options.enableStaleState()) { - staleStateManager.onStop(); - } + staleStateManager.setEnabled(options.enableStaleState()); staleStateManager.setDelayTime(options.staleStateTimeout()); updateMapWithOptions(options); } @@ -740,7 +756,7 @@ public final class LocationLayerPlugin { SensorManager sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); compassEngine = new LocationLayerCompassEngine(windowManager, sensorManager); compassEngine.addCompassListener(compassListener); - staleStateManager = new StaleStateManager(onLocationStaleListener, options.staleStateTimeout()); + staleStateManager = new StaleStateManager(onLocationStaleListener, options); updateMapWithOptions(options); diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/StaleStateManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/StaleStateManager.java index 5c180b5c47..9b6afd2d93 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/StaleStateManager.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/StaleStateManager.java @@ -10,35 +10,42 @@ import android.os.Handler; */ class StaleStateManager { + private boolean isEnabled; private final OnLocationStaleListener innerOnLocationStaleListeners; private final Handler handler; private boolean isStale = true; private long delayTime; - StaleStateManager(OnLocationStaleListener innerListener, long delayTime) { + StaleStateManager(OnLocationStaleListener innerListener, LocationLayerOptions options) { innerOnLocationStaleListeners = innerListener; - this.delayTime = delayTime; handler = new Handler(); - innerOnLocationStaleListeners.onStaleStateChange(true); + isEnabled = options.enableStaleState(); + delayTime = options.staleStateTimeout(); } private Runnable staleStateRunnable = new Runnable() { @Override public void run() { - isStale = true; - innerOnLocationStaleListeners.onStaleStateChange(true); + 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() { - if (isStale) { - isStale = false; - innerOnLocationStaleListeners.onStaleStateChange(false); - } + setState(false); postTheCallback(); } @@ -61,4 +68,13 @@ class StaleStateManager { 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/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerPluginTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerPluginTest.kt index 12a64850b0..1820d56d95 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerPluginTest.kt +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerPluginTest.kt @@ -2,7 +2,6 @@ package com.mapbox.mapboxsdk.plugins.locationlayer import android.Manifest import android.R -import android.arch.lifecycle.Lifecycle import android.content.Context import android.graphics.Color import android.graphics.RectF @@ -12,93 +11,69 @@ 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.filters.LargeTest -import android.support.test.rule.ActivityTestRule 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.CameraPosition import com.mapbox.mapboxsdk.camera.CameraUpdateFactory import com.mapbox.mapboxsdk.constants.Style import com.mapbox.mapboxsdk.geometry.LatLng -import com.mapbox.mapboxsdk.maps.MapView import com.mapbox.mapboxsdk.maps.MapboxMap -import com.mapbox.mapboxsdk.maps.MapboxMapOptions -import com.mapbox.mapboxsdk.maps.SupportMapFragment import com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.* import com.mapbox.mapboxsdk.plugins.locationlayer.modes.CameraMode import com.mapbox.mapboxsdk.plugins.locationlayer.modes.RenderMode import com.mapbox.mapboxsdk.plugins.utils.* import com.mapbox.mapboxsdk.plugins.utils.MapboxTestingUtils.Companion.MAPBOX_HEAVY_STYLE +import com.mapbox.mapboxsdk.plugins.utils.MapboxTestingUtils.Companion.MAP_CONNECTION_DELAY +import com.mapbox.mapboxsdk.plugins.utils.MapboxTestingUtils.Companion.MAP_RENDER_DELAY import com.mapbox.mapboxsdk.plugins.utils.MapboxTestingUtils.Companion.pushSourceUpdates -import com.mapbox.mapboxsdk.plugins.utils.PluginGenerationUtil.Companion.MAP_CONNECTION_DELAY -import com.mapbox.mapboxsdk.plugins.utils.PluginGenerationUtil.Companion.MAP_RENDER_DELAY -import com.mapbox.mapboxsdk.style.layers.PropertyFactory -import com.mapbox.mapboxsdk.style.sources.GeoJsonSource -import com.mapbox.mapboxsdk.testapp.activity.SingleFragmentActivity +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.rules.TestName -import org.junit.runner.RunWith -import timber.log.Timber -/** - * Test class that uses a map fragment to keep onMapReady actions isolated to within the test - */ -@RunWith(AndroidJUnit4::class) -@LargeTest -class LocationLayerPluginTest { - - @Rule - @JvmField - val activityRule = ActivityTestRule(SingleFragmentActivity::class.java, true, true) - - @Rule - @JvmField - val nameRule = TestName() +class LocationLayerPluginTest : BaseActivityTest() { @Rule @JvmField val permissionRule: GrantPermissionRule = GrantPermissionRule.grant(Manifest.permission.ACCESS_FINE_LOCATION) - private lateinit var idlingResource: OnMapFragmentReadyIdlingResource + override fun getActivityClass(): Class<*> { + return SingleActivity::class.java + } + private lateinit var styleChangeIdlingResource: StyleChangeIdlingResource - private lateinit var fragment: SupportMapFragment - private lateinit var mapboxMap: MapboxMap private val location: Location by lazy { val initLocation = Location("test") initLocation.latitude = 15.0 initLocation.longitude = 17.0 + initLocation.bearing = 10f + initLocation.accuracy = 150f initLocation } @Before - fun beforeTest() { + override fun beforeTest() { + super.beforeTest() - // Create a default support map fragment and pass it into the empty activity - val options = MapboxMapOptions() - .camera(CameraPosition.Builder().zoom(2.0).build()) // to match plugins min zoom - fragment = SupportMapFragment.newInstance(options) - activityRule.activity.setFragment(fragment) + location.latitude = 15.0 + location.longitude = 17.0 + location.bearing = 10f + location.accuracy = 150f - Timber.e("@Before: ${nameRule.methodName} - register idle resource") - // If idlingResource is null, throw Kotlin exception - idlingResource = OnMapFragmentReadyIdlingResource(fragment) styleChangeIdlingResource = StyleChangeIdlingResource() - IdlingRegistry.getInstance().register(idlingResource) IdlingRegistry.getInstance().register(styleChangeIdlingResource) - onView(withId(R.id.content)).check(matches(isDisplayed())) - mapboxMap = idlingResource.mapboxMap } @Test fun locationLayerPlugin_initializesLocationEngineCorrectlyWhenOnesNotProvided() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + validateTestSetup() + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context) val locationEngine = plugin.locationEngine assertThat(locationEngine, notNullValue()) @@ -108,14 +83,23 @@ class LocationLayerPluginTest { } } - executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, true)) + executePluginTest(pluginAction) } @Test fun locationLayerPlugin_initializesLocationEngineCorrectlyWhenOnesNotProvidedButHasOptions() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + validateTestSetup() + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin( + context, + LocationLayerOptions.builder(context) + .staleStateTimeout(200) + .enableStaleState(false) + .accuracyAlpha(.5f) + .accuracyColor(Color.BLUE) + .build()) val locationEngine = plugin.locationEngine val pluginOptions = plugin.locationLayerOptions @@ -130,24 +114,49 @@ class LocationLayerPluginTest { } } - val options = LocationLayerOptions.builder(fragment.activity) - .staleStateTimeout(200) - .enableStaleState(false) - .accuracyAlpha(.5f) - .accuracyColor(Color.BLUE) - .build() - - executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider( - activityRule.activity, true, null, options)) + executePluginTest(pluginAction) } @Test - fun settingMapStyleImmediatelyBeforeLoadingPlugin_doesStillLoadLayersProperly() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + fun locationLayerPlugin_doesntInitializeEngineWhenNullProvided() { + validateTestSetup() + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin( + null, + LocationLayerOptions.builder(context) + .staleStateTimeout(200) + .enableStaleState(false) + .accuracyAlpha(.5f) + .accuracyColor(Color.BLUE) + .build()) + + val locationEngine = plugin.locationEngine + val pluginOptions = plugin.locationLayerOptions + + assertThat(locationEngine, nullValue()) + assertThat(pluginOptions, notNullValue()) uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + assertThat(pluginOptions?.accuracyAlpha(), `is`(.5f)) + assertThat(pluginOptions?.accuracyColor(), `is`(Color.BLUE)) + } + } + + executePluginTest(pluginAction) + } + + @Test + fun settingMapStyleImmediatelyBeforeLoadingPlugin_doesStillLoadLayersProperly() { + validateTestSetup() + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + mapboxMap.setStyle(Style.LIGHT) + plugin.activateLocationLayerPlugin(context, false) + plugin.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) assertThat(plugin.renderMode, `is`(equalTo(RenderMode.NORMAL))) assertThat(mapboxMap.isLayerVisible(FOREGROUND_LAYER), `is`(true)) @@ -158,39 +167,26 @@ class LocationLayerPluginTest { } } - executePluginTest(pluginAction, object : GenericPluginAction.PluginProvider { - override fun providePlugin(mapView: MapView, mapboxMap: MapboxMap, context: Context): LocationLayerPlugin { - // changing the style just before instantiating the plugin - mapboxMap.setStyleUrl(Style.LIGHT) - val plugin = - PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, null, false) - .providePlugin(mapView, mapboxMap, context) - plugin.forceLocationUpdate(location) - return plugin - } - - override fun isPluginDataReady(plugin: LocationLayerPlugin, mapboxMap: MapboxMap): Boolean { - val source = mapboxMap.getSource(LOCATION_SOURCE) - return source != null && (source as GeoJsonSource).querySourceFeatures(null).isNotEmpty() - } - }) + executePluginTest(pluginAction) } @Test fun locationLayer_doesntShowUntilFirstLocationFix() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + validateTestSetup() + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) // Source should be present but empty - val mapView = fragment.view as MapView + 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 plugin.forceLocationUpdate(location) - uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) // Check if the puck is visible assertThat(mapboxMap.queryRenderedFeatures(location, FOREGROUND_LAYER).isEmpty(), `is`(false)) @@ -205,11 +201,18 @@ class LocationLayerPluginTest { @Test fun locationLayerOptions_disablingStaleStateDoesWorkCorrectly() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + validateTestSetup() + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, + LocationLayerOptions.builder(context) + .staleStateTimeout(200) + .enableStaleState(false) + .build()) plugin.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) uiController.loopMainThreadForAtLeast(200) uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) @@ -221,28 +224,34 @@ class LocationLayerPluginTest { } } - val options = LocationLayerOptions.builder(fragment.activity) - .staleStateTimeout(200) - .enableStaleState(false) - .build() - executePluginTest(pluginAction, - PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, options)) + executePluginTest(pluginAction) } @Test fun locationLayerOptions_loadsForegroundBitmapFromNameOption() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, + LocationLayerOptions.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()) + val foregroundDrawable = ContextCompat.getDrawable(context, R.drawable.ic_media_play) - mapboxMap.addImageFromDrawable("custom-foreground-bitmap", foregroundDrawable!!) - mapboxMap.addImageFromDrawable("custom-background-bitmap", foregroundDrawable) - mapboxMap.addImageFromDrawable("custom-foreground-stale-bitmap", foregroundDrawable) - mapboxMap.addImageFromDrawable("custom-background-stale-bitmap", foregroundDrawable) - mapboxMap.addImageFromDrawable("custom-bearing-bitmap", foregroundDrawable) + 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) + } plugin.forceLocationUpdate(location) - uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) assertThat(mapboxMap.queryRenderedFeatures(location, FOREGROUND_LAYER).isEmpty(), `is`(false)) val feature = mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0] @@ -254,55 +263,56 @@ class LocationLayerPluginTest { } } - val options = LocationLayerOptions.builder(fragment.activity) - .foregroundName("custom-foreground-bitmap") - .backgroundName("custom-background-bitmap") - .foregroundStaleName("custom-foreground-stale-bitmap") - .backgroundStaleName("custom-background-stale-bitmap") - .bearingName("custom-bearing-bitmap") - .build() - executePluginTest(pluginAction, - PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, options)) + executePluginTest(pluginAction) } @Test fun locationLayerOptions_loadsGpsNameWithGpsRenderMode() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, + LocationLayerOptions.builder(context) + .foregroundName("custom-foreground-bitmap") + .gpsName("custom-gps-bitmap") + .build()) + plugin.renderMode = RenderMode.GPS plugin.forceLocationUpdate(location) - uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) val foregroundDrawable = ContextCompat.getDrawable(context, R.drawable.ic_media_play) - mapboxMap.addImageFromDrawable("custom-foreground-bitmap", foregroundDrawable!!) - mapboxMap.addImageFromDrawable("custom-gps-bitmap", foregroundDrawable) + 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"))) } } - val options = LocationLayerOptions.builder(fragment.activity) - .foregroundName("custom-foreground-bitmap") - .gpsName("custom-gps-bitmap") - .build() - executePluginTest(pluginAction, - PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, options)) + executePluginTest(pluginAction) } @Test fun locationLayerOptions_customIconNameRevertsToDefault() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, + LocationLayerOptions.builder(context) + .foregroundName("custom-foreground-bitmap") + .gpsName("custom-gps-bitmap") + .build()) + plugin.renderMode = RenderMode.GPS plugin.forceLocationUpdate(location) - uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) val foregroundId = mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getStringProperty(PROPERTY_FOREGROUND_ICON) assertThat(foregroundId, `is`(equalTo("custom-gps-bitmap"))) - plugin.applyStyle(LocationLayerOptions.builder(fragment.activity).build()) + plugin.applyStyle(LocationLayerOptions.builder(context).build()) uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) val revertedForegroundId = mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getStringProperty(PROPERTY_FOREGROUND_ICON) @@ -310,22 +320,23 @@ class LocationLayerPluginTest { } } - val options = LocationLayerOptions.builder(fragment.activity) - .foregroundName("custom-foreground-bitmap") - .gpsName("custom-gps-bitmap") - .build() - executePluginTest(pluginAction, - PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, options)) + executePluginTest(pluginAction) } @Test fun locationLayerOptions_customGpsIconNameChangeBackWithMode() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + + plugin.activateLocationLayerPlugin(context, + LocationLayerOptions.builder(context) + .gpsName("custom-gps-bitmap") + .build()) + plugin.renderMode = RenderMode.GPS plugin.forceLocationUpdate(location) - uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) val foregroundId = mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getStringProperty(PROPERTY_FOREGROUND_ICON) assertThat(foregroundId, `is`(equalTo("custom-gps-bitmap"))) @@ -338,75 +349,73 @@ class LocationLayerPluginTest { } } - val options = LocationLayerOptions.builder(fragment.activity) - .gpsName("custom-gps-bitmap") - .build() - executePluginTest(pluginAction, - PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, options)) + executePluginTest(pluginAction) } @Test fun stillStaleAfterResuming() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { - val testLifecycleOwner = TestLifecycleOwner() - testLifecycleOwner.markState(Lifecycle.State.RESUMED) - testLifecycleOwner.lifecycle.addObserver(plugin) + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, + LocationLayerOptions.builder(context) + .staleStateTimeout(200) + .build()) plugin.forceLocationUpdate(location) - uiController.loopMainThreadForAtLeast(300) // engaging stale state + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + uiController.loopMainThreadForAtLeast(250) // engaging stale state uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) assertThat(mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getBooleanProperty(PROPERTY_LOCATION_STALE), `is`(true)) - testLifecycleOwner.markState(Lifecycle.State.CREATED) - testLifecycleOwner.markState(Lifecycle.State.RESUMED) - uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + plugin.onStop() + plugin.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)) } } - val options = LocationLayerOptions.builder(fragment.activity) - .staleStateTimeout(200) - .build() - executePluginTest(pluginAction, - PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, options, false)) + + executePluginTest(pluginAction) } @Test fun stillNotStaleAfterResuming() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { - val testLifecycleOwner = TestLifecycleOwner() - testLifecycleOwner.markState(Lifecycle.State.RESUMED) - testLifecycleOwner.lifecycle.addObserver(plugin) - + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.forceLocationUpdate(location) - uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) assertThat(mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getBooleanProperty(PROPERTY_LOCATION_STALE), `is`(false)) - testLifecycleOwner.markState(Lifecycle.State.CREATED) - testLifecycleOwner.markState(Lifecycle.State.RESUMED) + plugin.onStop() + plugin.onStart() uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) assertThat(mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getBooleanProperty(PROPERTY_LOCATION_STALE), `is`(false)) assertThat(mapboxMap.isLayerVisible(ACCURACY_LAYER), `is`(true)) } } - executePluginTest(pluginAction, - PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + executePluginTest(pluginAction) } @Test fun locationLayerOptions_accuracyRingWithColor() { val color = Color.parseColor("#4A90E2") - val rgbaColor = PropertyFactory.colorToRgbaString(color) + val rgbaColor = ColorUtils.colorToRgbaString(color) - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, + LocationLayerOptions.builder(context) + .accuracyColor(color) + .build()) + + plugin.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) // Check that the source property changes correctly mapboxMap.querySourceFeatures(LOCATION_SOURCE).also { @@ -417,22 +426,17 @@ class LocationLayerPluginTest { } } - val options = LocationLayerOptions.builder(fragment.activity) - .accuracyColor(color) - .build() - executePluginTest(pluginAction, - PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, options)) + executePluginTest(pluginAction) } @Test fun forceLocationUpdate_doesMoveLocationLayerIconToCorrectPosition() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { - + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.forceLocationUpdate(location) - - uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) val point: Point = mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].geometry() as Point @@ -446,19 +450,20 @@ class LocationLayerPluginTest { @Test fun disablingPluginHidesPuck() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { - + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.forceLocationUpdate(location) - uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) - val point: Point = mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].geometry() as Point + 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) - plugin.isLocationLayerEnabled = false + plugin.deactivateLocationLayerPlugin() uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) - assertThat(mapboxMap.querySourceFeatures(LOCATION_SOURCE).isEmpty(), `is`(true)) + assertThat(mapboxMap.queryRenderedFeatures(location, FOREGROUND_LAYER).isEmpty(), `is`(true)) } } executePluginTest(pluginAction) @@ -466,19 +471,18 @@ class LocationLayerPluginTest { @Test fun disablingPluginAndChangingStyleAllowsToEnableAgain() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { - + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.forceLocationUpdate(location) - uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) - plugin.isLocationLayerEnabled = false - uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + plugin.deactivateLocationLayerPlugin() mapboxMap.setStyle(Style.LIGHT) - uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) - plugin.isLocationLayerEnabled = true - uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + + plugin.activateLocationLayerPlugin(context, false) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) assertThat(mapboxMap.isLayerVisible(FOREGROUND_LAYER), `is`(true)) } } @@ -486,148 +490,131 @@ class LocationLayerPluginTest { } @Test - fun lifecycle_keepsEnabledWhenStoppedAndStarted() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { - val testLifecycleOwner = TestLifecycleOwner() - testLifecycleOwner.markState(Lifecycle.State.RESUMED) - testLifecycleOwner.lifecycle.addObserver(plugin) + fun lifecycle_isDisabledOnStart() { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + assertThat(plugin.isLocationLayerEnabled, `is`(false)) + plugin.onStop() + plugin.onStart() + assertThat(plugin.isLocationLayerEnabled, `is`(false)) + plugin.activateLocationLayerPlugin(context, false) + assertThat(plugin.isLocationLayerEnabled, `is`(true)) + } + } + executePluginTest(pluginAction) + } + @Test + fun lifecycle_keepsEnabledWhenStoppedAndStarted() { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) assertThat(plugin.isLocationLayerEnabled, `is`(true)) - testLifecycleOwner.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE) - testLifecycleOwner.handleLifecycleEvent(Lifecycle.Event.ON_STOP) - testLifecycleOwner.markState(Lifecycle.State.RESUMED) + plugin.onStop() + plugin.onStart() assertThat(plugin.isLocationLayerEnabled, `is`(true)) } } - executePluginTest(pluginAction, - PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, null, false)) + executePluginTest(pluginAction) } @Test fun lifecycle_keepsDisabledWhenStoppedAndStarted() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { - plugin.isLocationLayerEnabled = false - - val testLifecycleOwner = TestLifecycleOwner() - testLifecycleOwner.markState(Lifecycle.State.RESUMED) - testLifecycleOwner.lifecycle.addObserver(plugin) - + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) + plugin.deactivateLocationLayerPlugin() assertThat(plugin.isLocationLayerEnabled, `is`(false)) - testLifecycleOwner.markState(Lifecycle.State.CREATED) - testLifecycleOwner.markState(Lifecycle.State.RESUMED) + plugin.onStop() + plugin.onStart() assertThat(plugin.isLocationLayerEnabled, `is`(false)) } } - executePluginTest(pluginAction, - PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, null, false)) + executePluginTest(pluginAction) } @Test fun lifecycle_ableToChangeStyleAfterResuming() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { - - val testLifecycleOwner = TestLifecycleOwner() - testLifecycleOwner.markState(Lifecycle.State.RESUMED) - testLifecycleOwner.lifecycle.addObserver(plugin) + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) - testLifecycleOwner.markState(Lifecycle.State.CREATED) - testLifecycleOwner.markState(Lifecycle.State.RESUMED) + plugin.onStop() + plugin.onStart() mapboxMap.setStyle(Style.DARK) uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) } } - executePluginTest(pluginAction, - PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, null, false)) + executePluginTest(pluginAction) } @Test fun lifecycle_interruptedDuringStyleChange() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { - - val testLifecycleOwner = TestLifecycleOwner() - testLifecycleOwner.markState(Lifecycle.State.RESUMED) - testLifecycleOwner.lifecycle.addObserver(plugin) + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) mapboxMap.setStyle(Style.DARK) - - testLifecycleOwner.markState(Lifecycle.State.CREATED) - testLifecycleOwner.markState(Lifecycle.State.RESUMED) + plugin.onStop() + plugin.onStart() uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) } } - executePluginTest(pluginAction, - PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, null, false)) + executePluginTest(pluginAction) } @Test fun lifecycle_forceLocationUpdateAfterStopped() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { - - val testLifecycleOwner = TestLifecycleOwner() - testLifecycleOwner.markState(Lifecycle.State.RESUMED) - testLifecycleOwner.lifecycle.addObserver(plugin) - - testLifecycleOwner.markState(Lifecycle.State.CREATED) + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) + plugin.onStop() plugin.forceLocationUpdate(location) - uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) assertThat(mapboxMap.querySourceFeatures(LOCATION_SOURCE).isEmpty(), `is`(true)) } } - executePluginTest(pluginAction, - PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, null, false)) + executePluginTest(pluginAction) } @Test fun lifecycle_acceptAndReuseLocationUpdatesBeforeLayerStarted() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { - - val testLifecycleOwner = TestLifecycleOwner() - testLifecycleOwner.markState(Lifecycle.State.RESUMED) - testLifecycleOwner.lifecycle.addObserver(plugin) - - testLifecycleOwner.markState(Lifecycle.State.CREATED) + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) + plugin.onStop() plugin.forceLocationUpdate(location) - testLifecycleOwner.markState(Lifecycle.State.RESUMED) - uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + plugin.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) } } - executePluginTest(pluginAction, - PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, null, false)) + executePluginTest(pluginAction) } @Test fun lifecycle_lifecycleChangeRightAfterStyleReload() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { - - val testLifecycleOwner = TestLifecycleOwner() - testLifecycleOwner.markState(Lifecycle.State.RESUMED) - testLifecycleOwner.lifecycle.addObserver(plugin) - + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.forceLocationUpdate(location) mapboxMap.setStyle(Style.LIGHT) - testLifecycleOwner.markState(Lifecycle.State.CREATED) + plugin.onStop() uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) - testLifecycleOwner.markState(Lifecycle.State.RESUMED) - uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + plugin.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) @@ -640,17 +627,17 @@ class LocationLayerPluginTest { assertThat(mapboxMap.isLayerVisible(BEARING_LAYER), `is`(false)) } } - executePluginTest(pluginAction, - PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, null, false)) + executePluginTest(pluginAction) } @Test fun mapChange_settingPluginStyle() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { - styleChangeIdlingResource.waitForStyle(fragment.view as MapView, mapboxMap, MAPBOX_HEAVY_STYLE) - val options = LocationLayerOptions.builder(fragment.activity) + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) + styleChangeIdlingResource.waitForStyle((rule.activity as SingleActivity).mapView, mapboxMap, MAPBOX_HEAVY_STYLE) + val options = LocationLayerOptions.builder(context) .accuracyColor(Color.RED) .build() @@ -661,8 +648,7 @@ class LocationLayerPluginTest { uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) } } - executePluginTest(pluginAction, - PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + executePluginTest(pluginAction) // Waiting for style to finish loading while pushing updates onView(withId(R.id.content)).check(matches(isDisplayed())) @@ -670,10 +656,11 @@ class LocationLayerPluginTest { @Test fun mapChange_forcingLocation() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { - styleChangeIdlingResource.waitForStyle(fragment.view as MapView, mapboxMap, MAPBOX_HEAVY_STYLE) + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) + styleChangeIdlingResource.waitForStyle((rule.activity as SingleActivity).mapView, mapboxMap, MAPBOX_HEAVY_STYLE) pushSourceUpdates(styleChangeIdlingResource) { plugin.forceLocationUpdate(location) @@ -682,8 +669,7 @@ class LocationLayerPluginTest { uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) } } - executePluginTest(pluginAction, - PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + executePluginTest(pluginAction) // Waiting for style to finish loading while pushing updates onView(withId(R.id.content)).check(matches(isDisplayed())) @@ -691,10 +677,13 @@ class LocationLayerPluginTest { @Test fun mapChange_settingMapStyleBeforePluginCreation() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { - val options = LocationLayerOptions.builder(fragment.activity) + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + styleChangeIdlingResource.waitForStyle((rule.activity as SingleActivity).mapView, mapboxMap, MAPBOX_HEAVY_STYLE) + plugin.activateLocationLayerPlugin(context, false) + + val options = LocationLayerOptions.builder(context) .accuracyColor(Color.RED) .build() @@ -704,19 +693,7 @@ class LocationLayerPluginTest { } } } - - executePluginTest(pluginAction, object : GenericPluginAction.PluginProvider { - override fun providePlugin(mapView: MapView, mapboxMap: MapboxMap, context: Context): LocationLayerPlugin { - // changing the style just before instantiating the plugin - styleChangeIdlingResource.waitForStyle(mapView, mapboxMap, MAPBOX_HEAVY_STYLE) - return PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, null, false) - .providePlugin(mapView, mapboxMap, context) - } - - override fun isPluginDataReady(plugin: LocationLayerPlugin, mapboxMap: MapboxMap): Boolean { - return true - } - }) + executePluginTest(pluginAction) // Waiting for style to finish loading while pushing updates onView(withId(R.id.content)).check(matches(isDisplayed())) @@ -724,34 +701,36 @@ class LocationLayerPluginTest { @Test fun animators_layerBearingCorrect() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.renderMode = RenderMode.GPS location.bearing = 77f plugin.forceLocationUpdate(location) - uiController.loopMainThreadForAtLeast(1000) + 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 plugin.forceLocationUpdate(location) - uiController.loopMainThreadForAtLeast(2000) // Waiting for the animation to finish + 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) } } - executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + executePluginTest(pluginAction) } @Test fun animators_cameraLatLngBearingCorrect() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.cameraMode = CameraMode.TRACKING_GPS location.bearing = 77f plugin.forceLocationUpdate(location) - uiController.loopMainThreadForAtLeast(1000) + 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) @@ -760,28 +739,29 @@ class LocationLayerPluginTest { location.latitude = 30.0 location.longitude = 35.0 plugin.forceLocationUpdate(location) - uiController.loopMainThreadForAtLeast(2000) // Waiting for the animation to finish + 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) } } - executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + executePluginTest(pluginAction) } @Test fun animators_cameraBearingCorrect() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.cameraMode = CameraMode.NONE_GPS val latitude = mapboxMap.cameraPosition.target.latitude val longitude = mapboxMap.cameraPosition.target.longitude location.bearing = 77f plugin.forceLocationUpdate(location) - uiController.loopMainThreadForAtLeast(1000) + 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) @@ -790,21 +770,22 @@ class LocationLayerPluginTest { location.latitude = 30.0 location.longitude = 35.0 plugin.forceLocationUpdate(location) - uiController.loopMainThreadForAtLeast(2000) // Waiting for the animation to finish + 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) } } - executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + executePluginTest(pluginAction) } @Test fun animators_cameraNoneCorrect() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.cameraMode = CameraMode.NONE val latitude = mapboxMap.cameraPosition.target.latitude val longitude = mapboxMap.cameraPosition.target.longitude @@ -812,7 +793,7 @@ class LocationLayerPluginTest { location.bearing = 77f plugin.forceLocationUpdate(location) - uiController.loopMainThreadForAtLeast(1000) + 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) @@ -821,38 +802,40 @@ class LocationLayerPluginTest { location.latitude = 30.0 location.longitude = 35.0 plugin.forceLocationUpdate(location) - uiController.loopMainThreadForAtLeast(2000) // Waiting for the animation to finish + 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) } } - executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + executePluginTest(pluginAction) } @Test fun animators_focalPointAdjustment() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.cameraMode = CameraMode.TRACKING plugin.cameraMode = CameraMode.NONE plugin.forceLocationUpdate(location) - uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) assertThat(mapboxMap.uiSettings.focalPoint, nullValue()) } } - executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + executePluginTest(pluginAction) } @Test fun animators_dontZoomWhileNotTracking() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.cameraMode = CameraMode.NONE val zoom = mapboxMap.cameraPosition.zoom plugin.zoomWhileTracking(10.0) @@ -862,14 +845,15 @@ class LocationLayerPluginTest { } } - executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + executePluginTest(pluginAction) } @Test fun animators_zoomWhileTracking() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.cameraMode = CameraMode.TRACKING plugin.zoomWhileTracking(10.0) uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_ZOOM_ANIMATION_DURATION) @@ -878,15 +862,16 @@ class LocationLayerPluginTest { } } - executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + executePluginTest(pluginAction) } @Test @Ignore fun animators_zoomWhileTrackingCanceledOnModeChange() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.cameraMode = CameraMode.TRACKING plugin.zoomWhileTracking(15.0) uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_ZOOM_ANIMATION_DURATION / 2) @@ -897,24 +882,21 @@ class LocationLayerPluginTest { } } - executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + executePluginTest(pluginAction) } @Test fun animators_dontZoomWhileStopped() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { - - val testLifecycleOwner = TestLifecycleOwner() - testLifecycleOwner.markState(Lifecycle.State.RESUMED) - testLifecycleOwner.lifecycle.addObserver(plugin) + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.cameraMode = CameraMode.TRACKING uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) val zoom = mapboxMap.cameraPosition.zoom - testLifecycleOwner.markState(Lifecycle.State.CREATED) + plugin.onStop() plugin.zoomWhileTracking(10.0) uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_ZOOM_ANIMATION_DURATION) @@ -922,16 +904,16 @@ class LocationLayerPluginTest { } } - executePluginTest(pluginAction, - PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, null, false)) + executePluginTest(pluginAction) } @Test @Ignore fun animators_cancelZoomWhileTracking() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.cameraMode = CameraMode.TRACKING plugin.zoomWhileTracking(15.0) uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_ZOOM_ANIMATION_DURATION / 2) @@ -942,14 +924,15 @@ class LocationLayerPluginTest { } } - executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + executePluginTest(pluginAction) } @Test fun animators_dontTiltWhileNotTracking() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.cameraMode = CameraMode.NONE val tilt = mapboxMap.cameraPosition.tilt plugin.tiltWhileTracking(30.0) @@ -959,14 +942,15 @@ class LocationLayerPluginTest { } } - executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + executePluginTest(pluginAction) } @Test fun animators_tiltWhileTracking() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.cameraMode = CameraMode.TRACKING plugin.tiltWhileTracking(30.0) uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_TILT_ANIMATION_DURATION) @@ -975,15 +959,16 @@ class LocationLayerPluginTest { } } - executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + executePluginTest(pluginAction) } @Test @Ignore fun animators_tiltWhileTrackingCanceledOnModeChange() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.cameraMode = CameraMode.TRACKING plugin.tiltWhileTracking(30.0) uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_TILT_ANIMATION_DURATION / 2) @@ -994,23 +979,19 @@ class LocationLayerPluginTest { } } - executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + executePluginTest(pluginAction) } @Test fun animators_dontTiltWhileStopped() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { - - val testLifecycleOwner = TestLifecycleOwner() - testLifecycleOwner.markState(Lifecycle.State.RESUMED) - testLifecycleOwner.lifecycle.addObserver(plugin) - + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.cameraMode = CameraMode.TRACKING val tilt = mapboxMap.cameraPosition.tilt - testLifecycleOwner.markState(Lifecycle.State.CREATED) + plugin.onStop() plugin.tiltWhileTracking(30.0) uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_TILT_ANIMATION_DURATION) @@ -1018,16 +999,16 @@ class LocationLayerPluginTest { } } - executePluginTest(pluginAction, - PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity, false, null, null, false)) + executePluginTest(pluginAction) } @Test @Ignore fun animators_cancelTiltWhileTracking() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.cameraMode = CameraMode.TRACKING plugin.tiltWhileTracking(30.0) uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_TILT_ANIMATION_DURATION / 2) @@ -1038,21 +1019,22 @@ class LocationLayerPluginTest { } } - executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + executePluginTest(pluginAction) } @Test fun cameraPositionAdjustedToTrackingModeWhenPluginEnabled() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.cameraMode = CameraMode.TRACKING_GPS plugin.forceLocationUpdate(location) - plugin.isLocationLayerEnabled = false + plugin.deactivateLocationLayerPlugin() mapboxMap.moveCamera(CameraUpdateFactory.newLatLng(LatLng(51.0, 17.0))) mapboxMap.moveCamera(CameraUpdateFactory.bearingTo(90.0)) - plugin.isLocationLayerEnabled = true - uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + plugin.activateLocationLayerPlugin(context, false) + 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) @@ -1060,30 +1042,66 @@ class LocationLayerPluginTest { } } - executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + executePluginTest(pluginAction) } @Test - fun onPluginInitialized_defaultCompassEngineIsProvided() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + fun compassEngine_onPluginInitializedDefaultIsProvided() { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) assertTrue(plugin.compassEngine is LocationLayerCompassEngine) } } - executePluginTest(pluginAction, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) + executePluginTest(pluginAction) + } + + @Test + fun compassEngine_changesWhenNewProvided() { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) + 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() { + } + } + + plugin.compassEngine = engine + assertThat(plugin.compassEngine, notNullValue()) + assertThat(plugin.compassEngine, `is`(equalTo(engine))) + } + } + + executePluginTest(pluginAction) } @After - fun afterTest() { - Timber.e("@After: ${nameRule.methodName} - unregister idle resource") - IdlingRegistry.getInstance().unregister(idlingResource) + override fun afterTest() { + super.afterTest() IdlingRegistry.getInstance().unregister(styleChangeIdlingResource) } - private fun executePluginTest(listener: GenericPluginAction.OnPerformGenericPluginAction, - pluginProvider: GenericPluginAction.PluginProvider = PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity)) { - onView(withId(R.id.content)).perform(GenericPluginAction(fragment.view as MapView, mapboxMap, pluginProvider, listener)) + private fun executePluginTest(listener: LocationLayerPluginAction.OnPerformLocationLayerPluginAction) { + onView(withId(R.id.content)).perform(LocationLayerPluginAction(mapboxMap, listener)) } } \ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerTest.kt index 121c8f2d22..d7823031fc 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerTest.kt +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerTest.kt @@ -10,11 +10,8 @@ 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.filters.LargeTest -import android.support.test.rule.ActivityTestRule 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 @@ -23,10 +20,11 @@ import com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerConstants.* import com.mapbox.mapboxsdk.plugins.locationlayer.modes.RenderMode import com.mapbox.mapboxsdk.plugins.utils.* import com.mapbox.mapboxsdk.plugins.utils.MapboxTestingUtils.Companion.MAPBOX_HEAVY_STYLE +import com.mapbox.mapboxsdk.plugins.utils.MapboxTestingUtils.Companion.MAP_CONNECTION_DELAY +import com.mapbox.mapboxsdk.plugins.utils.MapboxTestingUtils.Companion.MAP_RENDER_DELAY import com.mapbox.mapboxsdk.plugins.utils.MapboxTestingUtils.Companion.pushSourceUpdates -import com.mapbox.mapboxsdk.plugins.utils.PluginGenerationUtil.Companion.MAP_CONNECTION_DELAY -import com.mapbox.mapboxsdk.plugins.utils.PluginGenerationUtil.Companion.MAP_RENDER_DELAY 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 @@ -37,47 +35,32 @@ import org.junit.Assert.assertThat import org.junit.Before import org.junit.Rule import org.junit.Test -import org.junit.rules.TestName -import org.junit.runner.RunWith -import timber.log.Timber -@RunWith(AndroidJUnit4::class) -@LargeTest -class LocationLayerTest { - - @Rule - @JvmField - val activityRule = ActivityTestRule(SingleActivity::class.java) - - @Rule - @JvmField - val nameRule = TestName() +class LocationLayerTest : BaseActivityTest() { @Rule @JvmField val permissionRule: GrantPermissionRule = grant(Manifest.permission.ACCESS_FINE_LOCATION) - private lateinit var idlingResource: OnMapReadyIdlingResource + override fun getActivityClass(): Class<*> { + return SingleActivity::class.java + } + private lateinit var styleChangeIdlingResource: StyleChangeIdlingResource - private lateinit var mapboxMap: MapboxMap private val location: Location by lazy { val initLocation = Location("test") initLocation.latitude = 15.0 initLocation.longitude = 17.0 + initLocation.bearing = 10f initLocation.accuracy = 2000f initLocation } @Before - fun beforeTest() { - Timber.e("@Before: ${nameRule.methodName} - register idle resource") - // If idlingResource is null, throw Kotlin exception - idlingResource = OnMapReadyIdlingResource(activityRule.activity) + override fun beforeTest() { + super.beforeTest() styleChangeIdlingResource = StyleChangeIdlingResource() - IdlingRegistry.getInstance().register(idlingResource) IdlingRegistry.getInstance().register(styleChangeIdlingResource) - onView(withId(android.R.id.content)).check(matches(isDisplayed())) - mapboxMap = idlingResource.mapboxMap } // @@ -86,9 +69,10 @@ class LocationLayerTest { @Test fun renderModeNormal_sourceDoesGetAdded() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.renderMode = RenderMode.NORMAL uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) assertThat(mapboxMap.getSource(LOCATION_SOURCE), notNullValue()) @@ -103,12 +87,13 @@ class LocationLayerTest { @Test fun renderModeNormal_trackingNormalLayersDoGetAdded() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.renderMode = RenderMode.NORMAL plugin.forceLocationUpdate(location) - uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + 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)) @@ -121,12 +106,13 @@ class LocationLayerTest { @Test fun renderModeCompass_bearingLayersDoGetAdded() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.renderMode = RenderMode.COMPASS plugin.forceLocationUpdate(location) - uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + 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)) @@ -139,12 +125,13 @@ class LocationLayerTest { @Test fun renderModeGps_navigationLayersDoGetAdded() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.renderMode = RenderMode.GPS plugin.forceLocationUpdate(location) - uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + 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)) @@ -157,11 +144,14 @@ class LocationLayerTest { @Test fun dontShowPuckWhenRenderModeSetAndPluginDisabled() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.forceLocationUpdate(location) - plugin.isLocationLayerEnabled = false + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + plugin.deactivateLocationLayerPlugin() + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER, shouldDisappear = true) plugin.renderMode = RenderMode.GPS uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) assertThat(mapboxMap.isLayerVisible(FOREGROUND_LAYER), `is`(false)) @@ -176,12 +166,15 @@ class LocationLayerTest { @Test fun whenLocationLayerPluginDisabled_doesSetAllLayersToVisibilityNone() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.renderMode = RenderMode.NORMAL plugin.forceLocationUpdate(location) - plugin.isLocationLayerEnabled = false + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + plugin.deactivateLocationLayerPlugin() + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER, shouldDisappear = true) uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) // Check that all layers visibilities are set to none @@ -197,14 +190,17 @@ class LocationLayerTest { @Test fun onMapChange_locationLayerLayersDoGetRedrawn() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.renderMode = RenderMode.NORMAL plugin.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) mapboxMap.setStyleUrl(Style.LIGHT) - plugin.forceLocationUpdate(location) uiController.loopMainThreadForAtLeast(MAP_CONNECTION_DELAY) + plugin.forceLocationUpdate(location) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) assertThat(plugin.renderMode, `is`(equalTo(RenderMode.NORMAL))) @@ -229,18 +225,21 @@ class LocationLayerTest { @Test fun whenStyleChanged_continuesUsingStaleIcons() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.applyStyle(LocationLayerOptions.builder(context).staleStateTimeout(100).build()) plugin.forceLocationUpdate(location) - uiController.loopMainThreadForAtLeast(200) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) + uiController.loopMainThreadForAtLeast(150) uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) assertThat(mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getBooleanProperty(PROPERTY_LOCATION_STALE), `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)) } @@ -250,11 +249,12 @@ class LocationLayerTest { @Test fun whenStyleChanged_staleStateChanges() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.applyStyle(LocationLayerOptions.builder(context).staleStateTimeout(1).build()) - styleChangeIdlingResource.waitForStyle(idlingResource.mapView, mapboxMap, MAPBOX_HEAVY_STYLE) + styleChangeIdlingResource.waitForStyle((rule.activity as SingleActivity).mapView, mapboxMap, MAPBOX_HEAVY_STYLE) pushSourceUpdates(styleChangeIdlingResource) { plugin.forceLocationUpdate(location) } @@ -268,13 +268,17 @@ class LocationLayerTest { @Test fun whenStyleChanged_layerVisibilityUpdates() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { - styleChangeIdlingResource.waitForStyle(idlingResource.mapView, mapboxMap, MAPBOX_HEAVY_STYLE) + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + styleChangeIdlingResource.waitForStyle((rule.activity as SingleActivity).mapView, mapboxMap, MAPBOX_HEAVY_STYLE) var show = true pushSourceUpdates(styleChangeIdlingResource) { - plugin.isLocationLayerEnabled = show + if (show) { + plugin.activateLocationLayerPlugin(context, false) + } else { + plugin.deactivateLocationLayerPlugin() + } show = !show } @@ -289,13 +293,14 @@ class LocationLayerTest { @Test fun accuracy_visibleWithNewLocation() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(location), 16.0)) - uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) plugin.forceLocationUpdate(location) - uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY + ACCURACY_RADIUS_ANIMATION_DURATION) + 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] @@ -307,12 +312,12 @@ class LocationLayerTest { @Test fun accuracy_visibleWhenCameraEased() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { - uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) plugin.forceLocationUpdate(location) - uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) + mapboxMap.waitForLayer(uiController, location, FOREGROUND_LAYER) mapboxMap.easeCamera(CameraUpdateFactory.newLatLngZoom(LatLng(location), 16.0), 300) uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY + 300) @@ -326,9 +331,10 @@ class LocationLayerTest { @Test fun accuracy_visibleWhenCameraMoved() { - val pluginAction = object : GenericPluginAction.OnPerformGenericPluginAction { - override fun onGenericPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, - uiController: UiController, context: Context) { + val pluginAction = object : LocationLayerPluginAction.OnPerformLocationLayerPluginAction { + override fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, + uiController: UiController, context: Context) { + plugin.activateLocationLayerPlugin(context, false) uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) plugin.forceLocationUpdate(location) uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) @@ -344,13 +350,12 @@ class LocationLayerTest { } @After - fun afterTest() { - Timber.e("@After: ${nameRule.methodName} - unregister idle resource") - IdlingRegistry.getInstance().unregister(idlingResource) + override fun afterTest() { + super.afterTest() IdlingRegistry.getInstance().unregister(styleChangeIdlingResource) } - private fun executePluginTest(listener: GenericPluginAction.OnPerformGenericPluginAction) { - onView(withId(android.R.id.content)).perform(GenericPluginAction(idlingResource.mapView, mapboxMap, PluginGenerationUtil.getLocationLayerPluginProvider(activityRule.activity), listener)) + private fun executePluginTest(listener: LocationLayerPluginAction.OnPerformLocationLayerPluginAction) { + onView(withId(R.id.content)).perform(LocationLayerPluginAction(mapboxMap, listener)) } } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/GenericPluginAction.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/GenericPluginAction.kt deleted file mode 100644 index 210f7b4758..0000000000 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/GenericPluginAction.kt +++ /dev/null @@ -1,48 +0,0 @@ -package com.mapbox.mapboxsdk.plugins.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.MapView -import com.mapbox.mapboxsdk.maps.MapboxMap -import com.mapbox.mapboxsdk.plugins.utils.PluginGenerationUtil.Companion.MAP_RENDER_DELAY -import org.hamcrest.Matcher - -class GenericPluginAction(private val mapView: MapView, private val mapboxMap: MapboxMap, private val pluginProvider: PluginProvider, - private val onPerformGenericPluginAction: OnPerformGenericPluginAction) : ViewAction { - - override fun getConstraints(): Matcher { - return isDisplayed() - } - - override fun getDescription(): String { - return javaClass.simpleName - } - - override fun perform(uiController: UiController, view: View) { - val plugin = pluginProvider.providePlugin(mapView, mapboxMap, view.context) - - // ensuring that the asynchronous renderer has time to render data we want to test - uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) - while (!pluginProvider.isPluginDataReady(plugin, mapboxMap)) { - uiController.loopMainThreadForAtLeast(MAP_RENDER_DELAY) - } - - onPerformGenericPluginAction.onGenericPluginAction( - plugin, - mapboxMap, - uiController, - view.context) - } - - interface OnPerformGenericPluginAction { - fun onGenericPluginAction(plugin: T, mapboxMap: MapboxMap, uiController: UiController, context: Context) - } - - interface PluginProvider { - fun providePlugin(mapView: MapView, mapboxMap: MapboxMap, context: Context): T - fun isPluginDataReady(plugin: T, mapboxMap: MapboxMap): Boolean - } -} \ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/LocationLayerPluginAction.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/LocationLayerPluginAction.kt new file mode 100644 index 0000000000..af2c9adf35 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/LocationLayerPluginAction.kt @@ -0,0 +1,40 @@ +package com.mapbox.mapboxsdk.plugins.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.plugins.locationlayer.LocationLayerPlugin +import org.hamcrest.Matcher + +class LocationLayerPluginAction(private val mapboxMap: MapboxMap, + private val onPerformLocationLayerPluginAction: OnPerformLocationLayerPluginAction) : ViewAction { + + override fun getConstraints(): Matcher { + return isDisplayed() + } + + override fun getDescription(): String { + return javaClass.simpleName + } + + override fun perform(uiController: UiController, view: View) { + val plugin = mapboxMap.locationLayerPlugin + + while (mapboxMap.getSource("mapbox-location-source") == null) { + uiController.loopMainThreadForAtLeast(MapboxTestingUtils.MAP_RENDER_DELAY) + } + + onPerformLocationLayerPluginAction.onLocationLayerPluginAction( + plugin, + mapboxMap, + uiController, + view.context) + } + + interface OnPerformLocationLayerPluginAction { + fun onLocationLayerPluginAction(plugin: LocationLayerPlugin, mapboxMap: MapboxMap, uiController: UiController, context: Context) + } +} \ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/MapboxTestingUtils.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/MapboxTestingUtils.kt index b65cb3278b..b77ab127d9 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/MapboxTestingUtils.kt +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/MapboxTestingUtils.kt @@ -7,6 +7,7 @@ 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 @@ -14,7 +15,7 @@ import com.mapbox.mapboxsdk.style.layers.Property import com.mapbox.mapboxsdk.style.sources.GeoJsonSource fun MapboxMap.querySourceFeatures(sourceId: String): List { - return this.getSourceAs(sourceId)?.querySourceFeatures(null) as List + return this.getSourceAs(sourceId)?.querySourceFeatures(null) ?: emptyList() } fun MapboxMap.queryRenderedFeatures(location: Location, layerId: String): List { @@ -27,9 +28,34 @@ 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++ + } +} + + class MapboxTestingUtils { companion object { + const val MAP_RENDER_DELAY = 250L + const val MAP_CONNECTION_DELAY = 1000L + const val RENDER_TIMEOUT = 3_000L + /** * Used to increase style load time for stress testing. */ @@ -71,7 +97,7 @@ fun MapboxMap.addImageFromDrawable(string: String, drawable: Drawable) { 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) + drawable.intrinsicHeight, Bitmap.Config.ARGB_8888) val canvas = Canvas(bitmap) drawable.setBounds(0, 0, canvas.width, canvas.height) drawable.draw(canvas) diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/PluginGenerationUtil.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/PluginGenerationUtil.kt deleted file mode 100644 index 9049a28298..0000000000 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/PluginGenerationUtil.kt +++ /dev/null @@ -1,51 +0,0 @@ -package com.mapbox.mapboxsdk.plugins.utils - -import android.content.Context -import android.support.v7.app.AppCompatActivity -import com.mapbox.android.core.location.LocationEngine -import com.mapbox.mapboxsdk.maps.MapView -import com.mapbox.mapboxsdk.maps.MapboxMap -import com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerOptions -import com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerPlugin - -class PluginGenerationUtil { - companion object { - fun getLocationLayerPluginProvider(activity: AppCompatActivity, - useDefaultEngine: Boolean = false, - engine: LocationEngine? = null, - options: LocationLayerOptions? = null, - registerLifecycleObserver: Boolean = true) - : GenericPluginAction.PluginProvider { - return object : GenericPluginAction.PluginProvider { - override fun providePlugin(mapView: MapView, mapboxMap: MapboxMap, context: Context): LocationLayerPlugin { - val plugin = if (useDefaultEngine) { - if (options != null) { - LocationLayerPlugin(mapView, mapboxMap, options) - } else { - LocationLayerPlugin(mapView, mapboxMap) - } - } else { - if (options != null) { - LocationLayerPlugin(mapView, mapboxMap, engine, options) - } else { - LocationLayerPlugin(mapView, mapboxMap, engine) - } - } - - if (registerLifecycleObserver) { - activity.lifecycle.addObserver(plugin) - } - - return plugin - } - - override fun isPluginDataReady(plugin: LocationLayerPlugin, mapboxMap: MapboxMap): Boolean { - return mapboxMap.getSource("mapbox-location-source") != null - } - } - } - - const val MAP_RENDER_DELAY = 250L - const val MAP_CONNECTION_DELAY = 1000L - } -} \ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/TestLifecycleOwner.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/TestLifecycleOwner.kt deleted file mode 100644 index ccb8da17a7..0000000000 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/plugins/utils/TestLifecycleOwner.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.mapbox.mapboxsdk.plugins.utils - -import android.arch.lifecycle.Lifecycle -import android.arch.lifecycle.LifecycleOwner -import android.arch.lifecycle.LifecycleRegistry - -class TestLifecycleOwner : LifecycleOwner { - private val lifecycleRegistry = LifecycleRegistry(this) - - override fun getLifecycle() = lifecycleRegistry - - fun markState(state: Lifecycle.State) { - lifecycleRegistry.markState(state) - } - - fun handleLifecycleEvent(event: Lifecycle.Event) { - lifecycleRegistry.handleLifecycleEvent(event) - } -} \ 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 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/debug/java/com/mapbox/mapboxsdk/testapp/activity/SingleActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/debug/java/com/mapbox/mapboxsdk/testapp/activity/SingleActivity.java index 3c7812f9b1..5daea88ba0 100644 --- 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 @@ -18,6 +18,10 @@ public class SingleActivity extends AppCompatActivity { mapView.onCreate(savedInstanceState); } + public MapView getMapView() { + return mapView; + } + @Override protected void onStart() { super.onStart(); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/debug/res/layout/activity_single.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/debug/res/layout/activity_single.xml index d7dfcf2dd0..f7e3d1f8ec 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/debug/res/layout/activity_single.xml +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/debug/res/layout/activity_single.xml @@ -8,6 +8,6 @@ android:id="@+id/mapView" android:layout_width="match_parent" android:layout_height="match_parent" - app:mapbox_cameraZoom="2.0" /> + app:mapbox_cameraZoomMin="2.0" /> \ No newline at end of file -- cgit v1.2.1 From bfe0b67572e877dbc55f27dfcfee7c75b953fc8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Paczos?= Date: Tue, 4 Sep 2018 12:51:38 +0200 Subject: [android] LocationLayer example activities --- .../plugins/locationlayer/LocationLayerPlugin.java | 28 +- .../android/MapboxGLAndroidSDKTestApp/build.gradle | 4 + .../src/main/AndroidManifest.xml | 44 +++ .../location/LocationLayerFragmentActivity.kt | 171 +++++++++ .../location/LocationLayerMapChangeActivity.java | 131 +++++++ .../location/LocationLayerModesActivity.java | 393 +++++++++++++++++++++ .../location/ManualLocationUpdatesActivity.java | 190 ++++++++++ .../mapboxsdk/testapp/activity/location/Utils.java | 59 ++++ .../src/main/res/drawable/custom_user_arrow.xml | 11 + .../src/main/res/drawable/custom_user_icon.xml | 10 + .../main/res/drawable/custom_user_puck_icon.xml | 23 ++ .../src/main/res/drawable/ic_location_disabled.xml | 9 + .../layout/activity_location_layer_fragment.xml | 24 ++ .../layout/activity_location_layer_map_change.xml | 30 ++ .../res/layout/activity_location_layer_mode.xml | 78 ++++ .../res/layout/activity_location_manual_update.xml | 43 +++ .../src/main/res/menu/menu_location_mode.xml | 20 ++ .../src/main/res/values/categories.xml | 1 + .../src/main/res/values/descriptions.xml | 4 + .../src/main/res/values/styles.xml | 12 + .../src/main/res/values/titles.xml | 4 + platform/android/gradle/dependencies.gradle | 94 ++--- 22 files changed, 1325 insertions(+), 58 deletions(-) create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationLayerFragmentActivity.kt create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationLayerMapChangeActivity.java create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationLayerModesActivity.java create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/ManualLocationUpdatesActivity.java create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/Utils.java create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/custom_user_arrow.xml create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/custom_user_icon.xml create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/custom_user_puck_icon.xml create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_location_disabled.xml create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_location_layer_fragment.xml create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_location_layer_map_change.xml create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_location_layer_mode.xml create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_location_manual_update.xml create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_location_mode.xml diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerPlugin.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerPlugin.java index 45a13ed58b..021729b6ba 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerPlugin.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/plugins/locationlayer/LocationLayerPlugin.java @@ -143,7 +143,7 @@ public final class LocationLayerPlugin { /** * This method will show the location icon and enable the camera tracking the location. *

- * Note: This constructor will initialize and use an internal {@link LocationEngine}. + * Note: This method will initialize and use an internal {@link LocationEngine}. * * @param context the context */ @@ -155,10 +155,10 @@ public final class LocationLayerPlugin { /** * This method will show the location icon and enable the camera tracking the location. - *

- * Note: This constructor will initialize and use an internal {@link LocationEngine}. * - * @param context the context + * @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 activateLocationLayerPlugin(@NonNull Context context, boolean useDefaultLocationEngine) { @@ -172,7 +172,7 @@ public final class LocationLayerPlugin { /** * This method will show the location icon and enable the camera tracking the location. *

- * Note: This constructor will initialize and use an internal {@link LocationEngine}. + * Note: This method will initialize and use an internal {@link LocationEngine}. * * @param context the context * @param styleRes the LocationLayerPlugin style res @@ -185,7 +185,7 @@ public final class LocationLayerPlugin { /** * This method will show the location icon and enable the camera tracking the location. *

- * Note: This constructor will initialize and use an internal {@link LocationEngine}. + * Note: This method will initialize and use an internal {@link LocationEngine}. *

* * @param context the context @@ -200,9 +200,6 @@ public final class LocationLayerPlugin { /** * This method will show the location icon and enable the camera tracking the location. - *

- * Note: This constructor will initialize and use an internal {@link LocationEngine}. - *

* * @param context the context * @param locationEngine the engine, or null if you'd like to only force location updates @@ -215,9 +212,16 @@ public final class LocationLayerPlugin { /** * This method will show the location icon and enable the camera tracking the location. - *

- * Note: This constructor will initialize and use an internal {@link LocationEngine}. - *

+ * + * @param context the context + * @param locationEngine the engine + */ + public void activateLocationLayerPlugin(@NonNull Context context, @NonNull LocationEngine locationEngine) { + activateLocationLayerPlugin(context, locationEngine, R.style.mapbox_LocationLayer); + } + + /** + * This method will show the location icon and enable the camera tracking the location. * * @param locationEngine the engine, or null if you'd like to only force location updates * @param options the options 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/main/AndroidManifest.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml index d9e2001479..8597a9ac14 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml @@ -815,6 +815,50 @@ android:name="android.support.PARENT_ACTIVITY" android:value="com.mapbox.mapboxsdk.testapp.activity.FeatureOverviewActivity" /> + + + + + + + + + + + + + + + + ?) { + Toast.makeText(this@LocationLayerFragmentActivity, "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, LocationLayerFragment.newInstance(), LocationLayerFragment.TAG) + .commit() + } + } else { + finish() + } + } + }) + permissionsManager.requestLocationPermissions(this) + } + } + + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults) + } + + class LocationLayerFragment : Fragment(), LocationEngineListener { + companion object { + const val TAG = "LLFragment" + fun newInstance(): LocationLayerFragment { + return LocationLayerFragment() + } + } + + private lateinit var mapView: MapView + private lateinit var mapboxMap: MapboxMap + private var plugin: LocationLayerPlugin? = 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 + plugin = mapboxMap.locationLayerPlugin + plugin?.activateLocationLayerPlugin(activity) + plugin?.locationEngine?.addLocationEngineListener(this) + } + } + + override fun onLocationChanged(location: Location?) { + if (location != null) { + mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(LatLng(location), 12.0)) + plugin?.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() + plugin?.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/LocationLayerMapChangeActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationLayerMapChangeActivity.java new file mode 100644 index 0000000000..e59627d35e --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationLayerMapChangeActivity.java @@ -0,0 +1,131 @@ +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.plugins.locationlayer.LocationLayerPlugin; +import com.mapbox.mapboxsdk.plugins.locationlayer.modes.RenderMode; +import com.mapbox.mapboxsdk.testapp.R; + +import java.util.List; + +public class LocationLayerMapChangeActivity 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 permissionsToExplain) { + Toast.makeText(LocationLayerMapChangeActivity.this, "You need to accept location permissions.", + Toast.LENGTH_SHORT).show(); + } + + @Override + public void onPermissionResult(boolean granted) { + if (granted) { + mapView.getMapAsync(LocationLayerMapChangeActivity.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; + activateLocationLayer(); + } + + @SuppressLint("MissingPermission") + private void activateLocationLayer() { + LocationLayerPlugin locationPlugin = mapboxMap.getLocationLayerPlugin(); + locationPlugin.activateLocationLayerPlugin(this); + locationPlugin.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/LocationLayerModesActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationLayerModesActivity.java new file mode 100644 index 0000000000..ce005c1825 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationLayerModesActivity.java @@ -0,0 +1,393 @@ +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.maps.MapView; +import com.mapbox.mapboxsdk.maps.MapboxMap; +import com.mapbox.mapboxsdk.maps.OnMapReadyCallback; +import com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerOptions; +import com.mapbox.mapboxsdk.plugins.locationlayer.LocationLayerPlugin; +import com.mapbox.mapboxsdk.plugins.locationlayer.OnCameraTrackingChangedListener; +import com.mapbox.mapboxsdk.plugins.locationlayer.OnLocationLayerClickListener; +import com.mapbox.mapboxsdk.plugins.locationlayer.modes.CameraMode; +import com.mapbox.mapboxsdk.plugins.locationlayer.modes.RenderMode; +import com.mapbox.mapboxsdk.testapp.R; + +import java.util.ArrayList; +import java.util.List; + +public class LocationLayerModesActivity extends AppCompatActivity implements OnMapReadyCallback, + LocationEngineListener, OnLocationLayerClickListener, OnCameraTrackingChangedListener { + + private MapView mapView; + private Button locationModeBtn; + private Button locationTrackingBtn; + + private PermissionsManager permissionsManager; + + private LocationLayerPlugin locationLayerPlugin; + 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"; + + @CameraMode.Mode + private int cameraMode = CameraMode.TRACKING; + + @RenderMode.Mode + private int renderMode = RenderMode.NORMAL; + + @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 (locationLayerPlugin == null) { + return; + } + showModeListDialog(); + } + }); + + locationTrackingBtn = findViewById(R.id.button_location_tracking); + locationTrackingBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (locationLayerPlugin == null) { + return; + } + showTrackingListDialog(); + } + }); + + + if (savedInstanceState != null) { + cameraMode = savedInstanceState.getInt(SAVED_STATE_CAMERA); + renderMode = savedInstanceState.getInt(SAVED_STATE_RENDER); + } + + mapView.onCreate(savedInstanceState); + + if (PermissionsManager.areLocationPermissionsGranted(this)) { + mapView.getMapAsync(this); + } else { + permissionsManager = new PermissionsManager(new PermissionsListener() { + @Override + public void onExplanationNeeded(List permissionsToExplain) { + Toast.makeText(LocationLayerModesActivity.this, "You need to accept location permissions.", + Toast.LENGTH_SHORT).show(); + } + + @Override + public void onPermissionResult(boolean granted) { + if (granted) { + mapView.getMapAsync(LocationLayerModesActivity.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(); + + locationLayerPlugin = mapboxMap.getLocationLayerPlugin(); + locationLayerPlugin.addOnLocationClickListener(this); + locationLayerPlugin.addOnCameraTrackingChangedListener(this); + locationLayerPlugin.setCameraMode(cameraMode); + setRendererMode(renderMode); + activateLocationLayer(); + } + + @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 (locationLayerPlugin == 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_plugin_disable) { + locationLayerPlugin.deactivateLocationLayerPlugin(); + return true; + } else if (id == R.id.action_plugin_enabled) { + activateLocationLayer(); + return true; + } + + return super.onOptionsItemSelected(item); + } + + private void activateLocationLayer() { + if (locationLayerPlugin != null) { + int[] padding; + if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { + padding = new int[] {0, 750, 0, 0}; + } else { + padding = new int[] {0, 250, 0, 0}; + } + + LocationLayerOptions options = LocationLayerOptions.builder(this) + .padding(padding) + .layerBelow("waterway-label") + .build(); + + locationLayerPlugin.activateLocationLayerPlugin(locationEngine, options); + } + } + + public void toggleStyle() { + customStyle = !customStyle; + locationLayerPlugin.applyStyle( + this, + customStyle ? R.style.CustomLocationLayer : R.style.mapbox_LocationLayer); + } + + public void toggleMapStyle() { + String styleUrl = mapboxMap.getStyleUrl().contentEquals(Style.DARK) ? Style.LIGHT : Style.DARK; + mapboxMap.setStyle(styleUrl); + } + + public LocationLayerPlugin getLocationLayerPlugin() { + return locationLayerPlugin; + } + + @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(); + } + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + mapView.onSaveInstanceState(outState); + outState.putInt(SAVED_STATE_CAMERA, cameraMode); + outState.putInt(SAVED_STATE_RENDER, renderMode); + } + + @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 onLocationLayerClick() { + Toast.makeText(this, "OnLocationLayerClick", Toast.LENGTH_LONG).show(); + } + + private void showModeListDialog() { + List modes = new ArrayList<>(); + modes.add("Normal"); + modes.add("Compass"); + modes.add("GPS"); + ArrayAdapter 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; + locationLayerPlugin.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 trackingTypes = new ArrayList<>(); + trackingTypes.add("None"); + trackingTypes.add("Tracking"); + trackingTypes.add("Tracking Compass"); + trackingTypes.add("Tracking GPS"); + trackingTypes.add("Tracking GPS North"); + ArrayAdapter 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")) { + locationLayerPlugin.setCameraMode(CameraMode.NONE); + } else if (selectedTrackingType.contentEquals("Tracking")) { + locationLayerPlugin.setCameraMode(CameraMode.TRACKING); + } else if (selectedTrackingType.contentEquals("Tracking Compass")) { + locationLayerPlugin.setCameraMode(CameraMode.TRACKING_COMPASS); + } else if (selectedTrackingType.contentEquals("Tracking GPS")) { + locationLayerPlugin.setCameraMode(CameraMode.TRACKING_GPS); + } else if (selectedTrackingType.contentEquals("Tracking GPS North")) { + locationLayerPlugin.setCameraMode(CameraMode.TRACKING_GPS_NORTH); + } + listPopup.dismiss(); + + if (locationLayerPlugin.getCameraMode() != CameraMode.NONE) { + locationLayerPlugin.zoomWhileTracking(15, 750, new MapboxMap.CancelableCallback() { + @Override + public void onCancel() { + // No impl + } + + @Override + public void onFinish() { + locationLayerPlugin.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 (cameraMode == CameraMode.NONE) { + locationTrackingBtn.setText("None"); + } else if (cameraMode == CameraMode.TRACKING) { + locationTrackingBtn.setText("Tracking"); + } else if (cameraMode == CameraMode.TRACKING_COMPASS) { + locationTrackingBtn.setText("Tracking Compass"); + } else if (cameraMode == CameraMode.TRACKING_GPS) { + locationTrackingBtn.setText("Tracking GPS"); + } else if (cameraMode == 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..3e9f0853ea --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/ManualLocationUpdatesActivity.java @@ -0,0 +1,190 @@ +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.plugins.locationlayer.LocationLayerPlugin; +import com.mapbox.mapboxsdk.plugins.locationlayer.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 LocationLayerPlugin locationLayerPlugin; + 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 (locationLayerPlugin != null && locationLayerPlugin.getLocationEngine() == null) { + locationLayerPlugin.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 (locationLayerPlugin != null) { + locationLayerPlugin.setLocationEngine(locationLayerPlugin.getLocationEngine() == null ? locationEngine : + null); + + if (locationLayerPlugin.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 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(); + locationLayerPlugin = mapboxMap.getLocationLayerPlugin(); + locationLayerPlugin.activateLocationLayerPlugin(this, locationEngine); + locationLayerPlugin.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/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 @@ + + + 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 @@ + + + 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 @@ + + + + + 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 @@ + + + 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 @@ + + + + + + + + \ 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 @@ + + + + + + + + \ 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 @@ + + + + + + + + + +