summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.ycm_extra_conf.py2
-rw-r--r--CMakeLists.txt12
-rw-r--r--LICENSE.md2
-rw-r--r--Makefile11
-rw-r--r--benchmark/api/query.benchmark.cpp2
-rw-r--r--benchmark/api/render.benchmark.cpp6
-rw-r--r--benchmark/function/camera_function.benchmark.cpp18
-rw-r--r--benchmark/function/composite_function.benchmark.cpp17
-rw-r--r--benchmark/function/source_function.benchmark.cpp17
-rw-r--r--benchmark/parse/filter.benchmark.cpp8
-rw-r--r--bin/offline.cpp76
-rw-r--r--bin/render.cpp115
-rw-r--r--circle.yml85
-rw-r--r--cmake/benchmark.cmake5
-rw-r--r--cmake/core-files.cmake92
-rw-r--r--cmake/core.cmake6
-rw-r--r--cmake/filesource.cmake8
-rw-r--r--cmake/glfw.cmake5
-rw-r--r--cmake/loop-darwin.cmake7
-rw-r--r--cmake/loop-uv.cmake5
-rw-r--r--cmake/mbgl.cmake9
-rw-r--r--cmake/node.cmake19
-rw-r--r--cmake/offline.cmake6
-rw-r--r--cmake/render.cmake7
-rw-r--r--cmake/test-files.cmake15
-rw-r--r--cmake/test.cmake5
-rwxr-xr-xdeps/ninja/ninja-linuxbin166960 -> 0 bytes
-rwxr-xr-xdeps/ninja/ninja-macosbin171356 -> 0 bytes
-rwxr-xr-xdeps/run_gyp8
-rw-r--r--docker/Dockerfile16
-rw-r--r--docker/bitrise/android/Dockerfile21
-rwxr-xr-xdocker/build.sh8
-rw-r--r--docker/clang-tidy/Dockerfile9
-rwxr-xr-xdocker/clang-tidy/run.sh14
-rwxr-xr-xdocker/clang-tidy/tidy.sh18
-rw-r--r--docker/george-edison55-precise-backports.gpg.key13
-rw-r--r--docker/george-edison55-precise-backports.list2
-rw-r--r--docker/linux/Dockerfile14
-rwxr-xr-xdocker/linux/run.sh14
-rwxr-xr-xdocker/linux/test.sh24
-rw-r--r--docker/ubuntu-toolchain-r.gpg.key13
-rw-r--r--docker/ubuntu-toolchain-r.list2
-rw-r--r--docs/TROUBLESHOOTING.md5
-rw-r--r--include/mbgl/map/map.hpp8
-rw-r--r--include/mbgl/map/mode.hpp12
-rw-r--r--include/mbgl/renderer/mode.hpp18
-rw-r--r--include/mbgl/renderer/renderer.hpp2
-rw-r--r--include/mbgl/renderer/renderer_backend.hpp2
-rw-r--r--include/mbgl/storage/offline.hpp6
-rw-r--r--include/mbgl/style/conversion.hpp259
-rw-r--r--include/mbgl/style/conversion/constant.hpp98
-rw-r--r--include/mbgl/style/conversion/coordinate.hpp21
-rw-r--r--include/mbgl/style/conversion/custom_geometry_source_options.hpp64
-rw-r--r--include/mbgl/style/conversion/data_driven_property_value.hpp28
-rw-r--r--include/mbgl/style/conversion/expression.hpp39
-rw-r--r--include/mbgl/style/conversion/filter.hpp243
-rw-r--r--include/mbgl/style/conversion/function.hpp47
-rw-r--r--include/mbgl/style/conversion/geojson.hpp10
-rw-r--r--include/mbgl/style/conversion/geojson_options.hpp79
-rw-r--r--include/mbgl/style/conversion/get_json_type.hpp14
-rw-r--r--include/mbgl/style/conversion/layer.hpp210
-rw-r--r--include/mbgl/style/conversion/light.hpp106
-rw-r--r--include/mbgl/style/conversion/make_property_setters.hpp211
-rw-r--r--include/mbgl/style/conversion/make_property_setters.hpp.ejs48
-rw-r--r--include/mbgl/style/conversion/position.hpp14
-rw-r--r--include/mbgl/style/conversion/property_value.hpp19
-rw-r--r--include/mbgl/style/conversion/source.hpp176
-rw-r--r--include/mbgl/style/conversion/tileset.hpp65
-rw-r--r--include/mbgl/style/conversion/transition_options.hpp32
-rw-r--r--include/mbgl/style/expression/array_assertion.hpp39
-rw-r--r--include/mbgl/style/expression/assertion.hpp33
-rw-r--r--include/mbgl/style/expression/at.hpp38
-rw-r--r--include/mbgl/style/expression/boolean_operator.hpp49
-rw-r--r--include/mbgl/style/expression/case.hpp36
-rw-r--r--include/mbgl/style/expression/check_subtype.hpp17
-rw-r--r--include/mbgl/style/expression/coalesce.hpp45
-rw-r--r--include/mbgl/style/expression/coercion.hpp34
-rw-r--r--include/mbgl/style/expression/compound_expression.hpp138
-rw-r--r--include/mbgl/style/expression/expression.hpp173
-rw-r--r--include/mbgl/style/expression/find_zoom_curve.hpp20
-rw-r--r--include/mbgl/style/expression/get_covering_stops.hpp18
-rw-r--r--include/mbgl/style/expression/interpolate.hpp177
-rw-r--r--include/mbgl/style/expression/is_constant.hpp35
-rw-r--r--include/mbgl/style/expression/is_expression.hpp13
-rw-r--r--include/mbgl/style/expression/let.hpp72
-rw-r--r--include/mbgl/style/expression/literal.hpp38
-rw-r--r--include/mbgl/style/expression/match.hpp45
-rw-r--r--include/mbgl/style/expression/parsing_context.hpp148
-rw-r--r--include/mbgl/style/expression/step.hpp45
-rw-r--r--include/mbgl/style/expression/type.hpp112
-rw-r--r--include/mbgl/style/expression/value.hpp153
-rw-r--r--include/mbgl/style/function/camera_function.hpp58
-rw-r--r--include/mbgl/style/function/composite_function.hpp134
-rw-r--r--include/mbgl/style/function/convert.hpp351
-rw-r--r--include/mbgl/style/function/source_function.hpp39
-rw-r--r--include/mbgl/style/layer.hpp4
-rw-r--r--include/mbgl/style/source.hpp4
-rw-r--r--include/mbgl/style/sources/custom_geometry_source.hpp56
-rw-r--r--include/mbgl/style/sources/geojson_source.hpp2
-rw-r--r--include/mbgl/style/types.hpp9
-rw-r--r--include/mbgl/tile/tile_id.hpp6
-rw-r--r--include/mbgl/util/any.hpp10
-rw-r--r--include/mbgl/util/enum.hpp1
-rw-r--r--include/mbgl/util/geo.hpp90
-rw-r--r--include/mbgl/util/interpolate.hpp33
-rw-r--r--include/mbgl/util/projection.hpp4
-rw-r--r--include/mbgl/util/string.hpp8
-rw-r--r--include/mbgl/util/tileset.hpp1
-rw-r--r--include/mbgl/util/unique_any.hpp275
-rw-r--r--include/mbgl/util/unitbezier.hpp6
m---------mapbox-gl-js0
-rw-r--r--misc/bench-icon.svg (renamed from common/bench-icon.svg)0
-rw-r--r--misc/ca-bundle.crt (renamed from common/ca-bundle.crt)451
-rw-r--r--misc/cloudformation.template (renamed from cloudformation/travis.template)0
-rw-r--r--misc/mb-icon-blue-circle.svg (renamed from common/mb-icon-blue-circle.svg)0
-rw-r--r--misc/mb-icon-blue-square.png (renamed from common/mb-icon-blue-square.png)bin35662 -> 35662 bytes
-rw-r--r--misc/mb-icon-blue-square.svg (renamed from common/mb-icon-blue-square.svg)0
-rw-r--r--misc/proto/binary_program.proto (renamed from proto/binary_program.proto)0
-rw-r--r--misc/proto/glyphs.proto (renamed from proto/glyphs.proto)0
-rw-r--r--misc/proto/style.proto (renamed from proto/style.proto)0
-rw-r--r--misc/proto/vector_tile.proto (renamed from proto/vector_tile.proto)0
-rw-r--r--package.json10
-rw-r--r--platform/android/CHANGELOG.md35
-rw-r--r--platform/android/MapboxGLAndroidSDK/build.gradle33
-rw-r--r--platform/android/MapboxGLAndroidSDK/gradle-checkstyle.gradle1
-rw-r--r--platform/android/MapboxGLAndroidSDK/gradle-javadoc.gradle2
-rw-r--r--platform/android/MapboxGLAndroidSDK/gradle.properties2
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/LibraryLoader.java34
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java2
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/GeometryConstants.java63
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java73
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java70
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcher.java37
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java51
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java18
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java13
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/expressions/Expression.java1761
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/BackgroundLayer.java2
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CircleLayer.java2
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/FillExtrusionLayer.java2
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/FillLayer.java2
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Layer.java13
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/LineLayer.java2
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java24
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java1058
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/RasterLayer.java5
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/SymbolLayer.java2
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/property_factory.java.ejs23
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CustomGeometrySource.java203
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonOptions.java11
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeometryTileProvider.java22
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/BitmapUtils.java28
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java17
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java14
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/style/expressions/ExpressionTest.java1010
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/build.gradle37
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java698
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/OrientationTest.java41
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/action/OrientationChangeAction.java74
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/BaseActivityTest.java10
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/MarkerTest.java51
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/MarkerViewTest.java65
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/PolygonTest.java50
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/PolylineTest.java42
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraAnimateTest.java248
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraEaseTest.java248
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraMoveTest.java249
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/feature/QueryRenderedFeaturesPropertiesTest.java17
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/geometry/LatLngBoundsTest.java18
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/AttributionTest.java15
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/CompassViewTest.java53
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/offline/OfflineUtilsTest.java44
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BackgroundLayerTest.java298
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerTest.java2075
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillExtrusionLayerTest.java1109
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerTest.java1042
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ImageTest.java23
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LightTest.java108
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java2193
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerTest.java600
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTests.java98
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java6527
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml14
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/FeatureOverviewActivity.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AnimatedMarkerActivity.java49
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.java80
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/DynamicMarkerChangeActivity.java35
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewActivity.java215
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolygonActivity.java16
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolylineActivity.java57
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PressForMarkerActivity.java35
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimationTypeActivity.java146
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimatorActivity.java112
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraPositionActivity.java8
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.java10
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/ManualZoomActivity.java15
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/MaxMinZoomActivity.java14
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/ScrollByActivity.java14
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/customlayer/CustomLayerActivity.java20
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxCountActivity.java46
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxHighlightActivity.java64
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxSymbolCountActivity.java78
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesPropertiesActivity.java64
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QuerySourceFeaturesActivity.java49
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/MultiMapActivity.java2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/ViewPagerActivity.java1
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/PrintActivity.java18
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/SnapshotActivity.java22
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/DynamicInfoWindowAdapterActivity.java59
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/InfoWindowAdapterActivity.java12
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/BottomSheetActivity.java41
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DebugModeActivity.java73
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DoubleMapActivity.java62
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/LocalGlyphActivity.java4
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapChangeActivity.java19
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapInDialogActivity.java11
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapPaddingActivity.java21
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/VisibilityChangeActivity.java12
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/DeleteRegionActivity.java15
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.java43
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/UpdateMetadataActivity.java17
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterActivity.java20
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterReuseActivity.java31
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/storage/UrlTransformActivity.java10
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/AnimatedImageSourceActivity.java1
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/BuildingFillExtrusionActivity.java38
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/CircleLayerActivity.java27
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/CustomSpriteActivity.java97
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/DataDrivenStyleActivity.java294
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/FillExtrusionActivity.java101
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/FillExtrusionStyleTestActivity.java8
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/GeoJsonClusteringActivity.java14
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/GridSourceActivity.java151
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleActivity.java200
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleTestActivity.java8
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleTimingTestActivity.java32
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/StyleFileActivity.java36
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java118
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolLayerActivity.java72
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/ZoomFunctionSymbolLayerActivity.java39
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/textureview/TextureViewAnimationActivity.java46
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/textureview/TextureViewDebugModeActivity.java70
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/textureview/TextureViewResizeActivity.java23
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/CustomLocationEngineActivity.java20
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MockLocationEngine.java9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationDrawableActivity.java10
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTintActivity.java134
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationToggleActivity.java18
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTrackingModeActivity.java56
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/adapter/FeatureSectionAdapter.java12
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineDownloadRegionDialog.java22
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineListRegionsDialog.java19
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/FontCache.java4
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/GeoParseUtil.java42
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/OfflineUtils.java19
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_data_driven_style.xml12
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_grid_source.xml17
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_local_glyph.xml2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_generator_symbol.xml4
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/actions.xml1
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml7
-rw-r--r--platform/android/README.md85
-rw-r--r--platform/android/build.gradle5
-rw-r--r--platform/android/config.cmake57
-rw-r--r--platform/android/dependencies.gradle6
-rw-r--r--platform/android/gradle/wrapper/gradle-wrapper.properties3
-rw-r--r--platform/android/mbgl/gl/gl_impl.hpp5
-rwxr-xr-xplatform/android/src/android_renderer_backend.cpp2
-rwxr-xr-xplatform/android/src/android_renderer_backend.hpp2
-rwxr-xr-xplatform/android/src/jni.cpp4
-rwxr-xr-xplatform/android/src/native_map_view.cpp28
-rwxr-xr-xplatform/android/src/native_map_view.hpp6
-rw-r--r--platform/android/src/style/android_conversion.hpp147
-rw-r--r--platform/android/src/style/conversion/filter.hpp3
-rw-r--r--platform/android/src/style/conversion/geojson.hpp24
-rw-r--r--platform/android/src/style/conversion/url_or_tileset.hpp9
-rw-r--r--platform/android/src/style/layers/layer.cpp21
-rw-r--r--platform/android/src/style/sources/custom_geometry_source.cpp143
-rw-r--r--platform/android/src/style/sources/custom_geometry_source.hpp47
-rw-r--r--platform/android/src/style/sources/geojson_source.cpp20
-rw-r--r--platform/android/src/style/sources/geojson_source.hpp5
-rw-r--r--platform/android/src/style/sources/image_source.cpp10
-rw-r--r--platform/android/src/style/sources/image_source.hpp5
-rw-r--r--platform/android/src/style/sources/raster_source.cpp10
-rw-r--r--platform/android/src/style/sources/raster_source.hpp5
-rw-r--r--platform/android/src/style/sources/source.cpp117
-rw-r--r--platform/android/src/style/sources/source.hpp36
-rw-r--r--platform/android/src/style/sources/sources.cpp60
-rw-r--r--platform/android/src/style/sources/sources.hpp18
-rw-r--r--platform/android/src/style/sources/unknown_source.cpp10
-rw-r--r--platform/android/src/style/sources/unknown_source.hpp5
-rw-r--r--platform/android/src/style/sources/vector_source.cpp10
-rw-r--r--platform/android/src/style/sources/vector_source.hpp5
-rw-r--r--platform/android/src/style/value.cpp2
-rw-r--r--platform/android/src/style/value.hpp8
-rw-r--r--platform/darwin/docs/theme/assets/css/jazzy.css.scss1
-rw-r--r--platform/darwin/mbgl/gl/gl_impl.hpp16
-rw-r--r--platform/darwin/mbgl/util/image+MGLAdditions.hpp2
-rw-r--r--platform/darwin/src/MGLAbstractShapeSource.h99
-rw-r--r--platform/darwin/src/MGLAbstractShapeSource.mm117
-rw-r--r--platform/darwin/src/MGLAbstractShapeSource_Private.h22
-rw-r--r--platform/darwin/src/MGLAccountManager.m2
-rw-r--r--platform/darwin/src/MGLAttributionInfo.mm1
-rw-r--r--platform/darwin/src/MGLComputedShapeSource.h113
-rw-r--r--platform/darwin/src/MGLComputedShapeSource.mm169
-rw-r--r--platform/darwin/src/MGLConversion.h223
-rw-r--r--platform/darwin/src/MGLFeature.mm6
-rw-r--r--platform/darwin/src/MGLMapSnapshotter.mm1
-rw-r--r--platform/darwin/src/MGLNetworkConfiguration.m2
-rw-r--r--platform/darwin/src/MGLPolygon+MGLAdditions.h7
-rw-r--r--platform/darwin/src/MGLPolygon+MGLAdditions.m27
-rw-r--r--platform/darwin/src/MGLPolygon.mm26
-rw-r--r--platform/darwin/src/MGLPolygon_Private.h11
-rw-r--r--platform/darwin/src/MGLPolyline+MGLAdditions.h7
-rw-r--r--platform/darwin/src/MGLPolyline+MGLAdditions.m14
-rw-r--r--platform/darwin/src/MGLPolyline.mm13
-rw-r--r--platform/darwin/src/MGLPolyline_Private.h12
-rw-r--r--platform/darwin/src/MGLRendererConfiguration.h2
-rw-r--r--platform/darwin/src/MGLShapeSource.h70
-rw-r--r--platform/darwin/src/MGLShapeSource.mm62
-rw-r--r--platform/darwin/src/MGLShapeSource_Private.h3
-rw-r--r--platform/darwin/src/MGLStyle.mm6
-rw-r--r--platform/darwin/src/MGLStyleValue_Private.h4
-rw-r--r--platform/darwin/src/MGLVectorSource+MGLAdditions.h15
-rw-r--r--platform/darwin/src/MGLVectorSource+MGLAdditions.m53
-rw-r--r--platform/darwin/src/MGLVectorSource.mm53
-rw-r--r--platform/darwin/src/MGLVectorSource_Private.h7
-rw-r--r--platform/darwin/src/headless_backend_cgl.cpp132
-rw-r--r--platform/darwin/src/headless_backend_eagl.mm61
-rw-r--r--platform/darwin/src/headless_display_cgl.cpp60
-rw-r--r--platform/darwin/src/image.mm2
-rw-r--r--platform/darwin/test/MGLAttributionInfoTests.m4
-rw-r--r--platform/darwin/test/MGLComputedShapeSourceTests.m24
-rw-r--r--platform/darwin/test/MGLShapeSourceTests.mm1
-rw-r--r--platform/default/headless_backend_osmesa.cpp44
-rw-r--r--platform/default/mbgl/gl/headless_backend.cpp17
-rw-r--r--platform/default/mbgl/gl/headless_backend.hpp15
-rw-r--r--platform/default/mbgl/gl/headless_display.cpp15
-rw-r--r--platform/default/mbgl/gl/headless_display.hpp34
-rw-r--r--platform/default/mbgl/gl/headless_frontend.cpp8
-rw-r--r--platform/default/mbgl/gl/headless_frontend.hpp5
-rw-r--r--platform/default/mbgl/map/map_snapshotter.cpp2
-rw-r--r--platform/default/mbgl/storage/offline.cpp6
-rw-r--r--platform/default/mbgl/storage/offline_download.cpp2
-rw-r--r--platform/default/mbgl/storage/offline_download.hpp2
-rw-r--r--platform/glfw/glfw_view.cpp2
-rw-r--r--platform/glfw/glfw_view.hpp2
-rw-r--r--platform/glfw/main.cpp100
-rw-r--r--platform/glfw/settings_json.hpp3
-rw-r--r--platform/ios/CHANGELOG.md11
-rw-r--r--platform/ios/DEVELOPING.md10
-rw-r--r--platform/ios/INSTALL.md6
-rw-r--r--platform/ios/README.md1
-rw-r--r--platform/ios/app/Assets.xcassets/AppIcon.appiconset/Contents.json3
-rw-r--r--platform/ios/app/Assets.xcassets/AppIcon.appiconset/Icon-1024.pngbin0 -> 12225 bytes
-rw-r--r--platform/ios/app/Info.plist2
-rw-r--r--platform/ios/app/MBXViewController.m104
-rw-r--r--platform/ios/benchmark/Info.plist2
-rw-r--r--platform/ios/config.cmake17
-rw-r--r--platform/ios/ios.xcodeproj/project.pbxproj93
-rw-r--r--platform/ios/ios.xcodeproj/xcshareddata/xcschemes/CI.xcscheme4
-rw-r--r--platform/ios/ios.xcodeproj/xcshareddata/xcschemes/bench.xcscheme4
-rw-r--r--platform/ios/ios.xcodeproj/xcshareddata/xcschemes/dynamic+static.xcscheme4
-rw-r--r--platform/ios/ios.xcodeproj/xcshareddata/xcschemes/dynamic.xcscheme4
-rw-r--r--platform/ios/ios.xcodeproj/xcshareddata/xcschemes/iosapp.xcscheme4
-rw-r--r--platform/ios/ios.xcodeproj/xcshareddata/xcschemes/static.xcscheme4
-rw-r--r--platform/ios/jazzy.yml4
-rw-r--r--platform/ios/src/MGLMapAccessibilityElement.mm5
-rw-r--r--platform/ios/src/MGLMapView.mm27
-rw-r--r--platform/ios/src/Mapbox.h2
-rw-r--r--platform/ios/src/UIImage+MGLAdditions.mm4
-rw-r--r--platform/ios/uitest/LaunchScreen.xib2
-rw-r--r--platform/ios/uitest/ios-tests.xcodeproj/xcshareddata/xcschemes/Mapbox GL Tests.xcscheme4
-rw-r--r--platform/linux/config.cmake14
-rw-r--r--platform/linux/mbgl/gl/gl_impl.hpp11
-rw-r--r--platform/linux/src/headless_backend_egl.cpp155
-rw-r--r--platform/linux/src/headless_backend_glx.cpp147
-rw-r--r--platform/linux/src/headless_display_egl.cpp68
-rw-r--r--platform/linux/src/headless_display_glx.cpp78
-rw-r--r--platform/macos/CHANGELOG.md13
-rw-r--r--platform/macos/app/Base.lproj/MainMenu.xib10
-rw-r--r--platform/macos/app/MapDocument.m95
-rw-r--r--platform/macos/config.cmake33
-rw-r--r--platform/macos/jazzy.yml4
-rw-r--r--platform/macos/macos.xcodeproj/project.pbxproj73
-rw-r--r--platform/macos/macos.xcodeproj/xcshareddata/xcschemes/CI.xcscheme8
-rw-r--r--platform/macos/macos.xcodeproj/xcshareddata/xcschemes/dynamic.xcscheme4
-rw-r--r--platform/macos/macos.xcodeproj/xcshareddata/xcschemes/macosapp.xcscheme4
-rw-r--r--platform/macos/sdk/Info.plist6
-rw-r--r--platform/macos/src/MGLMapView.mm2
-rw-r--r--platform/macos/src/Mapbox.h2
-rw-r--r--platform/macos/src/NSImage+MGLAdditions.mm4
-rw-r--r--platform/node/CHANGELOG.md11
-rw-r--r--platform/node/DEVELOPING.md2
-rw-r--r--platform/node/src/node_conversion.hpp183
-rw-r--r--platform/node/src/node_expression.cpp230
-rw-r--r--platform/node/src/node_expression.hpp40
-rw-r--r--platform/node/src/node_geojson.hpp17
-rw-r--r--platform/node/src/node_map.cpp110
-rw-r--r--platform/node/src/node_map.hpp4
-rw-r--r--platform/node/src/node_mapbox_gl_native.cpp2
-rw-r--r--platform/node/test/expression.test.js71
-rw-r--r--platform/node/test/ignores.json154
-rw-r--r--platform/node/test/js/map.test.js3
-rw-r--r--platform/node/test/suite_implementation.js22
-rw-r--r--platform/qt/config.cmake5
-rw-r--r--platform/qt/include/qmapbox.hpp4
-rw-r--r--platform/qt/include/qmapboxgl.hpp6
-rw-r--r--platform/qt/mbgl/gl/gl_impl.hpp178
-rw-r--r--platform/qt/qt.cmake32
-rw-r--r--platform/qt/qt5.cmake6
-rw-r--r--platform/qt/resources/common.qrc2
-rw-r--r--platform/qt/src/headless_backend_qt.cpp36
-rw-r--r--platform/qt/src/http_file_source.cpp3
-rw-r--r--platform/qt/src/http_request.cpp7
-rw-r--r--platform/qt/src/http_request.hpp2
-rw-r--r--platform/qt/src/qmapboxgl.cpp65
-rw-r--r--platform/qt/src/qmapboxgl_p.hpp9
-rw-r--r--platform/qt/src/qt_conversion.hpp191
-rw-r--r--platform/qt/src/qt_geojson.cpp166
-rw-r--r--platform/qt/src/qt_geojson.hpp194
-rw-r--r--platform/qt/src/qt_image.cpp5
-rwxr-xr-xplatform/qt/src/qt_logging.cpp12
-rw-r--r--platform/qt/src/sqlite3.cpp87
-rw-r--r--platform/qt/test/qmapboxgl.test.cpp5
-rw-r--r--scripts/generate-style-code.js4
-rwxr-xr-xscripts/update_ca_bundle.sh2
-rw-r--r--src/mbgl/annotation/render_annotation_source.cpp5
-rw-r--r--src/mbgl/annotation/render_annotation_source.hpp5
-rw-r--r--src/mbgl/geometry/feature_index.cpp28
-rw-r--r--src/mbgl/geometry/feature_index.hpp33
-rw-r--r--src/mbgl/gl/color_mode.hpp2
-rw-r--r--src/mbgl/gl/context.cpp19
-rw-r--r--src/mbgl/gl/context.hpp23
-rw-r--r--src/mbgl/gl/gl.hpp30
-rw-r--r--src/mbgl/gl/index_buffer.hpp1
-rw-r--r--src/mbgl/layout/symbol_instance.cpp33
-rw-r--r--src/mbgl/layout/symbol_instance.hpp16
-rw-r--r--src/mbgl/layout/symbol_layout.cpp275
-rw-r--r--src/mbgl/layout/symbol_layout.hpp22
-rw-r--r--src/mbgl/layout/symbol_projection.cpp156
-rw-r--r--src/mbgl/layout/symbol_projection.hpp42
-rw-r--r--src/mbgl/map/map.cpp35
-rw-r--r--src/mbgl/map/transform.cpp26
-rw-r--r--src/mbgl/map/transform.hpp8
-rw-r--r--src/mbgl/map/transform_state.cpp9
-rw-r--r--src/mbgl/map/transform_state.hpp3
-rw-r--r--src/mbgl/programs/attributes.hpp5
-rw-r--r--src/mbgl/programs/collision_box_program.hpp156
-rw-r--r--src/mbgl/programs/fill_extrusion_program.hpp10
-rw-r--r--src/mbgl/programs/programs.hpp4
-rw-r--r--src/mbgl/programs/symbol_program.cpp12
-rw-r--r--src/mbgl/programs/symbol_program.hpp85
-rw-r--r--src/mbgl/programs/uniforms.hpp1
-rw-r--r--src/mbgl/renderer/buckets/circle_bucket.cpp2
-rw-r--r--src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp6
-rw-r--r--src/mbgl/renderer/buckets/symbol_bucket.cpp167
-rw-r--r--src/mbgl/renderer/buckets/symbol_bucket.hpp58
-rw-r--r--src/mbgl/renderer/frame_history.cpp81
-rw-r--r--src/mbgl/renderer/frame_history.hpp41
-rw-r--r--src/mbgl/renderer/layers/render_circle_layer.cpp2
-rw-r--r--src/mbgl/renderer/layers/render_symbol_layer.cpp82
-rw-r--r--src/mbgl/renderer/paint_parameters.cpp2
-rw-r--r--src/mbgl/renderer/paint_parameters.hpp6
-rw-r--r--src/mbgl/renderer/paint_property_binder.hpp11
-rw-r--r--src/mbgl/renderer/render_layer.hpp11
-rw-r--r--src/mbgl/renderer/render_source.cpp3
-rw-r--r--src/mbgl/renderer/render_source.hpp4
-rw-r--r--src/mbgl/renderer/renderer_backend.cpp2
-rw-r--r--src/mbgl/renderer/renderer_impl.cpp132
-rw-r--r--src/mbgl/renderer/renderer_impl.hpp15
-rw-r--r--src/mbgl/renderer/sources/render_custom_geometry_source.cpp86
-rw-r--r--src/mbgl/renderer/sources/render_custom_geometry_source.hpp50
-rw-r--r--src/mbgl/renderer/sources/render_geojson_source.cpp5
-rw-r--r--src/mbgl/renderer/sources/render_geojson_source.hpp5
-rw-r--r--src/mbgl/renderer/sources/render_image_source.cpp57
-rw-r--r--src/mbgl/renderer/sources/render_image_source.hpp5
-rw-r--r--src/mbgl/renderer/sources/render_raster_source.cpp3
-rw-r--r--src/mbgl/renderer/sources/render_raster_source.hpp5
-rw-r--r--src/mbgl/renderer/sources/render_vector_source.cpp5
-rw-r--r--src/mbgl/renderer/sources/render_vector_source.hpp5
-rw-r--r--src/mbgl/renderer/tile_pyramid.cpp53
-rw-r--r--src/mbgl/renderer/tile_pyramid.hpp5
-rw-r--r--src/mbgl/shaders/collision_box.cpp67
-rw-r--r--src/mbgl/shaders/collision_circle.cpp83
-rw-r--r--src/mbgl/shaders/collision_circle.hpp16
-rw-r--r--src/mbgl/shaders/debug.cpp7
-rw-r--r--src/mbgl/shaders/fill_extrusion.cpp12
-rw-r--r--src/mbgl/shaders/fill_extrusion_pattern.cpp16
-rw-r--r--src/mbgl/shaders/preludes.cpp4
-rw-r--r--src/mbgl/shaders/symbol_icon.cpp24
-rw-r--r--src/mbgl/shaders/symbol_sdf.cpp54
-rw-r--r--src/mbgl/style/conversion/constant.cpp94
-rw-r--r--src/mbgl/style/conversion/coordinate.cpp29
-rw-r--r--src/mbgl/style/conversion/filter.cpp248
-rw-r--r--src/mbgl/style/conversion/geojson.cpp18
-rw-r--r--src/mbgl/style/conversion/geojson_options.cpp85
-rw-r--r--src/mbgl/style/conversion/get_json_type.cpp34
-rw-r--r--src/mbgl/style/conversion/json.hpp2
-rw-r--r--src/mbgl/style/conversion/layer.cpp206
-rw-r--r--src/mbgl/style/conversion/light.cpp115
-rw-r--r--src/mbgl/style/conversion/make_property_setters.hpp209
-rw-r--r--src/mbgl/style/conversion/make_property_setters.hpp.ejs46
-rw-r--r--src/mbgl/style/conversion/position.cpp22
-rw-r--r--src/mbgl/style/conversion/property_setter.hpp (renamed from include/mbgl/style/conversion/property_setter.hpp)14
-rw-r--r--src/mbgl/style/conversion/source.cpp175
-rw-r--r--src/mbgl/style/conversion/tileset.cpp73
-rw-r--r--src/mbgl/style/conversion/transition_options.cpp40
-rw-r--r--src/mbgl/style/custom_tile_loader.cpp109
-rw-r--r--src/mbgl/style/custom_tile_loader.hpp45
-rw-r--r--src/mbgl/style/expression/array_assertion.cpp86
-rw-r--r--src/mbgl/style/expression/assertion.cpp73
-rw-r--r--src/mbgl/style/expression/at.cpp64
-rw-r--r--src/mbgl/style/expression/boolean_operator.cpp87
-rw-r--r--src/mbgl/style/expression/case.cpp91
-rw-r--r--src/mbgl/style/expression/check_subtype.cpp60
-rw-r--r--src/mbgl/style/expression/coalesce.cpp62
-rw-r--r--src/mbgl/style/expression/coercion.cpp144
-rw-r--r--src/mbgl/style/expression/compound_expression.cpp568
-rw-r--r--src/mbgl/style/expression/find_zoom_curve.cpp76
-rw-r--r--src/mbgl/style/expression/get_covering_stops.cpp26
-rw-r--r--src/mbgl/style/expression/interpolate.cpp211
-rw-r--r--src/mbgl/style/expression/is_constant.cpp40
-rw-r--r--src/mbgl/style/expression/is_expression.cpp29
-rw-r--r--src/mbgl/style/expression/let.cpp92
-rw-r--r--src/mbgl/style/expression/literal.cpp108
-rw-r--r--src/mbgl/style/expression/match.cpp263
-rw-r--r--src/mbgl/style/expression/parsing_context.cpp208
-rw-r--r--src/mbgl/style/expression/step.cpp152
-rw-r--r--src/mbgl/style/expression/util.cpp39
-rw-r--r--src/mbgl/style/expression/util.hpp14
-rw-r--r--src/mbgl/style/expression/value.cpp322
-rw-r--r--src/mbgl/style/function/expression.cpp38
-rw-r--r--src/mbgl/style/parser.cpp6
-rw-r--r--src/mbgl/style/rapidjson_conversion.hpp152
-rw-r--r--src/mbgl/style/sources/custom_geometry_source.cpp45
-rw-r--r--src/mbgl/style/sources/custom_geometry_source_impl.cpp40
-rw-r--r--src/mbgl/style/sources/custom_geometry_source_impl.hpp29
-rw-r--r--src/mbgl/style/types.cpp1
-rw-r--r--src/mbgl/text/collision_feature.cpp81
-rw-r--r--src/mbgl/text/collision_feature.hpp48
-rw-r--r--src/mbgl/text/collision_index.cpp359
-rw-r--r--src/mbgl/text/collision_index.hpp70
-rw-r--r--src/mbgl/text/collision_tile.cpp267
-rw-r--r--src/mbgl/text/collision_tile.hpp71
-rw-r--r--src/mbgl/text/cross_tile_symbol_index.cpp165
-rw-r--r--src/mbgl/text/cross_tile_symbol_index.hpp64
-rw-r--r--src/mbgl/text/glyph.hpp8
-rw-r--r--src/mbgl/text/glyph_manager.cpp10
-rw-r--r--src/mbgl/text/glyph_manager.hpp2
-rw-r--r--src/mbgl/text/placement.cpp332
-rw-r--r--src/mbgl/text/placement.hpp91
-rw-r--r--src/mbgl/text/placement_config.hpp33
-rw-r--r--src/mbgl/text/shaping.cpp2
-rw-r--r--src/mbgl/tile/custom_geometry_tile.cpp91
-rw-r--r--src/mbgl/tile/custom_geometry_tile.hpp44
-rw-r--r--src/mbgl/tile/geometry_tile.cpp93
-rw-r--r--src/mbgl/tile/geometry_tile.hpp33
-rw-r--r--src/mbgl/tile/geometry_tile_worker.cpp34
-rw-r--r--src/mbgl/tile/geometry_tile_worker.hpp11
-rw-r--r--src/mbgl/tile/tile.cpp3
-rw-r--r--src/mbgl/tile/tile.hpp26
-rw-r--r--src/mbgl/util/grid_index.cpp292
-rw-r--r--src/mbgl/util/grid_index.hpp96
-rw-r--r--src/mbgl/util/mapbox.cpp6
-rw-r--r--src/mbgl/util/mapbox.hpp4
-rw-r--r--src/mbgl/util/tile_cover.cpp8
-rw-r--r--src/mbgl/util/tile_cover.hpp2
-rw-r--r--src/parsedate/parsedate.c18
-rw-r--r--test/api/annotations.test.cpp10
-rw-r--r--test/api/api_misuse.test.cpp2
-rw-r--r--test/api/custom_geometry_source.test.cpp71
-rw-r--r--test/api/custom_layer.test.cpp2
-rw-r--r--test/api/query.test.cpp2
-rw-r--r--test/api/recycle_map.cpp2
-rw-r--r--test/api/zoom_history.cpp2
-rw-r--r--test/fixtures/annotations/debug_sparse/expected.pngbin2933 -> 1387 bytes
-rw-r--r--test/fixtures/api/query_style.json12
-rw-r--r--test/fixtures/custom_geometry_source/grid/expected.pngbin0 -> 8302 bytes
-rw-r--r--test/fixtures/expression_equality/acos.a.json4
-rw-r--r--test/fixtures/expression_equality/acos.b.json4
-rw-r--r--test/fixtures/expression_equality/all.a.json17
-rw-r--r--test/fixtures/expression_equality/all.b.json17
-rw-r--r--test/fixtures/expression_equality/any.a.json17
-rw-r--r--test/fixtures/expression_equality/any.b.json17
-rw-r--r--test/fixtures/expression_equality/array.a.json11
-rw-r--r--test/fixtures/expression_equality/array.b.json11
-rw-r--r--test/fixtures/expression_equality/asin.a.json4
-rw-r--r--test/fixtures/expression_equality/asin.b.json4
-rw-r--r--test/fixtures/expression_equality/at.a.json20
-rw-r--r--test/fixtures/expression_equality/at.b.json20
-rw-r--r--test/fixtures/expression_equality/atan.a.json4
-rw-r--r--test/fixtures/expression_equality/atan.b.json4
-rw-r--r--test/fixtures/expression_equality/boolean.a.json7
-rw-r--r--test/fixtures/expression_equality/boolean.b.json7
-rw-r--r--test/fixtures/expression_equality/case.a.json14
-rw-r--r--test/fixtures/expression_equality/case.b.json14
-rw-r--r--test/fixtures/expression_equality/coalesce.a.json16
-rw-r--r--test/fixtures/expression_equality/coalesce.b.json16
-rw-r--r--test/fixtures/expression_equality/concat.a.json6
-rw-r--r--test/fixtures/expression_equality/concat.b.json6
-rw-r--r--test/fixtures/expression_equality/cos.a.json4
-rw-r--r--test/fixtures/expression_equality/cos.b.json4
-rw-r--r--test/fixtures/expression_equality/divide.a.json5
-rw-r--r--test/fixtures/expression_equality/divide.b.json5
-rw-r--r--test/fixtures/expression_equality/downcase.a.json4
-rw-r--r--test/fixtures/expression_equality/downcase.b.json4
-rw-r--r--test/fixtures/expression_equality/get.a.json7
-rw-r--r--test/fixtures/expression_equality/get.b.json7
-rw-r--r--test/fixtures/expression_equality/has.a.json4
-rw-r--r--test/fixtures/expression_equality/has.b.json4
-rw-r--r--test/fixtures/expression_equality/heatmap-density.a.json23
-rw-r--r--test/fixtures/expression_equality/heatmap-density.b.json23
-rw-r--r--test/fixtures/expression_equality/let.a.json25
-rw-r--r--test/fixtures/expression_equality/let.b.json25
-rw-r--r--test/fixtures/expression_equality/ln.a.json4
-rw-r--r--test/fixtures/expression_equality/ln.b.json6
-rw-r--r--test/fixtures/expression_equality/log10.a.json4
-rw-r--r--test/fixtures/expression_equality/log10.b.json4
-rw-r--r--test/fixtures/expression_equality/log2.a.json4
-rw-r--r--test/fixtures/expression_equality/log2.b.json4
-rw-r--r--test/fixtures/expression_equality/match.a.json12
-rw-r--r--test/fixtures/expression_equality/match.b.json12
-rw-r--r--test/fixtures/expression_equality/max.a.json6
-rw-r--r--test/fixtures/expression_equality/max.b.json6
-rw-r--r--test/fixtures/expression_equality/min.a.json5
-rw-r--r--test/fixtures/expression_equality/min.b.json5
-rw-r--r--test/fixtures/expression_equality/minus.a.json5
-rw-r--r--test/fixtures/expression_equality/minus.b.json5
-rw-r--r--test/fixtures/expression_equality/mod.a.json5
-rw-r--r--test/fixtures/expression_equality/mod.b.json5
-rw-r--r--test/fixtures/expression_equality/not.a.json10
-rw-r--r--test/fixtures/expression_equality/not.b.json10
-rw-r--r--test/fixtures/expression_equality/number.a.json7
-rw-r--r--test/fixtures/expression_equality/number.b.json7
-rw-r--r--test/fixtures/expression_equality/object.a.json7
-rw-r--r--test/fixtures/expression_equality/object.b.json7
-rw-r--r--test/fixtures/expression_equality/plus.a.json7
-rw-r--r--test/fixtures/expression_equality/plus.b.json7
-rw-r--r--test/fixtures/expression_equality/pow.a.json11
-rw-r--r--test/fixtures/expression_equality/pow.b.json11
-rw-r--r--test/fixtures/expression_equality/rgb.a.json6
-rw-r--r--test/fixtures/expression_equality/rgb.b.json6
-rw-r--r--test/fixtures/expression_equality/rgba.a.json7
-rw-r--r--test/fixtures/expression_equality/rgba.b.json7
-rw-r--r--test/fixtures/expression_equality/sin.a.json4
-rw-r--r--test/fixtures/expression_equality/sin.b.json4
-rw-r--r--test/fixtures/expression_equality/sqrt.a.json7
-rw-r--r--test/fixtures/expression_equality/sqrt.b.json7
-rw-r--r--test/fixtures/expression_equality/step.a.json18
-rw-r--r--test/fixtures/expression_equality/step.b.json18
-rw-r--r--test/fixtures/expression_equality/string.a.json7
-rw-r--r--test/fixtures/expression_equality/string.b.json7
-rw-r--r--test/fixtures/expression_equality/tan.a.json4
-rw-r--r--test/fixtures/expression_equality/tan.b.json4
-rw-r--r--test/fixtures/expression_equality/times.a.json7
-rw-r--r--test/fixtures/expression_equality/times.b.json7
-rw-r--r--test/fixtures/expression_equality/to-boolean.a.json7
-rw-r--r--test/fixtures/expression_equality/to-boolean.b.json7
-rw-r--r--test/fixtures/expression_equality/to-color.a.json7
-rw-r--r--test/fixtures/expression_equality/to-color.b.json7
-rw-r--r--test/fixtures/expression_equality/to-number.a.json7
-rw-r--r--test/fixtures/expression_equality/to-number.b.json7
-rw-r--r--test/fixtures/expression_equality/to-string.a.json7
-rw-r--r--test/fixtures/expression_equality/to-string.b.json7
-rw-r--r--test/fixtures/expression_equality/typeof.a.json7
-rw-r--r--test/fixtures/expression_equality/typeof.b.json7
-rw-r--r--test/fixtures/expression_equality/upcase.a.json4
-rw-r--r--test/fixtures/expression_equality/upcase.b.json4
-rw-r--r--test/fixtures/expression_equality/zoom.a.json13
-rw-r--r--test/fixtures/expression_equality/zoom.b.json13
-rw-r--r--test/fixtures/local_glyphs/droid/expected.pngbin0 -> 15747 bytes
-rw-r--r--test/fixtures/local_glyphs/mixed.json196
-rw-r--r--test/fixtures/local_glyphs/no_local/expected.pngbin0 -> 8579 bytes
-rw-r--r--test/fixtures/local_glyphs/ping_fang/expected.pngbin0 -> 15747 bytes
-rw-r--r--test/fixtures/map/offline/expected.pngbin47843 -> 48705 bytes
-rw-r--r--test/fixtures/shared_context/expected.pngbin0 -> 6109 bytes
-rw-r--r--test/fixtures/style_parser/expressions.info.json12
-rw-r--r--test/fixtures/style_parser/expressions.style.json74
-rw-r--r--test/gl/bucket.test.cpp27
-rw-r--r--test/gl/context.test.cpp114
-rw-r--r--test/map/map.test.cpp4
-rw-r--r--test/map/prefetch.test.cpp2
-rw-r--r--test/renderer/backend_scope.test.cpp9
-rw-r--r--test/src/app-info.plist2
-rw-r--r--test/src/mbgl/test/conversion_stubs.hpp124
-rw-r--r--test/src/mbgl/test/stub_file_source.cpp16
-rw-r--r--test/src/mbgl/test/stub_file_source.hpp8
-rw-r--r--test/storage/offline.test.cpp1
-rw-r--r--test/style/conversion/function.test.cpp36
-rw-r--r--test/style/conversion/geojson_options.test.cpp39
-rw-r--r--test/style/conversion/layer.test.cpp8
-rw-r--r--test/style/conversion/light.test.cpp7
-rw-r--r--test/style/expression/expression.test.cpp91
-rw-r--r--test/style/expression/util.test.cpp23
-rw-r--r--test/style/filter.test.cpp9
-rw-r--r--test/style/source.test.cpp40
-rw-r--r--test/text/cross_tile_symbol_index.test.cpp85
-rw-r--r--test/text/glyph_loader.test.cpp216
-rw-r--r--test/text/glyph_manager.test.cpp341
-rw-r--r--test/text/local_glyph_rasterizer.test.cpp86
-rw-r--r--test/tile/annotation_tile.test.cpp95
-rw-r--r--test/tile/custom_geometry_tile.test.cpp130
-rw-r--r--test/tile/geojson_tile.test.cpp2
-rw-r--r--test/tile/vector_tile.test.cpp5
-rw-r--r--test/util/geo.test.cpp125
-rw-r--r--test/util/grid_index.test.cpp53
-rw-r--r--test/util/mapbox.test.cpp1
-rw-r--r--test/util/memory.test.cpp6
-rw-r--r--test/util/unique_any.test.cpp186
710 files changed, 30564 insertions, 17058 deletions
diff --git a/.ycm_extra_conf.py b/.ycm_extra_conf.py
index e395609548..63616a1e98 100644
--- a/.ycm_extra_conf.py
+++ b/.ycm_extra_conf.py
@@ -38,6 +38,8 @@ import ycm_core
compilation_database_folders = [
'build/linux-x86_64/Debug',
+ 'build/qt-linux-x86_64/Debug',
+ 'build/qt4-linux-x86_64/Debug',
'build/macos/compdb/Debug',
]
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7f88252754..88368abbd5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -13,9 +13,13 @@ option(WITH_EGL "Use EGL backend" OFF)
if(WITH_CXX11ABI)
set(MASON_CXXABI_SUFFIX -cxx11abi)
- add_definitions(-D_GLIBCXX_USE_CXX11_ABI=1)
+ if(CMAKE_COMPILER_IS_GNUCXX)
+ add_definitions(-D_GLIBCXX_USE_CXX11_ABI=1)
+ endif()
else()
- add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
+ if(CMAKE_COMPILER_IS_GNUCXX)
+ add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
+ endif()
endif()
if(WITH_OSMESA AND WITH_EGL)
@@ -44,7 +48,6 @@ set_source_files_properties(src/mbgl/util/version.cpp PROPERTIES COMPILE_DEFINIT
mason_use(geometry VERSION 0.9.2 HEADER_ONLY)
mason_use(variant VERSION 1.1.4 HEADER_ONLY)
-mason_use(any VERSION 8fef1e9 HEADER_ONLY)
mason_use(unique_resource VERSION cba309e HEADER_ONLY)
mason_use(rapidjson VERSION 1.1.0 HEADER_ONLY)
mason_use(boost VERSION 1.62.0 HEADER_ONLY)
@@ -70,7 +73,8 @@ endif(WITH_COVERAGE)
set(CMAKE_CONFIGURATION_TYPES Debug Release RelWithDebugInfo Sanitize)
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -ftemplate-depth=1024 -Wall -Wextra -Wshadow -Wnon-virtual-dtor -Werror -Wno-variadic-macros -Wno-unknown-pragmas")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -ftemplate-depth=1024 -fPIC -fvisibility=hidden -Wall -Wextra -Wshadow -Wnon-virtual-dtor -Werror -Wno-variadic-macros -Wno-unknown-pragmas")
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -fvisibility=hidden -Wall -Wextra -Wshadow -Werror -Wno-variadic-macros -Wno-unknown-pragmas")
if(APPLE AND CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
# -Wno-error=unused-command-line-argument is required due to https://llvm.org/bugs/show_bug.cgi?id=7798
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=unused-command-line-argument")
diff --git a/LICENSE.md b/LICENSE.md
index d12e00b0e5..0b77be538e 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -1,4 +1,4 @@
-mapbox-gl-native copyright (c) 2014-2017 Mapbox.
+mapbox-gl-native copyright (c) 2014-2018 Mapbox.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
diff --git a/Makefile b/Makefile
index fbb4cd74f5..656a2772ec 100644
--- a/Makefile
+++ b/Makefile
@@ -142,6 +142,10 @@ node: $(MACOS_PROJ_PATH)
macos-test: $(MACOS_PROJ_PATH)
set -o pipefail && $(MACOS_XCODEBUILD) -scheme 'CI' test $(XCPRETTY)
+.PHONY: macos-lint
+macos-lint:
+ find platform/macos -type f -name '*.plist' | xargs plutil -lint
+
.PHONY: xpackage
xpackage: $(MACOS_PROJ_PATH)
SYMBOLS=$(SYMBOLS) ./platform/macos/scripts/package.sh
@@ -218,6 +222,11 @@ ios: $(IOS_PROJ_PATH)
iproj: $(IOS_PROJ_PATH)
open $(IOS_WORK_PATH)
+.PHONY: ios-lint
+ios-lint:
+ find platform/ios/framework -type f -name '*.plist' | xargs plutil -lint
+ find platform/ios/app -type f -name '*.plist' | xargs plutil -lint
+
.PHONY: ios-test
ios-test: $(IOS_PROJ_PATH)
set -o pipefail && $(IOS_XCODEBUILD_SIM) -scheme 'CI' test $(XCPRETTY)
@@ -296,7 +305,7 @@ linux: glfw-app render offline
.PHONY: linux-core
linux-core: $(LINUX_BUILD)
- $(NINJA) $(NINJA_ARGS) -j$(JOBS) -C $(LINUX_OUTPUT_PATH) mbgl-core mbgl-loop-uv
+ $(NINJA) $(NINJA_ARGS) -j$(JOBS) -C $(LINUX_OUTPUT_PATH) mbgl-core mbgl-loop-uv mbgl-filesource
.PHONY: test
test: $(LINUX_BUILD)
diff --git a/benchmark/api/query.benchmark.cpp b/benchmark/api/query.benchmark.cpp
index 75695c1ad7..7694585526 100644
--- a/benchmark/api/query.benchmark.cpp
+++ b/benchmark/api/query.benchmark.cpp
@@ -34,7 +34,7 @@ public:
DefaultFileSource fileSource{ "benchmark/fixtures/api/cache.db", "." };
ThreadPool threadPool{ 4 };
HeadlessFrontend frontend { { 1000, 1000 }, 1, fileSource, threadPool };
- Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), 1, fileSource, threadPool, MapMode::Still };
+ Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), 1, fileSource, threadPool, MapMode::Static};
ScreenBox box{{ 0, 0 }, { 1000, 1000 }};
};
diff --git a/benchmark/api/render.benchmark.cpp b/benchmark/api/render.benchmark.cpp
index 9f1ea68e0b..a1b557777f 100644
--- a/benchmark/api/render.benchmark.cpp
+++ b/benchmark/api/render.benchmark.cpp
@@ -41,7 +41,7 @@ static void prepare(Map& map, optional<std::string> json = {}) {
static void API_renderStill_reuse_map(::benchmark::State& state) {
RenderBenchmark bench;
HeadlessFrontend frontend { { 1000, 1000 }, 1, bench.fileSource, bench.threadPool };
- Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), 1, bench.fileSource, bench.threadPool, MapMode::Still };
+ Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), 1, bench.fileSource, bench.threadPool, MapMode::Static};
prepare(map);
while (state.KeepRunning()) {
@@ -52,7 +52,7 @@ static void API_renderStill_reuse_map(::benchmark::State& state) {
static void API_renderStill_reuse_map_switch_styles(::benchmark::State& state) {
RenderBenchmark bench;
HeadlessFrontend frontend { { 1000, 1000 }, 1, bench.fileSource, bench.threadPool };
- Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), 1, bench.fileSource, bench.threadPool, MapMode::Still };
+ Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), 1, bench.fileSource, bench.threadPool, MapMode::Static};
while (state.KeepRunning()) {
prepare(map, { "{}" });
@@ -67,7 +67,7 @@ static void API_renderStill_recreate_map(::benchmark::State& state) {
while (state.KeepRunning()) {
HeadlessFrontend frontend { { 1000, 1000 }, 1, bench.fileSource, bench.threadPool };
- Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), 1, bench.fileSource, bench.threadPool, MapMode::Still };
+ Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), 1, bench.fileSource, bench.threadPool, MapMode::Static};
prepare(map);
frontend.render(map);
}
diff --git a/benchmark/function/camera_function.benchmark.cpp b/benchmark/function/camera_function.benchmark.cpp
index 1f8fe4579f..26de5701db 100644
--- a/benchmark/function/camera_function.benchmark.cpp
+++ b/benchmark/function/camera_function.benchmark.cpp
@@ -1,20 +1,14 @@
#include <benchmark/benchmark.h>
#include <mbgl/style/function/source_function.hpp>
-
-#include <mbgl/style/rapidjson_conversion.hpp>
#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion/function.hpp>
-#include <rapidjson/document.h>
-
-
using namespace mbgl;
using namespace mbgl::style;
-static rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> createFunctionJSON(size_t stopCount) {
- rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> doc;
-
+static std::string createFunctionJSON(size_t stopCount) {
std::string stops = "[";
for (size_t i = 0; i < stopCount; i++) {
std::string value = std::to_string(24.0f / stopCount * i);
@@ -22,9 +16,7 @@ static rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> cr
stops += "[" + value + ", " + value + "]";
}
stops += "]";
-
- doc.Parse<0>(R"({"type": "exponential", "base": 2, "stops": )" + stops + "}");
- return doc;
+ return R"({"type": "exponential", "base": 2, "stops": )" + stops + "}";
}
static void Parse_CameraFunction(benchmark::State& state) {
@@ -35,7 +27,7 @@ static void Parse_CameraFunction(benchmark::State& state) {
state.PauseTiming();
auto doc = createFunctionJSON(stopCount);
state.ResumeTiming();
- optional<CameraFunction<float>> result = conversion::convert<CameraFunction<float>, JSValue>(doc, error);
+ optional<CameraFunction<float>> result = conversion::convertJSON<CameraFunction<float>>(doc, error);
if (!result) {
state.SkipWithError(error.message.c_str());
}
@@ -47,7 +39,7 @@ static void Evaluate_CameraFunction(benchmark::State& state) {
size_t stopCount = state.range(0);
auto doc = createFunctionJSON(stopCount);
conversion::Error error;
- optional<CameraFunction<float>> function = conversion::convert<CameraFunction<float>, JSValue>(doc, error);
+ optional<CameraFunction<float>> function = conversion::convertJSON<CameraFunction<float>>(doc, error);
if (!function) {
state.SkipWithError(error.message.c_str());
}
diff --git a/benchmark/function/composite_function.benchmark.cpp b/benchmark/function/composite_function.benchmark.cpp
index f04b6c7073..e2545e6349 100644
--- a/benchmark/function/composite_function.benchmark.cpp
+++ b/benchmark/function/composite_function.benchmark.cpp
@@ -5,19 +5,14 @@
#include <mbgl/style/function/composite_exponential_stops.hpp>
#include <mbgl/style/function/composite_function.hpp>
-#include <mbgl/style/rapidjson_conversion.hpp>
#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion/function.hpp>
-#include <rapidjson/document.h>
-
-
using namespace mbgl;
using namespace mbgl::style;
-static rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> createFunctionJSON(size_t stopCount) {
- rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> doc;
-
+static std::string createFunctionJSON(size_t stopCount) {
std::string stops = "[";
for (size_t outerStop = 0; outerStop < stopCount; outerStop++) {
for (size_t innerStop = 0; innerStop < stopCount; innerStop++) {
@@ -29,9 +24,7 @@ static rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> cr
}
}
stops += "]";
-
- doc.Parse<0>(R"({"type": "exponential", "base": 2, "stops": )" + stops + R"(, "property": "x"})");
- return doc;
+ return R"({"type": "exponential", "base": 2, "stops": )" + stops + R"(, "property": "x"})";
}
static void Parse_CompositeFunction(benchmark::State& state) {
@@ -42,7 +35,7 @@ static void Parse_CompositeFunction(benchmark::State& state) {
state.PauseTiming();
auto doc = createFunctionJSON(stopCount);
state.ResumeTiming();
- optional<CompositeFunction<float>> result = conversion::convert<style::CompositeFunction<float>, JSValue>(doc, error);
+ optional<CompositeFunction<float>> result = conversion::convertJSON<style::CompositeFunction<float>>(doc, error);
if (!result) {
state.SkipWithError(error.message.c_str());
}
@@ -54,7 +47,7 @@ static void Evaluate_CompositeFunction(benchmark::State& state) {
size_t stopCount = state.range(0);
auto doc = createFunctionJSON(stopCount);
conversion::Error error;
- optional<CompositeFunction<float>> function = conversion::convert<CompositeFunction<float>, JSValue>(doc, error);
+ optional<CompositeFunction<float>> function = conversion::convertJSON<CompositeFunction<float>>(doc, error);
if (!function) {
state.SkipWithError(error.message.c_str());
}
diff --git a/benchmark/function/source_function.benchmark.cpp b/benchmark/function/source_function.benchmark.cpp
index 14e729eee2..af361943e3 100644
--- a/benchmark/function/source_function.benchmark.cpp
+++ b/benchmark/function/source_function.benchmark.cpp
@@ -4,19 +4,14 @@
#include <mbgl/style/function/source_function.hpp>
-#include <mbgl/style/rapidjson_conversion.hpp>
#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion/function.hpp>
-#include <rapidjson/document.h>
-
-
using namespace mbgl;
using namespace mbgl::style;
-static rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> createFunctionJSON(size_t stopCount) {
- rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> doc;
-
+static std::string createFunctionJSON(size_t stopCount) {
std::string stops = "[";
for (size_t i = 0; i < stopCount; i++) {
std::string value = std::to_string(100.0f / stopCount * i);
@@ -24,9 +19,7 @@ static rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> cr
stops += "[" + value + ", " + value + "]";
}
stops += "]";
-
- doc.Parse<0>(R"({"type": "exponential", "base": 2, "stops": )" + stops + R"(, "property": "x"})");
- return doc;
+ return R"({"type": "exponential", "base": 2, "stops": )" + stops + R"(, "property": "x"})";
}
static void Parse_SourceFunction(benchmark::State& state) {
@@ -37,7 +30,7 @@ static void Parse_SourceFunction(benchmark::State& state) {
state.PauseTiming();
auto doc = createFunctionJSON(stopCount);
state.ResumeTiming();
- optional<SourceFunction<float>> result = conversion::convert<SourceFunction<float>, JSValue>(doc, error);
+ optional<SourceFunction<float>> result = conversion::convertJSON<SourceFunction<float>>(doc, error);
if (!result) {
state.SkipWithError(error.message.c_str());
}
@@ -49,7 +42,7 @@ static void Evaluate_SourceFunction(benchmark::State& state) {
size_t stopCount = state.range(0);
auto doc = createFunctionJSON(stopCount);
conversion::Error error;
- optional<SourceFunction<float>> function = conversion::convert<SourceFunction<float>, JSValue>(doc, error);
+ optional<SourceFunction<float>> function = conversion::convertJSON<SourceFunction<float>>(doc, error);
if (!function) {
state.SkipWithError(error.message.c_str());
}
diff --git a/benchmark/parse/filter.benchmark.cpp b/benchmark/parse/filter.benchmark.cpp
index d650cb72c9..4984668400 100644
--- a/benchmark/parse/filter.benchmark.cpp
+++ b/benchmark/parse/filter.benchmark.cpp
@@ -2,20 +2,16 @@
#include <mbgl/style/filter.hpp>
#include <mbgl/style/filter_evaluator.hpp>
-#include <mbgl/style/rapidjson_conversion.hpp>
#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion/filter.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
-#include <rapidjson/document.h>
-
using namespace mbgl;
style::Filter parse(const char* expression) {
- rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> doc;
- doc.Parse<0>(expression);
style::conversion::Error error;
- return *style::conversion::convert<style::Filter, JSValue>(doc, error);
+ return *style::conversion::convertJSON<style::Filter>(expression, error);
}
static void Parse_Filter(benchmark::State& state) {
diff --git a/bin/offline.cpp b/bin/offline.cpp
index ec2fb09096..5b403a6416 100644
--- a/bin/offline.cpp
+++ b/bin/offline.cpp
@@ -4,53 +4,63 @@
#include <mbgl/storage/default_file_source.hpp>
+#include <args/args.hxx>
+
#include <cstdlib>
#include <iostream>
#include <csignal>
#include <atomic>
+#include <sstream>
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunknown-pragmas"
-#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
-#pragma GCC diagnostic ignored "-Wshadow"
-#include <boost/program_options.hpp>
-#pragma GCC diagnostic pop
-
-namespace po = boost::program_options;
using namespace std::literals::chrono_literals;
int main(int argc, char *argv[]) {
- std::string style = mbgl::util::default_styles::streets.url;
- double north = 37.2, west = -122.8, south = 38.1, east = -121.7; // Bay area
- double minZoom = 0.0, maxZoom = 15.0, pixelRatio = 1.0;
- std::string output = "offline.db";
+ args::ArgumentParser argumentParser("Mapbox GL offline tool");
+ args::HelpFlag helpFlag(argumentParser, "help", "Display this help menu", {'h', "help"});
- const char* tokenEnv = getenv("MAPBOX_ACCESS_TOKEN");
- std::string token = tokenEnv ? tokenEnv : std::string();
-
- po::options_description desc("Allowed options");
- desc.add_options()
- ("style,s", po::value(&style)->value_name("URL"), "Map stylesheet")
- ("north", po::value(&north)->value_name("degrees")->default_value(north), "North latitude")
- ("west", po::value(&west)->value_name("degrees")->default_value(west), "West longitude")
- ("south", po::value(&south)->value_name("degrees")->default_value(south), "South latitude")
- ("east", po::value(&east)->value_name("degrees")->default_value(east), "East longitude")
- ("minZoom", po::value(&minZoom)->value_name("number")->default_value(minZoom), "Min zoom level")
- ("maxZoom", po::value(&maxZoom)->value_name("number")->default_value(maxZoom), "Max zoom level")
- ("pixelRatio", po::value(&pixelRatio)->value_name("number")->default_value(pixelRatio), "Pixel ratio")
- ("token,t", po::value(&token)->value_name("key")->default_value(token), "Mapbox access token")
- ("output,o", po::value(&output)->value_name("file")->default_value(output), "Output database file name")
- ;
+ args::ValueFlag<std::string> tokenValue(argumentParser, "key", "Mapbox access token", {'t', "token"});
+ args::ValueFlag<std::string> styleValue(argumentParser, "URL", "Map stylesheet", {'s', "style"});
+ args::ValueFlag<std::string> outputValue(argumentParser, "file", "Output database file name", {'o', "output"});
+
+ args::ValueFlag<double> northValue(argumentParser, "degrees", "North latitude", {"north"});
+ args::ValueFlag<double> westValue(argumentParser, "degrees", "West longitude", {"west"});
+ args::ValueFlag<double> southValue(argumentParser, "degrees", "South latitude", {"south"});
+ args::ValueFlag<double> eastValue(argumentParser, "degrees", "East longitude", {"east"});
+ args::ValueFlag<double> minZoomValue(argumentParser, "number", "Min zoom level", {"minZoom"});
+ args::ValueFlag<double> maxZoomValue(argumentParser, "number", "Max zoom level", {"maxZoom"});
+ args::ValueFlag<double> pixelRatioValue(argumentParser, "number", "Pixel ratio", {"pixelRatio"});
try {
- po::variables_map vm;
- po::store(po::parse_command_line(argc, argv, desc), vm);
- po::notify(vm);
- } catch(std::exception& e) {
- std::cout << "Error: " << e.what() << std::endl << desc;
+ argumentParser.ParseCLI(argc, argv);
+ } catch (args::Help) {
+ std::cout << argumentParser;
+ exit(0);
+ } catch (args::ParseError e) {
+ std::cerr << e.what() << std::endl;
+ std::cerr << argumentParser;
exit(1);
+ } catch (args::ValidationError e) {
+ std::cerr << e.what() << std::endl;
+ std::cerr << argumentParser;
+ exit(2);
}
+ std::string style = styleValue ? args::get(styleValue) : mbgl::util::default_styles::streets.url;
+
+ // Bay area
+ const double north = northValue ? args::get(northValue) : 37.2;
+ const double west = westValue ? args::get(westValue) : -122.8;
+ const double south = southValue ? args::get(southValue) : 38.1;
+ const double east = eastValue ? args::get(eastValue) : -121.7;
+
+ const double minZoom = minZoomValue ? args::get(minZoomValue) : 0.0;
+ const double maxZoom = maxZoomValue ? args::get(maxZoomValue) : 15.0;
+ const double pixelRatio = pixelRatioValue ? args::get(pixelRatioValue) : 1.0;
+ const std::string output = outputValue ? args::get(outputValue) : "offline.db";
+
+ const char* tokenEnv = getenv("MAPBOX_ACCESS_TOKEN");
+ const std::string token = tokenValue ? args::get(tokenValue) : (tokenEnv ? tokenEnv : std::string());
+
using namespace mbgl;
util::RunLoop loop;
diff --git a/bin/render.cpp b/bin/render.cpp
index 444921ff2b..6ceb32eb00 100644
--- a/bin/render.cpp
+++ b/bin/render.cpp
@@ -1,81 +1,82 @@
#include <mbgl/map/map.hpp>
#include <mbgl/util/image.hpp>
#include <mbgl/util/run_loop.hpp>
+#include <mbgl/util/default_styles.hpp>
#include <mbgl/gl/headless_frontend.hpp>
#include <mbgl/util/default_thread_pool.hpp>
#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/style/style.hpp>
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunknown-pragmas"
-#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
-#pragma GCC diagnostic ignored "-Wshadow"
-#include <boost/program_options.hpp>
-#pragma GCC diagnostic pop
-
-namespace po = boost::program_options;
+#include <args/args.hxx>
#include <cstdlib>
#include <iostream>
#include <fstream>
int main(int argc, char *argv[]) {
- std::string style_path;
- double lat = 0, lon = 0;
- double zoom = 0;
- double bearing = 0;
- double pitch = 0;
- double pixelRatio = 1;
-
- uint32_t width = 512;
- uint32_t height = 512;
- static std::string output = "out.png";
- std::string cache_file = "cache.sqlite";
- std::string asset_root = ".";
- std::string token;
- bool debug = false;
-
- po::options_description desc("Allowed options");
- desc.add_options()
- ("style,s", po::value(&style_path)->required()->value_name("json"), "Map stylesheet")
- ("lon,x", po::value(&lon)->value_name("degrees")->default_value(lon), "Longitude")
- ("lat,y", po::value(&lat)->value_name("degrees")->default_value(lat), "Latitude in degrees")
- ("zoom,z", po::value(&zoom)->value_name("number")->default_value(zoom), "Zoom level")
- ("bearing,b", po::value(&bearing)->value_name("degrees")->default_value(bearing), "Bearing")
- ("pitch,p", po::value(&pitch)->value_name("degrees")->default_value(pitch), "Pitch")
- ("width,w", po::value(&width)->value_name("pixels")->default_value(width), "Image width")
- ("height,h", po::value(&height)->value_name("pixels")->default_value(height), "Image height")
- ("ratio,r", po::value(&pixelRatio)->value_name("number")->default_value(pixelRatio), "Image scale factor")
- ("token,t", po::value(&token)->value_name("key")->default_value(token), "Mapbox access token")
- ("debug", po::bool_switch(&debug)->default_value(debug), "Debug mode")
- ("output,o", po::value(&output)->value_name("file")->default_value(output), "Output file name")
- ("cache,d", po::value(&cache_file)->value_name("file")->default_value(cache_file), "Cache database file name")
- ("assets,d", po::value(&asset_root)->value_name("file")->default_value(asset_root), "Directory to which asset:// URLs will resolve")
- ;
+ args::ArgumentParser argumentParser("Mapbox GL render tool");
+ args::HelpFlag helpFlag(argumentParser, "help", "Display this help menu", {"help"});
+
+ args::ValueFlag<std::string> tokenValue(argumentParser, "key", "Mapbox access token", {'t', "token"});
+ args::ValueFlag<std::string> styleValue(argumentParser, "URL", "Map stylesheet", {'s', "style"});
+ args::ValueFlag<std::string> outputValue(argumentParser, "file", "Output file name", {'o', "output"});
+ args::ValueFlag<std::string> cacheValue(argumentParser, "file", "Cache database file name", {'c', "cache"});
+ args::ValueFlag<std::string> assetsValue(argumentParser, "file", "Directory to which asset:// URLs will resolve", {'a', "assets"});
+
+ args::Flag debugFlag(argumentParser, "debug", "Debug mode", {"debug"});
+
+ args::ValueFlag<double> pixelRatioValue(argumentParser, "number", "Image scale factor", {'r', "ratio"});
+
+ args::ValueFlag<double> zoomValue(argumentParser, "number", "Zoom level", {'z', "zoom"});
+
+ args::ValueFlag<double> lonValue(argumentParser, "degrees", "Longitude", {'x', "lon"});
+ args::ValueFlag<double> latValue(argumentParser, "degrees", "Latitude", {'y', "lat"});
+ args::ValueFlag<double> bearingValue(argumentParser, "degrees", "Bearing", {'b', "bearing"});
+ args::ValueFlag<double> pitchValue(argumentParser, "degrees", "Pitch", {'p', "pitch"});
+ args::ValueFlag<uint32_t> widthValue(argumentParser, "pixels", "Image width", {'w', "width"});
+ args::ValueFlag<uint32_t> heightValue(argumentParser, "pixels", "Image height", {'h', "height"});
try {
- po::variables_map vm;
- po::store(po::parse_command_line(argc, argv, desc), vm);
- po::notify(vm);
- } catch(std::exception& e) {
- std::cout << "Error: " << e.what() << std::endl << desc;
+ argumentParser.ParseCLI(argc, argv);
+ } catch (args::Help) {
+ std::cout << argumentParser;
+ exit(0);
+ } catch (args::ParseError e) {
+ std::cerr << e.what() << std::endl;
+ std::cerr << argumentParser;
exit(1);
+ } catch (args::ValidationError e) {
+ std::cerr << e.what() << std::endl;
+ std::cerr << argumentParser;
+ exit(2);
}
+ std::string style = styleValue ? args::get(styleValue) : mbgl::util::default_styles::streets.url;
+ const double lat = latValue ? args::get(latValue) : 0;
+ const double lon = lonValue ? args::get(lonValue) : 0;
+ const double zoom = zoomValue ? args::get(zoomValue) : 0;
+ const double bearing = bearingValue ? args::get(bearingValue) : 0;
+ const double pitch = pitchValue ? args::get(pitchValue) : 0;
+ const double pixelRatio = pixelRatioValue ? args::get(pixelRatioValue) : 1;
+
+ const uint32_t width = widthValue ? args::get(widthValue) : 512;
+ const uint32_t height = heightValue ? args::get(heightValue) : 512;
+ const std::string output = outputValue ? args::get(outputValue) : "out.png";
+ const std::string cache_file = cacheValue ? args::get(cacheValue) : "cache.sqlite";
+ const std::string asset_root = assetsValue ? args::get(assetsValue) : ".";
+
+ // Try to load the token from the environment.
+ const char* tokenEnv = getenv("MAPBOX_ACCESS_TOKEN");
+ const std::string token = tokenValue ? args::get(tokenValue) : (tokenEnv ? tokenEnv : std::string());
+
+ const bool debug = debugFlag ? args::get(debugFlag) : false;
+
using namespace mbgl;
util::RunLoop loop;
DefaultFileSource fileSource(cache_file, asset_root);
- // Try to load the token from the environment.
- if (!token.size()) {
- const char *token_ptr = getenv("MAPBOX_ACCESS_TOKEN");
- if (token_ptr) {
- token = token_ptr;
- }
- }
-
// Set access token if present
if (token.size()) {
fileSource.setAccessToken(std::string(token));
@@ -83,13 +84,13 @@ int main(int argc, char *argv[]) {
ThreadPool threadPool(4);
HeadlessFrontend frontend({ width, height }, pixelRatio, fileSource, threadPool);
- Map map(frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, fileSource, threadPool, MapMode::Still);
+ Map map(frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, fileSource, threadPool, MapMode::Static);
- if (style_path.find("://") == std::string::npos) {
- style_path = std::string("file://") + style_path;
+ if (style.find("://") == std::string::npos) {
+ style = std::string("file://") + style;
}
- map.getStyle().loadURL(style_path);
+ map.getStyle().loadURL(style);
map.setLatLngZoom({ lat, lon }, zoom);
map.setBearing(bearing);
map.setPitch(pitch);
diff --git a/circle.yml b/circle.yml
index d76ab4a8ab..3378eb18ae 100644
--- a/circle.yml
+++ b/circle.yml
@@ -18,11 +18,11 @@ workflows:
filters:
tags:
only: /node-.*/
- - node6-clang39-debug:
+ - node6-gcc6-debug:
filters:
tags:
only: /node-.*/
- - linux-clang39-debug
+ - linux-clang-3.8-libcxx-debug
- linux-clang4-sanitize-address
- linux-clang4-sanitize-undefined
- linux-clang4-sanitize-thread
@@ -63,6 +63,15 @@ step-library:
paths: [ "node_modules", "/root/.ccache", "~/.ccache", "mason_packages/.binaries" ]
+ - &restore-gradle-cache
+ restore_cache:
+ keys:
+ - 'v3/{{ checksum "platform/android/dependencies.gradle" }}/{{ checksum "platform/android/build.gradle" }}/{{ checksum "platform/android/gradle/wrapper/gradle-wrapper.properties" }}'
+ - &save-gradle-cache
+ save_cache:
+ key: 'v3/{{ checksum "platform/android/dependencies.gradle" }}/{{ checksum "platform/android/build.gradle" }}/{{ checksum "platform/android/gradle/wrapper/gradle-wrapper.properties" }}'
+ paths: [ "/root/.gradle" ]
+
- &reset-ccache-stats
run:
name: Clear ccache statistics
@@ -207,7 +216,7 @@ jobs:
# ------------------------------------------------------------------------------
clang-tidy:
docker:
- - image: mbgl/ci:r4-linux-clang-3.9
+ - image: mbgl/7d2403f42e:linux-clang-3.9
working_directory: /src
environment:
LIBSYSCONFCPUS: 4
@@ -234,7 +243,7 @@ jobs:
# ------------------------------------------------------------------------------
android-debug-arm-v7:
docker:
- - image: mbgl/ci@sha256:c34e221294d81da80918d3e9a9df5de795b067e88f86d7c9a5e262763332536e
+ - image: mbgl/7d2403f42e:android-ndk-r16b
resource_class: large
working_directory: /src
environment:
@@ -246,6 +255,7 @@ jobs:
- checkout
- *generate-cache-key
- *restore-cache
+ - *restore-gradle-cache
- *reset-ccache-stats
- run:
name: Check code style
@@ -269,6 +279,7 @@ jobs:
make android-ui-test-arm-v7
- *show-ccache-stats
- *save-cache
+ - *save-gradle-cache
- run:
name: Log in to Google Cloud Platform
shell: /bin/bash -euo pipefail
@@ -283,22 +294,22 @@ jobs:
command: |
gcloud firebase test android models list
(gcloud firebase test android run --type instrumentation \
- --app platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk/MapboxGLAndroidSDKTestApp-debug.apk \
- --test platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk/MapboxGLAndroidSDKTestApp-debug-androidTest.apk \
+ --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 shamu --os-version-ids 22 --locales en --orientations portrait --timeout 20m \
2>&1 | tee firebase.log) || EXIT_CODE=$?
FIREBASE_TEST_BUCKET=$(sed -n 's|^.*\[https://console.developers.google.com/storage/browser/\([^]]*\).*|gs://\1|p' firebase.log)
echo "Downloading from: ${FIREBASE_TEST_BUCKET}"
- gsutil -m cp -n -R -Z "$FIREBASE_TEST_BUCKET*" platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk
+ gsutil -m cp -n -R -Z "$FIREBASE_TEST_BUCKET*" platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk/debug
echo "Try running ndk-stack on downloaded logcat to symbolicate the stacktraces:"
- find platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk -type f -name "logcat" -print0 | \
+ find platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk/debug -type f -name "logcat" -print0 | \
xargs -0 -I '{}' ${ANDROID_NDK_HOME}/ndk-stack -sym build/android-arm-v7/Debug -dump {}
exit ${EXIT_CODE:-0}
- store_artifacts:
- path: platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk
+ path: platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk/debug
destination: .
- store_artifacts:
path: platform/android/MapboxGLAndroidSDK/build/reports/lint-results.html
@@ -316,7 +327,7 @@ jobs:
# ------------------------------------------------------------------------------
android-release-all:
docker:
- - image: mbgl/ci@sha256:c34e221294d81da80918d3e9a9df5de795b067e88f86d7c9a5e262763332536e
+ - image: mbgl/7d2403f42e:android-ndk-r16b
resource_class: large
working_directory: /src
environment:
@@ -328,6 +339,7 @@ jobs:
- checkout
- *generate-cache-key
- *restore-cache
+ - *restore-gradle-cache
- *reset-ccache-stats
- run:
name: Generate Maven credentials
@@ -344,8 +356,9 @@ jobs:
command: make apackage
- *show-ccache-stats
- *save-cache
+ - *save-gradle-cache
- store_artifacts:
- path: platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk
+ path: platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk/release
destination: .
- deploy:
name: Show statistics
@@ -355,13 +368,13 @@ jobs:
- deploy:
name: Publish to Maven
command: |
- if [ "${CIRCLE_BRANCH}" == "release-agua" ]; then make run-android-upload-archives ; fi
+ if [ "${CIRCLE_BRANCH}" == "master" ]; then make run-android-upload-archives ; fi
# ------------------------------------------------------------------------------
node4-clang39-release:
docker:
- - image: mbgl/ci:r4-linux-clang-3.9-node-4
+ - image: mbgl/7d2403f42e:linux-clang-3.9-node-4
working_directory: /src
environment:
LIBSYSCONFCPUS: 4
@@ -384,7 +397,7 @@ jobs:
# ------------------------------------------------------------------------------
node6-clang39-release:
docker:
- - image: mbgl/ci:r4-linux-clang-3.9
+ - image: mbgl/7d2403f42e:linux-clang-3.9
working_directory: /src
environment:
LIBSYSCONFCPUS: 4
@@ -405,16 +418,16 @@ jobs:
- *upload-render-tests
# ------------------------------------------------------------------------------
- node6-clang39-debug:
+ node6-gcc6-debug:
docker:
- - image: mbgl/ci:r4-linux-clang-3.9
+ - image: mbgl/7d2403f42e:linux-gcc-6
+ resource_class: large
working_directory: /src
environment:
LIBSYSCONFCPUS: 4
JOBS: 4
BUILDTYPE: Debug
WITH_EGL: 1
- WITH_CXX11ABI: 0
steps:
- checkout
- *generate-cache-key
@@ -428,31 +441,29 @@ jobs:
- *upload-render-tests-recycle-map
# ------------------------------------------------------------------------------
- linux-clang39-debug:
+ linux-clang-3.8-libcxx-debug:
docker:
- - image: mbgl/ci:r4-linux-clang-3.9
+ - image: mbgl/7d2403f42e:linux-clang-3.8-libcxx
working_directory: /src
environment:
LIBSYSCONFCPUS: 4
JOBS: 4
BUILDTYPE: Debug
WITH_EGL: 1
+ WITH_CXX11ABI: 1
steps:
- checkout
- *generate-cache-key
- *restore-cache
- *reset-ccache-stats
- *build-linux
- - *build-benchmark
- - *build-test
- *show-ccache-stats
- *save-cache
- - *run-unit-tests
# ------------------------------------------------------------------------------
linux-clang4-sanitize-address:
docker:
- - image: mbgl/ci:r4-linux-clang-4
+ - image: mbgl/7d2403f42e:linux-clang-4
working_directory: /src
environment:
LIBSYSCONFCPUS: 4
@@ -482,7 +493,7 @@ jobs:
# ------------------------------------------------------------------------------
linux-clang4-sanitize-undefined:
docker:
- - image: mbgl/ci:r4-linux-clang-4
+ - image: mbgl/7d2403f42e:linux-clang-4
working_directory: /src
environment:
LIBSYSCONFCPUS: 4
@@ -512,7 +523,7 @@ jobs:
# ------------------------------------------------------------------------------
linux-clang4-sanitize-thread:
docker:
- - image: mbgl/ci:r4-linux-clang-4
+ - image: mbgl/7d2403f42e:linux-clang-4
working_directory: /src
environment:
LIBSYSCONFCPUS: 4
@@ -542,12 +553,12 @@ jobs:
# ------------------------------------------------------------------------------
linux-gcc4.9-debug:
docker:
- - image: mbgl/ci:r4-linux-gcc-4.9
+ - image: mbgl/7d2403f42e:linux-gcc-4.9
resource_class: large
working_directory: /src
environment:
LIBSYSCONFCPUS: 4
- JOBS: 2
+ JOBS: 4
BUILDTYPE: Debug
WITH_EGL: 1
WITH_CXX11ABI: 0
@@ -567,12 +578,12 @@ jobs:
# ------------------------------------------------------------------------------
linux-gcc5-debug-coverage:
docker:
- - image: mbgl/ci:r4-linux-gcc-5
+ - image: mbgl/7d2403f42e:linux-gcc-5
resource_class: large
working_directory: /src
environment:
LIBSYSCONFCPUS: 4
- JOBS: 2
+ JOBS: 4
BUILDTYPE: Debug
WITH_EGL: 1
WITH_COVERAGE: 1
@@ -595,12 +606,12 @@ jobs:
# ------------------------------------------------------------------------------
linux-gcc5-release-qt4:
docker:
- - image: mbgl/ci:r4-linux-gcc-5-qt-4
+ - image: mbgl/7d2403f42e:linux-gcc-5-qt-4
resource_class: large
working_directory: /src
environment:
LIBSYSCONFCPUS: 4
- JOBS: 2 # OOM, causing the compiler to crash.
+ JOBS: 4
BUILDTYPE: Release
GTEST_OUTPUT: xml
LD_PRELOAD: /usr/lib/x86_64-linux-gnu/libjemalloc.so
@@ -623,12 +634,12 @@ jobs:
# ------------------------------------------------------------------------------
linux-gcc5-release-qt5:
docker:
- - image: mbgl/ci:r4-linux-gcc-5-qt-5
+ - image: mbgl/7d2403f42e:linux-gcc-5-qt-5.9
resource_class: large
working_directory: /src
environment:
LIBSYSCONFCPUS: 4
- JOBS: 2 # OOM, causing the compiler to crash.
+ JOBS: 4
BUILDTYPE: Release
WITH_QT_I18N: 1
steps:
@@ -649,7 +660,7 @@ jobs:
JOBS: 1 # https://github.com/mapbox/mapbox-gl-native/issues/9108
command: |
xvfb-run --server-args="-screen 0 1024x768x24" \
- scripts/valgrind.sh build/qt-linux-x86_64/Release/mbgl-test --gtest_filter=-*.Load --gtest_filter=-Memory.Vector
+ build/qt-linux-x86_64/Release/mbgl-test --gtest_filter=-*.Load --gtest_filter=-Memory.Vector
# ------------------------------------------------------------------------------
ios-debug:
@@ -666,6 +677,9 @@ jobs:
- *reset-ccache-stats
- *build-ios-test
- *check-public-symbols
+ - run:
+ name: Lint plist files
+ command: make ios-lint
- *show-ccache-stats
- *save-cache
@@ -722,6 +736,9 @@ jobs:
- *reset-ccache-stats
- *build-macos-test
- *check-public-symbols
+ - run:
+ name: Lint plist files
+ command: make macos-lint
- *show-ccache-stats
- *save-cache
- store_artifacts:
diff --git a/cmake/benchmark.cmake b/cmake/benchmark.cmake
index 87351e97b1..ea5b3dfa7a 100644
--- a/cmake/benchmark.cmake
+++ b/cmake/benchmark.cmake
@@ -2,10 +2,6 @@ add_executable(mbgl-benchmark
${MBGL_BENCHMARK_FILES}
)
-target_compile_options(mbgl-benchmark
- PRIVATE -fvisibility-inlines-hidden
-)
-
target_include_directories(mbgl-benchmark
PRIVATE src
PRIVATE benchmark/include
@@ -19,6 +15,7 @@ target_link_libraries(mbgl-benchmark
target_add_mason_package(mbgl-benchmark PRIVATE boost)
target_add_mason_package(mbgl-benchmark PRIVATE benchmark)
+target_add_mason_package(mbgl-benchmark PRIVATE geojson)
target_add_mason_package(mbgl-benchmark PRIVATE rapidjson)
target_add_mason_package(mbgl-benchmark PRIVATE protozero)
target_add_mason_package(mbgl-benchmark PRIVATE vector-tile)
diff --git a/cmake/core-files.cmake b/cmake/core-files.cmake
index 33b3072f3a..15812da42d 100644
--- a/cmake/core-files.cmake
+++ b/cmake/core-files.cmake
@@ -156,6 +156,7 @@ set(MBGL_CORE_FILES
# renderer
include/mbgl/renderer/backend_scope.hpp
+ include/mbgl/renderer/mode.hpp
include/mbgl/renderer/query.hpp
include/mbgl/renderer/renderer.hpp
include/mbgl/renderer/renderer_backend.hpp
@@ -167,8 +168,6 @@ set(MBGL_CORE_FILES
src/mbgl/renderer/cross_faded_property_evaluator.cpp
src/mbgl/renderer/cross_faded_property_evaluator.hpp
src/mbgl/renderer/data_driven_property_evaluator.hpp
- src/mbgl/renderer/frame_history.cpp
- src/mbgl/renderer/frame_history.hpp
src/mbgl/renderer/group_by_layout.cpp
src/mbgl/renderer/group_by_layout.hpp
src/mbgl/renderer/image_atlas.cpp
@@ -243,6 +242,8 @@ set(MBGL_CORE_FILES
src/mbgl/renderer/layers/render_symbol_layer.hpp
# renderer/sources
+ src/mbgl/renderer/sources/render_custom_geometry_source.cpp
+ src/mbgl/renderer/sources/render_custom_geometry_source.hpp
src/mbgl/renderer/sources/render_geojson_source.cpp
src/mbgl/renderer/sources/render_geojson_source.hpp
src/mbgl/renderer/sources/render_image_source.cpp
@@ -257,6 +258,8 @@ set(MBGL_CORE_FILES
src/mbgl/shaders/circle.hpp
src/mbgl/shaders/collision_box.cpp
src/mbgl/shaders/collision_box.hpp
+ src/mbgl/shaders/collision_circle.cpp
+ src/mbgl/shaders/collision_circle.hpp
src/mbgl/shaders/debug.cpp
src/mbgl/shaders/debug.hpp
src/mbgl/shaders/extrusion_texture.cpp
@@ -333,6 +336,8 @@ set(MBGL_CORE_FILES
include/mbgl/style/types.hpp
include/mbgl/style/undefined.hpp
src/mbgl/style/collection.hpp
+ src/mbgl/style/custom_tile_loader.cpp
+ src/mbgl/style/custom_tile_loader.hpp
src/mbgl/style/image.cpp
src/mbgl/style/image_impl.cpp
src/mbgl/style/image_impl.hpp
@@ -363,23 +368,83 @@ set(MBGL_CORE_FILES
# style/conversion
include/mbgl/style/conversion/constant.hpp
include/mbgl/style/conversion/coordinate.hpp
+ include/mbgl/style/conversion/custom_geometry_source_options.hpp
include/mbgl/style/conversion/data_driven_property_value.hpp
+ include/mbgl/style/conversion/expression.hpp
include/mbgl/style/conversion/filter.hpp
include/mbgl/style/conversion/function.hpp
include/mbgl/style/conversion/geojson.hpp
include/mbgl/style/conversion/geojson_options.hpp
+ include/mbgl/style/conversion/get_json_type.hpp
include/mbgl/style/conversion/layer.hpp
include/mbgl/style/conversion/light.hpp
- include/mbgl/style/conversion/make_property_setters.hpp
include/mbgl/style/conversion/position.hpp
- include/mbgl/style/conversion/property_setter.hpp
include/mbgl/style/conversion/property_value.hpp
include/mbgl/style/conversion/source.hpp
include/mbgl/style/conversion/tileset.hpp
include/mbgl/style/conversion/transition_options.hpp
+ src/mbgl/style/conversion/constant.cpp
+ src/mbgl/style/conversion/coordinate.cpp
+ src/mbgl/style/conversion/filter.cpp
src/mbgl/style/conversion/geojson.cpp
+ src/mbgl/style/conversion/geojson_options.cpp
+ src/mbgl/style/conversion/get_json_type.cpp
src/mbgl/style/conversion/json.hpp
+ src/mbgl/style/conversion/layer.cpp
+ src/mbgl/style/conversion/light.cpp
+ src/mbgl/style/conversion/make_property_setters.hpp
+ src/mbgl/style/conversion/position.cpp
+ src/mbgl/style/conversion/property_setter.hpp
+ src/mbgl/style/conversion/source.cpp
src/mbgl/style/conversion/stringify.hpp
+ src/mbgl/style/conversion/tileset.cpp
+ src/mbgl/style/conversion/transition_options.cpp
+
+ # style/expression
+ include/mbgl/style/expression/array_assertion.hpp
+ include/mbgl/style/expression/assertion.hpp
+ include/mbgl/style/expression/at.hpp
+ include/mbgl/style/expression/boolean_operator.hpp
+ include/mbgl/style/expression/case.hpp
+ include/mbgl/style/expression/check_subtype.hpp
+ include/mbgl/style/expression/coalesce.hpp
+ include/mbgl/style/expression/coercion.hpp
+ include/mbgl/style/expression/compound_expression.hpp
+ include/mbgl/style/expression/expression.hpp
+ include/mbgl/style/expression/find_zoom_curve.hpp
+ include/mbgl/style/expression/get_covering_stops.hpp
+ include/mbgl/style/expression/interpolate.hpp
+ include/mbgl/style/expression/is_constant.hpp
+ include/mbgl/style/expression/is_expression.hpp
+ include/mbgl/style/expression/let.hpp
+ include/mbgl/style/expression/literal.hpp
+ include/mbgl/style/expression/match.hpp
+ include/mbgl/style/expression/parsing_context.hpp
+ include/mbgl/style/expression/step.hpp
+ include/mbgl/style/expression/type.hpp
+ include/mbgl/style/expression/value.hpp
+ src/mbgl/style/expression/array_assertion.cpp
+ src/mbgl/style/expression/assertion.cpp
+ src/mbgl/style/expression/at.cpp
+ src/mbgl/style/expression/boolean_operator.cpp
+ src/mbgl/style/expression/case.cpp
+ src/mbgl/style/expression/check_subtype.cpp
+ src/mbgl/style/expression/coalesce.cpp
+ src/mbgl/style/expression/coercion.cpp
+ src/mbgl/style/expression/compound_expression.cpp
+ src/mbgl/style/expression/find_zoom_curve.cpp
+ src/mbgl/style/expression/get_covering_stops.cpp
+ src/mbgl/style/expression/interpolate.cpp
+ src/mbgl/style/expression/is_constant.cpp
+ src/mbgl/style/expression/is_expression.cpp
+ src/mbgl/style/expression/let.cpp
+ src/mbgl/style/expression/literal.cpp
+ src/mbgl/style/expression/match.cpp
+ src/mbgl/style/expression/parsing_context.cpp
+ src/mbgl/style/expression/step.cpp
+ src/mbgl/style/expression/util.cpp
+ src/mbgl/style/expression/util.hpp
+ src/mbgl/style/expression/value.cpp
# style/function
include/mbgl/style/function/camera_function.hpp
@@ -388,11 +453,13 @@ set(MBGL_CORE_FILES
include/mbgl/style/function/composite_exponential_stops.hpp
include/mbgl/style/function/composite_function.hpp
include/mbgl/style/function/composite_interval_stops.hpp
+ include/mbgl/style/function/convert.hpp
include/mbgl/style/function/exponential_stops.hpp
include/mbgl/style/function/identity_stops.hpp
include/mbgl/style/function/interval_stops.hpp
include/mbgl/style/function/source_function.hpp
src/mbgl/style/function/categorical_stops.cpp
+ src/mbgl/style/function/expression.cpp
src/mbgl/style/function/identity_stops.cpp
# style/layers
@@ -444,10 +511,14 @@ set(MBGL_CORE_FILES
src/mbgl/style/layers/symbol_layer_properties.hpp
# style/sources
+ include/mbgl/style/sources/custom_geometry_source.hpp
include/mbgl/style/sources/geojson_source.hpp
include/mbgl/style/sources/image_source.hpp
include/mbgl/style/sources/raster_source.hpp
include/mbgl/style/sources/vector_source.hpp
+ src/mbgl/style/sources/custom_geometry_source.cpp
+ src/mbgl/style/sources/custom_geometry_source_impl.cpp
+ src/mbgl/style/sources/custom_geometry_source_impl.hpp
src/mbgl/style/sources/geojson_source.cpp
src/mbgl/style/sources/geojson_source_impl.cpp
src/mbgl/style/sources/geojson_source_impl.hpp
@@ -467,8 +538,10 @@ set(MBGL_CORE_FILES
src/mbgl/text/check_max_angle.hpp
src/mbgl/text/collision_feature.cpp
src/mbgl/text/collision_feature.hpp
- src/mbgl/text/collision_tile.cpp
- src/mbgl/text/collision_tile.hpp
+ src/mbgl/text/collision_index.cpp
+ src/mbgl/text/collision_index.hpp
+ src/mbgl/text/cross_tile_symbol_index.cpp
+ src/mbgl/text/cross_tile_symbol_index.hpp
src/mbgl/text/get_anchors.cpp
src/mbgl/text/get_anchors.hpp
src/mbgl/text/glyph.cpp
@@ -482,7 +555,8 @@ set(MBGL_CORE_FILES
src/mbgl/text/glyph_pbf.hpp
src/mbgl/text/glyph_range.hpp
src/mbgl/text/local_glyph_rasterizer.hpp
- src/mbgl/text/placement_config.hpp
+ src/mbgl/text/placement.cpp
+ src/mbgl/text/placement.hpp
src/mbgl/text/quads.cpp
src/mbgl/text/quads.hpp
src/mbgl/text/shaping.cpp
@@ -491,6 +565,8 @@ set(MBGL_CORE_FILES
# tile
include/mbgl/tile/tile_id.hpp
include/mbgl/tile/tile_necessity.hpp
+ src/mbgl/tile/custom_geometry_tile.cpp
+ src/mbgl/tile/custom_geometry_tile.hpp
src/mbgl/tile/geojson_tile.cpp
src/mbgl/tile/geojson_tile.hpp
src/mbgl/tile/geojson_tile_data.hpp
@@ -519,7 +595,6 @@ set(MBGL_CORE_FILES
src/mbgl/tile/vector_tile_data.hpp
# util
- include/mbgl/util/any.hpp
include/mbgl/util/async_request.hpp
include/mbgl/util/async_task.hpp
include/mbgl/util/char_array_buffer.hpp
@@ -556,6 +631,7 @@ set(MBGL_CORE_FILES
include/mbgl/util/timer.hpp
include/mbgl/util/traits.hpp
include/mbgl/util/type_list.hpp
+ include/mbgl/util/unique_any.hpp
include/mbgl/util/unitbezier.hpp
include/mbgl/util/util.hpp
include/mbgl/util/variant.hpp
diff --git a/cmake/core.cmake b/cmake/core.cmake
index c4e711f558..43ec141b78 100644
--- a/cmake/core.cmake
+++ b/cmake/core.cmake
@@ -2,11 +2,6 @@ add_library(mbgl-core STATIC
${MBGL_CORE_FILES}
)
-target_compile_options(mbgl-core
- PRIVATE -fPIC
- PRIVATE -fvisibility-inlines-hidden
-)
-
target_include_directories(mbgl-core
PUBLIC include
PRIVATE src
@@ -14,7 +9,6 @@ target_include_directories(mbgl-core
target_add_mason_package(mbgl-core PUBLIC geometry)
target_add_mason_package(mbgl-core PUBLIC variant)
-target_add_mason_package(mbgl-core PUBLIC any)
target_add_mason_package(mbgl-core PRIVATE unique_resource)
target_add_mason_package(mbgl-core PRIVATE rapidjson)
target_add_mason_package(mbgl-core PRIVATE boost)
diff --git a/cmake/filesource.cmake b/cmake/filesource.cmake
index bb1b4e8c05..861a845d6e 100644
--- a/cmake/filesource.cmake
+++ b/cmake/filesource.cmake
@@ -26,18 +26,10 @@ add_library(mbgl-filesource STATIC
target_add_mason_package(mbgl-filesource PUBLIC geometry)
target_add_mason_package(mbgl-filesource PUBLIC variant)
-target_add_mason_package(mbgl-filesource PUBLIC any)
target_add_mason_package(mbgl-filesource PRIVATE rapidjson)
target_add_mason_package(mbgl-filesource PRIVATE boost)
target_add_mason_package(mbgl-filesource PRIVATE geojson)
-set_xcode_property(mbgl-filesource GCC_SYMBOLS_PRIVATE_EXTERN YES)
-
-target_compile_options(mbgl-filesource
- PRIVATE -fPIC
- PRIVATE -fvisibility-inlines-hidden
-)
-
target_include_directories(mbgl-filesource
PRIVATE include
PRIVATE src
diff --git a/cmake/glfw.cmake b/cmake/glfw.cmake
index 29d8d2ba94..2b2cb47ecb 100644
--- a/cmake/glfw.cmake
+++ b/cmake/glfw.cmake
@@ -12,10 +12,6 @@ target_sources(mbgl-glfw
PRIVATE platform/default/mbgl/util/default_styles.hpp
)
-target_compile_options(mbgl-glfw
- PRIVATE -fvisibility-inlines-hidden
-)
-
target_include_directories(mbgl-glfw
PRIVATE platform/default
)
@@ -29,6 +25,7 @@ target_add_mason_package(mbgl-glfw PRIVATE geojson)
target_add_mason_package(mbgl-glfw PRIVATE geometry)
target_add_mason_package(mbgl-glfw PRIVATE glfw)
target_add_mason_package(mbgl-glfw PRIVATE variant)
+target_add_mason_package(mbgl-glfw PRIVATE args)
mbgl_platform_glfw()
diff --git a/cmake/loop-darwin.cmake b/cmake/loop-darwin.cmake
index 46511d2548..692aecb8a2 100644
--- a/cmake/loop-darwin.cmake
+++ b/cmake/loop-darwin.cmake
@@ -4,13 +4,6 @@ add_library(mbgl-loop-darwin STATIC
platform/darwin/src/timer.cpp
)
-set_xcode_property(mbgl-loop-darwin GCC_SYMBOLS_PRIVATE_EXTERN YES)
-
-target_compile_options(mbgl-loop-darwin
- PRIVATE -fPIC
- PRIVATE -fvisibility-inlines-hidden
-)
-
target_include_directories(mbgl-loop-darwin
PRIVATE include
PRIVATE src
diff --git a/cmake/loop-uv.cmake b/cmake/loop-uv.cmake
index 8840040963..f4e7ced00e 100644
--- a/cmake/loop-uv.cmake
+++ b/cmake/loop-uv.cmake
@@ -4,11 +4,6 @@ add_library(mbgl-loop-uv STATIC
platform/default/timer.cpp
)
-target_compile_options(mbgl-loop-uv
- PRIVATE -fPIC
- PRIVATE -fvisibility-inlines-hidden
-)
-
target_include_directories(mbgl-loop-uv
PRIVATE include
PRIVATE src
diff --git a/cmake/mbgl.cmake b/cmake/mbgl.cmake
index d853950c0d..0393ff366e 100644
--- a/cmake/mbgl.cmake
+++ b/cmake/mbgl.cmake
@@ -143,11 +143,14 @@ macro(initialize_xcode_cxx_build_settings target)
# -Wshadow
set_xcode_property(${target} GCC_WARN_SHADOW YES)
- # -Wno-unknown-pragmas
- set_xcode_property(${target} GCC_WARN_UNKNOWN_PRAGMAS YES)
-
# -Wnon-virtual-dtor
set_xcode_property(${target} GCC_WARN_NON_VIRTUAL_DESTRUCTOR YES)
+
+ # -Wnon-literal-conversion
+ set_xcode_property(${target} CLANG_WARN_NON_LITERAL_NULL_CONVERSION YES)
+
+ # -Wrange-loop-analysis
+ set_xcode_property(${target} CLANG_WARN_RANGE_LOOP_ANALYSIS YES)
endmacro(initialize_xcode_cxx_build_settings)
# CMake 3.1 does not have this yet.
diff --git a/cmake/node.cmake b/cmake/node.cmake
index c256b13f93..0c2f556b7d 100644
--- a/cmake/node.cmake
+++ b/cmake/node.cmake
@@ -13,6 +13,7 @@ set_target_properties("mbgl-node" PROPERTIES CXX_STANDARD 14)
target_sources(mbgl-node
PRIVATE platform/node/src/node_logging.hpp
PRIVATE platform/node/src/node_logging.cpp
+ PRIVATE platform/node/src/node_conversion.hpp
PRIVATE platform/node/src/node_map.hpp
PRIVATE platform/node/src/node_map.cpp
PRIVATE platform/node/src/node_request.hpp
@@ -21,14 +22,11 @@ target_sources(mbgl-node
PRIVATE platform/node/src/node_feature.cpp
PRIVATE platform/node/src/node_thread_pool.hpp
PRIVATE platform/node/src/node_thread_pool.cpp
+ PRIVATE platform/node/src/node_expression.hpp
+ PRIVATE platform/node/src/node_expression.cpp
PRIVATE platform/node/src/util/async_queue.hpp
)
-target_compile_options(mbgl-node
- PRIVATE -fPIC
- PRIVATE -fvisibility-inlines-hidden
-)
-
target_include_directories(mbgl-node
PRIVATE platform/default
)
@@ -93,6 +91,17 @@ xcode_create_scheme(
xcode_create_scheme(
TARGET mbgl-node
TYPE node
+ NAME "node expression tests"
+ ARGS
+ "platform/node/test/expression.test.js"
+ OPTIONAL_ARGS
+ "group"
+ "test"
+)
+
+xcode_create_scheme(
+ TARGET mbgl-node
+ TYPE node
NAME "node-benchmark"
ARGS
"platform/node/test/benchmark.js"
diff --git a/cmake/offline.cmake b/cmake/offline.cmake
index c9a3349792..13b6c3fe70 100644
--- a/cmake/offline.cmake
+++ b/cmake/offline.cmake
@@ -6,10 +6,6 @@ target_sources(mbgl-offline
PRIVATE platform/default/mbgl/util/default_styles.hpp
)
-target_compile_options(mbgl-offline
- PRIVATE -fvisibility-inlines-hidden
-)
-
target_include_directories(mbgl-offline
PRIVATE platform/default
)
@@ -19,7 +15,7 @@ target_link_libraries(mbgl-offline
)
target_add_mason_package(mbgl-offline PRIVATE boost)
-target_add_mason_package(mbgl-offline PRIVATE boost_libprogram_options)
+target_add_mason_package(mbgl-offline PRIVATE args)
mbgl_platform_offline()
diff --git a/cmake/render.cmake b/cmake/render.cmake
index f69aed16c0..c6e7d9dd59 100644
--- a/cmake/render.cmake
+++ b/cmake/render.cmake
@@ -2,10 +2,6 @@ add_executable(mbgl-render
bin/render.cpp
)
-target_compile_options(mbgl-render
- PRIVATE -fvisibility-inlines-hidden
-)
-
target_include_directories(mbgl-render
PRIVATE platform/default
)
@@ -15,7 +11,8 @@ target_link_libraries(mbgl-render
)
target_add_mason_package(mbgl-render PRIVATE boost)
-target_add_mason_package(mbgl-render PRIVATE boost_libprogram_options)
+target_add_mason_package(mbgl-render PRIVATE geojson)
+target_add_mason_package(mbgl-render PRIVATE args)
mbgl_platform_render()
diff --git a/cmake/test-files.cmake b/cmake/test-files.cmake
index 027c34f31e..55420ff2a8 100644
--- a/cmake/test-files.cmake
+++ b/cmake/test-files.cmake
@@ -15,6 +15,7 @@ set(MBGL_TEST_FILES
# api
test/api/annotations.test.cpp
test/api/api_misuse.test.cpp
+ test/api/custom_geometry_source.test.cpp
test/api/custom_layer.test.cpp
test/api/query.test.cpp
test/api/recycle_map.cpp
@@ -22,6 +23,7 @@ set(MBGL_TEST_FILES
# gl
test/gl/bucket.test.cpp
+ test/gl/context.test.cpp
test/gl/object.test.cpp
# include/mbgl
@@ -51,7 +53,6 @@ set(MBGL_TEST_FILES
test/sprite/sprite_parser.test.cpp
# src/mbgl/test
- test/src/mbgl/test/conversion_stubs.hpp
test/src/mbgl/test/fake_file_source.hpp
test/src/mbgl/test/fixture_log_observer.cpp
test/src/mbgl/test/fixture_log_observer.hpp
@@ -88,6 +89,10 @@ set(MBGL_TEST_FILES
test/style/conversion/light.test.cpp
test/style/conversion/stringify.test.cpp
+ # style/expression
+ test/style/expression/expression.test.cpp
+ test/style/expression/util.test.cpp
+
# style
test/style/filter.test.cpp
@@ -107,12 +112,14 @@ set(MBGL_TEST_FILES
test/style/style_parser.test.cpp
# text
- test/text/glyph_loader.test.cpp
+ test/text/cross_tile_symbol_index.test.cpp
+ test/text/local_glyph_rasterizer.test.cpp
+ test/text/glyph_manager.test.cpp
test/text/glyph_pbf.test.cpp
test/text/quads.test.cpp
# tile
- test/tile/annotation_tile.test.cpp
+ test/tile/custom_geometry_tile.test.cpp
test/tile/geojson_tile.test.cpp
test/tile/geometry_tile_data.test.cpp
test/tile/raster_tile.test.cpp
@@ -124,6 +131,7 @@ set(MBGL_TEST_FILES
test/util/async_task.test.cpp
test/util/dtoa.test.cpp
test/util/geo.test.cpp
+ test/util/grid_index.test.cpp
test/util/http_timeout.test.cpp
test/util/image.test.cpp
test/util/mapbox.test.cpp
@@ -140,5 +148,6 @@ set(MBGL_TEST_FILES
test/util/tile_cover.test.cpp
test/util/timer.test.cpp
test/util/token.test.cpp
+ test/util/unique_any.test.cpp
test/util/url.test.cpp
)
diff --git a/cmake/test.cmake b/cmake/test.cmake
index c821d53316..183263c5a9 100644
--- a/cmake/test.cmake
+++ b/cmake/test.cmake
@@ -8,10 +8,6 @@ else()
)
endif()
-target_compile_options(mbgl-test
- PRIVATE -fvisibility-inlines-hidden
-)
-
set_source_files_properties(test/src/mbgl/test/util.cpp PROPERTIES COMPILE_FLAGS -DNODE_EXECUTABLE="${NodeJS_EXECUTABLE}")
target_include_directories(mbgl-test
@@ -27,7 +23,6 @@ target_link_libraries(mbgl-test
target_add_mason_package(mbgl-test PRIVATE geometry)
target_add_mason_package(mbgl-test PRIVATE variant)
-target_add_mason_package(mbgl-test PRIVATE any)
target_add_mason_package(mbgl-test PRIVATE unique_resource)
target_add_mason_package(mbgl-test PRIVATE rapidjson)
target_add_mason_package(mbgl-test PRIVATE gtest)
diff --git a/deps/ninja/ninja-linux b/deps/ninja/ninja-linux
deleted file mode 100755
index e4a6202d99..0000000000
--- a/deps/ninja/ninja-linux
+++ /dev/null
Binary files differ
diff --git a/deps/ninja/ninja-macos b/deps/ninja/ninja-macos
deleted file mode 100755
index 64fcacc550..0000000000
--- a/deps/ninja/ninja-macos
+++ /dev/null
Binary files differ
diff --git a/deps/run_gyp b/deps/run_gyp
deleted file mode 100755
index f25d50a5dd..0000000000
--- a/deps/run_gyp
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env python
-import sys
-import os.path
-sys.path.insert(1, os.path.join(os.path.dirname(sys.argv[0]), 'gyp', 'pylib'))
-import gyp
-
-if __name__ == '__main__':
- sys.exit(gyp.script_main())
diff --git a/docker/Dockerfile b/docker/Dockerfile
deleted file mode 100644
index 64f1ca3c87..0000000000
--- a/docker/Dockerfile
+++ /dev/null
@@ -1,16 +0,0 @@
-FROM ubuntu:12.04
-
-ENV DEBIAN_FRONTEND noninteractive
-
-# Add other APT sources and keys
-ADD *.list /etc/apt/sources.list.d/
-ADD *.gpg.key /tmp/
-RUN find /tmp/*.gpg.key | xargs -n1 apt-key add
-
-# Recreate Travis CI environment
-RUN apt-get update -y
-RUN apt-get install -y git-core python-pip curl automake libtool make cmake pkg-config python-pip \
- libc6 libstdc++6 zlib1g-dev libcurl4-openssl-dev libpng-dev libsqlite3-dev \
- xvfb libglu1-mesa-dev libxrandr-dev libxinerama-dev libxi-dev libxcursor-dev xutils-dev \
- mesa-utils libxxf86vm-dev x11proto-xf86vidmode-dev cmake && \
- pip install awscli
diff --git a/docker/bitrise/android/Dockerfile b/docker/bitrise/android/Dockerfile
deleted file mode 100644
index 264fa01b98..0000000000
--- a/docker/bitrise/android/Dockerfile
+++ /dev/null
@@ -1,21 +0,0 @@
-FROM bitriseio/android-ndk:latest
-
-# Install Google Cloud SDK for Firebase
-RUN set -eu && \
- (echo "deb http://packages.cloud.google.com/apt cloud-sdk-$(lsb_release -c -s) main" | sudo tee /etc/apt/sources.list.d/google-cloud-sdk.list) && \
- (curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -) && \
- sudo apt-get update && \
- sudo apt-get install -y google-cloud-sdk python-dev python-setuptools ccache && \
- sudo apt-get clean && \
- sudo easy_install -U pip && \
- pip install --no-cache-dir awscli && \
- mkdir -p "${ANDROID_HOME}/licenses" && \
- (echo "8933bad161af4178b1185d1a37fbf41ea5269c55" > "${ANDROID_HOME}/licenses/android-sdk-license")
-
-RUN set -eu && \
- git clone --depth=1 "https://github.com/mapbox/mapbox-gl-native.git" . && \
- ccache -z && \
- BUILDTYPE=Debug make android-test-lib-arm-v7 && \
- BUILDTYPE=Debug make android-checkstyle && \
- ccache -s && \
- cd .. && rm -rf src && mkdir src
diff --git a/docker/build.sh b/docker/build.sh
deleted file mode 100755
index c6eb1b110d..0000000000
--- a/docker/build.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-
-#!/usr/bin/env bash
-
-set -e
-set -o pipefail
-
-docker build -t mapbox/gl-native:travis docker
diff --git a/docker/clang-tidy/Dockerfile b/docker/clang-tidy/Dockerfile
deleted file mode 100644
index c880391592..0000000000
--- a/docker/clang-tidy/Dockerfile
+++ /dev/null
@@ -1,9 +0,0 @@
-FROM mapbox/gl-native:travis
-
-# Install compiler
-RUN apt-get -y install clang-3.8 lldb-3.8 clang-tidy-3.8 clang-format-3.8
-
-RUN useradd -ms /bin/bash mapbox
-USER mapbox
-ENV HOME /home/mapbox
-WORKDIR /home/mapbox
diff --git a/docker/clang-tidy/run.sh b/docker/clang-tidy/run.sh
deleted file mode 100755
index 421aca9700..0000000000
--- a/docker/clang-tidy/run.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-set -o pipefail
-
-./docker/build.sh
-
-docker build -t mapbox/gl-native:clang-tidy docker/clang-tidy
-
-docker run \
- -i \
- -v `pwd`:/home/mapbox/build \
- -t mapbox/gl-native:clang-tidy \
- build/docker/clang-tidy/tidy.sh
diff --git a/docker/clang-tidy/tidy.sh b/docker/clang-tidy/tidy.sh
deleted file mode 100755
index 4c1b74595a..0000000000
--- a/docker/clang-tidy/tidy.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/env bash
-
-# set -e
-# set -o pipefail
-
-export CXX=clang++-3.8
-export BUILDTYPE=Release
-
-cd build
-
-# before_install
-source ./scripts/travis_helper.sh
-
-# install
-./platform/linux/scripts/install.sh
-
-export CLANG_TIDY=clang-tidy-3.8
-make tidy
diff --git a/docker/george-edison55-precise-backports.gpg.key b/docker/george-edison55-precise-backports.gpg.key
deleted file mode 100644
index 69971cfce8..0000000000
--- a/docker/george-edison55-precise-backports.gpg.key
+++ /dev/null
@@ -1,13 +0,0 @@
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: SKS 1.1.5
-Comment: Hostname: keyserver.ubuntu.com
-
-mI0ETFYUegEEAMF062ZPYWxX0blpJpLCz/oEXwvxJoQg1Sz4uD4Fs1FCfRwHMlydwbGvEjEr
-QG39OXf1y1+lGVI73BLcuDd/n0yBLN9brycDspZKnQ25VaRB6sl8EDR8XM5tiA/diW1EIygS
-Ad/NuwXv236e+1E+zvik6faeoxygJbbj0KN67Hx7ABEBAAG0HUxhdW5jaHBhZCBHZW9yZ2Ug
-RWRpc29uJ3MgUFBBiLYEEwECACAFAkxWFHoCGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAK
-CRAITs/Fgoq3JpJ0A/9RquDizs5oUhyqqT4t4EHEIH9+ckl/3cQj0peN5APA5TOqAS4iVxic
-GO3YB7yY4a+v5qQUalOMNAQRUigi3IwCcOSs94Bt5f7lK6xbU7mIO2D5a7cUCjN36FXe+oWp
-4s5odz5+9OZrIVzJw/NOdgneLqh2ts5jWGYmOg7POJk9mQ==
-=ItbQ
------END PGP PUBLIC KEY BLOCK-----
diff --git a/docker/george-edison55-precise-backports.list b/docker/george-edison55-precise-backports.list
deleted file mode 100644
index 2bae784dd6..0000000000
--- a/docker/george-edison55-precise-backports.list
+++ /dev/null
@@ -1,2 +0,0 @@
-deb http://ppa.launchpad.net/george-edison55/precise-backports/ubuntu precise main
-deb-src http://ppa.launchpad.net/george-edison55/precise-backports/ubuntu precise main
diff --git a/docker/linux/Dockerfile b/docker/linux/Dockerfile
deleted file mode 100644
index c797082d93..0000000000
--- a/docker/linux/Dockerfile
+++ /dev/null
@@ -1,14 +0,0 @@
-FROM mapbox/gl-native:travis
-
-# Install compiler
-RUN apt-get -y install gdb g++-5 gcc-5 libllvm3.4
-
-RUN useradd -ms /bin/bash mapbox
-USER mapbox
-ENV HOME /home/mapbox
-WORKDIR /home/mapbox
-
-# Node
-RUN git clone https://github.com/creationix/nvm.git ~/.nvm && \
- . ~/.nvm/nvm.sh && \
- NVM_DIR=~/.nvm nvm install 4.4.5
diff --git a/docker/linux/run.sh b/docker/linux/run.sh
deleted file mode 100755
index 3d41843cf2..0000000000
--- a/docker/linux/run.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-set -o pipefail
-
-./docker/build.sh
-
-docker build -t mapbox/gl-native:linux docker/linux
-
-docker run \
- -i \
- -v `pwd`:/home/mapbox/build \
- -t mapbox/gl-native:linux \
- build/docker/linux/test.sh
diff --git a/docker/linux/test.sh b/docker/linux/test.sh
deleted file mode 100755
index 207f7679cf..0000000000
--- a/docker/linux/test.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/env bash
-
-# set -e
-# set -o pipefail
-
-export _CXX=g++-5
-export _CC=gcc-5
-export BUILDTYPE=Release
-
-# Node
-. ~/.nvm/nvm.sh
-nvm use 4.4.5
-
-# Xvfb
-start-stop-daemon --start --pidfile ~/xvfb.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -screen 0 1024x768x24 -ac +extension GLX +render -noreset
-
-cd build
-
-# before_install
-source ./scripts/travis_helper.sh
-source ./scripts/travis_setup.sh
-
-make linux
-make test
diff --git a/docker/ubuntu-toolchain-r.gpg.key b/docker/ubuntu-toolchain-r.gpg.key
deleted file mode 100644
index 854eef8520..0000000000
--- a/docker/ubuntu-toolchain-r.gpg.key
+++ /dev/null
@@ -1,13 +0,0 @@
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: SKS 1.1.5
-Comment: Hostname: keyserver.ubuntu.com
-
-mI0ESuBvRwEEAMi4cDba7xlKaaoXjO1n1HX8RKrkW+HEIl79nSOSJyvzysajs7zUow/OzCQp
-9NswqrDmNuH1+lPTTRNAGtK8r2ouq2rnXT1mTl23dpgHZ9spseR73s4ZBGw/ag4bpU5dNUSt
-vfmHhIjVCuiSpNn7cyy1JSSvSs3N2mxteKjXLBf7ABEBAAG0GkxhdW5jaHBhZCBUb29sY2hh
-aW4gYnVpbGRziLYEEwECACAFAkrgb0cCGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRAe
-k3eiup7yfzGKA/4xzUqNACSlB+k+DxFFHqkwKa/ziFiAlkLQyyhm+iqz80htRZr7Ls/ZRYZl
-0aSU56/hLe0V+TviJ1s8qdN2lamkKdXIAFfavA04nOnTzyIBJ82EAUT3Nh45skMxo4z4iZMN
-msyaQpNl/m/lNtOLhR64v5ZybofB2EWkMxUzX8D/FQ==
-=LcUQ
------END PGP PUBLIC KEY BLOCK----- \ No newline at end of file
diff --git a/docker/ubuntu-toolchain-r.list b/docker/ubuntu-toolchain-r.list
deleted file mode 100644
index 741f4528e2..0000000000
--- a/docker/ubuntu-toolchain-r.list
+++ /dev/null
@@ -1,2 +0,0 @@
-deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu precise main
-deb-src http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu precise main \ No newline at end of file
diff --git a/docs/TROUBLESHOOTING.md b/docs/TROUBLESHOOTING.md
deleted file mode 100644
index 9832b5da0a..0000000000
--- a/docs/TROUBLESHOOTING.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# Troubleshooting
-
-To trigger a complete rebuild, run `make clean`.
-
-If you are having trouble getting the dependencies right, you can blow away the `mason_packages` directory, or run `make distclean`. This means the `Makefile` and configure script will automatically install the dependencies again on the next try.
diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp
index c5f90d99e1..5ba23a76dd 100644
--- a/include/mbgl/map/map.hpp
+++ b/include/mbgl/map/map.hpp
@@ -127,6 +127,14 @@ public:
void setViewportMode(ViewportMode);
ViewportMode getViewportMode() const;
+ // Projection mode
+ void setAxonometric(bool);
+ bool getAxonometric() const;
+ void setXSkew(double ySkew);
+ double getXSkew() const;
+ void setYSkew(double ySkew);
+ double getYSkew() const;
+
// Size
void setSize(Size);
Size getSize() const;
diff --git a/include/mbgl/map/mode.hpp b/include/mbgl/map/mode.hpp
index 05de2df22c..4ee289d855 100644
--- a/include/mbgl/map/mode.hpp
+++ b/include/mbgl/map/mode.hpp
@@ -11,16 +11,8 @@ using EnumType = uint32_t;
enum class MapMode : EnumType {
Continuous, // continually updating map
- Still, // a once-off still image
-};
-
-// We can avoid redundant GL calls when it is known that the GL context is not
-// being shared. In a shared GL context case, we need to make sure that the
-// correct GL configurations are in use - they might have changed between render
-// calls.
-enum class GLContextMode : EnumType {
- Unique,
- Shared,
+ Static, // a once-off still image of an arbitrary viewport
+ Tile // a once-off still image of a single tile
};
// We can choose to constrain the map both horizontally or vertically, or only
diff --git a/include/mbgl/renderer/mode.hpp b/include/mbgl/renderer/mode.hpp
new file mode 100644
index 0000000000..6ff42d8058
--- /dev/null
+++ b/include/mbgl/renderer/mode.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include <cstdint>
+
+namespace mbgl {
+
+using EnumType = uint32_t;
+
+// We can avoid redundant GL calls when it is known that the GL context is not
+// being shared. In a shared GL context case, we need to make sure that the
+// correct GL configurations are in use - they might have changed between render
+// calls.
+enum class GLContextMode : EnumType {
+ Unique,
+ Shared,
+};
+
+} // namespace mbgl
diff --git a/include/mbgl/renderer/renderer.hpp b/include/mbgl/renderer/renderer.hpp
index a60f3f6e4d..db28ee92fc 100644
--- a/include/mbgl/renderer/renderer.hpp
+++ b/include/mbgl/renderer/renderer.hpp
@@ -1,7 +1,7 @@
#pragma once
-#include <mbgl/map/mode.hpp>
#include <mbgl/renderer/query.hpp>
+#include <mbgl/renderer/mode.hpp>
#include <mbgl/annotation/annotation.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/util/geo.hpp>
diff --git a/include/mbgl/renderer/renderer_backend.hpp b/include/mbgl/renderer/renderer_backend.hpp
index 295838c71b..b83c128169 100644
--- a/include/mbgl/renderer/renderer_backend.hpp
+++ b/include/mbgl/renderer/renderer_backend.hpp
@@ -41,7 +41,7 @@ protected:
// Called with the name of an OpenGL extension that should be loaded. RendererBackend implementations
// must call the API-specific version that obtains the function pointer for this function,
// or a null pointer if unsupported/unavailable.
- virtual gl::ProcAddress initializeExtension(const char*) = 0;
+ virtual gl::ProcAddress getExtensionFunctionPointer(const char*) = 0;
// Called when the backend's GL context needs to be made active or inactive. These are called,
// as a matched pair, exclusively through BackendScope, in two situations:
diff --git a/include/mbgl/storage/offline.hpp b/include/mbgl/storage/offline.hpp
index 117dd0591b..ef4a499e83 100644
--- a/include/mbgl/storage/offline.hpp
+++ b/include/mbgl/storage/offline.hpp
@@ -30,15 +30,15 @@ public:
OfflineTilePyramidRegionDefinition(std::string, LatLngBounds, double, double, float);
/* Private */
- std::vector<CanonicalTileID> tileCover(SourceType, uint16_t tileSize, const Range<uint8_t>& zoomRange) const;
- uint64_t tileCount(SourceType, uint16_t tileSize, const Range<uint8_t>& zoomRange) const;
+ std::vector<CanonicalTileID> tileCover(style::SourceType, uint16_t tileSize, const Range<uint8_t>& zoomRange) const;
+ uint64_t tileCount(style::SourceType, uint16_t tileSize, const Range<uint8_t>& zoomRange) const;
const std::string styleURL;
const LatLngBounds bounds;
const double minZoom;
const double maxZoom;
const float pixelRatio;
private:
- Range<uint8_t> coveringZoomRange(SourceType, uint16_t tileSize, const Range<uint8_t>& zoomRange) const;
+ Range<uint8_t> coveringZoomRange(style::SourceType, uint16_t tileSize, const Range<uint8_t>& zoomRange) const;
};
/*
diff --git a/include/mbgl/style/conversion.hpp b/include/mbgl/style/conversion.hpp
index 27504a89b1..71c2cec237 100644
--- a/include/mbgl/style/conversion.hpp
+++ b/include/mbgl/style/conversion.hpp
@@ -1,6 +1,8 @@
#pragma once
#include <mbgl/util/optional.hpp>
+#include <mbgl/util/feature.hpp>
+#include <mbgl/util/geojson.hpp>
#include <string>
@@ -9,9 +11,8 @@ namespace style {
namespace conversion {
/*
- The `conversion` namespace defines conversions from a templated type `V` representing a JSON
- object conforming to the schema defined by the Mapbox Style Specification, to the various C++
- types that form the C++ model of that domain:
+ The `conversion` namespace defines conversions from JSON structures conforming to the schema defined by
+ the Mapbox Style Specification, to the various C++ types that form the C++ model of that domain:
* `std::unique_ptr<Source>`
* `std::unique_ptr<Layer>`
@@ -20,15 +21,31 @@ namespace conversion {
A single template function serves as the public interface:
- template <class T, class V>
- optional<T> convert(const V& value, Error& error);
+ template <class T>
+ optional<T> convert(const Convertible& input, Error& error);
Where `T` is one of the above types. If the conversion fails, the result is empty, and the
error parameter includes diagnostic text suitable for presentation to a library user. Otherwise,
a filled optional is returned.
- The implementation of `convert` requires that the following are legal expressions for a value `v`
- of type `const V&`:
+ `Convertible` is a type that encapsulates a special form of polymorphism over various underlying types that
+ can serve as input to the conversion algorithm. For instance, on macOS, we need to support
+ conversion from both RapidJSON types, and a JSON structure represented with `NSArray`/`NSDictionary`/etc.
+ On Qt, we need to support conversion from RapidJSON types and QVariant.
+
+ We don't want to use traditional forms of polymorphism to accomplish this:
+
+ * Compile time polymorphism using a template parameter for the actual value type leads to
+ excessive code bloat and long compile times.
+ * Runtime polymorphism using virtual methods requires extra heap allocation and ubiquitous
+ use of std::unique_ptr, unsuitable for this performance-sensitive code.
+
+ Therefore, we're using a custom implementation of runtime polymorphism where we manually create and
+ dispatch through a table of function pointers (vtable), while keeping the storage for any of the possible
+ underlying types inline on the stack, using `std::aligned_storage`.
+
+ For a given underlying type T, an explicit specialization of `ConversionTraits<T>` must be provided. This
+ specialization must provide the following static methods:
* `isUndefined(v)` -- returns a boolean indication whether `v` is undefined or a JSON null
@@ -48,21 +65,239 @@ namespace conversion {
* `toNumber(v)` -- returns `optional<float>`, absence indicating `v` is not a JSON number
* `toDouble(v)` -- returns `optional<double>`, absence indicating `v` is not a JSON number
* `toString(v)` -- returns `optional<std::string>`, absence indicating `v` is not a JSON string
- * `toValue(v)` -- returns `optional<mbgl::Value>`, a variant type, for generic conversion,
+ * `toValue(v)` -- returns `optional<Value>`, a variant type, for generic conversion,
absence indicating `v` is not a boolean, number, or string. Numbers should be converted to
unsigned integer, signed integer, or floating point, in descending preference.
- The mbgl core implements these requirements for RapidJSON types, and the node bindings implement
- them for v8 types.
+ In addition, the type T must be move-constructable. And finally, `Convertible::Storage`, a typedef for
+ `std::aligned_storage_t`, must be large enough to satisfy the memory requirements for any of the
+ possible underlying types. (A static assert will fail if this is not the case.)
+
+ `Convertible` itself is movable, but not copyable. A moved-from `Convertible` is in an invalid state;
+ you must not do anything with it except let it go out of scope.
*/
struct Error { std::string message; };
+template <typename T>
+class ConversionTraits;
+
+class Convertible {
+public:
+ template <typename T>
+ Convertible(T&& value) : vtable(vtableForType<std::decay_t<T>>()) {
+ static_assert(sizeof(Storage) >= sizeof(std::decay_t<T>), "Storage must be large enough to hold value type");
+ new (static_cast<void*>(&storage)) std::decay_t<T>(std::forward<T>(value));
+ }
+
+ Convertible(Convertible&& v)
+ : vtable(v.vtable)
+ {
+ if (vtable) {
+ vtable->move(std::move(v.storage), this->storage);
+ }
+ }
+
+ ~Convertible() {
+ if (vtable) {
+ vtable->destroy(storage);
+ }
+ }
+
+ Convertible& operator=(Convertible&& v) {
+ if (vtable) {
+ vtable->destroy(storage);
+ }
+ vtable = v.vtable;
+ if (vtable) {
+ vtable->move(std::move(v.storage), this->storage);
+ }
+ v.vtable = nullptr;
+ return *this;
+ }
+
+ Convertible() = delete;
+ Convertible(const Convertible&) = delete;
+ Convertible& operator=(const Convertible&) = delete;
+
+ friend inline bool isUndefined(const Convertible& v) {
+ assert(v.vtable);
+ return v.vtable->isUndefined(v.storage);
+ }
+
+ friend inline bool isArray(const Convertible& v) {
+ assert(v.vtable);
+ return v.vtable->isArray(v.storage);
+ }
+
+ friend inline std::size_t arrayLength(const Convertible& v) {
+ assert(v.vtable);
+ return v.vtable->arrayLength(v.storage);
+ }
+
+ friend inline Convertible arrayMember(const Convertible& v, std::size_t i) {
+ assert(v.vtable);
+ return v.vtable->arrayMember(v.storage, i);
+ }
+
+ friend inline bool isObject(const Convertible& v) {
+ assert(v.vtable);
+ return v.vtable->isObject(v.storage);
+ }
+
+ friend inline optional<Convertible> objectMember(const Convertible& v, const char * name) {
+ assert(v.vtable);
+ return v.vtable->objectMember(v.storage, name);
+ }
+
+ friend inline optional<Error> eachMember(const Convertible& v, const std::function<optional<Error> (const std::string&, const Convertible&)>& fn) {
+ assert(v.vtable);
+ return v.vtable->eachMember(v.storage, fn);
+ }
+
+ friend inline optional<bool> toBool(const Convertible& v) {
+ assert(v.vtable);
+ return v.vtable->toBool(v.storage);
+ }
+
+ friend inline optional<float> toNumber(const Convertible& v) {
+ assert(v.vtable);
+ return v.vtable->toNumber(v.storage);
+ }
+
+ friend inline optional<double> toDouble(const Convertible& v) {
+ assert(v.vtable);
+ return v.vtable->toDouble(v.storage);
+ }
+
+ friend inline optional<std::string> toString(const Convertible& v) {
+ assert(v.vtable);
+ return v.vtable->toString(v.storage);
+ }
+
+ friend inline optional<Value> toValue(const Convertible& v) {
+ assert(v.vtable);
+ return v.vtable->toValue(v.storage);
+ }
+
+ friend inline optional<GeoJSON> toGeoJSON(const Convertible& v, Error& error) {
+ assert(v.vtable);
+ return v.vtable->toGeoJSON(v.storage, error);
+ }
+
+private:
+#if __ANDROID__
+ // Android: JSValue* or mbgl::android::Value
+ using Storage = std::aligned_storage_t<32, 8>;
+#elif __QT__
+ // Qt: JSValue* or QVariant
+ using Storage = std::aligned_storage_t<32, 8>;
+#else
+ // Node: JSValue* or v8::Local<v8::Value>
+ // iOS/macOS: JSValue* or id
+ using Storage = std::aligned_storage_t<8, 8>;
+#endif
+
+ struct VTable {
+ void (*move) (Storage&& src, Storage& dest);
+ void (*destroy) (Storage&);
+
+ bool (*isUndefined) (const Storage&);
+
+ bool (*isArray) (const Storage&);
+ std::size_t (*arrayLength) (const Storage&);
+ Convertible (*arrayMember) (const Storage&, std::size_t);
+
+ bool (*isObject) (const Storage&);
+ optional<Convertible> (*objectMember) (const Storage&, const char *);
+ optional<Error> (*eachMember) (const Storage&, const std::function<optional<Error> (const std::string&, const Convertible&)>&);
+
+ optional<bool> (*toBool) (const Storage&);
+ optional<float> (*toNumber) (const Storage&);
+ optional<double> (*toDouble) (const Storage&);
+ optional<std::string> (*toString) (const Storage&);
+ optional<Value> (*toValue) (const Storage&);
+
+ // https://github.com/mapbox/mapbox-gl-native/issues/5623
+ optional<GeoJSON> (*toGeoJSON) (const Storage&, Error&);
+ };
+
+ // Extracted this function from the table below to work around a GCC bug with differing
+ // visibility settings for capturing lambdas: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80947
+ template <typename T>
+ static auto vtableEachMember(const Storage& s, const std::function<optional<Error>(const std::string&, const Convertible&)>& fn) {
+ return ConversionTraits<T>::eachMember(reinterpret_cast<const T&>(s), [&](const std::string& k, T&& v) {
+ return fn(k, Convertible(std::move(v)));
+ });
+ }
+
+ template <typename T>
+ static VTable* vtableForType() {
+ using Traits = ConversionTraits<T>;
+ static VTable vtable = {
+ [] (Storage&& src, Storage& dest) {
+ auto srcValue = reinterpret_cast<T&&>(src);
+ new (static_cast<void*>(&dest)) T(std::move(srcValue));
+ srcValue.~T();
+ },
+ [] (Storage& s) {
+ reinterpret_cast<T&>(s).~T();
+ },
+ [] (const Storage& s) {
+ return Traits::isUndefined(reinterpret_cast<const T&>(s));
+ },
+ [] (const Storage& s) {
+ return Traits::isArray(reinterpret_cast<const T&>(s));
+ },
+ [] (const Storage& s) {
+ return Traits::arrayLength(reinterpret_cast<const T&>(s));
+ },
+ [] (const Storage& s, std::size_t i) {
+ return Convertible(Traits::arrayMember(reinterpret_cast<const T&>(s), i));
+ },
+ [] (const Storage& s) {
+ return Traits::isObject(reinterpret_cast<const T&>(s));
+ },
+ [] (const Storage& s, const char * key) {
+ optional<T> member = Traits::objectMember(reinterpret_cast<const T&>(s), key);
+ if (member) {
+ return optional<Convertible>(Convertible(std::move(*member)));
+ } else {
+ return optional<Convertible>();
+ }
+ },
+ vtableEachMember<T>,
+ [] (const Storage& s) {
+ return Traits::toBool(reinterpret_cast<const T&>(s));
+ },
+ [] (const Storage& s) {
+ return Traits::toNumber(reinterpret_cast<const T&>(s));
+ },
+ [] (const Storage& s) {
+ return Traits::toDouble(reinterpret_cast<const T&>(s));
+ },
+ [] (const Storage& s) {
+ return Traits::toString(reinterpret_cast<const T&>(s));
+ },
+ [] (const Storage& s) {
+ return Traits::toValue(reinterpret_cast<const T&>(s));
+ },
+ [] (const Storage& s, Error& err) {
+ return Traits::toGeoJSON(reinterpret_cast<const T&>(s), err);
+ }
+ };
+ return &vtable;
+ }
+
+ VTable* vtable;
+ Storage storage;
+};
+
template <class T, class Enable = void>
struct Converter;
-template <class T, class V, class...Args>
-optional<T> convert(const V& value, Error& error, Args&&...args) {
+template <class T, class...Args>
+optional<T> convert(const Convertible& value, Error& error, Args&&...args) {
return Converter<T>()(value, error, std::forward<Args>(args)...);
}
diff --git a/include/mbgl/style/conversion/constant.hpp b/include/mbgl/style/conversion/constant.hpp
index 07c0a35fae..7b3249da52 100644
--- a/include/mbgl/style/conversion/constant.hpp
+++ b/include/mbgl/style/conversion/constant.hpp
@@ -1,7 +1,6 @@
#pragma once
#include <mbgl/style/conversion.hpp>
-#include <mbgl/util/optional.hpp>
#include <mbgl/util/color.hpp>
#include <mbgl/util/enum.hpp>
#include <mbgl/util/string.hpp>
@@ -16,47 +15,22 @@ namespace conversion {
template <>
struct Converter<bool> {
- template <class V>
- optional<bool> operator()(const V& value, Error& error) const {
- optional<bool> converted = toBool(value);
- if (!converted) {
- error = { "value must be a boolean" };
- return {};
- }
- return *converted;
- }
+ optional<bool> operator()(const Convertible& value, Error& error) const;
};
template <>
struct Converter<float> {
- template <class V>
- optional<float> operator()(const V& value, Error& error) const {
- optional<float> converted = toNumber(value);
- if (!converted) {
- error = { "value must be a number" };
- return {};
- }
- return *converted;
- }
+ optional<float> operator()(const Convertible& value, Error& error) const;
};
template <>
struct Converter<std::string> {
- template <class V>
- optional<std::string> operator()(const V& value, Error& error) const {
- optional<std::string> converted = toString(value);
- if (!converted) {
- error = { "value must be a string" };
- return {};
- }
- return *converted;
- }
+ optional<std::string> operator()(const Convertible& value, Error& error) const;
};
template <class T>
struct Converter<T, typename std::enable_if_t<std::is_enum<T>::value>> {
- template <class V>
- optional<T> operator()(const V& value, Error& error) const {
+ optional<T> operator()(const Convertible& value, Error& error) const {
optional<std::string> string = toString(value);
if (!string) {
error = { "value must be a string" };
@@ -75,28 +49,12 @@ struct Converter<T, typename std::enable_if_t<std::is_enum<T>::value>> {
template <>
struct Converter<Color> {
- template <class V>
- optional<Color> operator()(const V& value, Error& error) const {
- optional<std::string> string = toString(value);
- if (!string) {
- error = { "value must be a string" };
- return {};
- }
-
- optional<Color> color = Color::parse(*string);
- if (!color) {
- error = { "value must be a valid color" };
- return {};
- }
-
- return *color;
- }
+ optional<Color> operator()(const Convertible& value, Error& error) const;
};
template <size_t N>
struct Converter<std::array<float, N>> {
- template <class V>
- optional<std::array<float, N>> operator()(const V& value, Error& error) const {
+ optional<std::array<float, N>> operator()(const Convertible& value, Error& error) const {
if (!isArray(value) || arrayLength(value) != N) {
error = { "value must be an array of " + util::toString(N) + " numbers" };
return {};
@@ -117,52 +75,12 @@ struct Converter<std::array<float, N>> {
template <>
struct Converter<std::vector<float>> {
- template <class V>
- optional<std::vector<float>> operator()(const V& value, Error& error) const {
- if (!isArray(value)) {
- error = { "value must be an array" };
- return {};
- }
-
- std::vector<float> result;
- result.reserve(arrayLength(value));
-
- for (std::size_t i = 0; i < arrayLength(value); ++i) {
- optional<float> number = toNumber(arrayMember(value, i));
- if (!number) {
- error = { "value must be an array of numbers" };
- return {};
- }
- result.push_back(*number);
- }
-
- return result;
- }
+ optional<std::vector<float>> operator()(const Convertible& value, Error& error) const;
};
template <>
struct Converter<std::vector<std::string>> {
- template <class V>
- optional<std::vector<std::string>> operator()(const V& value, Error& error) const {
- if (!isArray(value)) {
- error = { "value must be an array" };
- return {};
- }
-
- std::vector<std::string> result;
- result.reserve(arrayLength(value));
-
- for (std::size_t i = 0; i < arrayLength(value); ++i) {
- optional<std::string> string = toString(arrayMember(value, i));
- if (!string) {
- error = { "value must be an array of strings" };
- return {};
- }
- result.push_back(*string);
- }
-
- return result;
- }
+ optional<std::vector<std::string>> operator()(const Convertible& value, Error& error) const;
};
} // namespace conversion
diff --git a/include/mbgl/style/conversion/coordinate.hpp b/include/mbgl/style/conversion/coordinate.hpp
index 732624e77f..e11db5e32f 100644
--- a/include/mbgl/style/conversion/coordinate.hpp
+++ b/include/mbgl/style/conversion/coordinate.hpp
@@ -10,26 +10,7 @@ namespace conversion {
template<>
struct Converter<LatLng> {
public:
- template <class V>
- optional<LatLng> operator() (const V& value, Error& error) const {
- if (!isArray(value) || arrayLength(value) < 2 ) {
- error = { "coordinate array must contain numeric longitude and latitude values" };
- return {};
- }
- //Style spec uses GeoJSON convention for specifying coordinates
- optional<double> latitude = toDouble(arrayMember(value, 1));
- optional<double> longitude = toDouble(arrayMember(value, 0));
-
- if (!latitude || !longitude) {
- error = { "coordinate array must contain numeric longitude and latitude values" };
- return {};
- }
- if (*latitude < -90 || *latitude > 90 ){
- error = { "coordinate latitude must be between -90 and 90" };
- return {};
- }
- return LatLng(*latitude, *longitude);
- }
+ optional<LatLng> operator() (const Convertible& value, Error& error) const;
};
} // namespace conversion
diff --git a/include/mbgl/style/conversion/custom_geometry_source_options.hpp b/include/mbgl/style/conversion/custom_geometry_source_options.hpp
new file mode 100644
index 0000000000..73b141e799
--- /dev/null
+++ b/include/mbgl/style/conversion/custom_geometry_source_options.hpp
@@ -0,0 +1,64 @@
+#pragma once
+
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/sources/custom_geometry_source.hpp>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+template <>
+struct Converter<CustomGeometrySource::Options> {
+
+ template <class V>
+ optional<CustomGeometrySource::Options> operator()(const V& value, Error& error) const {
+ CustomGeometrySource::Options options;
+
+ const auto minzoomValue = objectMember(value, "minzoom");
+ if (minzoomValue) {
+ if (toNumber(*minzoomValue)) {
+ options.zoomRange.min = static_cast<uint8_t>(*toNumber(*minzoomValue));
+ } else {
+ error = { "GeoJSON source minzoom value must be a number" };
+ return {};
+ }
+ }
+
+ const auto maxzoomValue = objectMember(value, "maxzoom");
+ if (maxzoomValue) {
+ if (toNumber(*maxzoomValue)) {
+ options.zoomRange.max = static_cast<uint8_t>(*toNumber(*maxzoomValue));
+ } else {
+ error = { "GeoJSON source maxzoom value must be a number" };
+ return {};
+ }
+ }
+
+ const auto bufferValue = objectMember(value, "buffer");
+ if (bufferValue) {
+ if (toNumber(*bufferValue)) {
+ options.tileOptions.buffer = static_cast<uint16_t>(*toNumber(*bufferValue));
+ } else {
+ error = { "GeoJSON source buffer value must be a number" };
+ return {};
+ }
+ }
+
+ const auto toleranceValue = objectMember(value, "tolerance");
+ if (toleranceValue) {
+ if (toNumber(*toleranceValue)) {
+ options.tileOptions.tolerance = static_cast<double>(*toNumber(*toleranceValue));
+ } else {
+ error = { "GeoJSON source tolerance value must be a number" };
+ return {};
+ }
+ }
+
+ return { options };
+ }
+
+};
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/conversion/data_driven_property_value.hpp b/include/mbgl/style/conversion/data_driven_property_value.hpp
index 79b15dcfb0..8880d28fb1 100644
--- a/include/mbgl/style/conversion/data_driven_property_value.hpp
+++ b/include/mbgl/style/conversion/data_driven_property_value.hpp
@@ -4,6 +4,13 @@
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/constant.hpp>
#include <mbgl/style/conversion/function.hpp>
+#include <mbgl/style/conversion/expression.hpp>
+#include <mbgl/style/expression/is_expression.hpp>
+#include <mbgl/style/expression/is_constant.hpp>
+#include <mbgl/style/expression/find_zoom_curve.hpp>
+
+#include <unordered_set>
+
namespace mbgl {
namespace style {
@@ -11,10 +18,27 @@ namespace conversion {
template <class T>
struct Converter<DataDrivenPropertyValue<T>> {
- template <class V>
- optional<DataDrivenPropertyValue<T>> operator()(const V& value, Error& error) const {
+
+ optional<DataDrivenPropertyValue<T>> operator()(const Convertible& value, Error& error) const {
if (isUndefined(value)) {
return DataDrivenPropertyValue<T>();
+ } else if (expression::isExpression(value)) {
+ optional<std::unique_ptr<Expression>> expression = convert<std::unique_ptr<Expression>>(
+ value,
+ error,
+ valueTypeToExpressionType<T>());
+
+ if (!expression) {
+ return {};
+ }
+
+ if (isFeatureConstant(**expression)) {
+ return DataDrivenPropertyValue<T>(CameraFunction<T>(std::move(*expression)));
+ } else if (isZoomConstant(**expression)) {
+ return DataDrivenPropertyValue<T>(SourceFunction<T>(std::move(*expression)));
+ } else {
+ return DataDrivenPropertyValue<T>(CompositeFunction<T>(std::move(*expression)));
+ }
} else if (!isObject(value)) {
optional<T> constant = convert<T>(value, error);
if (!constant) {
diff --git a/include/mbgl/style/conversion/expression.hpp b/include/mbgl/style/conversion/expression.hpp
new file mode 100644
index 0000000000..c5fcf906a7
--- /dev/null
+++ b/include/mbgl/style/conversion/expression.hpp
@@ -0,0 +1,39 @@
+#pragma once
+
+#include <mbgl/style/expression/parsing_context.hpp>
+#include <mbgl/style/expression/type.hpp>
+#include <mbgl/style/conversion.hpp>
+
+#include <memory>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+using namespace mbgl::style::expression;
+
+template<> struct Converter<std::unique_ptr<Expression>> {
+ optional<std::unique_ptr<Expression>> operator()(const Convertible& value, Error& error, type::Type expected) const {
+ ParsingContext ctx(optional<type::Type> {expected});
+ ParseResult parsed = ctx.parse(value);
+ if (parsed) {
+ return std::move(*parsed);
+ }
+ std::string combinedError;
+ for (const ParsingError& parsingError : ctx.getErrors()) {
+ if (combinedError.size() > 0) {
+ combinedError += "\n";
+ }
+ if (parsingError.key.size() > 0) {
+ combinedError += parsingError.key + ": ";
+ }
+ combinedError += parsingError.message;
+ }
+ error = { combinedError };
+ return {};
+ };
+};
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/conversion/filter.hpp b/include/mbgl/style/conversion/filter.hpp
index 986d1bf80d..9daf6ea7a4 100644
--- a/include/mbgl/style/conversion/filter.hpp
+++ b/include/mbgl/style/conversion/filter.hpp
@@ -2,7 +2,6 @@
#include <mbgl/style/filter.hpp>
#include <mbgl/style/conversion.hpp>
-#include <mbgl/util/geometry.hpp>
namespace mbgl {
namespace style {
@@ -11,247 +10,7 @@ namespace conversion {
template <>
struct Converter<Filter> {
public:
- template <class V>
- optional<Filter> operator()(const V& value, Error& error) const {
- if (!isArray(value)) {
- error = { "filter expression must be an array" };
- return {};
- }
-
- if (arrayLength(value) < 1) {
- error = { "filter expression must have at least 1 element" };
- return {};
- }
-
- optional<std::string> op = toString(arrayMember(value, 0));
- if (!op) {
- error = { "filter operator must be a string" };
- return {};
- }
-
- if (*op == "==") {
- return convertEqualityFilter<EqualsFilter, TypeEqualsFilter, IdentifierEqualsFilter>(value, error);
- } else if (*op == "!=") {
- return convertEqualityFilter<NotEqualsFilter, TypeNotEqualsFilter, IdentifierNotEqualsFilter>(value, error);
- } else if (*op == ">") {
- return convertBinaryFilter<GreaterThanFilter>(value, error);
- } else if (*op == ">=") {
- return convertBinaryFilter<GreaterThanEqualsFilter>(value, error);
- } else if (*op == "<") {
- return convertBinaryFilter<LessThanFilter>(value, error);
- } else if (*op == "<=") {
- return convertBinaryFilter<LessThanEqualsFilter>(value, error);
- } else if (*op == "in") {
- return convertSetFilter<InFilter, TypeInFilter, IdentifierInFilter>(value, error);
- } else if (*op == "!in") {
- return convertSetFilter<NotInFilter, TypeNotInFilter, IdentifierNotInFilter>(value, error);
- } else if (*op == "all") {
- return convertCompoundFilter<AllFilter>(value, error);
- } else if (*op == "any") {
- return convertCompoundFilter<AnyFilter>(value, error);
- } else if (*op == "none") {
- return convertCompoundFilter<NoneFilter>(value, error);
- } else if (*op == "has") {
- return convertUnaryFilter<HasFilter, HasIdentifierFilter>(value, error);
- } else if (*op == "!has") {
- return convertUnaryFilter<NotHasFilter, NotHasIdentifierFilter>(value, error);
- }
-
- error = { R"(filter operator must be one of "==", "!=", ">", ">=", "<", "<=", "in", "!in", "all", "any", "none", "has", or "!has")" };
- return {};
- }
-
-private:
- optional<Value> normalizeValue(const optional<Value>& value, Error& error) const {
- if (!value) {
- error = { "filter expression value must be a boolean, number, or string" };
- return {};
- } else {
- return *value;
- }
- }
-
- template <class V>
- optional<FeatureType> toFeatureType(const V& value, Error& error) const {
- optional<std::string> type = toString(value);
- if (!type) {
- error = { "value for $type filter must be a string" };
- return {};
- } else if (*type == "Point") {
- return FeatureType::Point;
- } else if (*type == "LineString") {
- return FeatureType::LineString;
- } else if (*type == "Polygon") {
- return FeatureType::Polygon;
- } else {
- error = { "value for $type filter must be Point, LineString, or Polygon" };
- return {};
- }
- }
-
- template <class V>
- optional<FeatureIdentifier> toFeatureIdentifier(const V& value, Error& error) const {
- optional<Value> identifier = toValue(value);
- if (!identifier) {
- error = { "filter expression value must be a boolean, number, or string" };
- return {};
- } else {
- return (*identifier).match(
- [] (uint64_t t) -> optional<FeatureIdentifier> { return { t }; },
- [] ( int64_t t) -> optional<FeatureIdentifier> { return { t }; },
- [] ( double t) -> optional<FeatureIdentifier> { return { t }; },
- [] (const std::string& t) -> optional<FeatureIdentifier> { return { t }; },
- [&] (const auto&) -> optional<FeatureIdentifier> {
- error = { "filter expression value must be a boolean, number, or string" };
- return {};
- });
- }
- }
-
- template <class FilterType, class IdentifierFilterType, class V>
- optional<Filter> convertUnaryFilter(const V& value, Error& error) const {
- if (arrayLength(value) < 2) {
- error = { "filter expression must have 2 elements" };
- return {};
- }
-
- optional<std::string> key = toString(arrayMember(value, 1));
- if (!key) {
- error = { "filter expression key must be a string" };
- return {};
- }
-
- if (*key == "$id") {
- return { IdentifierFilterType {} };
- } else {
- return { FilterType { *key } };
- }
- }
-
- template <class FilterType, class TypeFilterType, class IdentifierFilterType, class V>
- optional<Filter> convertEqualityFilter(const V& value, Error& error) const {
- if (arrayLength(value) < 3) {
- error = { "filter expression must have 3 elements" };
- return {};
- }
-
- optional<std::string> key = toString(arrayMember(value, 1));
- if (!key) {
- error = { "filter expression key must be a string" };
- return {};
- }
-
- if (*key == "$type") {
- optional<FeatureType> filterValue = toFeatureType(arrayMember(value, 2), error);
- if (!filterValue) {
- return {};
- }
-
- return { TypeFilterType { *filterValue } };
-
- } else if (*key == "$id") {
- optional<FeatureIdentifier> filterValue = toFeatureIdentifier(arrayMember(value, 2), error);
- if (!filterValue) {
- return {};
- }
-
- return { IdentifierFilterType { *filterValue } };
-
- } else {
- optional<Value> filterValue = normalizeValue(toValue(arrayMember(value, 2)), error);
- if (!filterValue) {
- return {};
- }
-
- return { FilterType { *key, *filterValue } };
- }
- }
-
- template <class FilterType, class V>
- optional<Filter> convertBinaryFilter(const V& value, Error& error) const {
- if (arrayLength(value) < 3) {
- error = { "filter expression must have 3 elements" };
- return {};
- }
-
- optional<std::string> key = toString(arrayMember(value, 1));
- if (!key) {
- error = { "filter expression key must be a string" };
- return {};
- }
-
- optional<Value> filterValue = normalizeValue(toValue(arrayMember(value, 2)), error);
- if (!filterValue) {
- return {};
- }
-
- return { FilterType { *key, *filterValue } };
- }
-
- template <class FilterType, class TypeFilterType, class IdentifierFilterType, class V>
- optional<Filter> convertSetFilter(const V& value, Error& error) const {
- if (arrayLength(value) < 2) {
- error = { "filter expression must at least 2 elements" };
- return {};
- }
-
- optional<std::string> key = toString(arrayMember(value, 1));
- if (!key) {
- error = { "filter expression key must be a string" };
- return {};
- }
-
- if (*key == "$type") {
- std::vector<FeatureType> values;
- for (std::size_t i = 2; i < arrayLength(value); ++i) {
- optional<FeatureType> filterValue = toFeatureType(arrayMember(value, i), error);
- if (!filterValue) {
- return {};
- }
- values.push_back(*filterValue);
- }
-
- return { TypeFilterType { std::move(values) } };
-
- } else if (*key == "$id") {
- std::vector<FeatureIdentifier> values;
- for (std::size_t i = 2; i < arrayLength(value); ++i) {
- optional<FeatureIdentifier> filterValue = toFeatureIdentifier(arrayMember(value, i), error);
- if (!filterValue) {
- return {};
- }
- values.push_back(*filterValue);
- }
-
- return { IdentifierFilterType { std::move(values) } };
-
- } else {
- std::vector<Value> values;
- for (std::size_t i = 2; i < arrayLength(value); ++i) {
- optional<Value> filterValue = normalizeValue(toValue(arrayMember(value, i)), error);
- if (!filterValue) {
- return {};
- }
- values.push_back(*filterValue);
- }
-
- return { FilterType { *key, std::move(values) } };
- }
- }
-
- template <class FilterType, class V>
- optional<Filter> convertCompoundFilter(const V& value, Error& error) const {
- std::vector<Filter> filters;
- for (std::size_t i = 1; i < arrayLength(value); ++i) {
- optional<Filter> element = operator()(arrayMember(value, i), error);
- if (!element) {
- return {};
- }
- filters.push_back(*element);
- }
-
- return { FilterType { std::move(filters) } };
- }
+ optional<Filter> operator()(const Convertible& value, Error& error) const;
};
} // namespace conversion
diff --git a/include/mbgl/style/conversion/function.hpp b/include/mbgl/style/conversion/function.hpp
index 752b6dd045..e230884944 100644
--- a/include/mbgl/style/conversion/function.hpp
+++ b/include/mbgl/style/conversion/function.hpp
@@ -11,8 +11,8 @@ namespace mbgl {
namespace style {
namespace conversion {
-template <class D, class R, class V>
-optional<std::map<D, R>> convertStops(const V& value, Error& error) {
+template <class D, class R>
+optional<std::map<D, R>> convertStops(const Convertible& value, Error& error) {
auto stopsValue = objectMember(value, "stops");
if (!stopsValue) {
error = { "function value must specify stops" };
@@ -63,8 +63,7 @@ template <class T>
struct Converter<ExponentialStops<T>> {
static constexpr const char * type = "exponential";
- template <class V>
- optional<ExponentialStops<T>> operator()(const V& value, Error& error) const {
+ optional<ExponentialStops<T>> operator()(const Convertible& value, Error& error) const {
auto stops = convertStops<float, T>(value, error);
if (!stops) {
return {};
@@ -89,8 +88,7 @@ template <class T>
struct Converter<IntervalStops<T>> {
static constexpr const char * type = "interval";
- template <class V>
- optional<IntervalStops<T>> operator()(const V& value, Error& error) const {
+ optional<IntervalStops<T>> operator()(const Convertible& value, Error& error) const {
auto stops = convertStops<float, T>(value, error);
if (!stops) {
return {};
@@ -101,8 +99,7 @@ struct Converter<IntervalStops<T>> {
template <>
struct Converter<CategoricalValue> {
- template <class V>
- optional<CategoricalValue> operator()(const V& value, Error& error) const {
+ optional<CategoricalValue> operator()(const Convertible& value, Error& error) const {
auto b = toBool(value);
if (b) {
return { *b };
@@ -127,8 +124,7 @@ template <class T>
struct Converter<CategoricalStops<T>> {
static constexpr const char * type = "categorical";
- template <class V>
- optional<CategoricalStops<T>> operator()(const V& value, Error& error) const {
+ optional<CategoricalStops<T>> operator()(const Convertible& value, Error& error) const {
auto stops = convertStops<CategoricalValue, T>(value, error);
if (!stops) {
return {};
@@ -142,8 +138,7 @@ template <class T>
struct Converter<IdentityStops<T>> {
static constexpr const char * type = "identity";
- template <class V>
- optional<IdentityStops<T>> operator()(const V&, Error&) const {
+ optional<IdentityStops<T>> operator()(const Convertible&, Error&) const {
return IdentityStops<T>();
}
};
@@ -154,8 +149,7 @@ struct StopsConverter;
template <class T, class... Ts>
struct StopsConverter<T, variant<Ts...>> {
public:
- template <class V>
- optional<variant<Ts...>> operator()(const V& value, Error& error) const {
+ optional<variant<Ts...>> operator()(const Convertible& value, Error& error) const {
std::string type = util::Interpolatable<T>::value ? "exponential" : "interval";
auto typeValue = objectMember(value, "type");
@@ -193,8 +187,7 @@ public:
template <class T>
struct Converter<CameraFunction<T>> {
- template <class V>
- optional<CameraFunction<T>> operator()(const V& value, Error& error) const {
+ optional<CameraFunction<T>> operator()(const Convertible& value, Error& error) const {
if (!isObject(value)) {
error = { "function must be an object" };
return {};
@@ -209,8 +202,8 @@ struct Converter<CameraFunction<T>> {
}
};
-template <class T, class V>
-optional<optional<T>> convertDefaultValue(const V& value, Error& error) {
+template <class T>
+optional<optional<T>> convertDefaultValue(const Convertible& value, Error& error) {
auto defaultValueValue = objectMember(value, "default");
if (!defaultValueValue) {
return optional<T>();
@@ -227,8 +220,7 @@ optional<optional<T>> convertDefaultValue(const V& value, Error& error) {
template <class T>
struct Converter<SourceFunction<T>> {
- template <class V>
- optional<SourceFunction<T>> operator()(const V& value, Error& error) const {
+ optional<SourceFunction<T>> operator()(const Convertible& value, Error& error) const {
if (!isObject(value)) {
error = { "function must be an object" };
return {};
@@ -267,8 +259,7 @@ struct CompositeValue : std::pair<float, S> {
template <class S>
struct Converter<CompositeValue<S>> {
- template <class V>
- optional<CompositeValue<S>> operator()(const V& value, Error& error) const {
+ optional<CompositeValue<S>> operator()(const Convertible& value, Error& error) const {
if (!isObject(value)) {
error = { "stop must be an object" };
return {};
@@ -304,8 +295,7 @@ template <class T>
struct Converter<CompositeExponentialStops<T>> {
static constexpr const char * type = "exponential";
- template <class V>
- optional<CompositeExponentialStops<T>> operator()(const V& value, Error& error) const {
+ optional<CompositeExponentialStops<T>> operator()(const Convertible& value, Error& error) const {
auto stops = convertStops<CompositeValue<float>, T>(value, error);
if (!stops) {
return {};
@@ -330,8 +320,7 @@ template <class T>
struct Converter<CompositeIntervalStops<T>> {
static constexpr const char * type = "interval";
- template <class V>
- optional<CompositeIntervalStops<T>> operator()(const V& value, Error& error) const {
+ optional<CompositeIntervalStops<T>> operator()(const Convertible& value, Error& error) const {
auto stops = convertStops<CompositeValue<float>, T>(value, error);
if (!stops) {
return {};
@@ -350,8 +339,7 @@ template <class T>
struct Converter<CompositeCategoricalStops<T>> {
static constexpr const char * type = "categorical";
- template <class V>
- optional<CompositeCategoricalStops<T>> operator()(const V& value, Error& error) const {
+ optional<CompositeCategoricalStops<T>> operator()(const Convertible& value, Error& error) const {
auto stops = convertStops<CompositeValue<CategoricalValue>, T>(value, error);
if (!stops) {
return {};
@@ -368,8 +356,7 @@ struct Converter<CompositeCategoricalStops<T>> {
template <class T>
struct Converter<CompositeFunction<T>> {
- template <class V>
- optional<CompositeFunction<T>> operator()(const V& value, Error& error) const {
+ optional<CompositeFunction<T>> operator()(const Convertible& value, Error& error) const {
if (!isObject(value)) {
error = { "function must be an object" };
return {};
diff --git a/include/mbgl/style/conversion/geojson.hpp b/include/mbgl/style/conversion/geojson.hpp
index 0b594f066c..403c5f953b 100644
--- a/include/mbgl/style/conversion/geojson.hpp
+++ b/include/mbgl/style/conversion/geojson.hpp
@@ -7,15 +7,13 @@ namespace mbgl {
namespace style {
namespace conversion {
+// Workaround until https://github.com/mapbox/mapbox-gl-native/issues/5623 is done.
+optional<GeoJSON> parseGeoJSON(const std::string&, Error&);
+
template <>
struct Converter<GeoJSON> {
public:
- optional<GeoJSON> operator()(const std::string&, Error&) const;
-
- // This is explicitly specialized in the .cpp file for JSValue. It may also be explicitly
- // specialized for SDK-specific types (e.g. mbgl::android::Value).
- template <class V>
- optional<GeoJSON> operator()(const V&, Error&) const;
+ optional<GeoJSON> operator()(const Convertible&, Error&) const;
};
} // namespace conversion
diff --git a/include/mbgl/style/conversion/geojson_options.hpp b/include/mbgl/style/conversion/geojson_options.hpp
index 1c9c18250c..3f625babb6 100644
--- a/include/mbgl/style/conversion/geojson_options.hpp
+++ b/include/mbgl/style/conversion/geojson_options.hpp
@@ -9,84 +9,7 @@ namespace conversion {
template <>
struct Converter<GeoJSONOptions> {
-
- template <class V>
- optional<GeoJSONOptions> operator()(const V& value, Error& error) const {
- GeoJSONOptions options;
-
- const auto minzoomValue = objectMember(value, "minzoom");
- if (minzoomValue) {
- if (toNumber(*minzoomValue)) {
- options.minzoom = static_cast<uint8_t>(*toNumber(*minzoomValue));
- } else {
- error = { "GeoJSON source minzoom value must be a number" };
- return {};
- }
- }
-
- const auto maxzoomValue = objectMember(value, "maxzoom");
- if (maxzoomValue) {
- if (toNumber(*maxzoomValue)) {
- options.maxzoom = static_cast<uint8_t>(*toNumber(*maxzoomValue));
- } else {
- error = { "GeoJSON source maxzoom value must be a number" };
- return {};
- }
- }
-
- const auto bufferValue = objectMember(value, "buffer");
- if (bufferValue) {
- if (toNumber(*bufferValue)) {
- options.buffer = static_cast<uint16_t>(*toNumber(*bufferValue));
- } else {
- error = { "GeoJSON source buffer value must be a number" };
- return {};
- }
- }
-
- const auto toleranceValue = objectMember(value, "tolerance");
- if (toleranceValue) {
- if (toNumber(*toleranceValue)) {
- options.tolerance = static_cast<double>(*toNumber(*toleranceValue));
- } else {
- error = { "GeoJSON source tolerance value must be a number" };
- return {};
- }
- }
-
- const auto clusterValue = objectMember(value, "cluster");
- if (clusterValue) {
- if (toBool(*clusterValue)) {
- options.cluster = *toBool(*clusterValue);
- } else {
- error = { "GeoJSON source cluster value must be a boolean" };
- return {};
- }
- }
-
- const auto clusterMaxZoomValue = objectMember(value, "clusterMaxZoom");
- if (clusterMaxZoomValue) {
- if (toNumber(*clusterMaxZoomValue)) {
- options.clusterMaxZoom = static_cast<uint8_t>(*toNumber(*clusterMaxZoomValue));
- } else {
- error = { "GeoJSON source clusterMaxZoom value must be a number" };
- return {};
- }
- }
-
- const auto clusterRadiusValue = objectMember(value, "clusterRadius");
- if (clusterRadiusValue) {
- if (toNumber(*clusterRadiusValue)) {
- options.clusterRadius = static_cast<double>(*toNumber(*clusterRadiusValue));
- } else {
- error = { "GeoJSON source clusterRadius value must be a number" };
- return {};
- }
- }
-
- return { options };
- }
-
+ optional<GeoJSONOptions> operator()(const Convertible& value, Error& error) const;
};
} // namespace conversion
diff --git a/include/mbgl/style/conversion/get_json_type.hpp b/include/mbgl/style/conversion/get_json_type.hpp
new file mode 100644
index 0000000000..f7efebccce
--- /dev/null
+++ b/include/mbgl/style/conversion/get_json_type.hpp
@@ -0,0 +1,14 @@
+#pragma once
+
+#include <mbgl/style/conversion.hpp>
+#include <string>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+std::string getJSONType(const Convertible& value);
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/conversion/layer.hpp b/include/mbgl/style/conversion/layer.hpp
index 1fe467165d..1c0e2e2f07 100644
--- a/include/mbgl/style/conversion/layer.hpp
+++ b/include/mbgl/style/conversion/layer.hpp
@@ -1,220 +1,24 @@
#pragma once
#include <mbgl/style/layer.hpp>
-#include <mbgl/style/layers/background_layer.hpp>
-#include <mbgl/style/layers/circle_layer.hpp>
-#include <mbgl/style/layers/fill_layer.hpp>
-#include <mbgl/style/layers/fill_extrusion_layer.hpp>
-#include <mbgl/style/layers/line_layer.hpp>
-#include <mbgl/style/layers/raster_layer.hpp>
-#include <mbgl/style/layers/symbol_layer.hpp>
#include <mbgl/style/conversion.hpp>
-#include <mbgl/style/conversion/constant.hpp>
-#include <mbgl/style/conversion/filter.hpp>
-#include <mbgl/style/conversion/make_property_setters.hpp>
+
+#include <memory>
namespace mbgl {
namespace style {
namespace conversion {
-template <class V>
-optional<Error> setLayoutProperty(Layer& layer, const std::string& name, const V& value) {
- static const auto setters = makeLayoutPropertySetters<V>();
- auto it = setters.find(name);
- if (it == setters.end()) {
- return Error { "property not found" };
- }
- return it->second(layer, value);
-}
-
-template <class V>
-optional<Error> setPaintProperty(Layer& layer, const std::string& name, const V& value) {
- static const auto setters = makePaintPropertySetters<V>();
- auto it = setters.find(name);
- if (it == setters.end()) {
- return Error { "property not found" };
- }
- return it->second(layer, value);
-}
-
-template <class V>
-optional<Error> setPaintProperties(Layer& layer, const V& value) {
- auto paintValue = objectMember(value, "paint");
- if (!paintValue) {
- return {};
- }
- return eachMember(*paintValue, [&] (const std::string& k, const V& v) {
- return setPaintProperty(layer, k, v);
- });
-}
-
template <>
struct Converter<std::unique_ptr<Layer>> {
public:
- template <class V>
- optional<std::unique_ptr<Layer>> operator()(const V& value, Error& error) const {
- if (!isObject(value)) {
- error = { "layer must be an object" };
- return {};
- }
-
- auto idValue = objectMember(value, "id");
- if (!idValue) {
- error = { "layer must have an id" };
- return {};
- }
-
- optional<std::string> id = toString(*idValue);
- if (!id) {
- error = { "layer id must be a string" };
- return {};
- }
-
- auto typeValue = objectMember(value, "type");
- if (!typeValue) {
- error = { "layer must have a type" };
- return {};
- }
-
- optional<std::string> type = toString(*typeValue);
- if (!type) {
- error = { "layer type must be a string" };
- return {};
- }
-
- optional<std::unique_ptr<Layer>> converted;
-
- if (*type == "fill") {
- converted = convertVectorLayer<FillLayer>(*id, value, error);
- } else if (*type == "fill-extrusion") {
- converted = convertVectorLayer<FillExtrusionLayer>(*id, value, error);
- } else if (*type == "line") {
- converted = convertVectorLayer<LineLayer>(*id, value, error);
- } else if (*type == "circle") {
- converted = convertVectorLayer<CircleLayer>(*id, value, error);
- } else if (*type == "symbol") {
- converted = convertVectorLayer<SymbolLayer>(*id, value, error);
- } else if (*type == "raster") {
- converted = convertRasterLayer(*id, value, error);
- } else if (*type == "background") {
- converted = convertBackgroundLayer(*id, value, error);
- } else {
- error = { "invalid layer type" };
- return {};
- }
-
- if (!converted) {
- return converted;
- }
-
- std::unique_ptr<Layer> layer = std::move(*converted);
-
- auto minzoomValue = objectMember(value, "minzoom");
- if (minzoomValue) {
- optional<float> minzoom = toNumber(*minzoomValue);
- if (!minzoom) {
- error = { "minzoom must be numeric" };
- return {};
- }
- layer->setMinZoom(*minzoom);
- }
-
- auto maxzoomValue = objectMember(value, "maxzoom");
- if (maxzoomValue) {
- optional<float> maxzoom = toNumber(*maxzoomValue);
- if (!maxzoom) {
- error = { "maxzoom must be numeric" };
- return {};
- }
- layer->setMaxZoom(*maxzoom);
- }
-
- auto layoutValue = objectMember(value, "layout");
- if (layoutValue) {
- if (!isObject(*layoutValue)) {
- error = { "layout must be an object" };
- return {};
- }
- optional<Error> error_ = eachMember(*layoutValue, [&] (const std::string& k, const V& v) {
- return setLayoutProperty(*layer, k, v);
- });
- if (error_) {
- error = *error_;
- return {};
- }
- }
-
- optional<Error> error_ = setPaintProperties(*layer, value);
- if (error_) {
- error = *error_;
- return {};
- }
-
- return std::move(layer);
- }
-
-private:
- template <class LayerType, class V>
- optional<std::unique_ptr<Layer>> convertVectorLayer(const std::string& id, const V& value, Error& error) const {
- auto sourceValue = objectMember(value, "source");
- if (!sourceValue) {
- error = { "layer must have a source" };
- return {};
- }
-
- optional<std::string> source = toString(*sourceValue);
- if (!source) {
- error = { "layer source must be a string" };
- return {};
- }
-
- std::unique_ptr<LayerType> layer = std::make_unique<LayerType>(id, *source);
-
- auto sourceLayerValue = objectMember(value, "source-layer");
- if (sourceLayerValue) {
- optional<std::string> sourceLayer = toString(*sourceLayerValue);
- if (!sourceLayer) {
- error = { "layer source-layer must be a string" };
- return {};
- }
- layer->setSourceLayer(*sourceLayer);
- }
-
- auto filterValue = objectMember(value, "filter");
- if (filterValue) {
- optional<Filter> filter = convert<Filter>(*filterValue, error);
- if (!filter) {
- return {};
- }
- layer->setFilter(*filter);
- }
-
- return { std::move(layer) };
- }
-
- template <class V>
- optional<std::unique_ptr<Layer>> convertRasterLayer(const std::string& id, const V& value, Error& error) const {
- auto sourceValue = objectMember(value, "source");
- if (!sourceValue) {
- error = { "layer must have a source" };
- return {};
- }
-
- optional<std::string> source = toString(*sourceValue);
- if (!source) {
- error = { "layer source must be a string" };
- return {};
- }
-
- return { std::make_unique<RasterLayer>(id, *source) };
- }
-
- template <class V>
- optional<std::unique_ptr<Layer>> convertBackgroundLayer(const std::string& id, const V&, Error&) const {
- return { std::make_unique<BackgroundLayer>(id) };
- }
+ optional<std::unique_ptr<Layer>> operator()(const Convertible& value, Error& error) const;
};
+optional<Error> setLayoutProperty(Layer& layer, const std::string& name, const Convertible& value);
+optional<Error> setPaintProperty(Layer& layer, const std::string& name, const Convertible& value);
+optional<Error> setPaintProperties(Layer& layer, const Convertible& value);
+
} // namespace conversion
} // namespace style
} // namespace mbgl
diff --git a/include/mbgl/style/conversion/light.hpp b/include/mbgl/style/conversion/light.hpp
index ba162516c0..289fca2e31 100644
--- a/include/mbgl/style/conversion/light.hpp
+++ b/include/mbgl/style/conversion/light.hpp
@@ -2,9 +2,6 @@
#include <mbgl/style/light.hpp>
#include <mbgl/style/conversion.hpp>
-#include <mbgl/style/conversion/position.hpp>
-#include <mbgl/style/conversion/property_value.hpp>
-#include <mbgl/style/conversion/transition_options.hpp>
namespace mbgl {
namespace style {
@@ -13,108 +10,7 @@ namespace conversion {
template <>
struct Converter<Light> {
public:
- template <class V>
- optional<Light> operator()(const V& value, Error& error) const {
- if (!isObject(value)) {
- error = { "light must be an object" };
- return {};
- }
-
- Light light;
-
- const auto anchor = objectMember(value, "anchor");
- if (anchor) {
- optional<PropertyValue<LightAnchorType>> convertedAnchor =
- convert<PropertyValue<LightAnchorType>>(*anchor, error);
-
- if (convertedAnchor) {
- light.setAnchor(*convertedAnchor);
- } else {
- return {};
- }
- }
-
- const auto anchorTransition = objectMember(value, "anchor-transition");
- if (anchorTransition) {
- optional<TransitionOptions> transition =
- convert<TransitionOptions>(*anchorTransition, error);
- if (transition) {
- light.setAnchorTransition(*transition);
- } else {
- return {};
- }
- }
-
- const auto color = objectMember(value, "color");
- if (color) {
- optional<PropertyValue<Color>> convertedColor =
- convert<PropertyValue<Color>>(*color, error);
-
- if (convertedColor) {
- light.setColor(*convertedColor);
- } else {
- return {};
- }
- }
-
- const auto colorTransition = objectMember(value, "color-transition");
- if (colorTransition) {
- optional<TransitionOptions> transition =
- convert<TransitionOptions>(*colorTransition, error);
- if (transition) {
- light.setColorTransition(*transition);
- } else {
- return {};
- }
- }
-
- const auto position = objectMember(value, "position");
- if (position) {
- optional<PropertyValue<Position>> convertedPosition =
- convert<PropertyValue<Position>>(*position, error);
-
- if (convertedPosition) {
- light.setPosition(*convertedPosition);
- } else {
- return {};
- }
- }
-
- const auto positionTransition = objectMember(value, "position-transition");
- if (positionTransition) {
- optional<TransitionOptions> transition =
- convert<TransitionOptions>(*positionTransition, error);
- if (transition) {
- light.setPositionTransition(*transition);
- } else {
- return {};
- }
- }
-
- const auto intensity = objectMember(value, "intensity");
- if (intensity) {
- optional<PropertyValue<float>> convertedIntensity =
- convert<PropertyValue<float>>(*intensity, error);
-
- if (convertedIntensity) {
- light.setIntensity(*convertedIntensity);
- } else {
- return {};
- }
- }
-
- const auto intensityTransition = objectMember(value, "intensity-transition");
- if (intensityTransition) {
- optional<TransitionOptions> transition =
- convert<TransitionOptions>(*intensityTransition, error);
- if (transition) {
- light.setIntensityTransition(*transition);
- } else {
- return {};
- }
- }
- return { std::move(light) };
- };
+ optional<Light> operator()(const Convertible& value, Error& error) const;
};
} // namespace conversion
diff --git a/include/mbgl/style/conversion/make_property_setters.hpp b/include/mbgl/style/conversion/make_property_setters.hpp
deleted file mode 100644
index 59b0e7be32..0000000000
--- a/include/mbgl/style/conversion/make_property_setters.hpp
+++ /dev/null
@@ -1,211 +0,0 @@
-#pragma once
-
-// This file is generated. Edit make_property_setters.hpp.ejs, then run `make style-code`.
-
-#include <mbgl/style/conversion/property_setter.hpp>
-
-#include <mbgl/style/layers/fill_layer.hpp>
-#include <mbgl/style/layers/line_layer.hpp>
-#include <mbgl/style/layers/symbol_layer.hpp>
-#include <mbgl/style/layers/circle_layer.hpp>
-#include <mbgl/style/layers/fill_extrusion_layer.hpp>
-#include <mbgl/style/layers/raster_layer.hpp>
-#include <mbgl/style/layers/background_layer.hpp>
-
-#include <unordered_map>
-
-namespace mbgl {
-namespace style {
-namespace conversion {
-
-template <class V>
-auto makeLayoutPropertySetters() {
- std::unordered_map<std::string, PropertySetter<V>> result;
-
- result["visibility"] = &setVisibility<V>;
-
-
- result["line-cap"] = &setProperty<V, LineLayer, PropertyValue<LineCapType>, &LineLayer::setLineCap>;
- result["line-join"] = &setProperty<V, LineLayer, DataDrivenPropertyValue<LineJoinType>, &LineLayer::setLineJoin>;
- result["line-miter-limit"] = &setProperty<V, LineLayer, PropertyValue<float>, &LineLayer::setLineMiterLimit>;
- result["line-round-limit"] = &setProperty<V, LineLayer, PropertyValue<float>, &LineLayer::setLineRoundLimit>;
-
- result["symbol-placement"] = &setProperty<V, SymbolLayer, PropertyValue<SymbolPlacementType>, &SymbolLayer::setSymbolPlacement>;
- result["symbol-spacing"] = &setProperty<V, SymbolLayer, PropertyValue<float>, &SymbolLayer::setSymbolSpacing>;
- result["symbol-avoid-edges"] = &setProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setSymbolAvoidEdges>;
- result["icon-allow-overlap"] = &setProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setIconAllowOverlap>;
- result["icon-ignore-placement"] = &setProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setIconIgnorePlacement>;
- result["icon-optional"] = &setProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setIconOptional>;
- result["icon-rotation-alignment"] = &setProperty<V, SymbolLayer, PropertyValue<AlignmentType>, &SymbolLayer::setIconRotationAlignment>;
- result["icon-size"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconSize>;
- result["icon-text-fit"] = &setProperty<V, SymbolLayer, PropertyValue<IconTextFitType>, &SymbolLayer::setIconTextFit>;
- result["icon-text-fit-padding"] = &setProperty<V, SymbolLayer, PropertyValue<std::array<float, 4>>, &SymbolLayer::setIconTextFitPadding>;
- result["icon-image"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<std::string>, &SymbolLayer::setIconImage>;
- result["icon-rotate"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconRotate>;
- result["icon-padding"] = &setProperty<V, SymbolLayer, PropertyValue<float>, &SymbolLayer::setIconPadding>;
- result["icon-keep-upright"] = &setProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setIconKeepUpright>;
- result["icon-offset"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<std::array<float, 2>>, &SymbolLayer::setIconOffset>;
- result["icon-anchor"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<SymbolAnchorType>, &SymbolLayer::setIconAnchor>;
- result["icon-pitch-alignment"] = &setProperty<V, SymbolLayer, PropertyValue<AlignmentType>, &SymbolLayer::setIconPitchAlignment>;
- result["text-pitch-alignment"] = &setProperty<V, SymbolLayer, PropertyValue<AlignmentType>, &SymbolLayer::setTextPitchAlignment>;
- result["text-rotation-alignment"] = &setProperty<V, SymbolLayer, PropertyValue<AlignmentType>, &SymbolLayer::setTextRotationAlignment>;
- result["text-field"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<std::string>, &SymbolLayer::setTextField>;
- result["text-font"] = &setProperty<V, SymbolLayer, PropertyValue<std::vector<std::string>>, &SymbolLayer::setTextFont>;
- result["text-size"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextSize>;
- result["text-max-width"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextMaxWidth>;
- result["text-line-height"] = &setProperty<V, SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextLineHeight>;
- result["text-letter-spacing"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextLetterSpacing>;
- result["text-justify"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<TextJustifyType>, &SymbolLayer::setTextJustify>;
- result["text-anchor"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<SymbolAnchorType>, &SymbolLayer::setTextAnchor>;
- result["text-max-angle"] = &setProperty<V, SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextMaxAngle>;
- result["text-rotate"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextRotate>;
- result["text-padding"] = &setProperty<V, SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextPadding>;
- result["text-keep-upright"] = &setProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setTextKeepUpright>;
- result["text-transform"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<TextTransformType>, &SymbolLayer::setTextTransform>;
- result["text-offset"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<std::array<float, 2>>, &SymbolLayer::setTextOffset>;
- result["text-allow-overlap"] = &setProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setTextAllowOverlap>;
- result["text-ignore-placement"] = &setProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setTextIgnorePlacement>;
- result["text-optional"] = &setProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setTextOptional>;
-
-
-
-
-
- return result;
-}
-
-template <class V>
-auto makePaintPropertySetters() {
- std::unordered_map<std::string, PropertySetter<V>> result;
-
- result["fill-antialias"] = &setProperty<V, FillLayer, PropertyValue<bool>, &FillLayer::setFillAntialias>;
- result["fill-antialias-transition"] = &setTransition<V, FillLayer, &FillLayer::setFillAntialiasTransition>;
- result["fill-opacity"] = &setProperty<V, FillLayer, DataDrivenPropertyValue<float>, &FillLayer::setFillOpacity>;
- result["fill-opacity-transition"] = &setTransition<V, FillLayer, &FillLayer::setFillOpacityTransition>;
- result["fill-color"] = &setProperty<V, FillLayer, DataDrivenPropertyValue<Color>, &FillLayer::setFillColor>;
- result["fill-color-transition"] = &setTransition<V, FillLayer, &FillLayer::setFillColorTransition>;
- result["fill-outline-color"] = &setProperty<V, FillLayer, DataDrivenPropertyValue<Color>, &FillLayer::setFillOutlineColor>;
- result["fill-outline-color-transition"] = &setTransition<V, FillLayer, &FillLayer::setFillOutlineColorTransition>;
- result["fill-translate"] = &setProperty<V, FillLayer, PropertyValue<std::array<float, 2>>, &FillLayer::setFillTranslate>;
- result["fill-translate-transition"] = &setTransition<V, FillLayer, &FillLayer::setFillTranslateTransition>;
- result["fill-translate-anchor"] = &setProperty<V, FillLayer, PropertyValue<TranslateAnchorType>, &FillLayer::setFillTranslateAnchor>;
- result["fill-translate-anchor-transition"] = &setTransition<V, FillLayer, &FillLayer::setFillTranslateAnchorTransition>;
- result["fill-pattern"] = &setProperty<V, FillLayer, PropertyValue<std::string>, &FillLayer::setFillPattern>;
- result["fill-pattern-transition"] = &setTransition<V, FillLayer, &FillLayer::setFillPatternTransition>;
-
- result["line-opacity"] = &setProperty<V, LineLayer, DataDrivenPropertyValue<float>, &LineLayer::setLineOpacity>;
- result["line-opacity-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineOpacityTransition>;
- result["line-color"] = &setProperty<V, LineLayer, DataDrivenPropertyValue<Color>, &LineLayer::setLineColor>;
- result["line-color-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineColorTransition>;
- result["line-translate"] = &setProperty<V, LineLayer, PropertyValue<std::array<float, 2>>, &LineLayer::setLineTranslate>;
- result["line-translate-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineTranslateTransition>;
- result["line-translate-anchor"] = &setProperty<V, LineLayer, PropertyValue<TranslateAnchorType>, &LineLayer::setLineTranslateAnchor>;
- result["line-translate-anchor-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineTranslateAnchorTransition>;
- result["line-width"] = &setProperty<V, LineLayer, DataDrivenPropertyValue<float>, &LineLayer::setLineWidth>;
- result["line-width-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineWidthTransition>;
- result["line-gap-width"] = &setProperty<V, LineLayer, DataDrivenPropertyValue<float>, &LineLayer::setLineGapWidth>;
- result["line-gap-width-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineGapWidthTransition>;
- result["line-offset"] = &setProperty<V, LineLayer, DataDrivenPropertyValue<float>, &LineLayer::setLineOffset>;
- result["line-offset-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineOffsetTransition>;
- result["line-blur"] = &setProperty<V, LineLayer, DataDrivenPropertyValue<float>, &LineLayer::setLineBlur>;
- result["line-blur-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineBlurTransition>;
- result["line-dasharray"] = &setProperty<V, LineLayer, PropertyValue<std::vector<float>>, &LineLayer::setLineDasharray>;
- result["line-dasharray-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineDasharrayTransition>;
- result["line-pattern"] = &setProperty<V, LineLayer, PropertyValue<std::string>, &LineLayer::setLinePattern>;
- result["line-pattern-transition"] = &setTransition<V, LineLayer, &LineLayer::setLinePatternTransition>;
-
- result["icon-opacity"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconOpacity>;
- result["icon-opacity-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setIconOpacityTransition>;
- result["icon-color"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<Color>, &SymbolLayer::setIconColor>;
- result["icon-color-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setIconColorTransition>;
- result["icon-halo-color"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<Color>, &SymbolLayer::setIconHaloColor>;
- result["icon-halo-color-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setIconHaloColorTransition>;
- result["icon-halo-width"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconHaloWidth>;
- result["icon-halo-width-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setIconHaloWidthTransition>;
- result["icon-halo-blur"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconHaloBlur>;
- result["icon-halo-blur-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setIconHaloBlurTransition>;
- result["icon-translate"] = &setProperty<V, SymbolLayer, PropertyValue<std::array<float, 2>>, &SymbolLayer::setIconTranslate>;
- result["icon-translate-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setIconTranslateTransition>;
- result["icon-translate-anchor"] = &setProperty<V, SymbolLayer, PropertyValue<TranslateAnchorType>, &SymbolLayer::setIconTranslateAnchor>;
- result["icon-translate-anchor-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setIconTranslateAnchorTransition>;
- result["text-opacity"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextOpacity>;
- result["text-opacity-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setTextOpacityTransition>;
- result["text-color"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<Color>, &SymbolLayer::setTextColor>;
- result["text-color-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setTextColorTransition>;
- result["text-halo-color"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<Color>, &SymbolLayer::setTextHaloColor>;
- result["text-halo-color-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setTextHaloColorTransition>;
- result["text-halo-width"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextHaloWidth>;
- result["text-halo-width-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setTextHaloWidthTransition>;
- result["text-halo-blur"] = &setProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextHaloBlur>;
- result["text-halo-blur-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setTextHaloBlurTransition>;
- result["text-translate"] = &setProperty<V, SymbolLayer, PropertyValue<std::array<float, 2>>, &SymbolLayer::setTextTranslate>;
- result["text-translate-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setTextTranslateTransition>;
- result["text-translate-anchor"] = &setProperty<V, SymbolLayer, PropertyValue<TranslateAnchorType>, &SymbolLayer::setTextTranslateAnchor>;
- result["text-translate-anchor-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setTextTranslateAnchorTransition>;
-
- result["circle-radius"] = &setProperty<V, CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleRadius>;
- result["circle-radius-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleRadiusTransition>;
- result["circle-color"] = &setProperty<V, CircleLayer, DataDrivenPropertyValue<Color>, &CircleLayer::setCircleColor>;
- result["circle-color-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleColorTransition>;
- result["circle-blur"] = &setProperty<V, CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleBlur>;
- result["circle-blur-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleBlurTransition>;
- result["circle-opacity"] = &setProperty<V, CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleOpacity>;
- result["circle-opacity-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleOpacityTransition>;
- result["circle-translate"] = &setProperty<V, CircleLayer, PropertyValue<std::array<float, 2>>, &CircleLayer::setCircleTranslate>;
- result["circle-translate-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleTranslateTransition>;
- result["circle-translate-anchor"] = &setProperty<V, CircleLayer, PropertyValue<TranslateAnchorType>, &CircleLayer::setCircleTranslateAnchor>;
- result["circle-translate-anchor-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleTranslateAnchorTransition>;
- result["circle-pitch-scale"] = &setProperty<V, CircleLayer, PropertyValue<CirclePitchScaleType>, &CircleLayer::setCirclePitchScale>;
- result["circle-pitch-scale-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCirclePitchScaleTransition>;
- result["circle-pitch-alignment"] = &setProperty<V, CircleLayer, PropertyValue<AlignmentType>, &CircleLayer::setCirclePitchAlignment>;
- result["circle-pitch-alignment-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCirclePitchAlignmentTransition>;
- result["circle-stroke-width"] = &setProperty<V, CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleStrokeWidth>;
- result["circle-stroke-width-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleStrokeWidthTransition>;
- result["circle-stroke-color"] = &setProperty<V, CircleLayer, DataDrivenPropertyValue<Color>, &CircleLayer::setCircleStrokeColor>;
- result["circle-stroke-color-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleStrokeColorTransition>;
- result["circle-stroke-opacity"] = &setProperty<V, CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleStrokeOpacity>;
- result["circle-stroke-opacity-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleStrokeOpacityTransition>;
-
- result["fill-extrusion-opacity"] = &setProperty<V, FillExtrusionLayer, PropertyValue<float>, &FillExtrusionLayer::setFillExtrusionOpacity>;
- result["fill-extrusion-opacity-transition"] = &setTransition<V, FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionOpacityTransition>;
- result["fill-extrusion-color"] = &setProperty<V, FillExtrusionLayer, DataDrivenPropertyValue<Color>, &FillExtrusionLayer::setFillExtrusionColor>;
- result["fill-extrusion-color-transition"] = &setTransition<V, FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionColorTransition>;
- result["fill-extrusion-translate"] = &setProperty<V, FillExtrusionLayer, PropertyValue<std::array<float, 2>>, &FillExtrusionLayer::setFillExtrusionTranslate>;
- result["fill-extrusion-translate-transition"] = &setTransition<V, FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionTranslateTransition>;
- result["fill-extrusion-translate-anchor"] = &setProperty<V, FillExtrusionLayer, PropertyValue<TranslateAnchorType>, &FillExtrusionLayer::setFillExtrusionTranslateAnchor>;
- result["fill-extrusion-translate-anchor-transition"] = &setTransition<V, FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionTranslateAnchorTransition>;
- result["fill-extrusion-pattern"] = &setProperty<V, FillExtrusionLayer, PropertyValue<std::string>, &FillExtrusionLayer::setFillExtrusionPattern>;
- result["fill-extrusion-pattern-transition"] = &setTransition<V, FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionPatternTransition>;
- result["fill-extrusion-height"] = &setProperty<V, FillExtrusionLayer, DataDrivenPropertyValue<float>, &FillExtrusionLayer::setFillExtrusionHeight>;
- result["fill-extrusion-height-transition"] = &setTransition<V, FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionHeightTransition>;
- result["fill-extrusion-base"] = &setProperty<V, FillExtrusionLayer, DataDrivenPropertyValue<float>, &FillExtrusionLayer::setFillExtrusionBase>;
- result["fill-extrusion-base-transition"] = &setTransition<V, FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionBaseTransition>;
-
- result["raster-opacity"] = &setProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterOpacity>;
- result["raster-opacity-transition"] = &setTransition<V, RasterLayer, &RasterLayer::setRasterOpacityTransition>;
- result["raster-hue-rotate"] = &setProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterHueRotate>;
- result["raster-hue-rotate-transition"] = &setTransition<V, RasterLayer, &RasterLayer::setRasterHueRotateTransition>;
- result["raster-brightness-min"] = &setProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterBrightnessMin>;
- result["raster-brightness-min-transition"] = &setTransition<V, RasterLayer, &RasterLayer::setRasterBrightnessMinTransition>;
- result["raster-brightness-max"] = &setProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterBrightnessMax>;
- result["raster-brightness-max-transition"] = &setTransition<V, RasterLayer, &RasterLayer::setRasterBrightnessMaxTransition>;
- result["raster-saturation"] = &setProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterSaturation>;
- result["raster-saturation-transition"] = &setTransition<V, RasterLayer, &RasterLayer::setRasterSaturationTransition>;
- result["raster-contrast"] = &setProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterContrast>;
- result["raster-contrast-transition"] = &setTransition<V, RasterLayer, &RasterLayer::setRasterContrastTransition>;
- result["raster-fade-duration"] = &setProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterFadeDuration>;
- result["raster-fade-duration-transition"] = &setTransition<V, RasterLayer, &RasterLayer::setRasterFadeDurationTransition>;
-
- result["background-color"] = &setProperty<V, BackgroundLayer, PropertyValue<Color>, &BackgroundLayer::setBackgroundColor>;
- result["background-color-transition"] = &setTransition<V, BackgroundLayer, &BackgroundLayer::setBackgroundColorTransition>;
- result["background-pattern"] = &setProperty<V, BackgroundLayer, PropertyValue<std::string>, &BackgroundLayer::setBackgroundPattern>;
- result["background-pattern-transition"] = &setTransition<V, BackgroundLayer, &BackgroundLayer::setBackgroundPatternTransition>;
- result["background-opacity"] = &setProperty<V, BackgroundLayer, PropertyValue<float>, &BackgroundLayer::setBackgroundOpacity>;
- result["background-opacity-transition"] = &setTransition<V, BackgroundLayer, &BackgroundLayer::setBackgroundOpacityTransition>;
-
- return result;
-}
-
-} // namespace conversion
-} // namespace style
-} // namespace mbgl
diff --git a/include/mbgl/style/conversion/make_property_setters.hpp.ejs b/include/mbgl/style/conversion/make_property_setters.hpp.ejs
deleted file mode 100644
index 19c9f70538..0000000000
--- a/include/mbgl/style/conversion/make_property_setters.hpp.ejs
+++ /dev/null
@@ -1,48 +0,0 @@
-#pragma once
-
-// This file is generated. Edit make_property_setters.hpp.ejs, then run `make style-code`.
-
-#include <mbgl/style/conversion/property_setter.hpp>
-
-<% for (const layer of locals.layers) { -%>
-#include <mbgl/style/layers/<%- layer.type.replace('-', '_') %>_layer.hpp>
-<% } -%>
-
-#include <unordered_map>
-
-namespace mbgl {
-namespace style {
-namespace conversion {
-
-template <class V>
-auto makeLayoutPropertySetters() {
- std::unordered_map<std::string, PropertySetter<V>> result;
-
- result["visibility"] = &setVisibility<V>;
-
-<% for (const layer of locals.layers) { -%>
-<% for (const property of layer.layoutProperties) { -%>
- result["<%- property.name %>"] = &setProperty<V, <%- camelize(layer.type) %>Layer, <%- propertyValueType(property) %>, &<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>>;
-<% } -%>
-
-<% } -%>
- return result;
-}
-
-template <class V>
-auto makePaintPropertySetters() {
- std::unordered_map<std::string, PropertySetter<V>> result;
-
-<% for (const layer of locals.layers) { -%>
-<% for (const property of layer.paintProperties) { -%>
- result["<%- property.name %>"] = &setProperty<V, <%- camelize(layer.type) %>Layer, <%- propertyValueType(property) %>, &<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>>;
- result["<%- property.name %>-transition"] = &setTransition<V, <%- camelize(layer.type) %>Layer, &<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>Transition>;
-<% } -%>
-
-<% } -%>
- return result;
-}
-
-} // namespace conversion
-} // namespace style
-} // namespace mbgl
diff --git a/include/mbgl/style/conversion/position.hpp b/include/mbgl/style/conversion/position.hpp
index 7036b03822..044c45862d 100644
--- a/include/mbgl/style/conversion/position.hpp
+++ b/include/mbgl/style/conversion/position.hpp
@@ -2,9 +2,6 @@
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/position.hpp>
-#include <mbgl/util/optional.hpp>
-
-#include <array>
namespace mbgl {
namespace style {
@@ -12,16 +9,7 @@ namespace conversion {
template <>
struct Converter<Position> {
- template <class V>
- optional<Position> operator()(const V& value, Error& error) const {
- optional<std::array<float, 3>> spherical = convert<std::array<float, 3>>(value, error);
-
- if (!spherical) {
- return {};
- }
-
- return Position(*spherical);
- }
+ optional<Position> operator()(const Convertible& value, Error& error) const;
};
} // namespace conversion
diff --git a/include/mbgl/style/conversion/property_value.hpp b/include/mbgl/style/conversion/property_value.hpp
index f8937da07d..97117de2ec 100644
--- a/include/mbgl/style/conversion/property_value.hpp
+++ b/include/mbgl/style/conversion/property_value.hpp
@@ -4,6 +4,11 @@
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/constant.hpp>
#include <mbgl/style/conversion/function.hpp>
+#include <mbgl/style/conversion/expression.hpp>
+#include <mbgl/style/expression/value.hpp>
+#include <mbgl/style/expression/is_constant.hpp>
+#include <mbgl/style/expression/is_expression.hpp>
+#include <mbgl/style/expression/find_zoom_curve.hpp>
namespace mbgl {
namespace style {
@@ -11,10 +16,20 @@ namespace conversion {
template <class T>
struct Converter<PropertyValue<T>> {
- template <class V>
- optional<PropertyValue<T>> operator()(const V& value, Error& error) const {
+ optional<PropertyValue<T>> operator()(const Convertible& value, Error& error) const {
if (isUndefined(value)) {
return PropertyValue<T>();
+ } else if (isExpression(value)) {
+ optional<std::unique_ptr<Expression>> expression = convert<std::unique_ptr<Expression>>(value, error, valueTypeToExpressionType<T>());
+ if (!expression) {
+ return {};
+ }
+ if (isFeatureConstant(**expression)) {
+ return { CameraFunction<T>(std::move(*expression)) };
+ } else {
+ error = { "property expressions not supported" };
+ return {};
+ }
} else if (isObject(value)) {
optional<CameraFunction<T>> function = convert<CameraFunction<T>>(value, error);
if (!function) {
diff --git a/include/mbgl/style/conversion/source.hpp b/include/mbgl/style/conversion/source.hpp
index e0563ac10b..2cf2e36da4 100644
--- a/include/mbgl/style/conversion/source.hpp
+++ b/include/mbgl/style/conversion/source.hpp
@@ -1,16 +1,9 @@
#pragma once
#include <mbgl/style/conversion.hpp>
-#include <mbgl/style/conversion/coordinate.hpp>
-#include <mbgl/style/conversion/geojson.hpp>
-#include <mbgl/style/conversion/geojson_options.hpp>
-#include <mbgl/style/conversion/tileset.hpp>
#include <mbgl/style/source.hpp>
-#include <mbgl/style/sources/geojson_source.hpp>
-#include <mbgl/style/sources/raster_source.hpp>
-#include <mbgl/style/sources/vector_source.hpp>
-#include <mbgl/style/sources/image_source.hpp>
-#include <mbgl/util/geo.hpp>
+
+#include <memory>
namespace mbgl {
namespace style {
@@ -19,170 +12,7 @@ namespace conversion {
template <>
struct Converter<std::unique_ptr<Source>> {
public:
-
- template <class V>
- optional<std::unique_ptr<Source>> operator()(const V& value, Error& error, const std::string& id) const {
- if (!isObject(value)) {
- error = { "source must be an object" };
- return {};
- }
-
- auto typeValue = objectMember(value, "type");
- if (!typeValue) {
- error = { "source must have a type" };
- return {};
- }
-
- optional<std::string> type = toString(*typeValue);
- if (!type) {
- error = { "source type must be a string" };
- return {};
- }
-
- if (*type == "raster") {
- return convertRasterSource(id, value, error);
- } else if (*type == "vector") {
- return convertVectorSource(id, value, error);
- } else if (*type == "geojson") {
- return convertGeoJSONSource(id, value, error);
- } else if (*type == "image") {
- return convertImageSource(id, value, error);
- } else {
- error = { "invalid source type" };
- return {};
- }
- }
-
-private:
- // A tile source can either specify a URL to TileJSON, or inline TileJSON.
- template <class V>
- optional<variant<std::string, Tileset>> convertURLOrTileset(const V& value, Error& error) const {
- auto urlVal = objectMember(value, "url");
- if (!urlVal) {
- optional<Tileset> tileset = convert<Tileset>(value, error);
- if (!tileset) {
- return {};
- }
- return { *tileset };
- }
-
- optional<std::string> url = toString(*urlVal);
- if (!url) {
- error = { "source url must be a string" };
- return {};
- }
-
- return { *url };
- }
-
- template <class V>
- optional<std::unique_ptr<Source>> convertRasterSource(const std::string& id,
- const V& value,
- Error& error) const {
- optional<variant<std::string, Tileset>> urlOrTileset = convertURLOrTileset(value, error);
- if (!urlOrTileset) {
- return {};
- }
-
- uint16_t tileSize = util::tileSize;
- auto tileSizeValue = objectMember(value, "tileSize");
- if (tileSizeValue) {
- optional<float> size = toNumber(*tileSizeValue);
- if (!size || *size < 0 || *size > std::numeric_limits<uint16_t>::max()) {
- error = { "invalid tileSize" };
- return {};
- }
- tileSize = *size;
- }
-
- return { std::make_unique<RasterSource>(id, std::move(*urlOrTileset), tileSize) };
- }
-
- template <class V>
- optional<std::unique_ptr<Source>> convertVectorSource(const std::string& id,
- const V& value,
- Error& error) const {
- optional<variant<std::string, Tileset>> urlOrTileset = convertURLOrTileset(value, error);
- if (!urlOrTileset) {
- return {};
- }
-
- return { std::make_unique<VectorSource>(id, std::move(*urlOrTileset)) };
- }
-
- template <class V>
- optional<std::unique_ptr<Source>> convertGeoJSONSource(const std::string& id,
- const V& value,
- Error& error) const {
- auto dataValue = objectMember(value, "data");
- if (!dataValue) {
- error = { "GeoJSON source must have a data value" };
- return {};
- }
-
- optional<GeoJSONOptions> options = convert<GeoJSONOptions>(value, error);
- if (!options) {
- return {};
- }
-
- auto result = std::make_unique<GeoJSONSource>(id, *options);
-
- if (isObject(*dataValue)) {
- optional<GeoJSON> geoJSON = convert<GeoJSON>(*dataValue, error);
- if (!geoJSON) {
- return {};
- }
- result->setGeoJSON(std::move(*geoJSON));
- } else if (toString(*dataValue)) {
- result->setURL(*toString(*dataValue));
- } else {
- error = { "GeoJSON data must be a URL or an object" };
- return {};
- }
-
- return { std::move(result) };
- }
-
- template <class V>
- optional<std::unique_ptr<Source>> convertImageSource(const std::string& id,
- const V& value,
- Error& error) const {
- auto urlValue = objectMember(value, "url");
- if (!urlValue) {
- error = { "Image source must have a url value" };
- return {};
- }
-
- auto urlString = toString(*urlValue);
- if (!urlString) {
- error = { "Image url must be a URL string" };
- return {};
- }
-
- auto coordinatesValue = objectMember(value, "coordinates");
- if (!coordinatesValue) {
- error = { "Image source must have a coordinates values" };
- return {};
- }
-
- if (!isArray(*coordinatesValue) || arrayLength(*coordinatesValue) != 4) {
- error = { "Image coordinates must be an array of four longitude latitude pairs" };
- return {};
- }
-
- std::array<LatLng, 4> coordinates;
- for (std::size_t i=0; i < 4; i++) {
- auto latLng = conversion::convert<LatLng>(arrayMember(*coordinatesValue,i), error);
- if (!latLng) {
- return {};
- }
- coordinates[i] = *latLng;
- }
- auto result = std::make_unique<ImageSource>(id, coordinates);
- result->setURL(*urlString);
-
- return { std::move(result) };
- }
+ optional<std::unique_ptr<Source>> operator()(const Convertible& value, Error& error, const std::string& id) const;
};
} // namespace conversion
diff --git a/include/mbgl/style/conversion/tileset.hpp b/include/mbgl/style/conversion/tileset.hpp
index 377170aa6a..1fb4acf70d 100644
--- a/include/mbgl/style/conversion/tileset.hpp
+++ b/include/mbgl/style/conversion/tileset.hpp
@@ -10,70 +10,7 @@ namespace conversion {
template <>
struct Converter<Tileset> {
public:
- template <class V>
- optional<Tileset> operator()(const V& value, Error& error) const {
- Tileset result;
-
- auto tiles = objectMember(value, "tiles");
- if (!tiles) {
- error = { "source must have tiles" };
- return {};
- }
-
- if (!isArray(*tiles)) {
- error = { "source tiles must be an array" };
- return {};
- }
-
- for (std::size_t i = 0; i < arrayLength(*tiles); i++) {
- optional<std::string> urlTemplate = toString(arrayMember(*tiles, i));
- if (!urlTemplate) {
- error = { "source tiles member must be a string" };
- return {};
- }
- result.tiles.push_back(std::move(*urlTemplate));
- }
-
- auto schemeValue = objectMember(value, "scheme");
- if (schemeValue) {
- optional<std::string> scheme = toString(*schemeValue);
- if (scheme && *scheme == "tms") {
- result.scheme = Tileset::Scheme::TMS;
- }
- }
-
- auto minzoomValue = objectMember(value, "minzoom");
- if (minzoomValue) {
- optional<float> minzoom = toNumber(*minzoomValue);
- if (!minzoom || *minzoom < 0 || *minzoom > std::numeric_limits<uint8_t>::max()) {
- error = { "invalid minzoom" };
- return {};
- }
- result.zoomRange.min = *minzoom;
- }
-
- auto maxzoomValue = objectMember(value, "maxzoom");
- if (maxzoomValue) {
- optional<float> maxzoom = toNumber(*maxzoomValue);
- if (!maxzoom || *maxzoom < 0 || *maxzoom > std::numeric_limits<uint8_t>::max()) {
- error = { "invalid maxzoom" };
- return {};
- }
- result.zoomRange.max = *maxzoom;
- }
-
- auto attributionValue = objectMember(value, "attribution");
- if (attributionValue) {
- optional<std::string> attribution = toString(*attributionValue);
- if (!attribution) {
- error = { "source attribution must be a string" };
- return {};
- }
- result.attribution = std::move(*attribution);
- }
-
- return result;
- }
+ optional<Tileset> operator()(const Convertible& value, Error& error) const;
};
} // namespace conversion
diff --git a/include/mbgl/style/conversion/transition_options.hpp b/include/mbgl/style/conversion/transition_options.hpp
index de8834d578..0563f39ac3 100644
--- a/include/mbgl/style/conversion/transition_options.hpp
+++ b/include/mbgl/style/conversion/transition_options.hpp
@@ -10,37 +10,7 @@ namespace conversion {
template <>
struct Converter<TransitionOptions> {
public:
- template <class V>
- optional<TransitionOptions> operator()(const V& value, Error& error) const {
- if (!isObject(value)) {
- error = { "transition must be an object" };
- return {};
- }
-
- TransitionOptions result;
-
- auto duration = objectMember(value, "duration");
- if (duration) {
- auto number = toNumber(*duration);
- if (!number) {
- error = { "duration must be a number" };
- return {};
- }
- result.duration = { std::chrono::milliseconds(int64_t(*number)) };
- }
-
- auto delay = objectMember(value, "delay");
- if (delay) {
- auto number = toNumber(*delay);
- if (!number) {
- error = { "delay must be a number" };
- return {};
- }
- result.delay = { std::chrono::milliseconds(int64_t(*number)) };
- }
-
- return result;
- }
+ optional<TransitionOptions> operator()(const Convertible& value, Error& error) const;
};
} // namespace conversion
diff --git a/include/mbgl/style/expression/array_assertion.hpp b/include/mbgl/style/expression/array_assertion.hpp
new file mode 100644
index 0000000000..2516eea024
--- /dev/null
+++ b/include/mbgl/style/expression/array_assertion.hpp
@@ -0,0 +1,39 @@
+#pragma once
+
+#include <mbgl/style/expression/expression.hpp>
+#include <mbgl/style/expression/type.hpp>
+#include <mbgl/style/expression/parsing_context.hpp>
+#include <mbgl/style/conversion.hpp>
+
+#include <memory>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+class ArrayAssertion : public Expression {
+public:
+ ArrayAssertion(type::Array type_, std::unique_ptr<Expression> input_) :
+ Expression(type_),
+ input(std::move(input_))
+ {}
+
+ static ParseResult parse(const mbgl::style::conversion::Convertible& value, ParsingContext& ctx);
+
+ EvaluationResult evaluate(const EvaluationContext& params) const override;
+ void eachChild(const std::function<void(const Expression&)>& visit) const override;
+
+ bool operator==(const Expression& e) const override {
+ if (auto rhs = dynamic_cast<const ArrayAssertion*>(&e)) {
+ return getType() == rhs->getType() && *input == *(rhs->input);
+ }
+ return false;
+ }
+
+private:
+ std::unique_ptr<Expression> input;
+};
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/expression/assertion.hpp b/include/mbgl/style/expression/assertion.hpp
new file mode 100644
index 0000000000..504d49f4e5
--- /dev/null
+++ b/include/mbgl/style/expression/assertion.hpp
@@ -0,0 +1,33 @@
+#pragma once
+#include <mbgl/style/expression/expression.hpp>
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/expression/parsing_context.hpp>
+#include <memory>
+#include <vector>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+class Assertion : public Expression {
+public:
+ Assertion(type::Type type_, std::vector<std::unique_ptr<Expression>> inputs_) :
+ Expression(type_),
+ inputs(std::move(inputs_))
+ {}
+
+ static ParseResult parse(const mbgl::style::conversion::Convertible& value, ParsingContext& ctx);
+
+ EvaluationResult evaluate(const EvaluationContext& params) const override;
+ void eachChild(const std::function<void(const Expression&)>& visit) const override;
+
+ bool operator==(const Expression& e) const override;
+
+private:
+ std::vector<std::unique_ptr<Expression>> inputs;
+};
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
+
diff --git a/include/mbgl/style/expression/at.hpp b/include/mbgl/style/expression/at.hpp
new file mode 100644
index 0000000000..e3eefa4fe8
--- /dev/null
+++ b/include/mbgl/style/expression/at.hpp
@@ -0,0 +1,38 @@
+#pragma once
+
+#include <mbgl/style/expression/expression.hpp>
+#include <mbgl/style/conversion.hpp>
+#include <memory>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+class At : public Expression {
+public:
+ At(std::unique_ptr<Expression> index_, std::unique_ptr<Expression> input_) :
+ Expression(input_->getType().get<type::Array>().itemType),
+ index(std::move(index_)),
+ input(std::move(input_))
+ {}
+
+ static ParseResult parse(const mbgl::style::conversion::Convertible& value, ParsingContext& ctx);
+
+ EvaluationResult evaluate(const EvaluationContext& params) const override;
+ void eachChild(const std::function<void(const Expression&)>&) const override;
+
+ bool operator==(const Expression& e) const override {
+ if (auto rhs = dynamic_cast<const At*>(&e)) {
+ return *index == *(rhs->index) && *input == *(rhs->input);
+ }
+ return false;
+ }
+
+private:
+ std::unique_ptr<Expression> index;
+ std::unique_ptr<Expression> input;
+};
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/expression/boolean_operator.hpp b/include/mbgl/style/expression/boolean_operator.hpp
new file mode 100644
index 0000000000..01231d706b
--- /dev/null
+++ b/include/mbgl/style/expression/boolean_operator.hpp
@@ -0,0 +1,49 @@
+#pragma once
+
+#include <mbgl/style/expression/expression.hpp>
+#include <mbgl/style/conversion.hpp>
+#include <memory>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+class Any : public Expression {
+public:
+ Any(std::vector<std::unique_ptr<Expression>> inputs_) :
+ Expression(type::Boolean),
+ inputs(std::move(inputs_))
+ {}
+
+ static ParseResult parse(const mbgl::style::conversion::Convertible& value, ParsingContext& ctx);
+
+ EvaluationResult evaluate(const EvaluationContext& params) const override;
+ void eachChild(const std::function<void(const Expression&)>& visit) const override;
+ bool operator==(const Expression& e) const override;
+
+private:
+ std::vector<std::unique_ptr<Expression>> inputs;
+};
+
+class All : public Expression {
+public:
+ All(std::vector<std::unique_ptr<Expression>> inputs_) :
+ Expression(type::Boolean),
+ inputs(std::move(inputs_))
+ {}
+
+ static ParseResult parse(const mbgl::style::conversion::Convertible& value, ParsingContext& ctx);
+
+ EvaluationResult evaluate(const EvaluationContext& params) const override;
+ void eachChild(const std::function<void(const Expression&)>& visit) const override;
+
+ bool operator==(const Expression& e) const override;
+
+private:
+ std::vector<std::unique_ptr<Expression>> inputs;
+};
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
+
diff --git a/include/mbgl/style/expression/case.hpp b/include/mbgl/style/expression/case.hpp
new file mode 100644
index 0000000000..ece2fe0329
--- /dev/null
+++ b/include/mbgl/style/expression/case.hpp
@@ -0,0 +1,36 @@
+#pragma once
+
+#include <mbgl/style/expression/expression.hpp>
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/expression/parsing_context.hpp>
+
+#include <memory>
+#include <vector>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+class Case : public Expression {
+public:
+ using Branch = std::pair<std::unique_ptr<Expression>, std::unique_ptr<Expression>>;
+
+ Case(type::Type type_, std::vector<Branch> branches_, std::unique_ptr<Expression> otherwise_)
+ : Expression(type_), branches(std::move(branches_)), otherwise(std::move(otherwise_)) {
+ }
+
+ static ParseResult parse(const mbgl::style::conversion::Convertible& value, ParsingContext& ctx);
+
+ EvaluationResult evaluate(const EvaluationContext& params) const override;
+ void eachChild(const std::function<void(const Expression&)>& visit) const override;
+
+ bool operator==(const Expression& e) const override;
+
+private:
+ std::vector<Branch> branches;
+ std::unique_ptr<Expression> otherwise;
+};
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/expression/check_subtype.hpp b/include/mbgl/style/expression/check_subtype.hpp
new file mode 100644
index 0000000000..90e5169de7
--- /dev/null
+++ b/include/mbgl/style/expression/check_subtype.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+#include <mbgl/style/expression/type.hpp>
+#include <mbgl/util/optional.hpp>
+#include <memory>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+namespace type {
+
+optional<std::string> checkSubtype(const Type& expected, const Type& t);
+
+} // namespace type
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/expression/coalesce.hpp b/include/mbgl/style/expression/coalesce.hpp
new file mode 100644
index 0000000000..4e6a9b3793
--- /dev/null
+++ b/include/mbgl/style/expression/coalesce.hpp
@@ -0,0 +1,45 @@
+#pragma once
+
+#include <mbgl/style/expression/expression.hpp>
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/expression/parsing_context.hpp>
+
+#include <memory>
+#include <map>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+class Coalesce : public Expression {
+public:
+ using Args = std::vector<std::unique_ptr<Expression>>;
+ Coalesce(const type::Type& type_, Args args_) :
+ Expression(type_),
+ args(std::move(args_))
+ {}
+
+ static ParseResult parse(const mbgl::style::conversion::Convertible& value, ParsingContext& ctx);
+
+
+ EvaluationResult evaluate(const EvaluationContext& params) const override;
+
+ void eachChild(const std::function<void(const Expression&)>& visit) const override;
+
+ bool operator==(const Expression& e) const override;
+
+ std::size_t getLength() const {
+ return args.size();
+ }
+
+ Expression* getChild(std::size_t i) const {
+ return args.at(i).get();
+ }
+
+private:
+ Args args;
+};
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/expression/coercion.hpp b/include/mbgl/style/expression/coercion.hpp
new file mode 100644
index 0000000000..665bb7ce7c
--- /dev/null
+++ b/include/mbgl/style/expression/coercion.hpp
@@ -0,0 +1,34 @@
+#pragma once
+#include <mbgl/style/expression/expression.hpp>
+#include <mbgl/style/conversion.hpp>
+#include <memory>
+#include <vector>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+/**
+ * Special form for error-coalescing coercion expressions "to-number",
+ * "to-color". Since these coercions can fail at runtime, they accept multiple
+ * arguments, only evaluating one at a time until one succeeds.
+ */
+class Coercion : public Expression {
+public:
+ Coercion(type::Type type_, std::vector<std::unique_ptr<Expression>> inputs_);
+
+ static ParseResult parse(const mbgl::style::conversion::Convertible& value, ParsingContext& ctx);
+
+ EvaluationResult evaluate(const EvaluationContext& params) const override;
+ void eachChild(const std::function<void(const Expression&)>& visit) const override;
+
+ bool operator==(const Expression& e) const override;
+private:
+ EvaluationResult (*coerceSingleValue) (const Value& v);
+ std::vector<std::unique_ptr<Expression>> inputs;
+};
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
+
diff --git a/include/mbgl/style/expression/compound_expression.hpp b/include/mbgl/style/expression/compound_expression.hpp
new file mode 100644
index 0000000000..fc3edbfd4a
--- /dev/null
+++ b/include/mbgl/style/expression/compound_expression.hpp
@@ -0,0 +1,138 @@
+#pragma once
+
+#include <mbgl/style/expression/expression.hpp>
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/expression/parsing_context.hpp>
+#include <mbgl/style/expression/type.hpp>
+#include <mbgl/style/expression/value.hpp>
+
+#include <mbgl/util/optional.hpp>
+#include <mbgl/util/variant.hpp>
+
+#include <memory>
+#include <vector>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+/*
+ CompoundExpression provides a mechanism for implementing an expression
+ simply by providing a list of pure functions of the form
+ (const T0& arg0, const T1& arg1, ...) -> Result<U> where T0, T1, ..., U are
+ member types of mbgl::style::expression::Value.
+
+ The majority of expressions specified in the style-spec are implemented in
+ this fashion (see compound_expression.cpp).
+*/
+
+
+/*
+ Represents the parameter list for an expression that takes an arbitrary
+ number of arguments (of a specific type).
+*/
+struct VarargsType { type::Type type; };
+template <typename T>
+struct Varargs : std::vector<T> { using std::vector<T>::vector; };
+
+namespace detail {
+// Base class for the Signature<Fn> structs that are used to determine the
+// each CompoundExpression definition's type::Type data from the type of its
+// "evaluate" function.
+struct SignatureBase {
+ SignatureBase(type::Type result_, variant<std::vector<type::Type>, VarargsType> params_) :
+ result(std::move(result_)),
+ params(std::move(params_))
+ {}
+ virtual ~SignatureBase() = default;
+ virtual std::unique_ptr<Expression> makeExpression(const std::string& name, std::vector<std::unique_ptr<Expression>>) const = 0;
+ type::Type result;
+ variant<std::vector<type::Type>, VarargsType> params;
+};
+} // namespace detail
+
+
+/*
+ Common base class for CompoundExpression<Signature> instances. Used to
+ allow downcasting (and access to things like name & parameter list) during
+ an Expression tree traversal.
+*/
+class CompoundExpressionBase : public Expression {
+public:
+ CompoundExpressionBase(std::string name_, const detail::SignatureBase& signature) :
+ Expression(signature.result),
+ name(std::move(name_)),
+ params(signature.params)
+ {}
+
+ std::string getName() const { return name; }
+ optional<std::size_t> getParameterCount() const {
+ return params.match(
+ [&](const VarargsType&) { return optional<std::size_t>(); },
+ [&](const std::vector<type::Type>& p) -> optional<std::size_t> { return p.size(); }
+ );
+ }
+
+private:
+ std::string name;
+ variant<std::vector<type::Type>, VarargsType> params;
+};
+
+template <typename Signature>
+class CompoundExpression : public CompoundExpressionBase {
+public:
+ using Args = typename Signature::Args;
+
+ CompoundExpression(const std::string& name_,
+ Signature signature_,
+ typename Signature::Args args_) :
+ CompoundExpressionBase(name_, signature_),
+ signature(signature_),
+ args(std::move(args_))
+ {}
+
+ EvaluationResult evaluate(const EvaluationContext& evaluationParams) const override {
+ return signature.apply(evaluationParams, args);
+ }
+
+ void eachChild(const std::function<void(const Expression&)>& visit) const override {
+ for (const std::unique_ptr<Expression>& e : args) {
+ visit(*e);
+ }
+ }
+
+ bool operator==(const Expression& e) const override {
+ if (auto rhs = dynamic_cast<const CompoundExpression*>(&e)) {
+ return getName() == rhs->getName() && Expression::childrenEqual(args, rhs->args);
+ }
+ return false;
+ }
+
+private:
+ Signature signature;
+ typename Signature::Args args;
+};
+
+/*
+ Holds the map of expression name => implementation (which is just one or
+ more evaluation functions, each wrapped in a Signature struct).
+*/
+struct CompoundExpressionRegistry {
+ using Definition = std::vector<std::unique_ptr<detail::SignatureBase>>;
+ static std::unordered_map<std::string, Definition> definitions;
+};
+
+ParseResult parseCompoundExpression(const std::string name, const mbgl::style::conversion::Convertible& value, ParsingContext& ctx);
+
+ParseResult createCompoundExpression(const std::string& name,
+ const CompoundExpressionRegistry::Definition& definition,
+ std::vector<std::unique_ptr<Expression>> args,
+ ParsingContext& ctx);
+
+ParseResult createCompoundExpression(const std::string& name,
+ std::vector<std::unique_ptr<Expression>> args,
+ ParsingContext& ctx);
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/expression/expression.hpp b/include/mbgl/style/expression/expression.hpp
new file mode 100644
index 0000000000..a22fc28724
--- /dev/null
+++ b/include/mbgl/style/expression/expression.hpp
@@ -0,0 +1,173 @@
+#pragma once
+
+#include <array>
+#include <vector>
+#include <memory>
+#include <mbgl/util/optional.hpp>
+#include <mbgl/util/variant.hpp>
+#include <mbgl/util/color.hpp>
+#include <mbgl/style/expression/type.hpp>
+#include <mbgl/style/expression/value.hpp>
+#include <mbgl/style/expression/parsing_context.hpp>
+
+namespace mbgl {
+
+class GeometryTileFeature;
+
+namespace style {
+namespace expression {
+
+class EvaluationError {
+public:
+ std::string message;
+};
+
+class EvaluationContext {
+public:
+ EvaluationContext(float zoom_) : zoom(zoom_), feature(nullptr) {}
+ EvaluationContext(GeometryTileFeature const * feature_) : zoom(optional<float>()), feature(feature_) {}
+ EvaluationContext(float zoom_, GeometryTileFeature const * feature_) :
+ zoom(zoom_), feature(feature_)
+ {}
+ EvaluationContext(optional<float> zoom_, GeometryTileFeature const * feature_, optional<double> heatmapDensity_) :
+ zoom(std::move(zoom_)), feature(feature_), heatmapDensity(std::move(heatmapDensity_))
+ {}
+
+ optional<float> zoom;
+ GeometryTileFeature const * feature;
+ optional<double> heatmapDensity;
+};
+
+template<typename T>
+class Result : private variant<EvaluationError, T> {
+public:
+ using variant<EvaluationError, T>::variant;
+ using Value = T;
+
+ Result() = default;
+
+ explicit operator bool () const {
+ return this->template is<T>();
+ }
+
+ // optional does some type trait magic for this one, so this might
+ // be problematic as is.
+ const T* operator->() const {
+ assert(this->template is<T>());
+ return std::addressof(this->template get<T>());
+ }
+
+ T* operator->() {
+ assert(this->template is<T>());
+ return std::addressof(this->template get<T>());
+ }
+
+ T& operator*() {
+ assert(this->template is<T>());
+ return this->template get<T>();
+ }
+
+ const T& operator*() const {
+ assert(this->template is<T>());
+ return this->template get<T>();
+ }
+
+ const EvaluationError& error() const {
+ assert(this->template is<EvaluationError>());
+ return this->template get<EvaluationError>();
+ }
+};
+
+class EvaluationResult : public Result<Value> {
+public:
+ using Result::Result; // NOLINT
+
+ EvaluationResult() = default;
+
+ EvaluationResult(const std::array<double, 4>& arr) :
+ Result(toExpressionValue(arr))
+ {}
+
+ // used only for the special (private) "error" expression
+ EvaluationResult(const type::ErrorType&) {
+ assert(false);
+ }
+};
+
+/*
+ Expression is an abstract class that serves as an interface and base class
+ for particular expression implementations.
+
+ CompoundExpression implements the majority of expressions in the spec by
+ inferring the argument and output from a simple function (const T0& arg0,
+ const T1& arg1, ...) -> Result<U> where T0, T1, ..., U are member types of
+ mbgl::style::expression::Value.
+
+ The other Expression subclasses (Let, Curve, Match, etc.) exist in order to
+ implement expressions that need specialized parsing, type checking, or
+ evaluation logic that can't be handled by CompoundExpression's inference
+ mechanism.
+
+ Each Expression subclass also provides a static
+ ParseResult ExpressionClass::parse(const V&, ParsingContext),
+ which handles parsing a style-spec JSON representation of the expression.
+*/
+class Expression {
+public:
+ Expression(type::Type type_) : type(std::move(type_)) {}
+ virtual ~Expression() = default;
+
+ virtual EvaluationResult evaluate(const EvaluationContext& params) const = 0;
+ virtual void eachChild(const std::function<void(const Expression&)>&) const = 0;
+ virtual bool operator==(const Expression&) const = 0;
+ bool operator!=(const Expression& rhs) const {
+ return !operator==(rhs);
+ }
+
+ type::Type getType() const { return type; };
+
+ EvaluationResult evaluate(optional<float> zoom, const Feature& feature, optional<double> heatmapDensity) const;
+
+protected:
+ template <typename T>
+ static bool childrenEqual(const T& lhs, const T& rhs) {
+ if (lhs.size() != rhs.size()) return false;
+ for (auto leftChild = lhs.begin(), rightChild = rhs.begin();
+ leftChild != lhs.end();
+ leftChild++, rightChild++)
+ {
+ if (!Expression::childEqual(*leftChild, *rightChild)) return false;
+ }
+ return true;
+ }
+
+ static bool childEqual(const std::unique_ptr<Expression>& lhs, const std::unique_ptr<Expression>& rhs) {
+ return *lhs == *rhs;
+ }
+
+ template <typename T>
+ static bool childEqual(const std::pair<T, std::unique_ptr<Expression>>& lhs,
+ const std::pair<T, std::unique_ptr<Expression>>& rhs) {
+ return lhs.first == rhs.first && *(lhs.second) == *(rhs.second);
+ }
+
+ template <typename T>
+ static bool childEqual(const std::pair<T, std::shared_ptr<Expression>>& lhs,
+ const std::pair<T, std::shared_ptr<Expression>>& rhs) {
+ return lhs.first == rhs.first && *(lhs.second) == *(rhs.second);
+ }
+
+ static bool childEqual(const std::pair<std::unique_ptr<Expression>, std::unique_ptr<Expression>>& lhs,
+ const std::pair<std::unique_ptr<Expression>, std::unique_ptr<Expression>>& rhs) {
+ return *(lhs.first) == *(rhs.first) && *(lhs.second) == *(rhs.second);
+ }
+
+
+
+private:
+ type::Type type;
+};
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/expression/find_zoom_curve.hpp b/include/mbgl/style/expression/find_zoom_curve.hpp
new file mode 100644
index 0000000000..6301938033
--- /dev/null
+++ b/include/mbgl/style/expression/find_zoom_curve.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <mbgl/style/expression/parsing_context.hpp>
+#include <mbgl/style/expression/interpolate.hpp>
+#include <mbgl/style/expression/step.hpp>
+
+#include <mbgl/util/variant.hpp>
+#include <mbgl/util/optional.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+optional<variant<const InterpolateBase*, const Step*, ParsingError>> findZoomCurve(const expression::Expression* e);
+
+variant<const InterpolateBase*, const Step*> findZoomCurveChecked(const expression::Expression* e);
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/expression/get_covering_stops.hpp b/include/mbgl/style/expression/get_covering_stops.hpp
new file mode 100644
index 0000000000..157aefe7bc
--- /dev/null
+++ b/include/mbgl/style/expression/get_covering_stops.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include <mbgl/style/expression/expression.hpp>
+#include <mbgl/util/range.hpp>
+#include <memory>
+#include <map>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+// Return the smallest range of stops that covers the interval [lower, upper]
+Range<float> getCoveringStops(const std::map<double, std::unique_ptr<Expression>>& stops,
+ const double lower, const double upper);
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/expression/interpolate.hpp b/include/mbgl/style/expression/interpolate.hpp
new file mode 100644
index 0000000000..439122f91c
--- /dev/null
+++ b/include/mbgl/style/expression/interpolate.hpp
@@ -0,0 +1,177 @@
+#pragma once
+
+#include <mbgl/style/expression/expression.hpp>
+#include <mbgl/style/expression/parsing_context.hpp>
+#include <mbgl/style/expression/get_covering_stops.hpp>
+#include <mbgl/style/conversion.hpp>
+
+#include <mbgl/util/interpolate.hpp>
+#include <mbgl/util/range.hpp>
+#include <mbgl/util/unitbezier.hpp>
+
+#include <memory>
+#include <map>
+
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+class ExponentialInterpolator {
+public:
+ ExponentialInterpolator(double base_) : base(base_) {}
+
+ double base;
+
+ double interpolationFactor(const Range<double>& inputLevels, const double input) const {
+ return util::interpolationFactor(base,
+ Range<float> {
+ static_cast<float>(inputLevels.min),
+ static_cast<float>(inputLevels.max)
+ },
+ input);
+ }
+
+ bool operator==(const ExponentialInterpolator& rhs) const {
+ return base == rhs.base;
+ }
+};
+
+class CubicBezierInterpolator {
+public:
+ CubicBezierInterpolator(double x1_, double y1_, double x2_, double y2_) : ub(x1_, y1_, x2_, y2_) {}
+
+ double interpolationFactor(const Range<double>& inputLevels, const double input) const {
+ return ub.solve(input / (inputLevels.max - inputLevels.min), 1e-6);
+ }
+
+ bool operator==(const CubicBezierInterpolator& rhs) const {
+ return ub == rhs.ub;
+ }
+
+ util::UnitBezier ub;
+};
+
+
+ParseResult parseInterpolate(const mbgl::style::conversion::Convertible& value, ParsingContext& ctx);
+
+class InterpolateBase : public Expression {
+public:
+ using Interpolator = variant<ExponentialInterpolator, CubicBezierInterpolator>;
+
+ InterpolateBase(const type::Type& type_,
+ Interpolator interpolator_,
+ std::unique_ptr<Expression> input_,
+ std::map<double, std::unique_ptr<Expression>> stops_
+ ) : Expression(type_),
+ interpolator(std::move(interpolator_)),
+ input(std::move(input_)),
+ stops(std::move(stops_))
+ {}
+
+ const std::unique_ptr<Expression>& getInput() const { return input; }
+
+ void eachChild(const std::function<void(const Expression&)>& visit) const override {
+ visit(*input);
+ for (const auto& stop : stops) {
+ visit(*stop.second);
+ }
+ }
+
+ // Return the smallest range of stops that covers the interval [lower, upper]
+ Range<float> getCoveringStops(const double lower, const double upper) const {
+ return ::mbgl::style::expression::getCoveringStops(stops, lower, upper);
+ }
+
+ double interpolationFactor(const Range<double>& inputLevels, const double inputValue) const {
+ return interpolator.match(
+ [&](const auto& interp) { return interp.interpolationFactor(inputLevels, inputValue); }
+ );
+ }
+
+protected:
+ const Interpolator interpolator;
+ const std::unique_ptr<Expression> input;
+ const std::map<double, std::unique_ptr<Expression>> stops;
+};
+
+template <typename T>
+class Interpolate : public InterpolateBase {
+public:
+ Interpolate(type::Type type_,
+ Interpolator interpolator_,
+ std::unique_ptr<Expression> input_,
+ std::map<double, std::unique_ptr<Expression>> stops_
+ ) : InterpolateBase(std::move(type_), std::move(interpolator_), std::move(input_), std::move(stops_))
+ {
+ static_assert(util::Interpolatable<T>::value, "Interpolate expression requires an interpolatable value type.");
+ }
+
+ EvaluationResult evaluate(const EvaluationContext& params) const override {
+ const EvaluationResult evaluatedInput = input->evaluate(params);
+ if (!evaluatedInput) { return evaluatedInput.error(); }
+ float x = *fromExpressionValue<float>(*evaluatedInput);
+
+ if (stops.empty()) {
+ return EvaluationError { "No stops in exponential curve." };
+ }
+
+ auto it = stops.upper_bound(x);
+ if (it == stops.end()) {
+ return stops.rbegin()->second->evaluate(params);
+ } else if (it == stops.begin()) {
+ return stops.begin()->second->evaluate(params);
+ } else {
+ float t = interpolationFactor({ std::prev(it)->first, it->first }, x);
+
+ if (t == 0.0f) {
+ return std::prev(it)->second->evaluate(params);
+ }
+ if (t == 1.0f) {
+ return it->second->evaluate(params);
+ }
+
+ EvaluationResult lower = std::prev(it)->second->evaluate(params);
+ if (!lower) {
+ return lower.error();
+ }
+ EvaluationResult upper = it->second->evaluate(params);
+ if (!upper) {
+ return upper.error();
+ }
+
+ if (!lower->is<T>()) {
+ return EvaluationError {
+ "Expected value to be of type " + toString(valueTypeToExpressionType<T>()) +
+ ", but found " + toString(typeOf(*lower)) + " instead."
+ };
+ }
+
+ if (!upper->is<T>()) {
+ return EvaluationError {
+ "Expected value to be of type " + toString(valueTypeToExpressionType<T>()) +
+ ", but found " + toString(typeOf(*upper)) + " instead."
+ };
+ }
+ return util::interpolate(lower->get<T>(), upper->get<T>(), t);
+ }
+ }
+
+ bool operator==(const Expression& e) const override {
+ if (auto rhs = dynamic_cast<const Interpolate*>(&e)) {
+ if (interpolator != rhs->interpolator ||
+ *input != *(rhs->input) ||
+ stops.size() != rhs->stops.size())
+ {
+ return false;
+ }
+
+ return Expression::childrenEqual(stops, rhs->stops);
+ }
+ return false;
+ }
+};
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/expression/is_constant.hpp b/include/mbgl/style/expression/is_constant.hpp
new file mode 100644
index 0000000000..29e03ccbc0
--- /dev/null
+++ b/include/mbgl/style/expression/is_constant.hpp
@@ -0,0 +1,35 @@
+#pragma once
+
+#include <mbgl/style/expression/expression.hpp>
+#include <mbgl/style/expression/compound_expression.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+template <typename T>
+bool isGlobalPropertyConstant(const Expression& expression, const T& properties) {
+ if (auto e = dynamic_cast<const CompoundExpressionBase*>(&expression)) {
+ for (const std::string& property : properties) {
+ if (e->getName() == property) {
+ return false;
+ }
+ }
+ }
+
+ bool isConstant = true;
+ expression.eachChild([&](const Expression& e) {
+ if (isConstant && !isGlobalPropertyConstant(e, properties)) {
+ isConstant = false;
+ }
+ });
+ return isConstant;
+};
+
+bool isFeatureConstant(const Expression& expression);
+bool isZoomConstant(const Expression& e);
+
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/expression/is_expression.hpp b/include/mbgl/style/expression/is_expression.hpp
new file mode 100644
index 0000000000..77c489619c
--- /dev/null
+++ b/include/mbgl/style/expression/is_expression.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+#include <mbgl/style/expression/expression.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+bool isExpression(const conversion::Convertible& value);
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/expression/let.hpp b/include/mbgl/style/expression/let.hpp
new file mode 100644
index 0000000000..aaa16ca0c2
--- /dev/null
+++ b/include/mbgl/style/expression/let.hpp
@@ -0,0 +1,72 @@
+#pragma once
+
+#include <mbgl/style/expression/expression.hpp>
+#include <mbgl/style/expression/parsing_context.hpp>
+#include <mbgl/style/conversion.hpp>
+
+#include <memory>
+#include <map>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+class Let : public Expression {
+public:
+ using Bindings = std::map<std::string, std::shared_ptr<Expression>>;
+
+ Let(Bindings bindings_, std::unique_ptr<Expression> result_) :
+ Expression(result_->getType()),
+ bindings(std::move(bindings_)),
+ result(std::move(result_))
+ {}
+
+ static ParseResult parse(const mbgl::style::conversion::Convertible&, ParsingContext&);
+
+ EvaluationResult evaluate(const EvaluationContext& params) const override;
+ void eachChild(const std::function<void(const Expression&)>&) const override;
+
+ bool operator==(const Expression& e) const override {
+ if (auto rhs = dynamic_cast<const Let*>(&e)) {
+ return *result == *(rhs->result);
+ }
+ return false;
+ }
+
+ Expression* getResult() const {
+ return result.get();
+ }
+
+private:
+ Bindings bindings;
+ std::unique_ptr<Expression> result;
+};
+
+class Var : public Expression {
+public:
+ Var(std::string name_, std::shared_ptr<Expression> value_) :
+ Expression(value_->getType()),
+ name(std::move(name_)),
+ value(value_)
+ {}
+
+ static ParseResult parse(const mbgl::style::conversion::Convertible&, ParsingContext&);
+
+ EvaluationResult evaluate(const EvaluationContext& params) const override;
+ void eachChild(const std::function<void(const Expression&)>&) const override;
+
+ bool operator==(const Expression& e) const override {
+ if (auto rhs = dynamic_cast<const Var*>(&e)) {
+ return *value == *(rhs->value);
+ }
+ return false;
+ }
+
+private:
+ std::string name;
+ std::shared_ptr<Expression> value;
+};
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/expression/literal.hpp b/include/mbgl/style/expression/literal.hpp
new file mode 100644
index 0000000000..a0819c7e73
--- /dev/null
+++ b/include/mbgl/style/expression/literal.hpp
@@ -0,0 +1,38 @@
+#pragma once
+
+#include <mbgl/style/expression/expression.hpp>
+#include <mbgl/style/expression/parsing_context.hpp>
+#include <mbgl/style/conversion.hpp>
+
+#include <memory>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+class Literal : public Expression {
+public:
+ Literal(Value value_) : Expression(typeOf(value_)), value(value_) {}
+ Literal(type::Array type_, std::vector<Value> value_) : Expression(type_), value(value_) {}
+ EvaluationResult evaluate(const EvaluationContext&) const override {
+ return value;
+ }
+
+ static ParseResult parse(const mbgl::style::conversion::Convertible&, ParsingContext&);
+
+ void eachChild(const std::function<void(const Expression&)>&) const override {}
+
+ bool operator==(const Expression& e) const override {
+ if (auto rhs = dynamic_cast<const Literal*>(&e)) {
+ return value == rhs->value;
+ }
+ return false;
+ }
+
+private:
+ Value value;
+};
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/expression/match.hpp b/include/mbgl/style/expression/match.hpp
new file mode 100644
index 0000000000..e17fe96bfe
--- /dev/null
+++ b/include/mbgl/style/expression/match.hpp
@@ -0,0 +1,45 @@
+#pragma once
+
+#include <mbgl/style/expression/expression.hpp>
+#include <mbgl/style/expression/parsing_context.hpp>
+#include <mbgl/style/conversion.hpp>
+
+#include <memory>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+template <typename T>
+class Match : public Expression {
+public:
+ using Branches = std::unordered_map<T, std::shared_ptr<Expression>>;
+
+ Match(type::Type type_,
+ std::unique_ptr<Expression> input_,
+ Branches branches_,
+ std::unique_ptr<Expression> otherwise_
+ ) : Expression(type_),
+ input(std::move(input_)),
+ branches(std::move(branches_)),
+ otherwise(std::move(otherwise_))
+ {}
+
+ void eachChild(const std::function<void(const Expression&)>& visit) const override;
+
+ bool operator==(const Expression& e) const override;
+
+ EvaluationResult evaluate(const EvaluationContext& params) const override;
+
+private:
+
+ std::unique_ptr<Expression> input;
+ Branches branches;
+ std::unique_ptr<Expression> otherwise;
+};
+
+ParseResult parseMatch(const mbgl::style::conversion::Convertible& value, ParsingContext& ctx);
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/expression/parsing_context.hpp b/include/mbgl/style/expression/parsing_context.hpp
new file mode 100644
index 0000000000..a983789cbd
--- /dev/null
+++ b/include/mbgl/style/expression/parsing_context.hpp
@@ -0,0 +1,148 @@
+#pragma once
+
+#include <mbgl/util/optional.hpp>
+#include <mbgl/util/string.hpp>
+#include <mbgl/style/expression/type.hpp>
+#include <mbgl/style/conversion.hpp>
+
+#include <map>
+#include <string>
+#include <vector>
+#include <memory>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+class Expression;
+
+struct ParsingError {
+ std::string message;
+ std::string key;
+ bool operator==(const ParsingError& rhs) const { return message == rhs.message && key == rhs.key; }
+};
+
+using ParseResult = optional<std::unique_ptr<Expression>>;
+
+namespace detail {
+
+class Scope {
+public:
+ Scope(const std::map<std::string, std::shared_ptr<Expression>>& bindings_, std::shared_ptr<Scope> parent_ = nullptr) :
+ bindings(bindings_),
+ parent(std::move(parent_))
+ {}
+
+ const std::map<std::string, std::shared_ptr<Expression>>& bindings;
+ std::shared_ptr<Scope> parent;
+
+ optional<std::shared_ptr<Expression>> get(const std::string& name) {
+ auto it = bindings.find(name);
+ if (it != bindings.end()) {
+ return {it->second};
+ } else if (parent) {
+ return parent->get(name);
+ } else {
+ return optional<std::shared_ptr<Expression>>();
+ }
+ }
+};
+
+} // namespace detail
+
+class ParsingContext {
+public:
+ ParsingContext() : errors(std::make_shared<std::vector<ParsingError>>()) {}
+ ParsingContext(std::string key_) : key(std::move(key_)), errors(std::make_shared<std::vector<ParsingError>>()) {}
+ explicit ParsingContext(optional<type::Type> expected_)
+ : expected(std::move(expected_)),
+ errors(std::make_shared<std::vector<ParsingError>>())
+ {}
+ ParsingContext(ParsingContext&&) = default;
+
+ ParsingContext(const ParsingContext&) = delete;
+ ParsingContext& operator=(const ParsingContext&) = delete;
+
+ std::string getKey() const { return key; }
+ optional<type::Type> getExpected() const { return expected; }
+ const std::vector<ParsingError>& getErrors() const { return *errors; }
+
+ /*
+ Parse the given style-spec JSON value into an Expression object.
+ Specifically, this function is responsible for determining the expression
+ type (either Literal, or the one named in value[0]) and dispatching to the
+ appropriate ParseXxxx::parse(const V&, ParsingContext) method.
+ */
+ ParseResult parse(const mbgl::style::conversion::Convertible& value);
+
+ /*
+ Parse a child expression.
+ */
+ ParseResult parse(const mbgl::style::conversion::Convertible&,
+ std::size_t,
+ optional<type::Type> = {});
+
+ /*
+ Parse a child expression.
+ */
+ ParseResult parse(const mbgl::style::conversion::Convertible&,
+ std::size_t index,
+ optional<type::Type>,
+ const std::map<std::string, std::shared_ptr<Expression>>&);
+
+ /*
+ Check whether `t` is a subtype of `expected`, collecting an error if not.
+ */
+ optional<std::string> checkType(const type::Type& t);
+
+ optional<std::shared_ptr<Expression>> getBinding(const std::string name) {
+ if (!scope) return optional<std::shared_ptr<Expression>>();
+ return scope->get(name);
+ }
+
+ void error(std::string message) {
+ errors->push_back({message, key});
+ }
+
+ void error(std::string message, std::size_t child) {
+ errors->push_back({message, key + "[" + util::toString(child) + "]"});
+ }
+
+ void error(std::string message, std::size_t child, std::size_t grandchild) {
+ errors->push_back({message, key + "[" + util::toString(child) + "][" + util::toString(grandchild) + "]"});
+ }
+
+ void appendErrors(ParsingContext&& ctx) {
+ errors->reserve(errors->size() + ctx.errors->size());
+ std::move(ctx.errors->begin(), ctx.errors->end(), std::inserter(*errors, errors->end()));
+ ctx.errors->clear();
+ }
+
+ void clearErrors() {
+ errors->clear();
+ }
+
+private:
+ ParsingContext(std::string key_,
+ std::shared_ptr<std::vector<ParsingError>> errors_,
+ optional<type::Type> expected_,
+ std::shared_ptr<detail::Scope> scope_)
+ : key(std::move(key_)),
+ expected(std::move(expected_)),
+ scope(std::move(scope_)),
+ errors(std::move(errors_))
+ {}
+
+ std::string key;
+ optional<type::Type> expected;
+ std::shared_ptr<detail::Scope> scope;
+ std::shared_ptr<std::vector<ParsingError>> errors;
+};
+
+using ParseFunction = ParseResult (*)(const conversion::Convertible&, ParsingContext&);
+using ExpressionRegistry = std::unordered_map<std::string, ParseFunction>;
+const ExpressionRegistry& getExpressionRegistry();
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/expression/step.hpp b/include/mbgl/style/expression/step.hpp
new file mode 100644
index 0000000000..e3c49bc609
--- /dev/null
+++ b/include/mbgl/style/expression/step.hpp
@@ -0,0 +1,45 @@
+
+#pragma once
+
+#include <mbgl/style/expression/expression.hpp>
+#include <mbgl/style/expression/parsing_context.hpp>
+#include <mbgl/style/conversion.hpp>
+
+#include <mbgl/util/range.hpp>
+
+#include <memory>
+#include <map>
+
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+class Step : public Expression {
+public:
+ Step(const type::Type& type_,
+ std::unique_ptr<Expression> input_,
+ std::map<double, std::unique_ptr<Expression>> stops_
+ ) : Expression(type_),
+ input(std::move(input_)),
+ stops(std::move(stops_))
+ {}
+
+ EvaluationResult evaluate(const EvaluationContext& params) const override;
+ void eachChild(const std::function<void(const Expression&)>& visit) const override;
+
+ const std::unique_ptr<Expression>& getInput() const { return input; }
+ Range<float> getCoveringStops(const double lower, const double upper) const;
+
+ bool operator==(const Expression& e) const override;
+
+ static ParseResult parse(const mbgl::style::conversion::Convertible& value, ParsingContext& ctx);
+
+private:
+ const std::unique_ptr<Expression> input;
+ const std::map<double, std::unique_ptr<Expression>> stops;
+};
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/expression/type.hpp b/include/mbgl/style/expression/type.hpp
new file mode 100644
index 0000000000..513c4bdc17
--- /dev/null
+++ b/include/mbgl/style/expression/type.hpp
@@ -0,0 +1,112 @@
+#pragma once
+
+#include <mbgl/util/optional.hpp>
+#include <mbgl/util/string.hpp>
+#include <mbgl/util/variant.hpp>
+#include <vector>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+namespace type {
+
+template <class T>
+std::string toString(const T& t);
+
+struct NullType {
+ constexpr NullType() {};
+ std::string getName() const { return "null"; }
+ bool operator==(const NullType&) const { return true; }
+};
+
+struct NumberType {
+ constexpr NumberType() {};
+ std::string getName() const { return "number"; }
+ bool operator==(const NumberType&) const { return true; }
+};
+
+struct BooleanType {
+ constexpr BooleanType() {};
+ std::string getName() const { return "boolean"; }
+ bool operator==(const BooleanType&) const { return true; }
+};
+
+struct StringType {
+ constexpr StringType() {};
+ std::string getName() const { return "string"; }
+ bool operator==(const StringType&) const { return true; }
+};
+
+struct ColorType {
+ constexpr ColorType() {};
+ std::string getName() const { return "color"; }
+ bool operator==(const ColorType&) const { return true; }
+};
+
+struct ObjectType {
+ constexpr ObjectType() {};
+ std::string getName() const { return "object"; }
+ bool operator==(const ObjectType&) const { return true; }
+};
+
+struct ErrorType {
+ constexpr ErrorType() {};
+ std::string getName() const { return "error"; }
+ bool operator==(const ErrorType&) const { return true; }
+};
+
+struct ValueType {
+ constexpr ValueType() {};
+ std::string getName() const { return "value"; }
+ bool operator==(const ValueType&) const { return true; }
+};
+
+constexpr NullType Null;
+constexpr NumberType Number;
+constexpr StringType String;
+constexpr BooleanType Boolean;
+constexpr ColorType Color;
+constexpr ValueType Value;
+constexpr ObjectType Object;
+constexpr ErrorType Error;
+
+struct Array;
+
+using Type = variant<
+ NullType,
+ NumberType,
+ BooleanType,
+ StringType,
+ ColorType,
+ ObjectType,
+ ValueType,
+ mapbox::util::recursive_wrapper<Array>,
+ ErrorType>;
+
+struct Array {
+ explicit Array(Type itemType_) : itemType(std::move(itemType_)) {}
+ Array(Type itemType_, std::size_t N_) : itemType(std::move(itemType_)), N(N_) {}
+ Array(Type itemType_, optional<std::size_t> N_) : itemType(std::move(itemType_)), N(std::move(N_)) {}
+ std::string getName() const {
+ if (N) {
+ return "array<" + toString(itemType) + ", " + util::toString(*N) + ">";
+ } else if (itemType == Value) {
+ return "array";
+ } else {
+ return "array<" + toString(itemType) + ">";
+ }
+ }
+
+ bool operator==(const Array& rhs) const { return itemType == rhs.itemType && N == rhs.N; }
+
+ Type itemType;
+ optional<std::size_t> N;
+};
+
+template <class T>
+std::string toString(const T& type) { return type.match([&] (const auto& t) { return t.getName(); }); }
+
+} // namespace type
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/expression/value.hpp b/include/mbgl/style/expression/value.hpp
new file mode 100644
index 0000000000..8baa9d2dba
--- /dev/null
+++ b/include/mbgl/style/expression/value.hpp
@@ -0,0 +1,153 @@
+#pragma once
+
+#include <mbgl/style/expression/type.hpp>
+#include <mbgl/style/position.hpp>
+#include <mbgl/style/types.hpp>
+#include <mbgl/util/color.hpp>
+#include <mbgl/util/enum.hpp>
+#include <mbgl/util/feature.hpp>
+#include <mbgl/util/variant.hpp>
+
+#include <array>
+#include <vector>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+struct Value;
+
+using ValueBase = variant<
+ NullValue,
+ bool,
+ double,
+ std::string,
+ Color,
+ mapbox::util::recursive_wrapper<std::vector<Value>>,
+ mapbox::util::recursive_wrapper<std::unordered_map<std::string, Value>>>;
+struct Value : ValueBase {
+ using ValueBase::ValueBase;
+
+ // Javascript's Number.MAX_SAFE_INTEGER
+ static uint64_t maxSafeInteger() { return 9007199254740991ULL; }
+
+ static bool isSafeInteger(uint64_t x) { return x <= maxSafeInteger(); };
+ static bool isSafeInteger(int64_t x) {
+ return static_cast<uint64_t>(x > 0 ? x : -x) <= maxSafeInteger();
+ }
+ static bool isSafeInteger(double x) {
+ return static_cast<uint64_t>(x > 0 ? x : -x) <= maxSafeInteger();
+ }
+
+};
+
+constexpr NullValue Null = NullValue();
+
+type::Type typeOf(const Value& value);
+std::string stringify(const Value& value);
+
+/*
+ Returns a Type object representing the expression type that corresponds to
+ the value type T. (Specialized for primitives and specific array types in
+ the .cpp.)
+*/
+template <typename T>
+type::Type valueTypeToExpressionType();
+
+/*
+ Conversions between style value types and expression::Value
+*/
+
+// no-op overloads
+Value toExpressionValue(const Value&);
+
+// T = Value (just wrap in optional)
+template <typename T>
+std::enable_if_t<std::is_same<T, Value>::value,
+optional<T>> fromExpressionValue(const Value& v)
+{
+ return optional<T>(v);
+}
+
+// T = member type of Value
+template <typename T>
+std::enable_if_t< std::is_convertible<T, Value>::value && !std::is_same<T, Value>::value,
+optional<T>> fromExpressionValue(const Value& v)
+{
+ return v.template is<T>() ? v.template get<T>() : optional<T>();
+}
+
+// real conversions
+template <typename T, typename Enable = std::enable_if_t< !std::is_convertible<T, Value>::value >>
+Value toExpressionValue(const T& value);
+
+template <typename T>
+std::enable_if_t< !std::is_convertible<T, Value>::value,
+optional<T>> fromExpressionValue(const Value& v);
+
+
+
+template <class T, class Enable = void>
+struct ValueConverter {
+ using ExpressionType = T;
+
+ static Value toExpressionValue(const T& value) {
+ return Value(value);
+ }
+ static optional<T> fromExpressionValue(const Value& value) {
+ return value.template is<T>() ? value.template get<T>() : optional<T>();
+ }
+};
+
+template <>
+struct ValueConverter<float> {
+ using ExpressionType = double;
+ static type::Type expressionType() { return type::Number; }
+ static Value toExpressionValue(const float value);
+ static optional<float> fromExpressionValue(const Value& value);
+};
+
+template<>
+struct ValueConverter<mbgl::Value> {
+ static Value toExpressionValue(const mbgl::Value& value);
+};
+
+template <typename T, std::size_t N>
+struct ValueConverter<std::array<T, N>> {
+ using ExpressionType = std::vector<Value>;
+ static type::Type expressionType() {
+ return type::Array(valueTypeToExpressionType<T>(), N);
+ }
+ static Value toExpressionValue(const std::array<T, N>& value);
+ static optional<std::array<T, N>> fromExpressionValue(const Value& value);
+};
+
+template <typename T>
+struct ValueConverter<std::vector<T>> {
+ using ExpressionType = std::vector<Value>;
+ static type::Type expressionType() {
+ return type::Array(valueTypeToExpressionType<T>());
+ }
+ static Value toExpressionValue(const std::vector<T>& value);
+ static optional<std::vector<T>> fromExpressionValue(const Value& value);
+};
+
+template <>
+struct ValueConverter<Position> {
+ using ExpressionType = std::vector<Value>;
+ static type::Type expressionType() { return type::Array(type::Number, 3); }
+ static Value toExpressionValue(const mbgl::style::Position& value);
+ static optional<Position> fromExpressionValue(const Value& v);
+};
+
+template <typename T>
+struct ValueConverter<T, std::enable_if_t< std::is_enum<T>::value >> {
+ using ExpressionType = std::string;
+ static type::Type expressionType() { return type::String; }
+ static Value toExpressionValue(const T& value);
+ static optional<T> fromExpressionValue(const Value& value);
+};
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/function/camera_function.hpp b/include/mbgl/style/function/camera_function.hpp
index 7fde365b3d..25b38e3616 100644
--- a/include/mbgl/style/function/camera_function.hpp
+++ b/include/mbgl/style/function/camera_function.hpp
@@ -1,10 +1,18 @@
#pragma once
+#include <mbgl/style/expression/expression.hpp>
+#include <mbgl/style/expression/interpolate.hpp>
+#include <mbgl/style/expression/step.hpp>
+#include <mbgl/style/expression/find_zoom_curve.hpp>
+#include <mbgl/style/expression/value.hpp>
+#include <mbgl/style/expression/is_constant.hpp>
+#include <mbgl/style/function/convert.hpp>
#include <mbgl/style/function/exponential_stops.hpp>
#include <mbgl/style/function/interval_stops.hpp>
#include <mbgl/util/interpolate.hpp>
#include <mbgl/util/variant.hpp>
+
namespace mbgl {
namespace style {
@@ -18,24 +26,60 @@ public:
IntervalStops<T>>,
variant<
IntervalStops<T>>>;
+
+ CameraFunction(std::unique_ptr<expression::Expression> expression_)
+ : expression(std::move(expression_)),
+ zoomCurve(expression::findZoomCurveChecked(expression.get()))
+ {
+ assert(!expression::isZoomConstant(*expression));
+ assert(expression::isFeatureConstant(*expression));
+ }
CameraFunction(Stops stops_)
- : stops(std::move(stops_)) {
- }
+ : stops(std::move(stops_)),
+ expression(stops.match([&] (const auto& s) {
+ return expression::Convert::toExpression(s);
+ })),
+ zoomCurve(expression::findZoomCurveChecked(expression.get()))
+ {}
T evaluate(float zoom) const {
- return stops.match([&] (const auto& s) {
- return s.evaluate(zoom).value_or(T());
- });
+ const expression::EvaluationResult result = expression->evaluate(expression::EvaluationContext(zoom, nullptr));
+ if (result) {
+ const optional<T> typed = expression::fromExpressionValue<T>(*result);
+ return typed ? *typed : T();
+ }
+ return T();
+ }
+
+ float interpolationFactor(const Range<float>& inputLevels, const float inputValue) const {
+ return zoomCurve.match(
+ [&](const expression::InterpolateBase* z) {
+ return z->interpolationFactor(Range<double> { inputLevels.min, inputLevels.max }, inputValue);
+ },
+ [&](const expression::Step*) { return 0.0f; }
+ );
+ }
+
+ Range<float> getCoveringStops(const float lower, const float upper) const {
+ return zoomCurve.match(
+ [&](auto z) { return z->getCoveringStops(lower, upper); }
+ );
}
friend bool operator==(const CameraFunction& lhs,
const CameraFunction& rhs) {
- return lhs.stops == rhs.stops;
+ return *lhs.expression == *rhs.expression;
}
- Stops stops;
bool useIntegerZoom = false;
+
+ // retained for compatibility with pre-expression function API
+ Stops stops;
+
+private:
+ std::shared_ptr<expression::Expression> expression;
+ const variant<const expression::InterpolateBase*, const expression::Step*> zoomCurve;
};
} // namespace style
diff --git a/include/mbgl/style/function/composite_function.hpp b/include/mbgl/style/function/composite_function.hpp
index 7b524b6021..b44bf8e6fe 100644
--- a/include/mbgl/style/function/composite_function.hpp
+++ b/include/mbgl/style/function/composite_function.hpp
@@ -1,5 +1,12 @@
#pragma once
+#include <mbgl/style/expression/expression.hpp>
+#include <mbgl/style/expression/interpolate.hpp>
+#include <mbgl/style/expression/step.hpp>
+#include <mbgl/style/expression/find_zoom_curve.hpp>
+#include <mbgl/style/expression/value.hpp>
+#include <mbgl/style/expression/is_constant.hpp>
+#include <mbgl/style/function/convert.hpp>
#include <mbgl/style/function/composite_exponential_stops.hpp>
#include <mbgl/style/function/composite_interval_stops.hpp>
#include <mbgl/style/function/composite_categorical_stops.hpp>
@@ -43,110 +50,71 @@ public:
CompositeIntervalStops<T>,
CompositeCategoricalStops<T>>>;
- CompositeFunction(std::string property_, Stops stops_, optional<T> defaultValue_ = {})
- : property(std::move(property_)),
- stops(std::move(stops_)),
- defaultValue(std::move(defaultValue_)) {
- }
-
- struct CoveringRanges {
- float zoom;
- Range<float> coveringZoomRange;
- Range<InnerStops> coveringStopsRange;
- };
-
- // Return the relevant stop zoom values and inner stops that bracket a given zoom level. This
- // is the first step toward evaluating the function, and is used for in the course of both partial
- // evaluation of data-driven paint properties, and full evaluation of data-driven layout properties.
- CoveringRanges coveringRanges(float zoom) const {
- return stops.match(
- [&] (const auto& s) {
- assert(!s.stops.empty());
- auto minIt = s.stops.lower_bound(zoom);
- auto maxIt = s.stops.upper_bound(zoom);
-
- // lower_bound yields first element >= zoom, but we want the *last*
- // element <= zoom, so if we found a stop > zoom, back up by one.
- if (minIt != s.stops.begin() && minIt != s.stops.end() && minIt->first > zoom) {
- minIt--;
- }
-
- return CoveringRanges {
- zoom,
- Range<float> {
- minIt == s.stops.end() ? s.stops.rbegin()->first : minIt->first,
- maxIt == s.stops.end() ? s.stops.rbegin()->first : maxIt->first
- },
- Range<InnerStops> {
- s.innerStops(minIt == s.stops.end() ? s.stops.rbegin()->second : minIt->second),
- s.innerStops(maxIt == s.stops.end() ? s.stops.rbegin()->second : maxIt->second)
- }
- };
- }
- );
+ CompositeFunction(std::unique_ptr<expression::Expression> expression_)
+ : expression(std::move(expression_)),
+ zoomCurve(expression::findZoomCurveChecked(expression.get()))
+ {
+ assert(!expression::isZoomConstant(*expression));
+ assert(!expression::isFeatureConstant(*expression));
}
- // Given a range of zoom values (typically two adjacent integer zoom levels, e.g. 5.0 and 6.0),
- // return the covering ranges for both. This is used in the course of partial evaluation for
- // data-driven paint properties.
- Range<CoveringRanges> rangeOfCoveringRanges(Range<float> zoomRange) {
- return Range<CoveringRanges> {
- coveringRanges(zoomRange.min),
- coveringRanges(zoomRange.max)
- };
- }
-
- // Given the covering ranges for range of zoom values (typically two adjacent integer zoom levels,
- // e.g. 5.0 and 6.0), and a feature, return the results of fully evaluating the function for that
- // feature at each of the two zoom levels. These two results are what go into the paint vertex buffers
- // for vertices associated with this feature. The shader will interpolate between them at render time.
+ CompositeFunction(std::string property_, Stops stops_, optional<T> defaultValue_ = {})
+ : property(std::move(property_)),
+ stops(std::move(stops_)),
+ defaultValue(std::move(defaultValue_)),
+ expression(stops.match([&] (const auto& s) {
+ return expression::Convert::toExpression(property, s);
+ })),
+ zoomCurve(expression::findZoomCurveChecked(expression.get()))
+ {}
+
+ // Return the range obtained by evaluating the function at each of the zoom levels in zoomRange
template <class Feature>
- Range<T> evaluate(const Range<CoveringRanges>& ranges, const Feature& feature, T finalDefaultValue) {
- optional<Value> value = feature.getValue(property);
- if (!value) {
- return Range<T> {
- defaultValue.value_or(finalDefaultValue),
- defaultValue.value_or(finalDefaultValue)
- };
- }
+ Range<T> evaluate(const Range<float>& zoomRange, const Feature& feature, T finalDefaultValue) {
return Range<T> {
- evaluateFinal(ranges.min, *value, finalDefaultValue),
- evaluateFinal(ranges.max, *value, finalDefaultValue)
+ evaluate(zoomRange.min, feature, finalDefaultValue),
+ evaluate(zoomRange.max, feature, finalDefaultValue)
};
}
- // Fully evaluate the function for a zoom value and feature. This is used when evaluating data-driven
- // layout properties.
template <class Feature>
T evaluate(float zoom, const Feature& feature, T finalDefaultValue) const {
- optional<Value> value = feature.getValue(property);
- if (!value) {
- return defaultValue.value_or(finalDefaultValue);
+ const expression::EvaluationResult result = expression->evaluate(expression::EvaluationContext({zoom}, &feature));
+ if (result) {
+ const optional<T> typed = expression::fromExpressionValue<T>(*result);
+ return typed ? *typed : defaultValue ? *defaultValue : finalDefaultValue;
}
- return evaluateFinal(coveringRanges(zoom), *value, finalDefaultValue);
+ return defaultValue ? *defaultValue : finalDefaultValue;
+ }
+
+ float interpolationFactor(const Range<float>& inputLevels, const float inputValue) const {
+ return zoomCurve.match(
+ [&](const expression::InterpolateBase* z) {
+ return z->interpolationFactor(Range<double> { inputLevels.min, inputLevels.max }, inputValue);
+ },
+ [&](const expression::Step*) { return 0.0f; }
+ );
+ }
+
+ Range<float> getCoveringStops(const float lower, const float upper) const {
+ return zoomCurve.match(
+ [&](auto z) { return z->getCoveringStops(lower, upper); }
+ );
}
friend bool operator==(const CompositeFunction& lhs,
const CompositeFunction& rhs) {
- return std::tie(lhs.property, lhs.stops, lhs.defaultValue)
- == std::tie(rhs.property, rhs.stops, rhs.defaultValue);
+ return *lhs.expression == *rhs.expression;
}
std::string property;
Stops stops;
optional<T> defaultValue;
bool useIntegerZoom = false;
-
+
private:
- T evaluateFinal(const CoveringRanges& ranges, const Value& value, T finalDefaultValue) const {
- auto eval = [&] (const auto& s) {
- return s.evaluate(value).value_or(defaultValue.value_or(finalDefaultValue));
- };
- return util::interpolate(
- ranges.coveringStopsRange.min.match(eval),
- ranges.coveringStopsRange.max.match(eval),
- util::interpolationFactor(1.0f, ranges.coveringZoomRange, ranges.zoom));
- }
+ std::shared_ptr<expression::Expression> expression;
+ const variant<const expression::InterpolateBase*, const expression::Step*> zoomCurve;
};
} // namespace style
diff --git a/include/mbgl/style/function/convert.hpp b/include/mbgl/style/function/convert.hpp
new file mode 100644
index 0000000000..9f7b7ed1f8
--- /dev/null
+++ b/include/mbgl/style/function/convert.hpp
@@ -0,0 +1,351 @@
+#pragma once
+
+#include <mbgl/style/expression/array_assertion.hpp>
+#include <mbgl/style/expression/assertion.hpp>
+#include <mbgl/style/expression/case.hpp>
+#include <mbgl/style/expression/coalesce.hpp>
+#include <mbgl/style/expression/compound_expression.hpp>
+#include <mbgl/style/expression/coercion.hpp>
+#include <mbgl/style/expression/interpolate.hpp>
+#include <mbgl/style/expression/expression.hpp>
+#include <mbgl/style/expression/literal.hpp>
+#include <mbgl/style/expression/match.hpp>
+#include <mbgl/style/expression/step.hpp>
+
+#include <mbgl/style/function/exponential_stops.hpp>
+#include <mbgl/style/function/interval_stops.hpp>
+#include <mbgl/style/function/categorical_stops.hpp>
+#include <mbgl/style/function/composite_exponential_stops.hpp>
+#include <mbgl/style/function/composite_interval_stops.hpp>
+#include <mbgl/style/function/composite_categorical_stops.hpp>
+#include <mbgl/style/function/identity_stops.hpp>
+
+#include <mbgl/util/enum.hpp>
+#include <mbgl/style/types.hpp>
+
+#include <string>
+
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+namespace detail {
+
+class ErrorExpression : public Expression {
+public:
+ ErrorExpression(std::string message_) : Expression(type::Error), message(std::move(message_)) {}
+ void eachChild(const std::function<void(const Expression&)>&) const override {}
+
+ bool operator==(const Expression& e) const override {
+ return dynamic_cast<const ErrorExpression*>(&e);
+ }
+
+ EvaluationResult evaluate(const EvaluationContext&) const override {
+ return EvaluationError{message};
+ }
+
+private:
+ std::string message;
+};
+
+} // namespace detail
+
+
+// Create expressions representing 'classic' (i.e. stop-based) style functions
+
+struct Convert {
+ template <typename T>
+ static std::unique_ptr<Literal> makeLiteral(const T& value) {
+ return std::make_unique<Literal>(Value(toExpressionValue(value)));
+ }
+
+ static std::unique_ptr<Expression> makeGet(type::Type type, const std::string& property) {
+ ParsingContext ctx;
+ std::vector<std::unique_ptr<Expression>> getArgs;
+ getArgs.push_back(makeLiteral(property));
+ ParseResult get = createCompoundExpression("get", std::move(getArgs), ctx);
+ assert(get);
+ assert(ctx.getErrors().size() == 0);
+
+ std::vector<std::unique_ptr<Expression>> assertionArgs;
+ assertionArgs.push_back(std::move(*get));
+
+ return std::make_unique<Assertion>(type, std::move(assertionArgs));
+ }
+
+ static std::unique_ptr<Expression> makeZoom() {
+ ParsingContext ctx;
+ ParseResult zoom = createCompoundExpression("zoom", std::vector<std::unique_ptr<Expression>>(), ctx);
+ assert(zoom);
+ assert(ctx.getErrors().size() == 0);
+ return std::move(*zoom);
+ }
+
+ static std::unique_ptr<Expression> makeError(std::string message) {
+ return std::make_unique<detail::ErrorExpression>(message);
+ }
+
+ template <typename OutputType>
+ static ParseResult makeInterpolate(type::Type type,
+ std::unique_ptr<Expression> input,
+ std::map<double, std::unique_ptr<Expression>> convertedStops,
+ typename Interpolate<OutputType>::Interpolator interpolator)
+ {
+ ParseResult curve = ParseResult(std::make_unique<Interpolate<OutputType>>(
+ std::move(type),
+ std::move(interpolator),
+ std::move(input),
+ std::move(convertedStops)
+ ));
+ assert(curve);
+ return std::move(*curve);
+ }
+
+ template <typename Key>
+ static ParseResult makeMatch(type::Type type,
+ std::unique_ptr<Expression> input,
+ std::map<CategoricalValue, std::unique_ptr<Expression>> stops) {
+ // match expression
+ typename Match<Key>::Branches branches;
+ for(auto it = stops.begin(); it != stops.end(); it++) {
+ assert(it->first.template is<Key>());
+ Key key = it->first.template get<Key>();
+ branches.emplace(
+ std::move(key),
+ std::move(it->second)
+ );
+ }
+
+ return ParseResult(std::make_unique<Match<Key>>(std::move(type),
+ std::move(input),
+ std::move(branches),
+ makeError("No matching label")));
+ }
+
+ static ParseResult makeCase(type::Type type,
+ std::unique_ptr<Expression> input,
+ std::map<CategoricalValue, std::unique_ptr<Expression>> stops) {
+ // case expression
+ std::vector<typename Case::Branch> branches;
+
+ auto it = stops.find(true);
+ std::unique_ptr<Expression> true_case = it == stops.end() ?
+ makeError("No matching label") :
+ std::move(it->second);
+
+ it = stops.find(false);
+ std::unique_ptr<Expression> false_case = it == stops.end() ?
+ makeError("No matching label") :
+ std::move(it->second);
+
+ branches.push_back(std::make_pair(std::move(input), std::move(true_case)));
+ return ParseResult(std::make_unique<Case>(std::move(type), std::move(branches), std::move(false_case)));
+ }
+
+ template <typename T>
+ static ParseResult fromCategoricalStops(std::map<CategoricalValue, T> stops, const std::string& property) {
+ assert(stops.size() > 0);
+
+ std::map<CategoricalValue, std::unique_ptr<Expression>> convertedStops;
+ for(const std::pair<CategoricalValue, T>& stop : stops) {
+ convertedStops.emplace(
+ stop.first,
+ makeLiteral(stop.second)
+ );
+ }
+
+ type::Type type = valueTypeToExpressionType<T>();
+
+ const CategoricalValue& firstKey = stops.begin()->first;
+ return firstKey.match(
+ [&](bool) {
+ return makeCase(type, makeGet(type::Boolean, property), std::move(convertedStops));
+ },
+ [&](const std::string&) {
+ return makeMatch<std::string>(type, makeGet(type::String, property), std::move(convertedStops));
+ },
+ [&](int64_t) {
+ return makeMatch<int64_t>(type, makeGet(type::Number, property), std::move(convertedStops));
+ }
+ );
+ }
+
+ template <typename T>
+ static std::map<double, std::unique_ptr<Expression>> convertStops(const std::map<float, T>& stops) {
+ std::map<double, std::unique_ptr<Expression>> convertedStops;
+ for(const auto& stop : stops) {
+ convertedStops.emplace(
+ stop.first,
+ makeLiteral(stop.second)
+ );
+ }
+ return convertedStops;
+ }
+
+ template <typename T>
+ static std::unique_ptr<Expression> toExpression(const ExponentialStops<T>& stops)
+ {
+ ParseResult e = makeInterpolate<typename ValueConverter<T>::ExpressionType>(
+ valueTypeToExpressionType<T>(),
+ makeZoom(),
+ convertStops(stops.stops),
+ ExponentialInterpolator(stops.base));
+ assert(e);
+ return std::move(*e);
+ }
+
+ template <typename T>
+ static std::unique_ptr<Expression> toExpression(const IntervalStops<T>& stops)
+ {
+ ParseResult e(std::make_unique<Step>(valueTypeToExpressionType<T>(),
+ makeZoom(),
+ convertStops(stops.stops)));
+ assert(e);
+ return std::move(*e);
+ }
+
+ template <typename T>
+ static std::unique_ptr<Expression> toExpression(const std::string& property,
+ const ExponentialStops<T>& stops)
+ {
+ ParseResult e = makeInterpolate<typename ValueConverter<T>::ExpressionType>(valueTypeToExpressionType<T>(),
+ makeGet(type::Number, property),
+ convertStops(stops.stops),
+ ExponentialInterpolator(stops.base));
+ assert(e);
+ return std::move(*e);
+ }
+
+ template <typename T>
+ static std::unique_ptr<Expression> toExpression(const std::string& property,
+ const IntervalStops<T>& stops)
+ {
+ std::unique_ptr<Expression> get = makeGet(type::Number, property);
+ ParseResult e(std::make_unique<Step>(valueTypeToExpressionType<T>(),
+ std::move(get),
+ convertStops(stops.stops)));
+ assert(e);
+ return std::move(*e);
+ }
+
+ template <typename T>
+ static std::unique_ptr<Expression> toExpression(const std::string& property,
+ const CategoricalStops<T>& stops)
+ {
+ ParseResult expr = fromCategoricalStops(stops.stops, property);
+ assert(expr);
+ return std::move(*expr);
+ }
+
+ // interpolatable zoom curve
+ template <typename T>
+ static typename std::enable_if_t<util::Interpolatable<T>::value,
+ ParseResult> makeZoomCurve(std::map<double, std::unique_ptr<Expression>> stops) {
+ return makeInterpolate<typename ValueConverter<T>::ExpressionType>(valueTypeToExpressionType<T>(),
+ makeZoom(),
+ std::move(stops),
+ ExponentialInterpolator(1.0));
+ }
+
+ // non-interpolatable zoom curve
+ template <typename T>
+ static typename std::enable_if_t<!util::Interpolatable<T>::value,
+ ParseResult> makeZoomCurve(std::map<double, std::unique_ptr<Expression>> stops) {
+ return ParseResult(std::make_unique<Step>(valueTypeToExpressionType<T>(), makeZoom(), std::move(stops)));
+ }
+
+ template <typename T>
+ static std::unique_ptr<Expression> toExpression(const std::string& property,
+ const CompositeExponentialStops<T>& stops)
+ {
+ std::map<double, std::unique_ptr<Expression>> outerStops;
+ for (const std::pair<float, std::map<float, T>>& stop : stops.stops) {
+ std::unique_ptr<Expression> get = makeGet(type::Number, property);
+ ParseResult innerInterpolate = makeInterpolate<typename ValueConverter<T>::ExpressionType>(valueTypeToExpressionType<T>(),
+ std::move(get),
+ convertStops(stop.second),
+ ExponentialInterpolator(stops.base));
+ assert(innerInterpolate);
+ outerStops.emplace(stop.first, std::move(*innerInterpolate));
+ }
+
+ ParseResult zoomCurve = makeZoomCurve<T>(std::move(outerStops));
+ assert(zoomCurve);
+ return std::move(*zoomCurve);
+ }
+
+ template <typename T>
+ static std::unique_ptr<Expression> toExpression(const std::string& property,
+ const CompositeIntervalStops<T>& stops)
+ {
+ std::map<double, std::unique_ptr<Expression>> outerStops;
+ for (const std::pair<float, std::map<float, T>>& stop : stops.stops) {
+ std::unique_ptr<Expression> get = makeGet(type::Number, property);
+ ParseResult innerInterpolate(std::make_unique<Step>(valueTypeToExpressionType<T>(),
+ std::move(get),
+ convertStops(stop.second)));
+ assert(innerInterpolate);
+ outerStops.emplace(stop.first, std::move(*innerInterpolate));
+ }
+
+ ParseResult zoomCurve = makeZoomCurve<T>(std::move(outerStops));
+ assert(zoomCurve);
+ return std::move(*zoomCurve);
+ }
+
+ template <typename T>
+ static std::unique_ptr<Expression> toExpression(const std::string& property,
+ const CompositeCategoricalStops<T>& stops)
+ {
+ std::map<double, std::unique_ptr<Expression>> outerStops;
+ for (const std::pair<float, std::map<CategoricalValue, T>>& stop : stops.stops) {
+ ParseResult innerInterpolate = fromCategoricalStops(stop.second, property);
+ assert(innerInterpolate);
+ outerStops.emplace(stop.first, std::move(*innerInterpolate));
+ }
+
+ ParseResult zoomCurve = makeZoomCurve<T>(std::move(outerStops));
+ assert(zoomCurve);
+ return std::move(*zoomCurve);
+ }
+
+
+ static std::unique_ptr<Expression> fromIdentityFunction(type::Type type, const std::string& property)
+ {
+ std::unique_ptr<Expression> input = type.match(
+ [&] (const type::StringType&) {
+ return makeGet(type::String, property);
+ },
+ [&] (const type::NumberType&) {
+ return makeGet(type::Number, property);
+ },
+ [&] (const type::BooleanType&) {
+ return makeGet(type::Boolean, property);
+ },
+ [&] (const type::ColorType&) {
+ std::vector<std::unique_ptr<Expression>> args;
+ args.push_back(makeGet(type::String, property));
+ return std::make_unique<Coercion>(type::Color, std::move(args));
+ },
+ [&] (const type::Array& arr) {
+ std::vector<std::unique_ptr<Expression>> getArgs;
+ getArgs.push_back(makeLiteral(property));
+ ParsingContext ctx;
+ ParseResult get = createCompoundExpression("get", std::move(getArgs), ctx);
+ assert(get);
+ assert(ctx.getErrors().size() == 0);
+ return std::make_unique<ArrayAssertion>(arr, std::move(*get));
+ },
+ [&] (const auto&) -> std::unique_ptr<Expression> {
+ return makeLiteral(Null);
+ }
+ );
+
+ return input;
+ }
+};
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/function/source_function.hpp b/include/mbgl/style/function/source_function.hpp
index 9c2ad101ec..02e4b604e2 100644
--- a/include/mbgl/style/function/source_function.hpp
+++ b/include/mbgl/style/function/source_function.hpp
@@ -1,5 +1,7 @@
#pragma once
+#include <mbgl/style/expression/is_constant.hpp>
+#include <mbgl/style/function/convert.hpp>
#include <mbgl/style/function/exponential_stops.hpp>
#include <mbgl/style/function/interval_stops.hpp>
#include <mbgl/style/function/categorical_stops.hpp>
@@ -27,33 +29,48 @@ public:
CategoricalStops<T>,
IdentityStops<T>>>;
+ SourceFunction(std::unique_ptr<expression::Expression> expression_)
+ : expression(std::move(expression_))
+ {
+ assert(expression::isZoomConstant(*expression));
+ assert(!expression::isFeatureConstant(*expression));
+ }
+
SourceFunction(std::string property_, Stops stops_, optional<T> defaultValue_ = {})
: property(std::move(property_)),
stops(std::move(stops_)),
- defaultValue(std::move(defaultValue_)) {
- }
+ defaultValue(std::move(defaultValue_)),
+ expression(stops.match([&] (const IdentityStops<T>&) {
+ return expression::Convert::fromIdentityFunction(expression::valueTypeToExpressionType<T>(), property);
+ }, [&] (const auto& s) {
+ return expression::Convert::toExpression(property, s);
+ }))
+ {}
template <class Feature>
T evaluate(const Feature& feature, T finalDefaultValue) const {
- optional<Value> v = feature.getValue(property);
- if (!v) {
- return defaultValue.value_or(finalDefaultValue);
+ const expression::EvaluationResult result = expression->evaluate(expression::EvaluationContext(&feature));
+ if (result) {
+ const optional<T> typed = expression::fromExpressionValue<T>(*result);
+ return typed ? *typed : defaultValue ? *defaultValue : finalDefaultValue;
}
- return stops.match([&] (const auto& s) -> T {
- return s.evaluate(*v).value_or(defaultValue.value_or(finalDefaultValue));
- });
+ return defaultValue ? *defaultValue : finalDefaultValue;
}
friend bool operator==(const SourceFunction& lhs,
const SourceFunction& rhs) {
- return std::tie(lhs.property, lhs.stops, lhs.defaultValue)
- == std::tie(rhs.property, rhs.stops, rhs.defaultValue);
+ return *lhs.expression == *rhs.expression;
}
+ bool useIntegerZoom = false;
+
+ // retained for compatibility with pre-expression function API
std::string property;
Stops stops;
optional<T> defaultValue;
- bool useIntegerZoom = false;
+
+private:
+ std::shared_ptr<expression::Expression> expression;
};
} // namespace style
diff --git a/include/mbgl/style/layer.hpp b/include/mbgl/style/layer.hpp
index c6a3c0e735..eb2dbf830b 100644
--- a/include/mbgl/style/layer.hpp
+++ b/include/mbgl/style/layer.hpp
@@ -1,7 +1,7 @@
#pragma once
#include <mbgl/util/noncopyable.hpp>
-#include <mbgl/util/any.hpp>
+#include <mbgl/util/unique_any.hpp>
#include <mbgl/util/immutable.hpp>
#include <mbgl/style/layer_type.hpp>
#include <mbgl/style/types.hpp>
@@ -126,7 +126,7 @@ public:
// For use in SDK bindings, which store a reference to a platform-native peer
// object here, so that separately-obtained references to this object share
// identical platform-native peers.
- any peer;
+ util::unique_any peer;
};
} // namespace style
diff --git a/include/mbgl/style/source.hpp b/include/mbgl/style/source.hpp
index cec9619451..0b6a6c72d9 100644
--- a/include/mbgl/style/source.hpp
+++ b/include/mbgl/style/source.hpp
@@ -2,7 +2,7 @@
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/optional.hpp>
-#include <mbgl/util/any.hpp>
+#include <mbgl/util/unique_any.hpp>
#include <mbgl/util/immutable.hpp>
#include <mbgl/style/types.hpp>
@@ -76,7 +76,7 @@ public:
// For use in SDK bindings, which store a reference to a platform-native peer
// object here, so that separately-obtained references to this object share
// identical platform-native peers.
- any peer;
+ util::unique_any peer;
};
} // namespace style
diff --git a/include/mbgl/style/sources/custom_geometry_source.hpp b/include/mbgl/style/sources/custom_geometry_source.hpp
new file mode 100644
index 0000000000..a0b990b44b
--- /dev/null
+++ b/include/mbgl/style/sources/custom_geometry_source.hpp
@@ -0,0 +1,56 @@
+#pragma once
+
+#include <mbgl/style/source.hpp>
+#include <mbgl/util/geo.hpp>
+#include <mbgl/util/geojson.hpp>
+#include <mbgl/util/range.hpp>
+#include <mbgl/util/constants.hpp>
+
+namespace mbgl {
+
+class OverscaledTileID;
+class CanonicalTileID;
+template <class T>
+class Actor;
+
+namespace style {
+
+using TileFunction = std::function<void(const CanonicalTileID&)>;
+
+class CustomTileLoader;
+
+class CustomGeometrySource : public Source {
+public:
+ struct TileOptions {
+ double tolerance = 0.375;
+ uint16_t tileSize = util::tileSize;
+ uint16_t buffer = 128;
+ };
+
+ struct Options {
+ TileFunction fetchTileFunction;
+ TileFunction cancelTileFunction;
+ Range<uint8_t> zoomRange = { 0, 18};
+ TileOptions tileOptions;
+ };
+public:
+ CustomGeometrySource(std::string id, CustomGeometrySource::Options options);
+ ~CustomGeometrySource() final;
+ void loadDescription(FileSource&) final;
+ void setTileData(const CanonicalTileID&, const GeoJSON&);
+ void invalidateTile(const CanonicalTileID&);
+ void invalidateRegion(const LatLngBounds&);
+ // Private implementation
+ class Impl;
+ const Impl& impl() const;
+private:
+ std::unique_ptr<Actor<CustomTileLoader>> loader;
+};
+
+template <>
+inline bool Source::is<CustomGeometrySource>() const {
+ return getType() == SourceType::CustomVector;
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/sources/geojson_source.hpp b/include/mbgl/style/sources/geojson_source.hpp
index 5bdf1ef957..372e7c7a78 100644
--- a/include/mbgl/style/sources/geojson_source.hpp
+++ b/include/mbgl/style/sources/geojson_source.hpp
@@ -3,6 +3,7 @@
#include <mbgl/style/source.hpp>
#include <mbgl/util/geojson.hpp>
#include <mbgl/util/optional.hpp>
+#include <mbgl/util/constants.hpp>
namespace mbgl {
@@ -14,6 +15,7 @@ struct GeoJSONOptions {
// GeoJSON-VT options
uint8_t minzoom = 0;
uint8_t maxzoom = 18;
+ uint16_t tileSize = util::tileSize;
uint16_t buffer = 128;
double tolerance = 0.375;
diff --git a/include/mbgl/style/types.hpp b/include/mbgl/style/types.hpp
index ec7358de8c..6fe457e181 100644
--- a/include/mbgl/style/types.hpp
+++ b/include/mbgl/style/types.hpp
@@ -4,18 +4,19 @@
namespace mbgl {
-// TODO: should be in public source.hpp header and style namespace
+namespace style {
+
+// TODO: should be in public source.hpp header
enum class SourceType : uint8_t {
Vector,
Raster,
GeoJSON,
Video,
Annotations,
- Image
+ Image,
+ CustomVector
};
-namespace style {
-
enum class VisibilityType : bool {
Visible,
None,
diff --git a/include/mbgl/tile/tile_id.hpp b/include/mbgl/tile/tile_id.hpp
index 0457dd3a07..11fb5ce537 100644
--- a/include/mbgl/tile/tile_id.hpp
+++ b/include/mbgl/tile/tile_id.hpp
@@ -30,9 +30,9 @@ public:
CanonicalTileID scaledTo(uint8_t z) const;
std::array<CanonicalTileID, 4> children() const;
- const uint8_t z;
- const uint32_t x;
- const uint32_t y;
+ uint8_t z;
+ uint32_t x;
+ uint32_t y;
};
::std::ostream& operator<<(::std::ostream& os, const CanonicalTileID& rhs);
diff --git a/include/mbgl/util/any.hpp b/include/mbgl/util/any.hpp
deleted file mode 100644
index eea64b188a..0000000000
--- a/include/mbgl/util/any.hpp
+++ /dev/null
@@ -1,10 +0,0 @@
-#pragma once
-
-#include <linb/any.hpp>
-
-namespace mbgl {
-
-using linb::any;
-using linb::any_cast;
-
-} // namespace mbgl
diff --git a/include/mbgl/util/enum.hpp b/include/mbgl/util/enum.hpp
index 369ca86bfd..608befd3c4 100644
--- a/include/mbgl/util/enum.hpp
+++ b/include/mbgl/util/enum.hpp
@@ -11,6 +11,7 @@ namespace mbgl {
template <typename T>
class Enum {
public:
+ using Type = T;
static const char * toString(T);
static optional<T> toEnum(const std::string&);
};
diff --git a/include/mbgl/util/geo.hpp b/include/mbgl/util/geo.hpp
index 6d725b102b..60043ee156 100644
--- a/include/mbgl/util/geo.hpp
+++ b/include/mbgl/util/geo.hpp
@@ -154,18 +154,84 @@ public:
sw.longitude() > ne.longitude();
}
- bool contains(const LatLng& point) const {
- return (point.latitude() >= sw.latitude() &&
- point.latitude() <= ne.latitude() &&
- point.longitude() >= sw.longitude() &&
- point.longitude() <= ne.longitude());
- }
-
- bool intersects(const LatLngBounds area) const {
- return (area.ne.latitude() > sw.latitude() &&
- area.sw.latitude() < ne.latitude() &&
- area.ne.longitude() > sw.longitude() &&
- area.sw.longitude() < ne.longitude());
+ bool crossesAntimeridian() const {
+ return (sw.wrapped().longitude() > ne.wrapped().longitude());
+ }
+
+ bool contains(const LatLng& point, LatLng::WrapMode wrap = LatLng::Unwrapped) const {
+ bool containsLatitude = point.latitude() >= sw.latitude() &&
+ point.latitude() <= ne.latitude();
+ if (!containsLatitude) {
+ return false;
+ }
+
+ bool containsUnwrappedLongitude = point.longitude() >= sw.longitude() &&
+ point.longitude() <= ne.longitude();
+ if (containsUnwrappedLongitude) {
+ return true;
+ } else if (wrap == LatLng::Wrapped) {
+ LatLngBounds wrapped(sw.wrapped(), ne.wrapped());
+ auto ptLon = point.wrapped().longitude();
+ if (crossesAntimeridian()) {
+ return (ptLon >= wrapped.sw.longitude() &&
+ ptLon <= util::LONGITUDE_MAX) ||
+ (ptLon <= wrapped.ne.longitude() &&
+ ptLon >= -util::LONGITUDE_MAX);
+ } else {
+ return (ptLon >= wrapped.sw.longitude() &&
+ ptLon <= wrapped.ne.longitude());
+ }
+ }
+ return false;
+ }
+
+ bool contains(const LatLngBounds& area, LatLng::WrapMode wrap = LatLng::Unwrapped) const {
+ bool containsLatitude = area.north() <= north() && area.south() >= south();
+ if (!containsLatitude) {
+ return false;
+ }
+
+ bool containsUnwrapped = area.east() <= east() && area.west() >= west();
+ if(containsUnwrapped) {
+ return true;
+ } else if (wrap == LatLng::Wrapped) {
+ LatLngBounds wrapped(sw.wrapped(), ne.wrapped());
+ LatLngBounds other(area.sw.wrapped(), area.ne.wrapped());
+ if (crossesAntimeridian() & !area.crossesAntimeridian()) {
+ return (other.east() <= util::LONGITUDE_MAX && other.west() >= wrapped.west()) ||
+ (other.east() <= wrapped.east() && other.west() >= -util::LONGITUDE_MAX);
+ } else {
+ return other.east() <= wrapped.east() && other.west() >= wrapped.west();
+ }
+ }
+ return false;
+ }
+
+ bool intersects(const LatLngBounds area, LatLng::WrapMode wrap = LatLng::Unwrapped) const {
+ bool latitudeIntersects = area.north() > south() && area.south() < north();
+ if (!latitudeIntersects) {
+ return false;
+ }
+
+ bool longitudeIntersects = area.east() > west() && area.west() < east();
+ if (longitudeIntersects) {
+ return true;
+ } else if (wrap == LatLng::Wrapped) {
+ LatLngBounds wrapped(sw.wrapped(), ne.wrapped());
+ LatLngBounds other(area.sw.wrapped(), area.ne.wrapped());
+ if (crossesAntimeridian()) {
+ return area.crossesAntimeridian() ||
+ other.east() > wrapped.west() ||
+ other.west() < wrapped.east();
+ } else if (other.crossesAntimeridian()){
+ return other.east() > wrapped.west() ||
+ other.west() < wrapped.east();
+ } else {
+ return other.east() > wrapped.west() &&
+ other.west() < wrapped.east();
+ }
+ }
+ return false;
}
private:
diff --git a/include/mbgl/util/interpolate.hpp b/include/mbgl/util/interpolate.hpp
index 6738987598..aff730a0a2 100644
--- a/include/mbgl/util/interpolate.hpp
+++ b/include/mbgl/util/interpolate.hpp
@@ -3,6 +3,7 @@
#include <mbgl/util/color.hpp>
#include <mbgl/util/range.hpp>
#include <mbgl/style/position.hpp>
+#include <mbgl/style/expression/value.hpp>
#include <array>
#include <vector>
@@ -47,6 +48,36 @@ public:
}
};
+
+// In order to accept Array<Number, N> as an output value for Curve
+// expressions, we need to have an interpolatable std::vector type.
+// However, style properties like line-dasharray are represented using
+// std::vector<float>, and should NOT be considered interpolatable.
+// So, we use std::vector<Value> to represent expression array values,
+// asserting that (a) the vectors are the same size, and (b) they contain
+// only numeric values. (These invariants should be relatively safe,
+// being enforced by the expression type system.)
+template<>
+struct Interpolator<std::vector<style::expression::Value>> {
+ std::vector<style::expression::Value> operator()(const std::vector<style::expression::Value>& a,
+ const std::vector<style::expression::Value>& b,
+ const double t) const {
+ assert(a.size() == b.size());
+ if (a.size() == 0) return {};
+ std::vector<style::expression::Value> result;
+ for (std::size_t i = 0; i < a.size(); i++) {
+ assert(a[i].template is<double>());
+ assert(b[i].template is<double>());
+ style::expression::Value item = interpolate(
+ a[i].template get<double>(),
+ b[i].template get<double>(),
+ t);
+ result.push_back(item);
+ }
+ return result;
+ }
+};
+
template <>
struct Interpolator<style::Position> {
public:
@@ -101,5 +132,7 @@ struct Interpolatable
std::true_type,
std::false_type> {};
+
+
} // namespace util
} // namespace mbgl
diff --git a/include/mbgl/util/projection.hpp b/include/mbgl/util/projection.hpp
index f64502c5bc..1613af3b36 100644
--- a/include/mbgl/util/projection.hpp
+++ b/include/mbgl/util/projection.hpp
@@ -92,8 +92,8 @@ public:
const double t2z = tileSize * std::pow(2, zoom);
Point<double> pt = project_(point, t2z);
// Flip y coordinate
- auto x = std::round(std::min(pt.x, t2z));
- auto y = std::round(std::min(t2z - pt.y, t2z));
+ auto x = ::round(std::min(pt.x, t2z));
+ auto y = ::round(std::min(t2z - pt.y, t2z));
return { x, y };
}
private:
diff --git a/include/mbgl/util/string.hpp b/include/mbgl/util/string.hpp
index 82d317c620..13498ccb92 100644
--- a/include/mbgl/util/string.hpp
+++ b/include/mbgl/util/string.hpp
@@ -25,6 +25,10 @@ inline int stoi(const std::string &str)
return atoi(str.c_str());
}
+inline float stof(const std::string &str) {
+ return static_cast<float>(atof(str.c_str()));
+}
+
} // namespace std
#endif
@@ -65,5 +69,9 @@ inline std::string toString(std::exception_ptr error) {
}
}
+inline float stof(const std::string& str) {
+ return std::stof(str);
+}
+
} // namespace util
} // namespace mbgl
diff --git a/include/mbgl/util/tileset.hpp b/include/mbgl/util/tileset.hpp
index 61aa47d4ea..5a03e1a9da 100644
--- a/include/mbgl/util/tileset.hpp
+++ b/include/mbgl/util/tileset.hpp
@@ -3,6 +3,7 @@
#include <mbgl/util/range.hpp>
#include <mbgl/util/constants.hpp>
+#include <tuple>
#include <vector>
#include <string>
#include <cstdint>
diff --git a/include/mbgl/util/unique_any.hpp b/include/mbgl/util/unique_any.hpp
new file mode 100644
index 0000000000..d488930a03
--- /dev/null
+++ b/include/mbgl/util/unique_any.hpp
@@ -0,0 +1,275 @@
+#pragma once
+
+#include <typeinfo>
+#include <type_traits>
+#include <stdexcept>
+namespace mbgl {
+namespace util {
+
+class bad_any_cast : public std::bad_cast {
+public:
+ const char* what() const noexcept override {
+ return "bad any_cast<>()";
+ }
+};
+/**
+ * A variant of `std::any` for non-copyable types.
+ *
+ * Use `unique_any` for non-copyable types (e.g. `std::unique_ptr<T>`)
+ * or to ensure that no copies are made of copyable types that are
+ * moved in.
+ *
+ * `uniqe_any` differs from `std::any` in that it does not support copy construction
+ * or copy assignment. It also does not require the contained type to be copy
+ * constructible.
+ *
+ * The `any_cast<T>()` methods work similar to `std::any_cast<T>()` except that
+ * non-copyable types may only be cast to references.
+ *
+ * Example usage:
+ * unique_any u1(3);
+ * auto u2 = unique_any(std::move(u1)); // u1 is moved from
+ * int i = any_cast<int>(u2);
+ *
+ * unique_any u2;
+ * u2 = std::unique_ptr<int>(new int);
+ * std::unique_ptr<int> iPtr = any_cast<std::unique_ptr<int>>(std::move(u2));
+ *
+ * Inspired by linb::any (https://github.com/thelink2012/any) and the
+ * libc++ implementation (https://github.com/llvm-mirror/libcxx).
+ */
+class unique_any final
+{
+public:
+ unique_any() = default;
+
+ //Copy constructor (deleted)
+ unique_any(const unique_any& rhs) = delete;
+
+ unique_any(unique_any&& rhs) : vtable(rhs.vtable) {
+ if (vtable) {
+ vtable->move(std::move(rhs.storage), storage);
+ }
+ rhs.vtable = nullptr;
+ }
+
+ // Constructs with a direct-initilizated object of type ValueType
+ template <typename ValueType,
+ typename _Vt = std::decay_t<ValueType>,
+ typename = std::enable_if_t<!std::is_same<_Vt, unique_any>::value> >
+ unique_any(ValueType&& value) {
+ create(std::forward<ValueType>(value));
+ }
+
+ ~unique_any() {
+ reset();
+ }
+
+ unique_any& operator=(unique_any&& rhs) {
+ unique_any(std::move(rhs)).swap(*this);
+ return *this;
+ }
+
+ template <class ValueType,
+ typename = std::enable_if_t<!std::is_same<std::decay_t<ValueType>, unique_any>::value> >
+ unique_any& operator=(ValueType&& rhs) {
+ unique_any(std::forward<ValueType>(rhs)).swap(*this);
+ return *this;
+ }
+
+ void reset() {
+ if (vtable) {
+ vtable->destroy(storage);
+ vtable = nullptr;
+ }
+ }
+
+ void swap(unique_any& rhs) {
+ if (this == &rhs) {
+ return;
+ } else {
+ unique_any tmp(std::move(rhs));
+ rhs.vtable = vtable;
+ if (rhs.vtable) {
+ rhs.vtable->move(std::move(storage), rhs.storage);
+ }
+ vtable = tmp.vtable;
+ if (vtable) {
+ vtable->move(std::move(tmp.storage), storage);
+ }
+ }
+ }
+
+ const std::type_info& type() const {
+ return !has_value()? typeid(void) : vtable->type();
+ }
+
+ bool has_value() const {
+ return vtable != nullptr;
+ }
+
+private:
+
+ union Storage {
+ using StackStorage = std::aligned_storage_t<3*sizeof(void*), std::alignment_of<void*>::value>;
+ Storage() = default;
+
+ void * dynamic { nullptr };
+ StackStorage stack;
+ };
+
+ template<typename T>
+ struct AllocateOnStack : std::integral_constant<bool,
+ sizeof(T) <= sizeof(Storage::stack)
+ && std::alignment_of<T>::value <= std::alignment_of<Storage::StackStorage>::value
+ && std::is_nothrow_move_constructible<T>::value> {
+ };
+
+ struct VTable {
+ virtual ~VTable() = default;
+ virtual void move(Storage&& src, Storage& dest) = 0;
+ virtual void destroy(Storage&) = 0;
+ virtual const std::type_info& type() = 0;
+ };
+
+ template <typename ValueType>
+ struct VTableHeap : public VTable {
+ void move(Storage&& src, Storage& dest) override {
+ destroy(dest);
+ dest.dynamic = src.dynamic;
+ }
+
+ void destroy(Storage& s) override {
+ if (s.dynamic) {
+ delete reinterpret_cast<ValueType*>(s.dynamic);
+ }
+ s.dynamic = nullptr;
+ }
+
+ const std::type_info& type() override {
+ return typeid(ValueType);
+ }
+ };
+
+ template <typename ValueType>
+ struct VTableStack : public VTable {
+ void move(Storage&& src, Storage& dest) override {
+ auto srcValue = reinterpret_cast<ValueType&&>(src.stack);
+ new (static_cast<void*>(&dest.stack)) ValueType(std::move(srcValue));
+ srcValue.~ValueType();
+ }
+
+ void destroy(Storage& s) override {
+ reinterpret_cast<ValueType&>(s.stack).~ValueType();
+ }
+
+ const std::type_info& type() override {
+ return typeid(ValueType);
+ }
+ };
+
+ template <typename ValueType>
+ static VTable* vtableForType() {
+ using VTableType = std::conditional_t<AllocateOnStack<ValueType>::value, VTableStack<ValueType>, VTableHeap<ValueType> >;
+ static VTableType vtable;
+ return &vtable;
+ }
+
+ template <typename ValueType, typename _Vt>
+ std::enable_if_t<AllocateOnStack<_Vt>::value>
+ createStorage(ValueType&& value) {
+ new (static_cast<void*>(&storage.stack)) _Vt(std::forward<ValueType>(value));
+ }
+
+ template <typename ValueType, typename _Vt>
+ std::enable_if_t<!AllocateOnStack<_Vt>::value>
+ createStorage(ValueType&& value) {
+ storage.dynamic = static_cast<void*>(new _Vt(std::forward<ValueType>(value)));
+ }
+
+ template <typename ValueType>
+ void create(ValueType&& value) {
+ using _Vt = std::decay_t<ValueType>;
+ vtable = vtableForType<_Vt>();
+ createStorage<ValueType, _Vt>(std::forward<ValueType>(value));
+ }
+
+ VTable* vtable { nullptr };
+ Storage storage;
+
+protected:
+ template<class ValueType>
+ friend const ValueType* any_cast(const unique_any* operand) ;
+
+ template<class ValueType>
+ friend ValueType* any_cast(unique_any* operand) ;
+
+ template<typename ValueType, typename _Vt = std::decay_t<ValueType> >
+ ValueType* cast()
+ {
+ return reinterpret_cast<ValueType *>(
+ AllocateOnStack<_Vt>::value ? &storage.stack : storage.dynamic);
+ }
+};
+
+template<typename ValueType>
+inline const ValueType* any_cast(const unique_any* any)
+{
+ return any_cast<ValueType>(const_cast<unique_any *>(any));
+}
+
+template<typename ValueType>
+inline ValueType* any_cast(unique_any* any)
+{
+ if(any == nullptr || any->type() != typeid(ValueType))
+ return nullptr;
+ else
+ return any->cast<ValueType>();
+}
+
+template<typename ValueType, typename _Vt = std::decay_t<ValueType> >
+inline ValueType any_cast(const unique_any& any)
+{
+ static_assert(std::is_constructible<ValueType, const _Vt&>::value,
+ "any_cast type can't construct copy of contained object");
+ auto temp = any_cast<_Vt>(&any);
+ if (temp == nullptr) {
+ throw bad_any_cast();
+ }
+ return static_cast<ValueType>(*temp);
+}
+
+template<typename ValueType, typename _Vt = std::decay_t<ValueType> >
+inline ValueType any_cast(unique_any& any)
+{
+ static_assert(std::is_constructible<ValueType, const _Vt&>::value,
+ "any_cast type can't construct copy of contained object");
+ auto temp = any_cast<_Vt>(&any);
+ if (temp == nullptr) {
+ throw bad_any_cast();
+ }
+ return static_cast<ValueType>(*temp);
+}
+
+template<typename ValueType, typename _Vt = std::remove_cv_t<ValueType> >
+inline ValueType any_cast(unique_any&& any)
+{
+ auto temp = any_cast<_Vt>(&any);
+ if (temp == nullptr) {
+ throw bad_any_cast();
+ }
+ auto retValue = static_cast<ValueType>(std::move(*temp));
+ any.reset();
+ return std::move(retValue);
+}
+
+} // namespace util
+} // namespace mbgl
+
+namespace std {
+
+inline void swap(mbgl::util::unique_any& lhs, mbgl::util::unique_any& rhs) {
+ lhs.swap(rhs);
+}
+
+} // namespace std
diff --git a/include/mbgl/util/unitbezier.hpp b/include/mbgl/util/unitbezier.hpp
index 6e644e2d1f..92f23d6718 100644
--- a/include/mbgl/util/unitbezier.hpp
+++ b/include/mbgl/util/unitbezier.hpp
@@ -26,6 +26,7 @@
#pragma once
#include <cmath>
+#include <tuple>
namespace mbgl {
namespace util {
@@ -102,6 +103,11 @@ struct UnitBezier {
double solve(double x, double epsilon) const {
return sampleCurveY(solveCurveX(x, epsilon));
}
+
+ bool operator==(const UnitBezier& rhs) const {
+ return std::tie(cx, bx, ax, cy, by, ay) ==
+ std::tie(rhs.cx, rhs.bx, rhs.ax, rhs.cy, rhs.by, rhs.ay);
+ }
private:
const double cx;
diff --git a/mapbox-gl-js b/mapbox-gl-js
-Subproject 3634d945477cb7dbbf1e0bebf4cf51542821895
+Subproject 2e6fc8901ec3937a0e71da40dff9d7d037dee74
diff --git a/common/bench-icon.svg b/misc/bench-icon.svg
index 28df6f600d..28df6f600d 100644
--- a/common/bench-icon.svg
+++ b/misc/bench-icon.svg
diff --git a/common/ca-bundle.crt b/misc/ca-bundle.crt
index 256da1ff70..6fd701b72c 100644
--- a/common/ca-bundle.crt
+++ b/misc/ca-bundle.crt
@@ -1,7 +1,7 @@
##
## Bundle of CA Root Certificates
##
-## Certificate data from Mozilla as of: Fri Jan 27 10:57:10 2017 GMT
+## Certificate data from Mozilla as of: Wed Dec 13 12:22:38 2017 GMT
##
## This is a bundle of X.509 certificates of public Certificate Authorities
## (CA). These were automatically extracted from Mozilla's root certificates
@@ -14,7 +14,7 @@
## Just configure this file as the SSLCACertificateFile.
##
## Conversion done with mk-ca-bundle.pl version 1.27.
-## SHA256: dffa79e6aa993f558e82884abf7bb54bf440ab66ee91d82a27a627f6f2a4ace4
+## SHA256: 2b2dbe5244e0047e088c597998883a913f6c5fffd1cb5c0fe5a368c8466cb2ec
##
@@ -130,30 +130,6 @@ Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H
RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
-----END CERTIFICATE-----
-AddTrust Low-Value Services Root
-================================
------BEGIN CERTIFICATE-----
-MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
-QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRU
-cnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMwMTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQsw
-CQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBO
-ZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEB
-AQUAA4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ulCDtbKRY6
-54eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6ntGO0/7Gcrjyvd7ZWxbWr
-oulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyldI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1
-Zmne3yzxbrww2ywkEtvrNTVokMsAsJchPXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJui
-GMx1I4S+6+JNM3GOGvDC+Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8w
-HQYDVR0OBBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8EBTAD
-AQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBlMQswCQYDVQQGEwJT
-RTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEw
-HwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxt
-ZBsfzQ3duQH6lmM0MkhHma6X7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0Ph
-iVYrqW9yTkkz43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY
-eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJlpz/+0WatC7xr
-mYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOAWiFeIc9TVPC6b4nbqKqVz4vj
-ccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk=
------END CERTIFICATE-----
-
AddTrust External Root
======================
-----BEGIN CERTIFICATE-----
@@ -178,54 +154,6 @@ e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u
G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
-----END CERTIFICATE-----
-AddTrust Public Services Root
-=============================
------BEGIN CERTIFICATE-----
-MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
-QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSAwHgYDVQQDExdBZGRU
-cnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAxMDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJ
-BgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5l
-dHdvcmsxIDAeBgNVBAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEF
-AAOCAQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV6tsfSlbu
-nyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nXGCwwfQ56HmIexkvA/X1i
-d9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnPdzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSG
-Aa2Il+tmzV7R/9x98oTaunet3IAIx6eH1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAw
-HM+A+WD+eeSI8t0A65RF62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0G
-A1UdDgQWBBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
-/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDELMAkGA1UEBhMCU0Ux
-FDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29yazEgMB4G
-A1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4
-JNojVhaTdt02KLmuG7jD8WS6IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL
-+YPoRNWyQSW/iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao
-GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh4SINhwBk/ox9
-Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQmXiLsks3/QppEIW1cxeMiHV9H
-EufOX1362KqxMy3ZdvJOOjMMK7MtkAY=
------END CERTIFICATE-----
-
-AddTrust Qualified Certificates Root
-====================================
------BEGIN CERTIFICATE-----
-MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
-QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSMwIQYDVQQDExpBZGRU
-cnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcx
-CzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQ
-IE5ldHdvcmsxIzAhBgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG
-9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwqxBb/4Oxx
-64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G87B4pfYOQnrjfxvM0PC3
-KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i2O+tCBGaKZnhqkRFmhJePp1tUvznoD1o
-L/BLcHwTOK28FSXx1s6rosAx1i+f4P8UWfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GR
-wVY18BTcZTYJbqukB8c10cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HU
-MIHRMB0GA1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/
-BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6FrpGkwZzELMAkGA1UE
-BhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29y
-azEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlmaWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQAD
-ggEBABmrder4i2VhlRO6aQTvhsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxG
-GuoYQ992zPlmhpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X
-dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3P6CxB9bpT9ze
-RXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9YiQBCYz95OdBEsIJuQRno3eDB
-iFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5noxqE=
------END CERTIFICATE-----
-
Entrust Root Certification Authority
====================================
-----BEGIN CERTIFICATE-----
@@ -273,27 +201,6 @@ XE0zX5IJL4hmXXeXxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm
Mw==
-----END CERTIFICATE-----
-GeoTrust Global CA 2
-====================
------BEGIN CERTIFICATE-----
-MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
-R2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwHhcNMDQwMzA0MDUw
-MDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j
-LjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
-ggEKAoIBAQDvPE1APRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/
-NTL8Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hLTytCOb1k
-LUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL5mkWRxHCJ1kDs6ZgwiFA
-Vvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7S4wMcoKK+xfNAGw6EzywhIdLFnopsk/b
-HdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQF
-MAMBAf8wHQYDVR0OBBYEFHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNH
-K266ZUapEBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6tdEPx7
-srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv/NgdRN3ggX+d6Yvh
-ZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywNA0ZF66D0f0hExghAzN4bcLUprbqL
-OzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkC
-x1YAzUm5s2x7UwQa4qjJqhIFI8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqF
-H4z1Ir+rzoPz4iIprn2DQKi6bA==
------END CERTIFICATE-----
-
GeoTrust Universal CA
=====================
-----BEGIN CERTIFICATE-----
@@ -419,56 +326,6 @@ Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z
12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
-----END CERTIFICATE-----
-Comodo Secure Services root
-===========================
------BEGIN CERTIFICATE-----
-MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
-R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
-TGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAw
-MDAwMFoXDTI4MTIzMTIzNTk1OVowfjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFu
-Y2hlc3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAi
-BgNVBAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP
-ADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPMcm3ye5drswfxdySRXyWP
-9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3SHpR7LZQdqnXXs5jLrLxkU0C8j6ysNstc
-rbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rC
-oznl2yY4rYsK7hljxxwk3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3V
-p6ea5EQz6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNVHQ4E
-FgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w
-gYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL1NlY3VyZUNlcnRpZmlj
-YXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRwOi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlm
-aWNhdGVTZXJ2aWNlcy5jcmwwDQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm
-4J4oqF7Tt/Q05qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj
-Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtIgKvcnDe4IRRL
-DXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJaD61JlfutuC23bkpgHl9j6Pw
-pCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDlizeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1H
-RR3B7Hzs/Sk=
------END CERTIFICATE-----
-
-Comodo Trusted Services root
-============================
------BEGIN CERTIFICATE-----
-MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
-R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
-TGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEw
-MDAwMDBaFw0yODEyMzEyMzU5NTlaMH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1h
-bmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUw
-IwYDVQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0BAQEFAAOC
-AQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWWfnJSoBVC21ndZHoa0Lh7
-3TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMtTGo87IvDktJTdyR0nAducPy9C1t2ul/y
-/9c3S0pgePfw+spwtOpZqqPOSC+pw7ILfhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6
-juljatEPmsbS9Is6FARW1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsS
-ivnkBbA7kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0GA1Ud
-DgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
-/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21vZG9jYS5jb20vVHJ1c3RlZENlcnRp
-ZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRodHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENl
-cnRpZmljYXRlU2VydmljZXMuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8Ntw
-uleGFTQQuS9/HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32
-pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxISjBc/lDb+XbDA
-BHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+xqFx7D+gIIxmOom0jtTYsU0l
-R+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/AtyjcndBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O
-9y5Xt5hwXsjEeLBi
------END CERTIFICATE-----
-
QuoVadis Root CA
================
-----BEGIN CERTIFICATE-----
@@ -608,32 +465,6 @@ EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH
llpwrN9M
-----END CERTIFICATE-----
-UTN USERFirst Hardware Root CA
-==============================
------BEGIN CERTIFICATE-----
-MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCBlzELMAkGA1UE
-BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl
-IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAd
-BgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgx
-OTIyWjCBlzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0
-eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVz
-ZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwggEiMA0GCSqGSIb3
-DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlI
-wrthdBKWHTxqctU8EGc6Oe0rE81m65UJM6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFd
-tqdt++BxF2uiiPsA3/4aMXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8
-i4fDidNdoI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqIDsjf
-Pe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9KsyoUhbAgMBAAGjgbkw
-gbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKFyXyYbKJhDlV0HN9WF
-lp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNF
-UkZpcnN0LUhhcmR3YXJlLmNybDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUF
-BwMGBggrBgEFBQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM
-//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28GpgoiskliCE7/yMgUsogW
-XecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gECJChicsZUN/KHAG8HQQZexB2
-lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kn
-iCrVWFCVH/A7HFe7fRQ5YiuayZSSKqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67
-nfhmqA==
------END CERTIFICATE-----
-
Camerfirma Chambers of Commerce Root
====================================
-----BEGIN CERTIFICATE-----
@@ -831,38 +662,6 @@ CZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDeLMDDav7v3Aun+kbfYNucpllQdSNpc5Oy
+fwC00fmcc4QAu4njIT/rEUNE1yDMuAlpYYsfPQS
-----END CERTIFICATE-----
-Swisscom Root CA 1
-==================
------BEGIN CERTIFICATE-----
-MIIF2TCCA8GgAwIBAgIQXAuFXAvnWUHfV8w/f52oNjANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQG
-EwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2VydGlmaWNhdGUgU2Vy
-dmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3QgQ0EgMTAeFw0wNTA4MTgxMjA2MjBaFw0yNTA4
-MTgyMjA2MjBaMGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGln
-aXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAxMIIC
-IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0LmwqAzZuz8h+BvVM5OAFmUgdbI9m2BtRsiM
-MW8Xw/qabFbtPMWRV8PNq5ZJkCoZSx6jbVfd8StiKHVFXqrWW/oLJdihFvkcxC7mlSpnzNApbjyF
-NDhhSbEAn9Y6cV9Nbc5fuankiX9qUvrKm/LcqfmdmUc/TilftKaNXXsLmREDA/7n29uj/x2lzZAe
-AR81sH8A25Bvxn570e56eqeqDFdvpG3FEzuwpdntMhy0XmeLVNxzh+XTF3xmUHJd1BpYwdnP2IkC
-b6dJtDZd0KTeByy2dbcokdaXvij1mB7qWybJvbCXc9qukSbraMH5ORXWZ0sKbU/Lz7DkQnGMU3nn
-7uHbHaBuHYwadzVcFh4rUx80i9Fs/PJnB3r1re3WmquhsUvhzDdf/X/NTa64H5xD+SpYVUNFvJbN
-cA78yeNmuk6NO4HLFWR7uZToXTNShXEuT46iBhFRyePLoW4xCGQMwtI89Tbo19AOeCMgkckkKmUp
-WyL3Ic6DXqTz3kvTaI9GdVyDCW4pa8RwjPWd1yAv/0bSKzjCL3UcPX7ape8eYIVpQtPM+GP+HkM5
-haa2Y0EQs3MevNP6yn0WR+Kn1dCjigoIlmJWbjTb2QK5MHXjBNLnj8KwEUAKrNVxAmKLMb7dxiNY
-MUJDLXT5xp6mig/p/r+D5kNXJLrvRjSq1xIBOO0CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYw
-HQYDVR0hBBYwFDASBgdghXQBUwABBgdghXQBUwABMBIGA1UdEwEB/wQIMAYBAf8CAQcwHwYDVR0j
-BBgwFoAUAyUv3m+CATpcLNwroWm1Z9SM0/0wHQYDVR0OBBYEFAMlL95vggE6XCzcK6FptWfUjNP9
-MA0GCSqGSIb3DQEBBQUAA4ICAQA1EMvspgQNDQ/NwNurqPKIlwzfky9NfEBWMXrrpA9gzXrzvsMn
-jgM+pN0S734edAY8PzHyHHuRMSG08NBsl9Tpl7IkVh5WwzW9iAUPWxAaZOHHgjD5Mq2eUCzneAXQ
-MbFamIp1TpBcahQq4FJHgmDmHtqBsfsUC1rxn9KVuj7QG9YVHaO+htXbD8BJZLsuUBlL0iT43R4H
-VtA4oJVwIHaM190e3p9xxCPvgxNcoyQVTSlAPGrEqdi3pkSlDfTgnXceQHAm/NrZNuR55LU/vJtl
-vrsRls/bxig5OgjOR1tTWsWZ/l2p3e9M1MalrQLmjAcSHm8D0W+go/MpvRLHUKKwf4ipmXeascCl
-OS5cfGniLLDqN2qk4Vrh9VDlg++luyqI54zb/W1elxmofmZ1a3Hqv7HHb6D0jqTsNFFbjCYDcKF3
-1QESVwA12yPeDooomf2xEG9L/zgtYE4snOtnta1J7ksfrK/7DZBaZmBwXarNeNQk7shBoJMBkpxq
-nvy5JMWzFYJ+vq6VK+uxwNrjAWALXmmshFZhvnEX/h0TD/7Gh0Xp/jKgGg0TpJRVcaUWi7rKibCy
-x/yP2FS1k2Kdzs9Z+z0YzirLNRWCXf9UIltxUvu3yf5gmwBBZPCqKuy2QkPOiWaByIufOVQDJdMW
-NY6E0F/6MBr1mmz0DlP5OlvRHA==
------END CERTIFICATE-----
-
DigiCert Assured ID Root CA
===========================
-----BEGIN CERTIFICATE-----
@@ -1220,33 +1019,6 @@ wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD
ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey
-----END CERTIFICATE-----
-WellsSecure Public Root Certificate Authority
-=============================================
------BEGIN CERTIFICATE-----
-MIIEvTCCA6WgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoM
-F1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYw
-NAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN
-MDcxMjEzMTcwNzU0WhcNMjIxMjE0MDAwNzU0WjCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dl
-bGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYD
-VQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G
-CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDub7S9eeKPCCGeOARBJe+rWxxTkqxtnt3CxC5FlAM1
-iGd0V+PfjLindo8796jE2yljDpFoNoqXjopxaAkH5OjUDk/41itMpBb570OYj7OeUt9tkTmPOL13
-i0Nj67eT/DBMHAGTthP796EfvyXhdDcsHqRePGj4S78NuR4uNuip5Kf4D8uCdXw1LSLWwr8L87T8
-bJVhHlfXBIEyg1J55oNjz7fLY4sR4r1e6/aN7ZVyKLSsEmLpSjPmgzKuBXWVvYSV2ypcm44uDLiB
-K0HmOFafSZtsdvqKXfcBeYF8wYNABf5x/Qw/zE5gCQ5lRxAvAcAFP4/4s0HvWkJ+We/SlwxlAgMB
-AAGjggE0MIIBMDAPBgNVHRMBAf8EBTADAQH/MDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6Ly9jcmwu
-cGtpLndlbGxzZmFyZ28uY29tL3dzcHJjYS5jcmwwDgYDVR0PAQH/BAQDAgHGMB0GA1UdDgQWBBQm
-lRkQ2eihl5H/3BnZtQQ+0nMKajCBsgYDVR0jBIGqMIGngBQmlRkQ2eihl5H/3BnZtQQ+0nMKaqGB
-i6SBiDCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRww
-GgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMg
-Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCAQEwDQYJKoZIhvcNAQEFBQADggEBALkVsUSRzCPI
-K0134/iaeycNzXK7mQDKfGYZUMbVmO2rvwNa5U3lHshPcZeG1eMd/ZDJPHV3V3p9+N701NX3leZ0
-bh08rnyd2wIDBSxxSyU+B+NemvVmFymIGjifz6pBA4SXa5M4esowRBskRDPQ5NHcKDj0E0M1NSlj
-qHyita04pO2t/caaH/+Xc/77szWnk4bGdpEA5qxRFsQnMlzbc9qlk1eOPm01JghZ1edE13YgY+es
-E2fDbbFwRnzVlhE9iW9dqKHrjQrawx0zbKPqZxmamX9LPYNRKh3KL4YMon4QLSvUFpULB6ouFJJJ
-tylv2G0xffX8oRAHh84vWdw+WNs=
------END CERTIFICATE-----
-
COMODO ECC Certification Authority
==================================
-----BEGIN CERTIFICATE-----
@@ -1308,46 +1080,6 @@ hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZiFj4A4xylNoEY
okxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ/L7fCg0=
-----END CERTIFICATE-----
-Microsec e-Szigno Root CA
-=========================
------BEGIN CERTIFICATE-----
-MIIHqDCCBpCgAwIBAgIRAMy4579OKRr9otxmpRwsDxEwDQYJKoZIhvcNAQEFBQAwcjELMAkGA1UE
-BhMCSFUxETAPBgNVBAcTCEJ1ZGFwZXN0MRYwFAYDVQQKEw1NaWNyb3NlYyBMdGQuMRQwEgYDVQQL
-EwtlLVN6aWdubyBDQTEiMCAGA1UEAxMZTWljcm9zZWMgZS1Temlnbm8gUm9vdCBDQTAeFw0wNTA0
-MDYxMjI4NDRaFw0xNzA0MDYxMjI4NDRaMHIxCzAJBgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVz
-dDEWMBQGA1UEChMNTWljcm9zZWMgTHRkLjEUMBIGA1UECxMLZS1Temlnbm8gQ0ExIjAgBgNVBAMT
-GU1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
-AQDtyADVgXvNOABHzNuEwSFpLHSQDCHZU4ftPkNEU6+r+ICbPHiN1I2uuO/TEdyB5s87lozWbxXG
-d36hL+BfkrYn13aaHUM86tnsL+4582pnS4uCzyL4ZVX+LMsvfUh6PXX5qqAnu3jCBspRwn5mS6/N
-oqdNAoI/gqyFxuEPkEeZlApxcpMqyabAvjxWTHOSJ/FrtfX9/DAFYJLG65Z+AZHCabEeHXtTRbjc
-QR/Ji3HWVBTji1R4P770Yjtb9aPs1ZJ04nQw7wHb4dSrmZsqa/i9phyGI0Jf7Enemotb9HI6QMVJ
-PqW+jqpx62z69Rrkav17fVVA71hu5tnVvCSrwe+3AgMBAAGjggQ3MIIEMzBnBggrBgEFBQcBAQRb
-MFkwKAYIKwYBBQUHMAGGHGh0dHBzOi8vcmNhLmUtc3ppZ25vLmh1L29jc3AwLQYIKwYBBQUHMAKG
-IWh0dHA6Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNydDAPBgNVHRMBAf8EBTADAQH/MIIBcwYD
-VR0gBIIBajCCAWYwggFiBgwrBgEEAYGoGAIBAQEwggFQMCgGCCsGAQUFBwIBFhxodHRwOi8vd3d3
-LmUtc3ppZ25vLmh1L1NaU1ovMIIBIgYIKwYBBQUHAgIwggEUHoIBEABBACAAdABhAG4A+gBzAO0A
-dAB2AOEAbgB5ACAA6QByAHQAZQBsAG0AZQB6AOkAcwDpAGgAZQB6ACAA6QBzACAAZQBsAGYAbwBn
-AGEAZADhAHMA4QBoAG8AegAgAGEAIABTAHoAbwBsAGcA4QBsAHQAYQB0APMAIABTAHoAbwBsAGcA
-4QBsAHQAYQB0AOEAcwBpACAAUwB6AGEAYgDhAGwAeQB6AGEAdABhACAAcwB6AGUAcgBpAG4AdAAg
-AGsAZQBsAGwAIABlAGwAagDhAHIAbgBpADoAIABoAHQAdABwADoALwAvAHcAdwB3AC4AZQAtAHMA
-egBpAGcAbgBvAC4AaAB1AC8AUwBaAFMAWgAvMIHIBgNVHR8EgcAwgb0wgbqggbeggbSGIWh0dHA6
-Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNybIaBjmxkYXA6Ly9sZGFwLmUtc3ppZ25vLmh1L0NO
-PU1pY3Jvc2VjJTIwZS1Temlnbm8lMjBSb290JTIwQ0EsT1U9ZS1Temlnbm8lMjBDQSxPPU1pY3Jv
-c2VjJTIwTHRkLixMPUJ1ZGFwZXN0LEM9SFU/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdDtiaW5h
-cnkwDgYDVR0PAQH/BAQDAgEGMIGWBgNVHREEgY4wgYuBEGluZm9AZS1zemlnbm8uaHWkdzB1MSMw
-IQYDVQQDDBpNaWNyb3NlYyBlLVN6aWduw7MgUm9vdCBDQTEWMBQGA1UECwwNZS1TemlnbsOzIEhT
-WjEWMBQGA1UEChMNTWljcm9zZWMgS2Z0LjERMA8GA1UEBxMIQnVkYXBlc3QxCzAJBgNVBAYTAkhV
-MIGsBgNVHSMEgaQwgaGAFMegSXUWYYTbMUuE0vE3QJDvTtz3oXakdDByMQswCQYDVQQGEwJIVTER
-MA8GA1UEBxMIQnVkYXBlc3QxFjAUBgNVBAoTDU1pY3Jvc2VjIEx0ZC4xFDASBgNVBAsTC2UtU3pp
-Z25vIENBMSIwIAYDVQQDExlNaWNyb3NlYyBlLVN6aWdubyBSb290IENBghEAzLjnv04pGv2i3Gal
-HCwPETAdBgNVHQ4EFgQUx6BJdRZhhNsxS4TS8TdAkO9O3PcwDQYJKoZIhvcNAQEFBQADggEBANMT
-nGZjWS7KXHAM/IO8VbH0jgdsZifOwTsgqRy7RlRw7lrMoHfqaEQn6/Ip3Xep1fvj1KcExJW4C+FE
-aGAHQzAxQmHl7tnlJNUb3+FKG6qfx1/4ehHqE5MAyopYse7tDk2016g2JnzgOsHVV4Lxdbb9iV/a
-86g4nzUGCM4ilb7N1fy+W955a9x6qWVmvrElWl/tftOsRm1M9DKHtCAE4Gx4sHfRhUZLphK3dehK
-yVZs15KrnfVJONJPU+NVkBHbmJbGSfI+9J8b4PeI3CVimUTYc78/MPMMNz7UwiiAc7EBt51alhQB
-S6kRnSlqLtBdgcDPsiBDxwPgN05dCtxZICU=
------END CERTIFICATE-----
-
Certigna
========
-----BEGIN CERTIFICATE-----
@@ -1493,49 +1225,6 @@ vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz
TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD
-----END CERTIFICATE-----
-CNNIC ROOT
-==========
------BEGIN CERTIFICATE-----
-MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJDTjEOMAwGA1UE
-ChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2MDcwOTE0WhcNMjcwNDE2MDcw
-OTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1Qw
-ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzD
-o+/hn7E7SIX1mlwhIhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tiz
-VHa6dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZOV/kbZKKT
-VrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrCGHn2emU1z5DrvTOTn1Or
-czvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gNv7Sg2Ca+I19zN38m5pIEo3/PIKe38zrK
-y5nLAgMBAAGjczBxMBEGCWCGSAGG+EIBAQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscC
-wQ7vptU7ETAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991S
-lgrHAsEO76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnKOOK5
-Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvHugDnuL8BV8F3RTIM
-O/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7HgviyJA/qIYM/PmLXoXLT1tLYhFHxUV8
-BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fLbuXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2
-G8kS1sHNzYDzAgE8yGnLRUhj2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5m
-mxE=
------END CERTIFICATE-----
-
-ApplicationCA - Japanese Government
-===================================
------BEGIN CERTIFICATE-----
-MIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJKUDEcMBoGA1UEChMT
-SmFwYW5lc2UgR292ZXJubWVudDEWMBQGA1UECxMNQXBwbGljYXRpb25DQTAeFw0wNzEyMTIxNTAw
-MDBaFw0xNzEyMTIxNTAwMDBaMEMxCzAJBgNVBAYTAkpQMRwwGgYDVQQKExNKYXBhbmVzZSBHb3Zl
-cm5tZW50MRYwFAYDVQQLEw1BcHBsaWNhdGlvbkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
-CgKCAQEAp23gdE6Hj6UG3mii24aZS2QNcfAKBZuOquHMLtJqO8F6tJdhjYq+xpqcBrSGUeQ3DnR4
-fl+Kf5Sk10cI/VBaVuRorChzoHvpfxiSQE8tnfWuREhzNgaeZCw7NCPbXCbkcXmP1G55IrmTwcrN
-wVbtiGrXoDkhBFcsovW8R0FPXjQilbUfKW1eSvNNcr5BViCH/OlQR9cwFO5cjFW6WY2H/CPek9AE
-jP3vbb3QesmlOmpyM8ZKDQUXKi17safY1vC+9D/qDihtQWEjdnjDuGWk81quzMKq2edY3rZ+nYVu
-nyoKb58DKTCXKB28t89UKU5RMfkntigm/qJj5kEW8DOYRwIDAQABo4GeMIGbMB0GA1UdDgQWBBRU
-WssmP3HMlEYNllPqa0jQk/5CdTAOBgNVHQ8BAf8EBAMCAQYwWQYDVR0RBFIwUKROMEwxCzAJBgNV
-BAYTAkpQMRgwFgYDVQQKDA/ml6XmnKzlm73mlL/lupwxIzAhBgNVBAsMGuOCouODl+ODquOCseOD
-vOOCt+ODp+ODs0NBMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADlqRHZ3ODrs
-o2dGD/mLBqj7apAxzn7s2tGJfHrrLgy9mTLnsCTWw//1sogJhyzjVOGjprIIC8CFqMjSnHH2HZ9g
-/DgzE+Ge3Atf2hZQKXsvcJEPmbo0NI2VdMV+eKlmXb3KIXdCEKxmJj3ekav9FfBv7WxfEPjzFvYD
-io+nEhEMy/0/ecGc/WLuo89UDNErXxc+4z6/wCs+CZv+iKZ+tJIX/COUgb1up8WMwusRRdv4QcmW
-dupwX3kSa+SjB1oF7ydJzyGfikwJcGapJsErEU4z0g781mzSDjJkaP+tBXhfAx2o45CsJOAPQKdL
-rosot4LKGAfmt1t06SAZf7IbiVQ=
------END CERTIFICATE-----
-
GeoTrust Primary Certification Authority - G3
=============================================
-----BEGIN CERTIFICATE-----
@@ -2630,93 +2319,6 @@ poLWccret9W6aAjtmcz9opLLabid+Qqkpj5PkygqYWwHJgD/ll9ohri4zspV4KuxPX+Y1zMOWj3Y
eMLEYC/HYvBhkdI4sPaeVdtAgAUSM84dkpvRabP/v/GSCmE1P93+hvS84Bpxs2Km
-----END CERTIFICATE-----
-China Internet Network Information Center EV Certificates Root
-==============================================================
------BEGIN CERTIFICATE-----
-MIID9zCCAt+gAwIBAgIESJ8AATANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCQ04xMjAwBgNV
-BAoMKUNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyMUcwRQYDVQQDDD5D
-aGluYSBJbnRlcm5ldCBOZXR3b3JrIEluZm9ybWF0aW9uIENlbnRlciBFViBDZXJ0aWZpY2F0ZXMg
-Um9vdDAeFw0xMDA4MzEwNzExMjVaFw0zMDA4MzEwNzExMjVaMIGKMQswCQYDVQQGEwJDTjEyMDAG
-A1UECgwpQ2hpbmEgSW50ZXJuZXQgTmV0d29yayBJbmZvcm1hdGlvbiBDZW50ZXIxRzBFBgNVBAMM
-PkNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyIEVWIENlcnRpZmljYXRl
-cyBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm35z7r07eKpkQ0H1UN+U8i6y
-jUqORlTSIRLIOTJCBumD1Z9S7eVnAztUwYyZmczpwA//DdmEEbK40ctb3B75aDFk4Zv6dOtouSCV
-98YPjUesWgbdYavi7NifFy2cyjw1l1VxzUOFsUcW9SxTgHbP0wBkvUCZ3czY28Sf1hNfQYOL+Q2H
-klY0bBoQCxfVWhyXWIQ8hBouXJE0bhlffxdpxWXvayHG1VA6v2G5BY3vbzQ6sm8UY78WO5upKv23
-KzhmBsUs4qpnHkWnjQRmQvaPK++IIGmPMowUc9orhpFjIpryp9vOiYurXccUwVswah+xt54ugQEC
-7c+WXmPbqOY4twIDAQABo2MwYTAfBgNVHSMEGDAWgBR8cks5x8DbYqVPm6oYNJKiyoOCWTAPBgNV
-HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUfHJLOcfA22KlT5uqGDSSosqD
-glkwDQYJKoZIhvcNAQEFBQADggEBACrDx0M3j92tpLIM7twUbY8opJhJywyA6vPtI2Z1fcXTIWd5
-0XPFtQO3WKwMVC/GVhMPMdoG52U7HW8228gd+f2ABsqjPWYWqJ1MFn3AlUa1UeTiH9fqBk1jjZaM
-7+czV0I664zBechNdn3e9rG3geCg+aF4RhcaVpjwTj2rHO3sOdwHSPdj/gauwqRcalsyiMXHM4Ws
-ZkJHwlgkmeHlPuV1LI5D1l08eB6olYIpUNHRFrrvwb562bTYzB5MRuF3sTGrvSrIzo9uoV1/A3U0
-5K2JRVRevq4opbs/eHnrc7MKDf2+yfdWrPa37S+bISnHOLaVxATywy39FCqQmbkHzJ8=
------END CERTIFICATE-----
-
-Swisscom Root CA 2
-==================
------BEGIN CERTIFICATE-----
-MIIF2TCCA8GgAwIBAgIQHp4o6Ejy5e/DfEoeWhhntjANBgkqhkiG9w0BAQsFADBkMQswCQYDVQQG
-EwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2VydGlmaWNhdGUgU2Vy
-dmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3QgQ0EgMjAeFw0xMTA2MjQwODM4MTRaFw0zMTA2
-MjUwNzM4MTRaMGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGln
-aXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAyMIIC
-IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAlUJOhJ1R5tMJ6HJaI2nbeHCOFvErjw0DzpPM
-LgAIe6szjPTpQOYXTKueuEcUMncy3SgM3hhLX3af+Dk7/E6J2HzFZ++r0rk0X2s682Q2zsKwzxNo
-ysjL67XiPS4h3+os1OD5cJZM/2pYmLcX5BtS5X4HAB1f2uY+lQS3aYg5oUFgJWFLlTloYhyxCwWJ
-wDaCFCE/rtuh/bxvHGCGtlOUSbkrRsVPACu/obvLP+DHVxxX6NZp+MEkUp2IVd3Chy50I9AU/SpH
-Wrumnf2U5NGKpV+GY3aFy6//SSj8gO1MedK75MDvAe5QQQg1I3ArqRa0jG6F6bYRzzHdUyYb3y1a
-SgJA/MTAtukxGggo5WDDH8SQjhBiYEQN7Aq+VRhxLKX0srwVYv8c474d2h5Xszx+zYIdkeNL6yxS
-NLCK/RJOlrDrcH+eOfdmQrGrrFLadkBXeyq96G4DsguAhYidDMfCd7Camlf0uPoTXGiTOmekl9Ab
-mbeGMktg2M7v0Ax/lZ9vh0+Hio5fCHyqW/xavqGRn1V9TrALacywlKinh/LTSlDcX3KwFnUey7QY
-Ypqwpzmqm59m2I2mbJYV4+by+PGDYmy7Velhk6M99bFXi08jsJvllGov34zflVEpYKELKeRcVVi3
-qPyZ7iVNTA6z00yPhOgpD/0QVAKFyPnlw4vP5w8CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYw
-HQYDVR0hBBYwFDASBgdghXQBUwIBBgdghXQBUwIBMBIGA1UdEwEB/wQIMAYBAf8CAQcwHQYDVR0O
-BBYEFE0mICKJS9PVpAqhb97iEoHF8TwuMB8GA1UdIwQYMBaAFE0mICKJS9PVpAqhb97iEoHF8Twu
-MA0GCSqGSIb3DQEBCwUAA4ICAQAyCrKkG8t9voJXiblqf/P0wS4RfbgZPnm3qKhyN2abGu2sEzsO
-v2LwnN+ee6FTSA5BesogpxcbtnjsQJHzQq0Qw1zv/2BZf82Fo4s9SBwlAjxnffUy6S8w5X2lejjQ
-82YqZh6NM4OKb3xuqFp1mrjX2lhIREeoTPpMSQpKwhI3qEAMw8jh0FcNlzKVxzqfl9NX+Ave5XLz
-o9v/tdhZsnPdTSpxsrpJ9csc1fV5yJmz/MFMdOO0vSk3FQQoHt5FRnDsr7p4DooqzgB53MBfGWcs
-a0vvaGgLQ+OswWIJ76bdZWGgr4RVSJFSHMYlkSrQwSIjYVmvRRGFHQEkNI/Ps/8XciATwoCqISxx
-OQ7Qj1zB09GOInJGTB2Wrk9xseEFKZZZ9LuedT3PDTcNYtsmjGOpI99nBjx8Oto0QuFmtEYE3saW
-mA9LSHokMnWRn6z3aOkquVVlzl1h0ydw2Df+n7mvoC5Wt6NlUe07qxS/TFED6F+KBZvuim6c779o
-+sjaC+NCydAXFJy3SuCvkychVSa1ZC+N8f+mQAWFBVzKBxlcCxMoTFh/wqXvRdpg065lYZ1Tg3TC
-rvJcwhbtkj6EPnNgiLx29CzP0H1907he0ZESEOnN3col49XtmS++dYFLJPlFRpTJKSFTnCZFqhMX
-5OfNeOI5wSsSnqaeG8XmDtkx2Q==
------END CERTIFICATE-----
-
-Swisscom Root EV CA 2
-=====================
------BEGIN CERTIFICATE-----
-MIIF4DCCA8igAwIBAgIRAPL6ZOJ0Y9ON/RAdBB92ylgwDQYJKoZIhvcNAQELBQAwZzELMAkGA1UE
-BhMCY2gxETAPBgNVBAoTCFN3aXNzY29tMSUwIwYDVQQLExxEaWdpdGFsIENlcnRpZmljYXRlIFNl
-cnZpY2VzMR4wHAYDVQQDExVTd2lzc2NvbSBSb290IEVWIENBIDIwHhcNMTEwNjI0MDk0NTA4WhcN
-MzEwNjI1MDg0NTA4WjBnMQswCQYDVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsT
-HERpZ2l0YWwgQ2VydGlmaWNhdGUgU2VydmljZXMxHjAcBgNVBAMTFVN3aXNzY29tIFJvb3QgRVYg
-Q0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMT3HS9X6lds93BdY7BxUglgRCgz
-o3pOCvrY6myLURYaVa5UJsTMRQdBTxB5f3HSek4/OE6zAMaVylvNwSqD1ycfMQ4jFrclyxy0uYAy
-Xhqdk/HoPGAsp15XGVhRXrwsVgu42O+LgrQ8uMIkqBPHoCE2G3pXKSinLr9xJZDzRINpUKTk4Rti
-GZQJo/PDvO/0vezbE53PnUgJUmfANykRHvvSEaeFGHR55E+FFOtSN+KxRdjMDUN/rhPSays/p8Li
-qG12W0OfvrSdsyaGOx9/5fLoZigWJdBLlzin5M8J0TbDC77aO0RYjb7xnglrPvMyxyuHxuxenPaH
-Za0zKcQvidm5y8kDnftslFGXEBuGCxobP/YCfnvUxVFkKJ3106yDgYjTdLRZncHrYTNaRdHLOdAG
-alNgHa/2+2m8atwBz735j9m9W8E6X47aD0upm50qKGsaCnw8qyIL5XctcfaCNYGu+HuB5ur+rPQa
-m3Rc6I8k9l2dRsQs0h4rIWqDJ2dVSqTjyDKXZpBy2uPUZC5f46Fq9mDU5zXNysRojddxyNMkM3Ox
-bPlq4SjbX8Y96L5V5jcb7STZDxmPX2MYWFCBUWVv8p9+agTnNCRxunZLWB4ZvRVgRaoMEkABnRDi
-xzgHcgplwLa7JSnaFp6LNYth7eVxV4O1PHGf40+/fh6Bn0GXAgMBAAGjgYYwgYMwDgYDVR0PAQH/
-BAQDAgGGMB0GA1UdIQQWMBQwEgYHYIV0AVMCAgYHYIV0AVMCAjASBgNVHRMBAf8ECDAGAQH/AgED
-MB0GA1UdDgQWBBRF2aWBbj2ITY1x0kbBbkUe88SAnTAfBgNVHSMEGDAWgBRF2aWBbj2ITY1x0kbB
-bkUe88SAnTANBgkqhkiG9w0BAQsFAAOCAgEAlDpzBp9SSzBc1P6xXCX5145v9Ydkn+0UjrgEjihL
-j6p7jjm02Vj2e6E1CqGdivdj5eu9OYLU43otb98TPLr+flaYC/NUn81ETm484T4VvwYmneTwkLbU
-wp4wLh/vx3rEUMfqe9pQy3omywC0Wqu1kx+AiYQElY2NfwmTv9SoqORjbdlk5LgpWgi/UOGED1V7
-XwgiG/W9mR4U9s70WBCCswo9GcG/W6uqmdjyMb3lOGbcWAXH7WMaLgqXfIeTK7KK4/HsGOV1timH
-59yLGn602MnTihdsfSlEvoqq9X46Lmgxk7lq2prg2+kupYTNHAq4Sgj5nPFhJpiTt3tm7JFe3VE/
-23MPrQRYCd0EApUKPtN236YQHoA96M2kZNEzx5LH4k5E4wnJTsJdhw4Snr8PyQUQ3nqjsTzyP6Wq
-J3mtMX0f/fwZacXduT98zca0wjAefm6S139hdlqP65VNvBFuIXxZN5nQBrz5Bm0yFqXZaajh3DyA
-HmBR3NdUIR7KYndP+tiPsys6DXhyyWhBWkdKwqPrGtcKqzwyVcgKEZzfdNbwQBUdyLmPtTbFr/gi
-uMod89a2GQ+fYWVq6nTIfI/DT11lgh/ZDYnadXL77/FHZxOzyNEZiCcmmpl5fx7kLD977vHeTYuW
-l8PVP3wbI+2ksx0WckNLIOFZfsLorSa/ovc=
------END CERTIFICATE-----
-
CA Disig Root R1
================
-----BEGIN CERTIFICATE-----
@@ -3538,30 +3140,6 @@ lpKQd/Ct9JDpEXjXk4nAPQu6KfTomZ1yju2dL+6SfaHx/126M2CFYv4HAqGEVka+lgqaE9chTLd8
B59OTj+RdPsnnRHM3eaxynFNExc5JsUpISuTKWqW+qtB4Uu2NQvAmxU=
-----END CERTIFICATE-----
-TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H6
-====================================================
------BEGIN CERTIFICATE-----
-MIIEJjCCAw6gAwIBAgIGfaHyZeyKMA0GCSqGSIb3DQEBCwUAMIGxMQswCQYDVQQGEwJUUjEPMA0G
-A1UEBwwGQW5rYXJhMU0wSwYDVQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmls
-acWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBF
-bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg2MB4XDTEzMTIxODA5
-MDQxMFoXDTIzMTIxNjA5MDQxMFowgbExCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExTTBL
-BgNVBAoMRFTDnFJLVFJVU1QgQmlsZ2kgxLBsZXRpxZ9pbSB2ZSBCaWxpxZ9pbSBHw7x2ZW5sacSf
-aSBIaXptZXRsZXJpIEEuxZ4uMUIwQAYDVQQDDDlUw5xSS1RSVVNUIEVsZWt0cm9uaWsgU2VydGlm
-aWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLEgSDYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
-AoIBAQCdsGjW6L0UlqMACprx9MfMkU1xeHe59yEmFXNRFpQJRwXiM/VomjX/3EsvMsew7eKC5W/a
-2uqsxgbPJQ1BgfbBOCK9+bGlprMBvD9QFyv26WZV1DOzXPhDIHiTVRZwGTLmiddk671IUP320EED
-wnS3/faAz1vFq6TWlRKb55cTMgPp1KtDWxbtMyJkKbbSk60vbNg9tvYdDjTu0n2pVQ8g9P0pu5Fb
-HH3GQjhtQiht1AH7zYiXSX6484P4tZgvsycLSF5W506jM7NE1qXyGJTtHB6plVxiSvgNZ1GpryHV
-+DKdeboaX+UEVU0TRv/yz3THGmNtwx8XEsMeED5gCLMxAgMBAAGjQjBAMB0GA1UdDgQWBBTdVRcT
-9qzoSCHK77Wv0QAy7Z6MtTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG
-9w0BAQsFAAOCAQEAb1gNl0OqFlQ+v6nfkkU/hQu7VtMMUszIv3ZnXuaqs6fvuay0EBQNdH49ba3R
-fdCaqaXKGDsCQC4qnFAUi/5XfldcEQlLNkVS9z2sFP1E34uXI9TDwe7UU5X+LEr+DXCqu4svLcsy
-o4LyVN/Y8t3XSHLuSqMplsNEzm61kod2pLv0kmzOLBQJZo6NrRa1xxsJYTvjIKIDgI6tflEATseW
-hvtDmHd9KMeP2Cpu54Rvl0EpABZeTeIT6lnAY2c6RPuY/ATTMHKm9ocJV612ph1jmv3XZch4gyt1
-O6VbuA1df74jrlZVlFjvH4GMKrLN5ptjnhi85WsGtAuYSyher4hYyw==
------END CERTIFICATE-----
-
Certinomis - Root CA
====================
-----BEGIN CERTIFICATE-----
@@ -4041,3 +3619,28 @@ TxgKqpAd60Ae36EeRJIQmvKN4dFLRp7oRUKX6kWZ8+xm1QL68qZKJKrezrnK+T+Tb/mjuuqlPpmt
7kGUnF4ZLvhFSZl0kbAEb+MEWrGrKqv+x9CWttrhSmQGbmBNvUJO/3jaJMobtNeWOWyu8Q6qp31I
iyBMz2TWuJdGsE7RKlY6oJO9r4Ak4Ap+58rVyuiFVdw2KuGUaJPHZnJED4AhMmwlxyOAgwrr
-----END CERTIFICATE-----
+
+TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1
+=============================================
+-----BEGIN CERTIFICATE-----
+MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIxGDAWBgNVBAcT
+D0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxpbXNlbCB2ZSBUZWtub2xvamlr
+IEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0wKwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24g
+TWVya2V6aSAtIEthbXUgU00xNjA0BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRp
+ZmlrYXNpIC0gU3VydW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYD
+VQQGEwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXllIEJpbGlt
+c2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklUQUsxLTArBgNVBAsTJEth
+bXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBTTTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11
+IFNNIFNTTCBLb2sgU2VydGlmaWthc2kgLSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAr3UwM6q7a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y8
+6Ij5iySrLqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INrN3wc
+wv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2XYacQuFWQfw4tJzh0
+3+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/iSIzL+aFCr2lqBs23tPcLG07xxO9
+WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4fAJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQU
+ZT/HiobGPN08VFw1+DrtUgxHV8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
+KoZIhvcNAQELBQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh
+AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPfIPP54+M638yc
+lNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4lzwDGrpDxpa5RXI4s6ehlj2R
+e37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0j
+q5Rm+K37DwhuJi1/FwcJsoz7UMCflo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM=
+-----END CERTIFICATE-----
diff --git a/cloudformation/travis.template b/misc/cloudformation.template
index db4e59eb7e..db4e59eb7e 100644
--- a/cloudformation/travis.template
+++ b/misc/cloudformation.template
diff --git a/common/mb-icon-blue-circle.svg b/misc/mb-icon-blue-circle.svg
index 93f8c86a50..93f8c86a50 100644
--- a/common/mb-icon-blue-circle.svg
+++ b/misc/mb-icon-blue-circle.svg
diff --git a/common/mb-icon-blue-square.png b/misc/mb-icon-blue-square.png
index 0a9bc1cdea..0a9bc1cdea 100644
--- a/common/mb-icon-blue-square.png
+++ b/misc/mb-icon-blue-square.png
Binary files differ
diff --git a/common/mb-icon-blue-square.svg b/misc/mb-icon-blue-square.svg
index de531b179b..de531b179b 100644
--- a/common/mb-icon-blue-square.svg
+++ b/misc/mb-icon-blue-square.svg
diff --git a/proto/binary_program.proto b/misc/proto/binary_program.proto
index 9d06a209c3..9d06a209c3 100644
--- a/proto/binary_program.proto
+++ b/misc/proto/binary_program.proto
diff --git a/proto/glyphs.proto b/misc/proto/glyphs.proto
index 6930b47a2b..6930b47a2b 100644
--- a/proto/glyphs.proto
+++ b/misc/proto/glyphs.proto
diff --git a/proto/style.proto b/misc/proto/style.proto
index 90e5b65061..90e5b65061 100644
--- a/proto/style.proto
+++ b/misc/proto/style.proto
diff --git a/proto/vector_tile.proto b/misc/proto/vector_tile.proto
index 1cde2c7aa9..1cde2c7aa9 100644
--- a/proto/vector_tile.proto
+++ b/misc/proto/vector_tile.proto
diff --git a/package.json b/package.json
index fb62bc63ed..4ff4b32735 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@mapbox/mapbox-gl-native",
- "version": "3.5.6",
+ "version": "3.5.8",
"description": "Renders map tiles with Mapbox GL",
"keywords": [
"mapbox",
@@ -13,8 +13,8 @@
},
"license": "BSD-2-Clause",
"dependencies": {
- "nan": "^2.4.0",
- "node-pre-gyp": "^0.6.36",
+ "nan": "^2.6.2",
+ "node-pre-gyp": "^0.6.37",
"npm-run-all": "^4.0.2"
},
"devDependencies": {
@@ -23,6 +23,7 @@
"ejs": "^2.4.1",
"express": "^4.11.1",
"flow-remove-types": "^1.2.1",
+ "json-stringify-pretty-compact": "^1.0.4",
"lodash": "^4.16.4",
"mapbox-gl-styles": "2.0.2",
"pixelmatch": "^4.0.2",
@@ -38,7 +39,8 @@
"install": "node-pre-gyp install --fallback-to-build=false || make node",
"test": "tape platform/node/test/js/**/*.test.js",
"test-memory": "node --expose-gc platform/node/test/memory.test.js",
- "test-suite": "run-s test-render test-query",
+ "test-suite": "run-s test-render test-query test-expressions",
+ "test-expressions": "node platform/node/test/expression.test.js",
"test-render": "node platform/node/test/render.test.js",
"test-query": "node platform/node/test/query.test.js"
},
diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md
index c22072e1a0..79223e21ea 100644
--- a/platform/android/CHANGELOG.md
+++ b/platform/android/CHANGELOG.md
@@ -71,9 +71,9 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to
## 5.2.0-beta.3 - October 26, 2017
-- Reorganize dependencies [#10268](https://github.com/mapbox/mapbox-gl-native/pull/10268)
-- Blacklist VAO usage on adreno 3xx [#10291](https://github.com/mapbox/mapbox-gl-native/pull/10291)
-- On stop null check [#10259](https://github.com/mapbox/mapbox-gl-native/pull/10259)
+- Reorganize dependencies [#10268](https://github.com/mapbox/mapbox-gl-native/pull/10268)
+- Blacklist VAO usage on adreno 3xx [#10291](https://github.com/mapbox/mapbox-gl-native/pull/10291)
+- On stop null check [#10259](https://github.com/mapbox/mapbox-gl-native/pull/10259)
## 5.2.0-beta.2 - October 19, 2017
@@ -86,13 +86,13 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to
- Add an UnsatisfiedLinkError safeguard [#10180](https://github.com/mapbox/mapbox-gl-native/pull/10180)
- Hold off handling hover events untill map has been created [#10142](https://github.com/mapbox/mapbox-gl-native/pull/10142)
- Added `MapboxMap.getCameraForGeometry()` to get a camera with zoom level and center coordinate computed to fit a shape [#10107](https://github.com/mapbox/mapbox-gl-native/pull/10107)
-- Fine tune gesture zoom & rotation [#10134](https://github.com/mapbox/mapbox-gl-native/pull/10134)
+- Fine tune gesture zoom & rotation [#10134](https://github.com/mapbox/mapbox-gl-native/pull/10134)
## 5.2.0-beta.1 - October 6, 2017
-* Allow multiple listeners for camera events, deprecate old API [#10141](https://github.com/mapbox/mapbox-gl-native/pull/10141)
-* Update symbol layer example with location [#10092](https://github.com/mapbox/mapbox-gl-native/pull/10092)
-* Make OfflineTilePyramidRegionDefinition parceable [#10080](https://github.com/mapbox/mapbox-gl-native/pull/10080)
+- Allow multiple listeners for camera events, deprecate old API [#10141](https://github.com/mapbox/mapbox-gl-native/pull/10141)
+- Update symbol layer example with location [#10092](https://github.com/mapbox/mapbox-gl-native/pull/10092)
+- Make OfflineTilePyramidRegionDefinition parceable [#10080](https://github.com/mapbox/mapbox-gl-native/pull/10080)
- Fix 5.2.0-SNAPSHOT CI build failing [#10079](https://github.com/mapbox/mapbox-gl-native/pull/10079)
- Deprecate MarkerView [#9782](https://github.com/mapbox/mapbox-gl-native/pull/9782)
- Hide overlain views on initalisation [#10068](https://github.com/mapbox/mapbox-gl-native/pull/10068)
@@ -139,10 +139,17 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to
- Fix javadoc comment for public setOfflineMapboxTileCountLimit method [#9454](https://github.com/mapbox/mapbox-gl-native/pull/9454)
- add Map change & visibility test activities [#9425](https://github.com/mapbox/mapbox-gl-native/pull/9425)
- build release package once during ci build [#9351](https://github.com/mapbox/mapbox-gl-native/pull/9351)
-* Add support for ImageSource [#9110](https://github.com/mapbox/mapbox-gl-native/pull/9110)
-* Increased the default maximum zoom level from 20 to 22. [#9835](https://github.com/mapbox/mapbox-gl-native/pull/9835)
+- Add support for ImageSource [#9110](https://github.com/mapbox/mapbox-gl-native/pull/9110)
+- Increased the default maximum zoom level from 20 to 22. [#9835](https://github.com/mapbox/mapbox-gl-native/pull/9835)
-### 5.1.4 - September 25, 2017
+## 5.1.5 - October 31, 2017
+
+* Remove obsolete terminate context/display calls [#10162](https://github.com/mapbox/mapbox-gl-native/pull/10162)
+* Determine need for clip ID based on actual layers/tiles [#10216](https://github.com/mapbox/mapbox-gl-native/pull/10216)
+* Correctly alter sprite URLs [#10217](https://github.com/mapbox/mapbox-gl-native/pull/10217)
+* Russian and Ukrainian localizations [#9945](https://github.com/mapbox/mapbox-gl-native/pull/9945)
+
+## 5.1.4 - September 25, 2017
* Update translations [#10033](https://github.com/mapbox/mapbox-gl-native/pull/10033) & [#9945](https://github.com/mapbox/mapbox-gl-native/pull/9945)
* Continue rendering tiles despite erros [#10012](https://github.com/mapbox/mapbox-gl-native/pull/10012)
@@ -235,7 +242,7 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to
* Infinite location animation updates [#9194](https://github.com/mapbox/mapbox-gl-native/pull/9194)
* Invoke callback with valid fling gestures [#9192](https://github.com/mapbox/mapbox-gl-native/pull/9192)
* Keep location tracking after screen rotation [#9187](https://github.com/mapbox/mapbox-gl-native/pull/9187)
-* Update components with camera values when animating [#9174](https://github.com/mapbox/mapbox-gl-native/pull/9174)
+* Update components with camera values when animating [#9174](https://github.com/mapbox/mapbox-gl-native/pull/9174)
* Validate if gestures should execute [#9173](https://github.com/mapbox/mapbox-gl-native/pull/9173)
* Custom location source and LOST integration [#9142](https://github.com/mapbox/mapbox-gl-native/pull/9142)
@@ -637,12 +644,6 @@ Mapbox Android 4.0.0 is the most ambitious Android release to date with 3 major
- Satellite Streets Style ([#2739](https://github.com/mapbox/mapbox-gl-native/issues/2739))
- **RESOLVED** Black Screen On Ice Cream Sandwich and Jelly Bean devices ([#2802](https://github.com/mapbox/mapbox-gl-native/issues/2802))
-
## 2.1.0 - October 21, 2015
- Initial Android release.
-
-Known issues:
-
-- Black Screen On Ice Cream Sandwich and Jelly Bean devices ([#2802](https://github.com/mapbox/mapbox-gl-native/issues/2802))
- - Resolved in 2.2.0
diff --git a/platform/android/MapboxGLAndroidSDK/build.gradle b/platform/android/MapboxGLAndroidSDK/build.gradle
index ce886b1001..70c98f534a 100644
--- a/platform/android/MapboxGLAndroidSDK/build.gradle
+++ b/platform/android/MapboxGLAndroidSDK/build.gradle
@@ -1,27 +1,20 @@
apply plugin: 'com.android.library'
dependencies {
- compile rootProject.ext.dep.supportAnnotations
- compile rootProject.ext.dep.supportFragmentV4
- compile rootProject.ext.dep.timber
- compile rootProject.ext.dep.okhttp3
- provided(rootProject.ext.dep.lost) {
- exclude group: 'com.android.support'
- }
- testCompile rootProject.ext.dep.junit
- testCompile rootProject.ext.dep.mockito
- testCompile rootProject.ext.dep.robolectric
-
- // Mapbox Android Services (GeoJSON support)
- compile(rootProject.ext.dep.mapboxJavaGeoJSON) {
- transitive = true
- }
-
- // Mapbox Android Services (Telemetry support)
- compile(rootProject.ext.dep.mapboxAndroidTelemetry) {
- transitive = true
+ api rootProject.ext.dep.mapboxAndroidTelemetry
+ api rootProject.ext.dep.mapboxJavaGeoJSON
+ implementation rootProject.ext.dep.supportAnnotations
+ implementation rootProject.ext.dep.supportFragmentV4
+ implementation rootProject.ext.dep.timber
+ implementation rootProject.ext.dep.okhttp3
+ compileOnly(rootProject.ext.dep.lost) {
+ exclude group: 'com.google.guava'
exclude group: 'com.android.support'
}
+ testImplementation rootProject.ext.dep.lost
+ testImplementation rootProject.ext.dep.junit
+ testImplementation rootProject.ext.dep.mockito
+ testImplementation rootProject.ext.dep.robolectric
}
android {
@@ -120,7 +113,7 @@ android {
}
lintOptions {
- disable 'MissingTranslation', 'TypographyQuotes'
+ disable 'MissingTranslation', 'TypographyQuotes', 'ObsoleteLintCustomCheck', 'MissingPermission'
baseline file("lint-baseline-local.xml")
checkAllWarnings true
warningsAsErrors false
diff --git a/platform/android/MapboxGLAndroidSDK/gradle-checkstyle.gradle b/platform/android/MapboxGLAndroidSDK/gradle-checkstyle.gradle
index e0bc076d3d..420ccb473a 100644
--- a/platform/android/MapboxGLAndroidSDK/gradle-checkstyle.gradle
+++ b/platform/android/MapboxGLAndroidSDK/gradle-checkstyle.gradle
@@ -16,6 +16,7 @@ task checkstyle(type: Checkstyle) {
exclude '**/style/layers/PropertyFactory.java'
exclude '**/style/layers/*Layer.java'
exclude '**/style/light/Light.java'
+ exclude '**/Expression.java' // allowing single character signature as e()
classpath = files()
ignoreFailures = false
}
diff --git a/platform/android/MapboxGLAndroidSDK/gradle-javadoc.gradle b/platform/android/MapboxGLAndroidSDK/gradle-javadoc.gradle
index eeb5e9b4d6..39372b4378 100644
--- a/platform/android/MapboxGLAndroidSDK/gradle-javadoc.gradle
+++ b/platform/android/MapboxGLAndroidSDK/gradle-javadoc.gradle
@@ -10,7 +10,7 @@ android.libraryVariants.all { variant ->
options.windowTitle("Mapbox Android SDK $VERSION_NAME Reference")
options.docTitle("Mapbox Android SDK $VERSION_NAME")
options.header("Mapbox Android SDK $VERSION_NAME Reference")
- options.bottom("&copy; 2015&ndash;2017 Mapbox. All rights reserved.")
+ options.bottom("&copy; 2015&ndash;2018 Mapbox. All rights reserved.")
options.links("http://docs.oracle.com/javase/7/docs/api/")
options.linksOffline("http://d.android.com/reference/", "$System.env.ANDROID_HOME/docs/reference")
options.overview("src/main/java/overview.html")
diff --git a/platform/android/MapboxGLAndroidSDK/gradle.properties b/platform/android/MapboxGLAndroidSDK/gradle.properties
index f1257f346e..f00eb1d77f 100644
--- a/platform/android/MapboxGLAndroidSDK/gradle.properties
+++ b/platform/android/MapboxGLAndroidSDK/gradle.properties
@@ -1,5 +1,5 @@
GROUP=com.mapbox.mapboxsdk
-VERSION_NAME=5.3.0-SNAPSHOT
+VERSION_NAME=6.0.0-SNAPSHOT
POM_DESCRIPTION=Mapbox GL Android SDK
POM_URL=https://github.com/mapbox/mapbox-gl-native
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/LibraryLoader.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/LibraryLoader.java
index a024f0ab70..6633d5d952 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/LibraryLoader.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/LibraryLoader.java
@@ -3,18 +3,46 @@ package com.mapbox.mapboxsdk;
import timber.log.Timber;
/**
- * Centralises the knowledge about "mapbox-gl" library loading.
+ * Loads the mapbox-gl shared library
+ * <p>
+ * By default uses the {@link System#loadLibrary(String)},
+ * use {@link #setLibraryLoader(LibraryLoader)} to provide an alternative library loading hook.
+ * </p>
*/
-public class LibraryLoader {
+public abstract class LibraryLoader {
+
+ private static final LibraryLoader DEFAULT = new LibraryLoader() {
+ @Override
+ public void load(String name) {
+ System.loadLibrary(name);
+ }
+ };
+
+ private static volatile LibraryLoader loader = DEFAULT;
+
+ /**
+ * Set the library loader that loads the shared library.
+ *
+ * @param libraryLoader the library loader
+ */
+ public static void setLibraryLoader(LibraryLoader libraryLoader) {
+ loader = libraryLoader;
+ }
/**
* Loads "libmapbox-gl.so" native shared library.
+ * <p>
+ * Catches UnsatisfiedLinkErrors and prints a warning to logcat.
+ * </p>
*/
public static void load() {
try {
- System.loadLibrary("mapbox-gl");
+ loader.load("mapbox-gl");
} catch (UnsatisfiedLinkError error) {
Timber.e(error, "Failed to load native shared library.");
}
}
+
+ public abstract void load(String name);
}
+
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java
index 357bcd5f99..b67b6e96f2 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java
@@ -12,10 +12,10 @@ import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.exceptions.MapboxConfigurationException;
import com.mapbox.mapboxsdk.location.LocationSource;
import com.mapbox.mapboxsdk.net.ConnectivityReceiver;
+import com.mapbox.services.android.telemetry.MapboxTelemetry;
import com.mapbox.services.android.telemetry.location.LocationEngine;
import com.mapbox.services.android.telemetry.location.LocationEnginePriority;
import com.mapbox.services.android.telemetry.location.LocationEngineProvider;
-import com.mapbox.services.android.telemetry.MapboxTelemetry;
import timber.log.Timber;
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/GeometryConstants.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/GeometryConstants.java
new file mode 100644
index 0000000000..1a7544d33a
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/GeometryConstants.java
@@ -0,0 +1,63 @@
+package com.mapbox.mapboxsdk.constants;
+
+/**
+ * Contains constants used throughout the sdk classes.
+ *
+ * @since 6.0.0
+ */
+public class GeometryConstants {
+
+ /**
+ * The <a href='http://en.wikipedia.org/wiki/Earth_radius#Equatorial_radius'>equatorial radius</a>
+ * value in meters
+ *
+ * @since 6.0.0
+ */
+ public static final int RADIUS_EARTH_METERS = 6378137;
+
+ /**
+ * This constant represents the lowest longitude value available to represent a geolocation.
+ *
+ * @since 6.0.0
+ */
+ public static final double MIN_LONGITUDE = -180;
+
+ /**
+ * This constant represents the highest longitude value available to represent a geolocation.
+ *
+ * @since 6.0.0
+ */
+ public static final double MAX_LONGITUDE = 180;
+
+ /**
+ * This constant represents the lowest latitude value available to represent a geolocation.
+ *
+ * @since 6.0.0
+ */
+ public static final double MIN_LATITUDE = -90;
+
+ /**
+ * This constant represents the highest latitude value available to represent a geolocation.
+ *
+ * @since 6.0.0
+ */
+ public static final double MAX_LATITUDE = 90;
+
+ /**
+ * Maximum latitude value in Mercator projection.
+ *
+ * @since 6.0.0
+ */
+ public static final double MAX_MERCATOR_LATITUDE = 85.05112877980659;
+
+ /**
+ * Minimum latitude value in Mercator projection.
+ *
+ * @since 6.0.0
+ */
+ public static final double MIN_MERCATOR_LATITUDE = -85.05112877980659;
+
+ private GeometryConstants() {
+ // Private constructor to prevent initializing of this class.
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java
index eb57241196..79023e2fd9 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java
@@ -5,8 +5,8 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.FloatRange;
-import com.mapbox.services.android.telemetry.constants.GeoConstants;
-import com.mapbox.services.android.telemetry.utils.MathUtils;
+import com.mapbox.mapboxsdk.constants.GeometryConstants;
+
/**
* A geographical location which contains a single latitude, longitude pair, with
@@ -105,20 +105,20 @@ public class LatLng implements ILatLng, Parcelable {
/**
* Set the latitude, in degrees.
* <p>
- * This value is in the range of [-85.05112878, 85.05112878], see {@link GeoConstants#MIN_LATITUDE} and
- * {@link GeoConstants#MAX_LATITUDE}
+ * This value is in the range of [-90, 90], see {@link GeometryConstants#MIN_LATITUDE} and
+ * {@link GeometryConstants#MAX_LATITUDE}
* </p>
*
* @param latitude the latitude value in degrees
- * @see GeoConstants#MIN_LATITUDE
- * @see GeoConstants#MAX_LATITUDE
+ * @see GeometryConstants#MIN_LATITUDE
+ * @see GeometryConstants#MAX_LATITUDE
*/
public void setLatitude(
- @FloatRange(from = GeoConstants.MIN_LATITUDE, to = GeoConstants.MAX_LATITUDE) double latitude) {
+ @FloatRange(from = GeometryConstants.MIN_LATITUDE, to = GeometryConstants.MAX_LATITUDE) double latitude) {
if (Double.isNaN(latitude)) {
throw new IllegalArgumentException("latitude must not be NaN");
}
- if (Math.abs(latitude) > 90.0) {
+ if (Math.abs(latitude) > GeometryConstants.MAX_LATITUDE) {
throw new IllegalArgumentException("latitude must be between -90 and 90");
}
this.latitude = latitude;
@@ -127,13 +127,13 @@ public class LatLng implements ILatLng, Parcelable {
/**
* Get the latitude, in degrees.
* <p>
- * This value is in the range of [-85.05112878, 85.05112878], see {@link GeoConstants#MIN_LATITUDE} and
- * {@link GeoConstants#MAX_LATITUDE}
+ * This value is in the range of [-90, 90], see {@link GeometryConstants#MIN_LATITUDE} and
+ * {@link GeometryConstants#MAX_LATITUDE}
* </p>
*
* @return the latitude value in degrees
- * @see GeoConstants#MIN_LATITUDE
- * @see GeoConstants#MAX_LATITUDE
+ * @see GeometryConstants#MIN_LATITUDE
+ * @see GeometryConstants#MAX_LATITUDE
*/
@Override
public double getLatitude() {
@@ -143,15 +143,15 @@ public class LatLng implements ILatLng, Parcelable {
/**
* Set the longitude, in degrees.
* <p>
- * This value is in the range of [-180, 180], see {@link GeoConstants#MIN_LONGITUDE} and
- * {@link GeoConstants#MAX_LONGITUDE}
+ * This value is in the range of [-180, 180], see {@link GeometryConstants#MIN_LONGITUDE} and
+ * {@link GeometryConstants#MAX_LONGITUDE}
* </p>
*
* @param longitude the longitude value in degrees
- * @see GeoConstants#MIN_LONGITUDE
- * @see GeoConstants#MAX_LONGITUDE
+ * @see GeometryConstants#MIN_LONGITUDE
+ * @see GeometryConstants#MAX_LONGITUDE
*/
- public void setLongitude(@FloatRange(from = GeoConstants.MIN_LONGITUDE, to = GeoConstants.MAX_LONGITUDE)
+ public void setLongitude(@FloatRange(from = GeometryConstants.MIN_LONGITUDE, to = GeometryConstants.MAX_LONGITUDE)
double longitude) {
if (Double.isNaN(longitude)) {
throw new IllegalArgumentException("longitude must not be NaN");
@@ -165,13 +165,13 @@ public class LatLng implements ILatLng, Parcelable {
/**
* Get the longitude, in degrees.
* <p>
- * This value is in the range of [-180, 180], see {@link GeoConstants#MIN_LONGITUDE} and
- * {@link GeoConstants#MAX_LONGITUDE}
+ * This value is in the range of [-180, 180], see {@link GeometryConstants#MIN_LONGITUDE} and
+ * {@link GeometryConstants#MAX_LONGITUDE}
* </p>
*
* @return the longitude value in degrees
- * @see GeoConstants#MIN_LONGITUDE
- * @see GeoConstants#MAX_LONGITUDE
+ * @see GeometryConstants#MIN_LONGITUDE
+ * @see GeometryConstants#MAX_LONGITUDE
*/
@Override
public double getLongitude() {
@@ -204,8 +204,33 @@ public class LatLng implements ILatLng, Parcelable {
* @return new LatLng object with wrapped Longitude
*/
public LatLng wrap() {
- longitude = MathUtils.wrap(longitude, GeoConstants.MIN_LONGITUDE, GeoConstants.MAX_LONGITUDE);
- return this;
+ return new LatLng(latitude, wrap(longitude, GeometryConstants.MIN_LONGITUDE, GeometryConstants.MAX_LONGITUDE));
+ }
+
+
+ /**
+ * Constrains value to the given range (including min & max) via modular arithmetic.
+ * <p>
+ * Same formula as used in Core GL (wrap.hpp)
+ * std::fmod((std::fmod((value - min), d) + d), d) + min;
+ *
+ * Multiples of max value will be wrapped to max.
+ *
+ * @param value Value to wrap
+ * @param min Minimum value
+ * @param max Maximum value
+ * @return Wrapped value
+ */
+ static double wrap(double value, double min, double max) {
+ double delta = max - min;
+
+ double firstMod = (value - min) % delta;
+ double secondMod = (firstMod + delta) % delta;
+
+ if (value >= max && secondMod == 0) {
+ return max;
+ }
+ return secondMod + min;
}
/**
@@ -305,6 +330,6 @@ public class LatLng implements ILatLng, Parcelable {
final double t3 = Math.sin(a1) * Math.sin(b1);
final double tt = Math.acos(t1 + t2 + t3);
- return GeoConstants.RADIUS_EARTH_METERS * tt;
+ return GeometryConstants.RADIUS_EARTH_METERS * tt;
}
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java
index 4fcb91033c..6d027a0cef 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java
@@ -5,8 +5,8 @@ import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
+import com.mapbox.mapboxsdk.constants.GeometryConstants;
import com.mapbox.mapboxsdk.exceptions.InvalidLatLngBoundsException;
-import com.mapbox.services.android.telemetry.constants.GeoConstants;
import java.util.ArrayList;
import java.util.List;
@@ -48,8 +48,8 @@ public class LatLngBounds implements Parcelable {
*/
public static LatLngBounds world() {
return new LatLngBounds.Builder()
- .include(new LatLng(GeoConstants.MAX_LATITUDE, GeoConstants.MAX_LONGITUDE))
- .include(new LatLng(GeoConstants.MIN_LATITUDE, GeoConstants.MIN_LONGITUDE))
+ .include(new LatLng(GeometryConstants.MAX_LATITUDE, GeometryConstants.MAX_LONGITUDE))
+ .include(new LatLng(GeometryConstants.MIN_LATITUDE, GeometryConstants.MIN_LONGITUDE))
.build();
}
@@ -194,10 +194,10 @@ public class LatLngBounds implements Parcelable {
* @return LatLngBounds
*/
static LatLngBounds fromLatLngs(final List<? extends ILatLng> latLngs) {
- double minLat = 90;
- double minLon = 180;
- double maxLat = -90;
- double maxLon = -180;
+ double minLat = GeometryConstants.MAX_LATITUDE;
+ double minLon = GeometryConstants.MAX_LONGITUDE;
+ double maxLat = GeometryConstants.MIN_LATITUDE;
+ double maxLon = GeometryConstants.MIN_LONGITUDE;
for (final ILatLng gp : latLngs) {
final double latitude = gp.getLatitude();
@@ -231,6 +231,30 @@ public class LatLngBounds implements Parcelable {
return new LatLngBounds(latNorth, lonEast, latSouth, lonWest);
}
+ private static double lat_(int z, int y) {
+ double n = Math.PI - 2.0 * Math.PI * y / Math.pow(2.0, z);
+ return Math.toDegrees(Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))));
+ }
+
+ private static double lon_(int z, int x) {
+ return x / Math.pow(2.0, z) * 360.0 - GeometryConstants.MAX_LONGITUDE;
+ }
+
+ /**
+ * Constructs a LatLngBounds from a Tile identifier.
+ *
+ * Returned bounds will have latitude in the range of Mercator projection.
+ * @see GeometryConstants#MIN_MERCATOR_LATITUDE
+ * @see GeometryConstants#MAX_MERCATOR_LATITUDE
+ *
+ * @param z Tile zoom level.
+ * @param x Tile X coordinate.
+ * @param y Tile Y coordinate.
+ */
+ public static LatLngBounds from(int z, int x, int y) {
+ return new LatLngBounds(lat_(z, y), lon_(z, x + 1), lat_(z, y + 1), lon_(z, x));
+ }
+
/**
* Constructs a LatLngBounds from current bounds with an additional latitude-longitude pair.
*
@@ -305,17 +329,17 @@ public class LatLngBounds implements Parcelable {
* Returns a new LatLngBounds that stretches to include another LatLngBounds,
* given by corner points.
*
- * @param lonNorth Northern Longitude
- * @param latEast Eastern Latitude
- * @param lonSouth Southern Longitude
- * @param latWest Western Longitude
+ * @param latNorth Northern Latitude
+ * @param lonEast Eastern Longitude
+ * @param latSouth Southern Latitude
+ * @param lonWest Western Longitude
* @return BoundingBox
*/
- public LatLngBounds union(final double lonNorth, final double latEast, final double lonSouth, final double latWest) {
- return new LatLngBounds((this.latitudeNorth < lonNorth) ? lonNorth : this.latitudeNorth,
- (this.longitudeEast < latEast) ? latEast : this.longitudeEast,
- (this.latitudeSouth > lonSouth) ? lonSouth : this.latitudeSouth,
- (this.longitudeWest > latWest) ? latWest : this.longitudeWest);
+ public LatLngBounds union(final double latNorth, final double lonEast, final double latSouth, final double lonWest) {
+ return new LatLngBounds((this.latitudeNorth < latNorth) ? latNorth : this.latitudeNorth,
+ (this.longitudeEast < lonEast) ? lonEast : this.longitudeEast,
+ (this.latitudeSouth > latSouth) ? latSouth : this.latitudeSouth,
+ (this.longitudeWest > lonWest) ? lonWest : this.longitudeWest);
}
/**
@@ -326,13 +350,13 @@ public class LatLngBounds implements Parcelable {
*/
@Nullable
public LatLngBounds intersect(LatLngBounds box) {
- double minLatWest = Math.max(getLonWest(), box.getLonWest());
- double maxLatEast = Math.min(getLonEast(), box.getLonEast());
- if (maxLatEast > minLatWest) {
- double minLonSouth = Math.max(getLatSouth(), box.getLatSouth());
- double maxLonNorth = Math.min(getLatNorth(), box.getLatNorth());
- if (maxLonNorth > minLonSouth) {
- return new LatLngBounds(maxLonNorth, maxLatEast, minLonSouth, minLatWest);
+ double minLonWest = Math.max(getLonWest(), box.getLonWest());
+ double maxLonEast = Math.min(getLonEast(), box.getLonEast());
+ if (maxLonEast > minLonWest) {
+ double minLatSouth = Math.max(getLatSouth(), box.getLatSouth());
+ double maxLatNorth = Math.min(getLatNorth(), box.getLatNorth());
+ if (maxLatNorth > minLatSouth) {
+ return new LatLngBounds(maxLatNorth, maxLonEast, minLatSouth, minLonWest);
}
}
return null;
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcher.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcher.java
index 605c8912e2..69a43d4d3e 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcher.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcher.java
@@ -127,16 +127,43 @@ class CameraChangeDispatcher implements MapboxMap.OnCameraMoveStartedListener, M
idle = false;
moveStartedReason = reason;
handler.post(onCameraMoveStartedRunnable);
+
+ // new API
+ if (!onCameraMoveStarted.isEmpty()) {
+ for (OnCameraMoveStartedListener cameraMoveStartedListener : onCameraMoveStarted) {
+ cameraMoveStartedListener.onCameraMoveStarted(reason);
+ }
+ }
}
@Override
public void onCameraMove() {
handler.post(onCameraMoveRunnable);
+ if (onCameraMoveListener != null && !idle) {
+ onCameraMoveListener.onCameraMove();
+ }
+
+ // new API
+ if (!onCameraMove.isEmpty() && !idle) {
+ for (OnCameraMoveListener cameraMoveListener : onCameraMove) {
+ cameraMoveListener.onCameraMove();
+ }
+ }
}
@Override
public void onCameraMoveCanceled() {
handler.post(onCameraMoveCancelRunnable);
+ if (onCameraMoveCanceledListener != null && !idle) {
+ onCameraMoveCanceledListener.onCameraMoveCanceled();
+ }
+
+ // new API
+ if (!onCameraMoveCanceled.isEmpty() && !idle) {
+ for (OnCameraMoveCanceledListener cameraMoveCanceledListener : onCameraMoveCanceled) {
+ cameraMoveCanceledListener.onCameraMoveCanceled();
+ }
+ }
}
@Override
@@ -144,6 +171,16 @@ class CameraChangeDispatcher implements MapboxMap.OnCameraMoveStartedListener, M
if (!idle) {
idle = true;
handler.post(onCameraIdleRunnable);
+ if (onCameraIdleListener != null) {
+ onCameraIdleListener.onCameraIdle();
+ }
+
+ // new API
+ if (!onCameraIdle.isEmpty()) {
+ for (OnCameraIdleListener cameraIdleListener : onCameraIdle) {
+ cameraIdleListener.onCameraIdle();
+ }
+ }
}
}
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 77d2ac0e28..256f49ef52 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
@@ -22,7 +22,6 @@ import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ZoomButtonsController;
-
import com.mapbox.mapboxsdk.R;
import com.mapbox.mapboxsdk.annotations.Annotation;
import com.mapbox.mapboxsdk.annotations.MarkerViewManager;
@@ -37,7 +36,10 @@ import com.mapbox.mapboxsdk.maps.widgets.MyLocationViewSettings;
import com.mapbox.mapboxsdk.net.ConnectivityReceiver;
import com.mapbox.mapboxsdk.storage.FileSource;
import com.mapbox.services.android.telemetry.MapboxTelemetry;
+import timber.log.Timber;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
@@ -45,11 +47,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.opengles.GL10;
-
-import timber.log.Timber;
-
import static com.mapbox.mapboxsdk.maps.widgets.CompassView.TIME_MAP_NORTH_ANIMATION;
import static com.mapbox.mapboxsdk.maps.widgets.CompassView.TIME_WAIT_IDLE;
@@ -273,7 +270,7 @@ public class MapView extends FrameLayout {
/**
* <p>
* You must call this method from the parent's Activity#onCreate(Bundle)} or
- * Fragment#onCreate(Bundle).
+ * Fragment#onViewCreated(View, Bundle).
* </p>
* You must set a valid access token with {@link com.mapbox.mapboxsdk.Mapbox#getInstance(Context, String)}
* before you call this method or an exception will be thrown.
@@ -296,51 +293,43 @@ public class MapView extends FrameLayout {
mapRenderer = new TextureViewMapRenderer(getContext(), textureView, options.getLocalIdeographFontFamily()) {
@Override
protected void onSurfaceCreated(GL10 gl, EGLConfig config) {
- MapView.this.post(new Runnable() {
- @Override
- public void run() {
- // Initialise only once
- if (mapboxMap == null) {
- initialiseMap();
- mapboxMap.onStart();
- }
- }
- });
-
+ initRenderSurface();
super.onSurfaceCreated(gl, config);
}
};
+
addView(textureView, 0);
} else {
GLSurfaceView glSurfaceView = (GLSurfaceView) findViewById(R.id.surfaceView);
glSurfaceView.setZOrderMediaOverlay(mapboxMapOptions.getRenderSurfaceOnTop());
-
mapRenderer = new GLSurfaceViewMapRenderer(getContext(), glSurfaceView, options.getLocalIdeographFontFamily()) {
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
- MapView.this.post(new Runnable() {
- @Override
- public void run() {
- // Initialise only once
- if (mapboxMap == null) {
- initialiseMap();
- mapboxMap.onStart();
- }
- }
- });
-
+ initRenderSurface();
super.onSurfaceCreated(gl, config);
}
};
glSurfaceView.setVisibility(View.VISIBLE);
-
}
nativeMapView = new NativeMapView(this, mapRenderer);
nativeMapView.resizeView(getMeasuredWidth(), getMeasuredHeight());
}
+ private void initRenderSurface() {
+ post(new Runnable() {
+ @Override
+ public void run() {
+ // Initialise only when not destroyed and only once
+ if (!destroyed && mapboxMap == null) {
+ initialiseMap();
+ mapboxMap.onStart();
+ }
+ }
+ });
+ }
+
/**
* You must call this method from the parent's Activity#onSaveInstanceState(Bundle)
* or Fragment#onSaveInstanceState(Bundle).
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 4da2f63eeb..9525d48820 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
@@ -564,7 +564,7 @@ public final class MapboxMap {
*
* @return the TrackingSettings asssociated with this map
* @deprecated use location layer plugin from
- * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugins/locationlayer instead.
+ * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugin-locationlayer instead.
*/
@Deprecated
public TrackingSettings getTrackingSettings() {
@@ -580,7 +580,7 @@ public final class MapboxMap {
*
* @return the MyLocationViewSettings associated with this map
* @deprecated use location layer plugin from
- * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugins/locationlayer instead.
+ * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugin-locationlayer instead.
*/
@Deprecated
public MyLocationViewSettings getMyLocationViewSettings() {
@@ -2092,7 +2092,7 @@ public final class MapboxMap {
*
* @return True if the my-location layer is enabled, false otherwise.
* @deprecated use location layer plugin from
- * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugins/locationlayer instead.
+ * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugin-locationlayer instead.
*/
@Deprecated
public boolean isMyLocationEnabled() {
@@ -2110,7 +2110,7 @@ public final class MapboxMap {
*
* @param enabled True to enable; false to disable.
* @deprecated use location layer plugin from
- * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugins/locationlayer instead.
+ * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugin-locationlayer instead.
*/
@Deprecated
public void setMyLocationEnabled(boolean enabled) {
@@ -2122,7 +2122,7 @@ public final class MapboxMap {
*
* @return The currently displayed user location.
* @deprecated use location layer plugin from
- * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugins/locationlayer instead.
+ * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugin-locationlayer instead.
*/
@Nullable
@Deprecated
@@ -2137,7 +2137,7 @@ public final class MapboxMap {
* @param listener The callback that's invoked when the user clicks on a marker.
* To unset the callback, use null.
* @deprecated use location layer plugin from
- * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugins/locationlayer instead.
+ * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugin-locationlayer instead.
*/
@Deprecated
public void setOnMyLocationChangeListener(@Nullable MapboxMap.OnMyLocationChangeListener
@@ -2150,7 +2150,7 @@ public final class MapboxMap {
*
* @param locationSource A {@link LocationEngine} location source to use in the my-location layer.
* @deprecated use location layer plugin from
- * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugins/locationlayer instead.
+ * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugin-locationlayer instead.
*/
@Deprecated
public void setLocationSource(@Nullable LocationEngine locationSource) {
@@ -2163,7 +2163,7 @@ public final class MapboxMap {
* @param listener The callback that's invoked when the location tracking mode changes.
* To unset the callback, use null.
* @deprecated use location layer plugin from
- * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugins/locationlayer instead.
+ * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugin-locationlayer instead.
*/
@Deprecated
public void setOnMyLocationTrackingModeChangeListener(
@@ -2177,7 +2177,7 @@ public final class MapboxMap {
* @param listener The callback that's invoked when the bearing tracking mode changes.
* To unset the callback, use null.
* @deprecated use location layer plugin from
- * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugins/locationlayer instead.
+ * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugin-locationlayer instead.
*/
@Deprecated
public void setOnMyBearingTrackingModeChangeListener(@Nullable OnMyBearingTrackingModeChangeListener listener) {
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
index e8eb7e8718..f1635c898f 100755
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
@@ -733,7 +733,7 @@ final class NativeMapView {
if (isDestroyedOn("addSource")) {
return;
}
- nativeAddSource(source.getNativePtr());
+ nativeAddSource(source, source.getNativePtr());
}
@Nullable
@@ -741,14 +741,15 @@ final class NativeMapView {
if (isDestroyedOn("removeSource")) {
return null;
}
- return nativeRemoveSourceById(sourceId);
+ Source source = getSource(sourceId);
+ return removeSource(source);
}
public Source removeSource(@NonNull Source source) {
if (isDestroyedOn("removeSource")) {
return null;
}
- nativeRemoveSource(source.getNativePtr());
+ nativeRemoveSource(source, source.getNativePtr());
return source;
}
@@ -1027,11 +1028,9 @@ final class NativeMapView {
private native Source nativeGetSource(String sourceId);
- private native void nativeAddSource(long nativeSourcePtr) throws CannotAddSourceException;
+ private native void nativeAddSource(Source source, long sourcePtr) throws CannotAddSourceException;
- private native Source nativeRemoveSourceById(String sourceId);
-
- private native void nativeRemoveSource(long sourcePtr);
+ private native void nativeRemoveSource(Source source, long sourcePtr);
private native void nativeAddImage(String name, int width, int height, float pixelRatio,
byte[] array);
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
new file mode 100644
index 0000000000..4d09fcaac6
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/expressions/Expression.java
@@ -0,0 +1,1761 @@
+package com.mapbox.mapboxsdk.style.expressions;
+
+import android.support.annotation.ColorInt;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.annotation.Size;
+
+import com.mapbox.mapboxsdk.style.layers.PropertyFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The value for any layout property, paint property, or filter may be specified as an expression.
+ * An expression defines a formula for computing the value of the property using the operators described below.
+ * The set of expression operators provided by Mapbox GL includes:
+ * <p>
+ * <ul>
+ * <li>Element</li>
+ * <li>Mathematical operators for performing arithmetic and other operations on numeric values</li>
+ * <li>Logical operators for manipulating boolean values and making conditional decisions</li>
+ * <li>String operators for manipulating strings</li>
+ * <li>Data operators, providing access to the properties of source features</li>
+ * <li>Camera operators, providing access to the parameters defining the current map view</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Expressions are represented as JSON arrays.
+ * The first element of an expression array is a string naming the expression operator,
+ * e.g. "*"or "case". Subsequent elements (if any) are the arguments to the expression.
+ * Each argument is either a literal value (a string, number, boolean, or null), or another expression array.
+ * </p>
+ * <p>
+ * Data expression: a data expression is any expression that access feature data -- that is,
+ * any expression that uses one of the data operators:get,has,id,geometry-type, or properties.
+ * Data expressions allow a feature's properties to determine its appearance.
+ * They can be used to differentiate features within the same layer and to create data visualizations.
+ * </p>
+ * <p>
+ * Camera expression: a camera expression is any expression that uses the zoom operator.
+ * Such expressions allow the the appearance of a layer to change with the map's zoom level.
+ * Camera expressions can be used to create the appearance of depth and to control data density.
+ * </p>
+ * <p>
+ * Composition: a single expression may use a mix of data operators, camera operators, and other operators.
+ * Such composite expressions allows a layer's appearance to be determined by
+ * a combination of the zoom level and individual feature properties.
+ * </p>
+ *
+ * @param <T> the type of the expression
+ */
+public class Expression<T> {
+
+ private final String operator;
+ private final Expression[] arguments;
+
+ /**
+ * Creates an empty expression for expression literals
+ */
+ Expression() {
+ operator = null;
+ arguments = null;
+ }
+
+ /**
+ * Creates an expression from its operator and varargs expressions.
+ *
+ * @param operator the expression operator
+ * @param arguments expressions input
+ */
+ public Expression(@NonNull String operator, @Nullable Expression... arguments) {
+ this.operator = operator;
+ this.arguments = arguments;
+ }
+
+ /**
+ * Converts the expression to Object array representation.
+ * <p>
+ * The output will later be converted to a JSON Object array.
+ * </p>
+ *
+ * @return the converted object array expression
+ */
+ @NonNull
+ public Object[] toArray() {
+ List<Object> array = new ArrayList<>();
+ array.add(operator);
+ if (arguments != null) {
+ for (Expression argument : arguments) {
+ if (argument instanceof Expression.ExpressionLiteral) {
+ array.add(toValue((ExpressionLiteral) argument));
+ } else {
+ array.add(argument.toArray());
+ }
+ }
+ }
+ return array.toArray();
+ }
+
+ /**
+ * Converts the expression value to an Object.
+ *
+ * @param expressionValue the expression value to convert
+ * @return the converted object expression
+ */
+ private Object toValue(ExpressionLiteral expressionValue) {
+ Object value = expressionValue.toValue();
+ if (value instanceof Expression.Color) {
+ return ((Expression.Color) value).convertColor();
+ } else if (value instanceof Expression.ExpressionLiteral) {
+ return toValue((ExpressionLiteral) value);
+ } else if (value instanceof Expression) {
+ return ((Expression) value).toArray();
+ }
+ return value;
+ }
+
+ /**
+ * ExpressionLiteral wraps an object to be used as a literal in an expression.
+ * <p>
+ * ExpressionLiteral is created with {@link #literal(Number)}, {@link #literal(boolean)},
+ * {@link #literal(String)} and {@link #literal(Object)}.
+ * </p>
+ *
+ * @param <T>
+ */
+ private static class ExpressionLiteral<T> extends Expression<T> {
+
+ protected T object;
+
+ /**
+ * Create an ExpressionValue wrapper.
+ *
+ * @param object the object to be wrapped
+ */
+ ExpressionLiteral(@NonNull T object) {
+ this.object = object;
+ }
+
+ /**
+ * Get the wrapped object.
+ *
+ * @return the wrapped object
+ */
+ Object toValue() {
+ return object;
+ }
+ }
+
+ //
+ // Types
+ //
+
+ /**
+ * Expression interpolator type.
+ * <p>
+ * Is used for first parameter of {@link #interpolate(Expression, Expression, Stop...)}.
+ * </p>
+ */
+ private static class Interpolator {
+ }
+
+ /**
+ * Expression color type.
+ */
+ public static class Color {
+
+ private int color;
+
+ /**
+ * Creates a color color type from a color int.
+ *
+ * @param color the int color
+ */
+ public Color(@ColorInt int color) {
+ this.color = color;
+ }
+
+ /**
+ * Converts the int color to rgba(d, d, d, d) string representation
+ *
+ * @return
+ */
+ public String convertColor() {
+ return PropertyFactory.colorToRgbaString(color);
+ }
+ }
+
+ /**
+ * Expression array type.
+ */
+ public static class Array {
+ }
+
+ /**
+ * Expression stop type.
+ * <p>
+ * Can be used for {@link #stop(Object, Object)} as part of varargs parameter in
+ * {@link #step(Number, Expression, Stop...)} or {@link #interpolate(Expression, Expression, Stop...)}.
+ * </p>
+ */
+ public static class Stop {
+
+ private Object value;
+ private Object output;
+
+ public Stop(Object value, Object output) {
+ this.value = value;
+ this.output = output;
+ }
+ }
+
+ //
+ // Literals
+ //
+
+ /**
+ * Create a literal number expression.
+ *
+ * @param number the number
+ * @return the expression
+ */
+ public static Expression<Number> literal(@NonNull Number number) {
+ return new ExpressionLiteral<>(number);
+ }
+
+ /**
+ * Create a literal string expression.
+ *
+ * @param string the string
+ * @return the expression
+ */
+ public static Expression<String> literal(@NonNull String string) {
+ return new ExpressionLiteral<>(string);
+ }
+
+ /**
+ * Create a literal boolean expression.
+ *
+ * @param bool the boolean
+ * @return the expression
+ */
+ public static Expression<Boolean> literal(boolean bool) {
+ return new ExpressionLiteral<>(bool);
+ }
+
+ /**
+ * Create a literal object expression
+ *
+ * @param object the object
+ * @return the expression
+ */
+ public static Expression<Object> literal(@NonNull Object object) {
+ return new ExpressionLiteral<>(object);
+ }
+
+ //
+ // Color
+ //
+
+ /**
+ * Expression literal utility method to convert a color int to an color expression
+ *
+ * @param color the int color
+ * @return the color expression
+ */
+ public static Expression<Color> color(@ColorInt int color) {
+ return new ExpressionLiteral<>(new Color(color));
+ }
+
+ /**
+ * Creates a color value from red, green, and blue components, which must range between 0 and 255,
+ * and an alpha component of 1.
+ * <p>
+ * If any component is out of range, the expression is an error.
+ * </p>
+ *
+ * @param red red color expression
+ * @param green green color expression
+ * @param blue blue color expression
+ * @return expression
+ */
+ public static Expression<Color> rgb(@NonNull Expression<Number> red, @NonNull Expression<Number> green,
+ @NonNull Expression<Number> blue) {
+ return new Expression<>("rgb", red, green, blue);
+ }
+
+ /**
+ * Creates a color value from red, green, and blue components, which must range between 0 and 255,
+ * and an alpha component of 1.
+ * <p>
+ * If any component is out of range, the expression is an error.
+ * </p>
+ *
+ * @param red red color value
+ * @param green green color value
+ * @param blue blue color value
+ * @return expression
+ */
+ public static Expression<Color> rgb(@NonNull Number red, @NonNull Number green, @NonNull Number blue) {
+ return rgb(literal(red), literal(green), literal(blue));
+ }
+
+ /**
+ * Creates a color value from red, green, blue components, which must range between 0 and 255,
+ * and an alpha component which must range between 0 and 1.
+ * <p>
+ * If any component is out of range, the expression is an error.
+ * </p>
+ *
+ * @param red red color value
+ * @param green green color value
+ * @param blue blue color value
+ * @param alpha alpha color value
+ * @return expression
+ */
+ public static Expression<Color> rgba(@NonNull Expression<Number> red, @NonNull Expression<Number> green,
+ @NonNull Expression<Number> blue, @NonNull Expression<Number> alpha) {
+ return new Expression<>("rgba", red, green, blue, alpha);
+ }
+
+ /**
+ * Creates a color value from red, green, blue components, which must range between 0 and 255,
+ * and an alpha component which must range between 0 and 1.
+ * <p>
+ * If any component is out of range, the expression is an error.
+ * </p>
+ *
+ * @param red red color value
+ * @param green green color value
+ * @param blue blue color value
+ * @param alpha alpha color value
+ * @return expression
+ */
+ public static Expression<Color> rgba(@NonNull Number red, @NonNull Number green, @NonNull Number blue, @NonNull Number alpha) {
+ return rgba(literal(red), literal(green), literal(blue), literal(alpha));
+ }
+
+ /**
+ * Returns a four-element array containing the input color's red, green, blue, and alpha components, in that order.
+ *
+ * @param expression an expression to convert to a color
+ * @return expression
+ */
+ public static Expression<Array> toRgba(@NonNull Expression<Color> expression) {
+ return new Expression<>("to-rgba", expression);
+ }
+
+ //
+ // Decision
+ //
+
+ /**
+ * Returns true if the input values are equal, false otherwise.
+ * The inputs must be numbers, strings, or booleans, and both of the same type.
+ *
+ * @param compareOne the first expression
+ * @param compareTwo the second expression
+ * @return expression
+ */
+ public static Expression<Boolean> eq(@NonNull Expression compareOne, @NonNull Expression compareTwo) {
+ return new Expression<>("==", compareOne, compareTwo);
+ }
+
+ /**
+ * Returns true if the input values are equal, false otherwise.
+ *
+ * @param compareOne the first boolean
+ * @param compareTwo the second boolean
+ * @return expression
+ */
+ public static Expression<Boolean> eq(boolean compareOne, boolean compareTwo) {
+ return eq(literal(compareOne), literal(compareTwo));
+ }
+
+ /**
+ * Returns true if the input values are equal, false otherwise.
+ *
+ * @param compareOne the first number
+ * @param compareTwo the second number
+ * @return expression
+ */
+ public static Expression<Boolean> eq(@NonNull String compareOne, @NonNull String compareTwo) {
+ return eq(literal(compareOne), literal(compareTwo));
+ }
+
+ /**
+ * Returns true if the input values are equal, false otherwise.
+ *
+ * @param compareOne the first number
+ * @param compareTwo the second number
+ * @return expression
+ */
+ public static Expression<Boolean> eq(@NonNull Number compareOne, @NonNull Number compareTwo) {
+ return eq(literal(compareOne), literal(compareTwo));
+ }
+
+ /**
+ * Returns true if the input values are not equal, false otherwise.
+ * The inputs must be numbers, strings, or booleans, and both of the same type.
+ *
+ * @param compareOne the first expression
+ * @param compareTwo the second expression
+ * @return expression
+ */
+ public static Expression<Boolean> neq(@NonNull Expression compareOne, @NonNull Expression compareTwo) {
+ return new Expression<>("!=", compareOne, compareTwo);
+ }
+
+ /**
+ * Returns true if the input values are equal, false otherwise.
+ *
+ * @param compareOne the first boolean
+ * @param compareTwo the second boolean
+ * @return expression
+ */
+ public static Expression<Boolean> neq(boolean compareOne, boolean compareTwo) {
+ return new Expression<>("!=", literal(compareOne), literal(compareTwo));
+ }
+
+ /**
+ * Returns `true` if the input values are not equal, `false` otherwise.
+ *
+ * @param compareOne the first string
+ * @param compareTwo the second string
+ * @return expression
+ */
+ public static Expression<Boolean> neq(@NonNull String compareOne, @NonNull String compareTwo) {
+ return new Expression<>("!=", literal(compareOne), literal(compareTwo));
+ }
+
+ /**
+ * Returns `true` if the input values are not equal, `false` otherwise.
+ *
+ * @param compareOne the first number
+ * @param compareTwo the second number
+ * @return expression
+ */
+ public static Expression<Boolean> neq(@NonNull Number compareOne, @NonNull Number compareTwo) {
+ return new Expression<>("!=", literal(compareOne), literal(compareTwo));
+ }
+
+ /**
+ * Returns true if the first input is strictly greater than the second, false otherwise.
+ * The inputs must be numbers or strings, and both of the same type.
+ *
+ * @param compareOne the first expression
+ * @param compareTwo the second expression
+ * @return expression
+ */
+ public static Expression<Boolean> gt(@NonNull Expression compareOne, @NonNull Expression compareTwo) {
+ return new Expression<>(">", compareOne, compareTwo);
+ }
+
+ /**
+ * Returns true if the first input is strictly greater than the second, false otherwise.
+ *
+ * @param compareOne the first number
+ * @param compareTwo the second number
+ * @return expression
+ */
+ public static Expression<Boolean> gt(@NonNull Number compareOne, @NonNull Number compareTwo) {
+ return new Expression<>(">", literal(compareOne), literal(compareTwo));
+ }
+
+ /**
+ * Returns true if the first input is strictly greater than the second, false otherwise.
+ *
+ * @param compareOne the first string
+ * @param compareTwo the second string
+ * @return expression
+ */
+ public static Expression<Boolean> gt(@NonNull String compareOne, @NonNull String compareTwo) {
+ return new Expression<>(">", literal(compareOne), literal(compareTwo));
+ }
+
+ /**
+ * Returns true if the first input is strictly less than the second, false otherwise.
+ * The inputs must be numbers or strings, and both of the same type.
+ *
+ * @param compareOne the first number
+ * @param compareTwo the second number
+ * @return expression
+ */
+ public static Expression<Boolean> lt(@NonNull Expression compareOne, @NonNull Expression compareTwo) {
+ return new Expression<>("<", compareOne, compareTwo);
+ }
+
+ /**
+ * Returns true if the first input is strictly less than the second, false otherwise.
+ *
+ * @param compareOne the first number
+ * @param compareTwo the second number
+ * @return expression
+ */
+ public static Expression<Boolean> lt(@NonNull Number compareOne, @NonNull Number compareTwo) {
+ return new Expression<>("<", literal(compareOne), literal(compareTwo));
+ }
+
+ /**
+ * Returns true if the first input is strictly less than the second, false otherwise.
+ *
+ * @param compareOne the first string
+ * @param compareTwo the second string
+ * @return expression
+ */
+ public static Expression<Boolean> lt(@NonNull String compareOne, @NonNull String compareTwo) {
+ return new Expression<>("<", literal(compareOne), literal(compareTwo));
+ }
+
+ /**
+ * Returns true if the first input is greater than or equal to the second, false otherwise.
+ * The inputs must be numbers or strings, and both of the same type.
+ *
+ * @param compareOne the first expression
+ * @param compareTwo the second expression
+ * @return expression
+ */
+ public static Expression<Boolean> gte(@NonNull Expression compareOne, @NonNull Expression compareTwo) {
+ return new Expression<>(">=", compareOne, compareTwo);
+ }
+
+ /**
+ * Returns true if the first input is greater than or equal to the second, false otherwise.
+ *
+ * @param compareOne the first number
+ * @param compareTwo the second number
+ * @return expression
+ */
+ public static Expression<Boolean> gte(@NonNull Number compareOne, @NonNull Number compareTwo) {
+ return new Expression<>(">=", literal(compareOne), literal(compareTwo));
+ }
+
+ /**
+ * Returns true if the first input is greater than or equal to the second, false otherwise.
+ *
+ * @param compareOne the first string
+ * @param compareTwo the second string
+ * @return expression
+ */
+ public static Expression<Boolean> gte(@NonNull String compareOne, @NonNull String compareTwo) {
+ return new Expression<>(">=", literal(compareOne), literal(compareTwo));
+ }
+
+ /**
+ * Returns true if the first input is less than or equal to the second, false otherwise.
+ * The inputs must be numbers or strings, and both of the same type.
+ *
+ * @param compareOne the first expression
+ * @param compareTwo the second expression
+ * @return expression
+ */
+ public static Expression<Boolean> lte(@NonNull Expression compareOne, @NonNull Expression compareTwo) {
+ return new Expression<>("<=", compareOne, compareTwo);
+ }
+
+ /**
+ * Returns true if the first input is less than or equal to the second, false otherwise.
+ *
+ * @param compareOne the first number
+ * @param compareTwo the second number
+ * @return expression
+ */
+ public static Expression<Boolean> lte(@NonNull Number compareOne, @NonNull Number compareTwo) {
+ return new Expression<>("<=", literal(compareOne), literal(compareTwo));
+ }
+
+ /**
+ * Returns true if the first input is less than or equal to the second, false otherwise.
+ *
+ * @param compareOne the first string
+ * @param compareTwo the second string
+ * @return expression
+ */
+ public static Expression<Boolean> lte(@NonNull String compareOne, @NonNull String compareTwo) {
+ return new Expression<>("<=", literal(compareOne), literal(compareTwo));
+ }
+
+ /**
+ * Returns `true` if all the inputs are `true`, `false` otherwise.
+ * <p>
+ * The inputs are evaluated in order, and evaluation is short-circuiting:
+ * once an input expression evaluates to `false`,
+ * the result is `false` and no further input expressions are evaluated.
+ * </p>
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression<Boolean> all(@NonNull Expression<Boolean>... input) {
+ return new Expression<>("all", input);
+ }
+
+ /**
+ * Returns `true` if any of the inputs are `true`, `false` otherwise.
+ * <p>
+ * The inputs are evaluated in order, and evaluation is short-circuiting:
+ * once an input expression evaluates to `true`,
+ * the result is `true` and no further input expressions are evaluated.
+ * </p>
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression<Boolean> any(@NonNull Expression<Boolean>... input) {
+ return new Expression<>("any", input);
+ }
+
+ /**
+ * Logical negation. Returns `true` if the input is `false`, and `false` if the input is `true`.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression<Boolean> not(@NonNull Expression<Boolean> input) {
+ return new Expression<>("!", input);
+ }
+
+ /**
+ * Logical negation. Returns `true` if the input is `false`, and `false` if the input is `true`.
+ *
+ * @param input boolean input
+ * @return expression
+ */
+ public static Expression<Boolean> not(boolean input) {
+ return not(literal(input));
+ }
+
+ /**
+ * Selects the first output whose corresponding test condition evaluates to true.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression switchCase(@NonNull @Size(min = 1) Expression... input) {
+ return new Expression("case", input);
+ }
+
+ /**
+ * Selects the output whose label value matches the input value, or the fallback value if no match is found.
+ * The `input` can be any string or number expression.
+ * Each label can either be a single literal value or an array of values.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression match(@NonNull @Size(min = 2) Expression... input) {
+ return new Expression("match", input);
+ }
+
+ /**
+ * Selects the output whose label value matches the input value, or the fallback value if no match is found.
+ * The `input` can be any string or number expression.
+ * Each label can either be a single literal value or an array of values.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression match(@NonNull Expression input, @NonNull Stop... stops) {
+ Expression[] expressions = new Expression[stops.length * 2];
+ for (int i = 0; i < stops.length; i++) {
+ expressions[i * 2] = literal(stops[i].value);
+ expressions[i * 2 + 1] = literal(stops[i].output);
+ }
+ return match(join(new Expression[] {input}, expressions));
+ }
+
+ /**
+ * Evaluates each expression in turn until the first non-null value is obtained, and returns that value.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression coalesce(@NonNull Expression... input) {
+ return new Expression("coalesce", input);
+ }
+
+ //
+ // FeatureData
+ //
+
+ /**
+ * Gets the feature properties object.
+ * <p>
+ * Note that in some cases, it may be more efficient to use {@link #get(Expression)}} instead.
+ * </p>
+ *
+ * @return expression
+ */
+ public static Expression<Object> properties() {
+ return new Expression<>("properties");
+ }
+
+ /**
+ * Gets the feature's geometry type: Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon.
+ *
+ * @return expression
+ */
+ public static Expression<String> geometryType() {
+ return new Expression<>("geometry-type");
+ }
+
+ /**
+ * Gets the feature's id, if it has one.
+ *
+ * @return expression
+ */
+ public static Expression<Number> id() {
+ return new Expression<>("id");
+ }
+
+ //
+ // Heatmap
+ //
+
+ /**
+ * Gets the kernel density estimation of a pixel in a heatmap layer,
+ * which is a relative measure of how many data points are crowded around a particular pixel.
+ * Can only be used in the `heatmap-color` property.
+ *
+ * @return expression
+ */
+ public static Expression<Number> heatmapDensity() {
+ return new Expression<>("heatmap-density");
+ }
+
+ //
+ // Lookup
+ //
+
+ /**
+ * Retrieves an item from an array.
+ *
+ * @param number the index expression
+ * @param expression the array expression
+ * @return expression
+ */
+ public static Expression<Object> at(@NonNull Expression<Number> number, @NonNull Expression expression) {
+ return new Expression<>("at", number, expression);
+ }
+
+ /**
+ * Retrieves an item from an array.
+ *
+ * @param number the index expression
+ * @param expression the array expression
+ * @return expression
+ */
+ public static Expression<Object> at(@NonNull Number number, @NonNull Expression expression) {
+ return at(literal(number), expression);
+ }
+
+ /**
+ * Retrieves a property value from the current feature's properties,
+ * or from another object if a second argument is provided.
+ * Returns null if the requested property is missing.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression get(@NonNull Expression<String> input) {
+ return new Expression<>("get", input);
+ }
+
+ /**
+ * Retrieves a property value from the current feature's properties,
+ * or from another object if a second argument is provided.
+ * Returns null if the requested property is missing.
+ *
+ * @param input string input
+ * @return expression
+ */
+ public static Expression get(@NonNull String input) {
+ return get(literal(input));
+ }
+
+ /**
+ * Retrieves a property value from another object.
+ * Returns null if the requested property is missing.
+ *
+ * @param key a property value key
+ * @param object an expression object
+ * @return expression
+ */
+ public static Expression get(@NonNull Expression<String> key, @NonNull Expression<Object> object) {
+ return new Expression<>("get", key, object);
+ }
+
+ /**
+ * Retrieves a property value from another object.
+ * Returns null if the requested property is missing.
+ *
+ * @param key a property value key
+ * @param object an expression object
+ * @return expression
+ */
+ public static Expression get(@NonNull String key, @NonNull Expression<Object> object) {
+ return get(literal(key), object);
+ }
+
+ /**
+ * Tests for the presence of an property value in the current feature's properties.
+ *
+ * @param key the expression property value key
+ * @return expression
+ */
+ public static Expression<Boolean> has(@NonNull Expression<String> key) {
+ return new Expression<>("has", key);
+ }
+
+ /**
+ * Tests for the presence of an property value in the current feature's properties.
+ *
+ * @param key the property value key
+ * @return expression
+ */
+ public static Expression<Boolean> has(@NonNull String key) {
+ return has(literal(key));
+ }
+
+ /**
+ * Tests for the presence of an property value from another object.
+ *
+ * @param key the expression property value key
+ * @param object an expression object
+ * @return expression
+ */
+ public static Expression<Boolean> has(@NonNull Expression<String> key, @NonNull Expression<Object> object) {
+ return new Expression<>("has", key, object);
+ }
+
+ /**
+ * Tests for the presence of an property value from another object.
+ *
+ * @param key the property value key
+ * @param object an expression object
+ * @return expression
+ */
+ public static Expression<Boolean> has(@NonNull String key, @NonNull Expression<Object> object) {
+ return has(literal(key), object);
+ }
+
+ /**
+ * Gets the length of an array or string.
+ *
+ * @param expression an expression object or expression string
+ * @return expression
+ */
+ public static Expression<Number> length(@NonNull Expression<?> expression) {
+ return new Expression<>("length", expression);
+ }
+
+ /**
+ * Gets the length of an array or string.
+ *
+ * @param input a string
+ * @return expression
+ */
+ public static Expression<Number> length(@NonNull String input) {
+ return length(literal(input));
+ }
+
+ //
+ // Math
+ //
+
+ /**
+ * Returns mathematical constant ln(2).
+ *
+ * @return expression
+ */
+ public static Expression<Number> ln2() {
+ return new Expression<>("ln2");
+ }
+
+ /**
+ * Returns the mathematical constant pi.
+ *
+ * @return expression
+ */
+ public static Expression<Number> pi() {
+ return new Expression<>("pi");
+ }
+
+ /**
+ * Returns the mathematical constant e.
+ *
+ * @return expression
+ */
+ public static Expression<Number> e() {
+ return new Expression<>("e");
+ }
+
+ /**
+ * Returns the sum of the inputs.
+ *
+ * @param numbers the numbers to calculate the sum for
+ * @return expression
+ */
+ public static Expression<Number> sum(@Size(min = 2) Expression<Number>... numbers) {
+ return new Expression<>("+", numbers);
+ }
+
+ /**
+ * Returns the sum of the inputs.
+ *
+ * @param numbers the numbers to calculate the sum for
+ * @return expression
+ */
+ @SuppressWarnings("unchecked")
+ public static Expression<Number> sum(@Size(min = 2) Number... numbers) {
+ Expression<Number>[] numberExpression = (Expression<Number>[]) new Expression<?>[numbers.length];
+ for (int i = 0; i < numbers.length; i++) {
+ numberExpression[i] = literal(numbers[i]);
+ }
+ return sum(numberExpression);
+ }
+
+ /**
+ * Returns the product of the inputs.
+ *
+ * @param numbers the numbers to calculate the product for
+ * @return expression
+ */
+ public static Expression<Number> product(@Size(min = 2) Expression<Number>... numbers) {
+ return new Expression<>("*", numbers);
+ }
+
+ /**
+ * Returns the product of the inputs.
+ *
+ * @param numbers the numbers to calculate the product for
+ * @return expression
+ */
+ @SuppressWarnings("unchecked")
+ public static Expression<Number> product(@Size(min = 2) Number... numbers) {
+ Expression<Number>[] numberExpression = (Expression<Number>[]) new Expression<?>[numbers.length];
+ for (int i = 0; i < numbers.length; i++) {
+ numberExpression[i] = literal(numbers[i]);
+ }
+ return product(numberExpression);
+ }
+
+ /**
+ * Returns the result of subtracting a number from 0.
+ *
+ * @param number the number subtract from 0
+ * @return expression
+ */
+ public static Expression<Number> subtract(@NonNull Expression<Number> number) {
+ return new Expression<>("-", number);
+ }
+
+ /**
+ * Returns the result of subtracting a number from 0.
+ *
+ * @param number the number subtract from 0
+ * @return expression
+ */
+ public static Expression<Number> subtract(@NonNull Number number) {
+ return subtract(literal(number));
+ }
+
+ /**
+ * Returns the result of subtracting the second input from the first.
+ *
+ * @param first the first number
+ * @param second the second number
+ * @return expression
+ */
+ public static Expression<Number> subtract(@NonNull Expression<Number> first, @NonNull Expression<Number> second) {
+ return new Expression<>("-", first, second);
+ }
+
+ /**
+ * Returns the result of subtracting the second input from the first.
+ *
+ * @param first the first number
+ * @param second the second number
+ * @return expression
+ */
+ public static Expression<Number> subtract(@NonNull Number first, @NonNull Number second) {
+ return subtract(literal(first), literal(second));
+ }
+
+ /**
+ * Returns the result of floating point division of the first input by the second.
+ *
+ * @param first the first number
+ * @param second the second number
+ * @return expression
+ */
+ public static Expression<Number> division(@NonNull Expression<Number> first, @NonNull Expression<Number> second) {
+ return new Expression<>("/", first, second);
+ }
+
+ /**
+ * Returns the result of floating point division of the first input by the second.
+ *
+ * @param first the first number
+ * @param second the second number
+ * @return expression
+ */
+ public static Expression<Number> division(@NonNull Number first, @NonNull Number second) {
+ return division(literal(first), literal(second));
+ }
+
+ /**
+ * Returns the remainder after integer division of the first input by the second.
+ *
+ * @param first the first number
+ * @param second the second number
+ * @return expression
+ */
+ public static Expression<Number> mod(@NonNull Expression<Number> first, @NonNull Expression<Number> second) {
+ return new Expression<>("%", first, second);
+ }
+
+ /**
+ * Returns the remainder after integer division of the first input by the second.
+ *
+ * @param first the first number
+ * @param second the second number
+ * @return expression
+ */
+ public static Expression<Number> mod(@NonNull Number first, @NonNull Number second) {
+ return mod(literal(first), literal(second));
+ }
+
+ /**
+ * Returns the result of raising the first input to the power specified by the second.
+ *
+ * @param first the first number
+ * @param second the second number
+ * @return expression
+ */
+ public static Expression<Number> pow(@NonNull Expression<Number> first, @NonNull Expression<Number> second) {
+ return new Expression<>("^", first, second);
+ }
+
+ /**
+ * Returns the result of raising the first input to the power specified by the second.
+ *
+ * @param first the first number
+ * @param second the second number
+ * @return expression
+ */
+ public static Expression<Number> pow(@NonNull Number first, @NonNull Number second) {
+ return pow(literal(first), literal(second));
+ }
+
+ /**
+ * Returns the square root of the input
+ *
+ * @param number the number to take the square root from
+ * @return expression
+ */
+ public static Expression<Number> sqrt(@NonNull Expression<Number> number) {
+ return new Expression<>("sqrt", number);
+ }
+
+ /**
+ * Returns the square root of the input
+ *
+ * @param number the number to take the square root from
+ * @return expression
+ */
+ public static Expression<Number> sqrt(@NonNull Number number) {
+ return sqrt(literal(number));
+ }
+
+ /**
+ * Returns the base-ten logarithm of the input.
+ *
+ * @param number the number to take base-ten logarithm from
+ * @return expression
+ */
+ public static Expression<Number> log10(@NonNull Expression<Number> number) {
+ return new Expression<>("log10", number);
+ }
+
+ /**
+ * Returns the base-ten logarithm of the input.
+ *
+ * @param number the number to take base-ten logarithm from
+ * @return expression
+ */
+ public static Expression<Number> log10(@NonNull Number number) {
+ return log10(literal(number));
+ }
+
+ /**
+ * Returns the natural logarithm of the input.
+ *
+ * @param number the number to take natural logarithm from
+ * @return expression
+ */
+ public static Expression<Number> ln(Expression<Number> number) {
+ return new Expression<>("ln", number);
+ }
+
+ /**
+ * Returns the natural logarithm of the input.
+ *
+ * @param number the number to take natural logarithm from
+ * @return expression
+ */
+ public static Expression<Number> ln(Number number) {
+ return ln(literal(number));
+ }
+
+ /**
+ * Returns the base-two logarithm of the input.
+ *
+ * @param number the number to take base-two logarithm from
+ * @return expression
+ */
+ public static Expression<Number> log2(@NonNull Expression<Number> number) {
+ return new Expression<>("log2", number);
+ }
+
+ /**
+ * Returns the base-two logarithm of the input.
+ *
+ * @param number the number to take base-two logarithm from
+ * @return expression
+ */
+ public static Expression<Number> log2(@NonNull Number number) {
+ return log2(literal(number));
+ }
+
+ /**
+ * Returns the sine of the input.
+ *
+ * @param number the number to calculate the sine for
+ * @return expression
+ */
+ public static Expression<Number> sin(@NonNull Expression<Number> number) {
+ return new Expression<>("sin", number);
+ }
+
+ /**
+ * Returns the sine of the input.
+ *
+ * @param number the number to calculate the sine for
+ * @return expression
+ */
+ public static Expression<Number> sin(@NonNull Number number) {
+ return sin(literal(number));
+ }
+
+ /**
+ * Returns the cosine of the input.
+ *
+ * @param number the number to calculate the cosine for
+ * @return expression
+ */
+ public static Expression<Number> cos(@NonNull Expression<Number> number) {
+ return new Expression<>("cos", number);
+ }
+
+ /**
+ * Returns the cosine of the input.
+ *
+ * @param number the number to calculate the cosine for
+ * @return expression
+ */
+ public static Expression<Number> cos(@NonNull Number number) {
+ return new Expression<>("cos", literal(number));
+ }
+
+ /**
+ * Returns the tangent of the input.
+ *
+ * @param number the number to calculate the tangent for
+ * @return expression
+ */
+ public static Expression<Number> tan(@NonNull Expression<Number> number) {
+ return new Expression<>("tan", number);
+ }
+
+ /**
+ * Returns the tangent of the input.
+ *
+ * @param number the number to calculate the tangent for
+ * @return expression
+ */
+ public static Expression<Number> tan(@NonNull Number number) {
+ return new Expression<>("tan", literal(number));
+ }
+
+ /**
+ * Returns the arcsine of the input.
+ *
+ * @param number the number to calculate the arcsine for
+ * @return expression
+ */
+ public static Expression<Number> asin(@NonNull Expression<Number> number) {
+ return new Expression<>("asin", number);
+ }
+
+ /**
+ * Returns the arcsine of the input.
+ *
+ * @param number the number to calculate the arcsine for
+ * @return expression
+ */
+ public static Expression<Number> asin(@NonNull Number number) {
+ return asin(literal(number));
+ }
+
+ /**
+ * Returns the arccosine of the input.
+ *
+ * @param number the number to calculate the arccosine for
+ * @return expression
+ */
+ public static Expression<Number> acos(@NonNull Expression<Number> number) {
+ return new Expression<>("acos", number);
+ }
+
+ /**
+ * Returns the arccosine of the input.
+ *
+ * @param number the number to calculate the arccosine for
+ * @return expression
+ */
+ public static Expression<Number> acos(@NonNull Number number) {
+ return acos(literal(number));
+ }
+
+ /**
+ * Returns the arctangent of the input.
+ *
+ * @param number the number to calculate the arctangent for
+ * @return expression
+ */
+ public static Expression<Number> atan(@NonNull Expression<Number> number) {
+ return new Expression("atan", number);
+ }
+
+ /**
+ * Returns the arctangent of the input.
+ *
+ * @param number the number to calculate the arctangent for
+ * @return expression
+ */
+ public static Expression<Number> atan(@NonNull Number number) {
+ return atan(literal(number));
+ }
+
+ /**
+ * Returns the minimum value of the inputs.
+ *
+ * @param numbers varargs of numbers to get the minimum from
+ * @return expression
+ */
+ public static Expression<Number> min(@Size(min = 1) Expression<Number>... numbers) {
+ return new Expression<>("min", numbers);
+ }
+
+ /**
+ * Returns the minimum value of the inputs.
+ *
+ * @param numbers varargs of numbers to get the minimum from
+ * @return expression
+ */
+ @SuppressWarnings("unchecked")
+ public static Expression<Number> min(@Size(min = 1) Number... numbers) {
+ Expression<Number>[] numberExpression = (Expression<Number>[]) new Expression<?>[numbers.length];
+ for (int i = 0; i < numbers.length; i++) {
+ numberExpression[i] = literal(numbers[i]);
+ }
+ return min(numberExpression);
+ }
+
+ /**
+ * Returns the maximum value of the inputs.
+ *
+ * @param numbers varargs of numbers to get the maximum from
+ * @return expression
+ */
+ public static Expression<Number> max(@Size(min = 1) Expression<Number>... numbers) {
+ return new Expression<>("max", numbers);
+ }
+
+ /**
+ * Returns the maximum value of the inputs.
+ *
+ * @param numbers varargs of numbers to get the maximum from
+ * @return expression
+ */
+ @SuppressWarnings("unchecked")
+ public static Expression<Number> max(@Size(min = 1) Number... numbers) {
+ Expression<Number>[] numberExpression = (Expression<Number>[]) new Expression<?>[numbers.length];
+ for (int i = 0; i < numbers.length; i++) {
+ numberExpression[i] = literal(numbers[i]);
+ }
+ return max(numberExpression);
+ }
+
+ //
+ // String
+ //
+
+ /**
+ * Returns the input string converted to uppercase.
+ * <p>
+ * Follows the Unicode Default Case Conversion algorithm
+ * and the locale-insensitive case mappings in the Unicode Character Database.
+ * </p>
+ *
+ * @param string the string to upcase
+ * @return expression
+ */
+ public static Expression<String> upcase(@NonNull Expression<String> string) {
+ return new Expression<>("upcase", string);
+ }
+
+ /**
+ * Returns the input string converted to uppercase.
+ * <p>
+ * Follows the Unicode Default Case Conversion algorithm
+ * and the locale-insensitive case mappings in the Unicode Character Database.
+ * </p>
+ *
+ * @param string string to upcase
+ * @return expression
+ */
+ public static Expression<String> upcase(@NonNull String string) {
+ return upcase(literal(string));
+ }
+
+ /**
+ * Returns the input string converted to lowercase.
+ * <p>
+ * Follows the Unicode Default Case Conversion algorithm
+ * and the locale-insensitive case mappings in the Unicode Character Database.
+ * </p>
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression<String> downcase(@NonNull Expression<String> input) {
+ return new Expression<>("downcase", input);
+ }
+
+ /**
+ * Returns the input string converted to lowercase.
+ * <p>
+ * Follows the Unicode Default Case Conversion algorithm
+ * and the locale-insensitive case mappings in the Unicode Character Database.
+ * </p>
+ *
+ * @param input string to downcase
+ * @return expression
+ */
+ public static Expression<String> downcase(@NonNull String input) {
+ return downcase(literal(input));
+ }
+
+ /**
+ * Returns a string consisting of the concatenation of the inputs.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression<String> concat(@NonNull Expression<String>... input) {
+ return new Expression<>("concat", input);
+ }
+
+ /**
+ * Returns a string consisting of the concatenation of the inputs.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ @SuppressWarnings("unchecked")
+ public static Expression<String> concat(@NonNull String... input) {
+ Expression<String>[] stringExpression = (Expression<String>[]) new Expression<?>[input.length];
+ for (int i = 0; i < input.length; i++) {
+ stringExpression[i] = literal(input[i]);
+ }
+ return concat(stringExpression);
+ }
+
+ //
+ // Types
+ //
+
+ /**
+ * Asserts that the input is an array (optionally with a specific item type and length).
+ * If, when the input expression is evaluated, it is not of the asserted type,
+ * then this assertion will cause the whole expression to be aborted.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression<Boolean> array(@NonNull Expression input) {
+ return new Expression<>("array", input);
+ }
+
+ /**
+ * Returns a string describing the type of the given value.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression<String> typeOf(@NonNull Expression input) {
+ return new Expression<>("typeof", input);
+ }
+
+ /**
+ * Asserts that the input value is a string.
+ * If multiple values are provided, each one is evaluated in order until a string value is obtained.
+ * If none of the inputs are strings, the expression is an error.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression<Boolean> string(@NonNull Expression input) {
+ return new Expression<>("string", input);
+ }
+
+ /**
+ * Asserts that the input value is a number.
+ * If multiple values are provided, each one is evaluated in order until a number value is obtained.
+ * If none of the inputs are numbers, the expression is an error.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression<Boolean> number(@NonNull Expression input) {
+ return new Expression<>("number", input);
+ }
+
+ /**
+ * Asserts that the input value is a boolean.
+ * If multiple values are provided, each one is evaluated in order until a boolean value is obtained.
+ * If none of the inputs are booleans, the expression is an error.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression<Boolean> bool(@NonNull Expression input) {
+ return new Expression<>("boolean", input);
+ }
+
+ /**
+ * Asserts that the input value is an object. If it is not, the expression is an error
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression<Boolean> object(@NonNull Expression input) {
+ return new Expression<>("object", input);
+ }
+
+ /**
+ * Converts the input value to a string.
+ * If the input is null, the result is null.
+ * If the input is a boolean, the result is true or false.
+ * If the input is a number, it is converted to a string by NumberToString in the ECMAScript Language Specification.
+ * If the input is a color, it is converted to a string of the form "rgba(r,g,b,a)",
+ * where `r`, `g`, and `b` are numerals ranging from 0 to 255, and `a` ranges from 0 to 1.
+ * Otherwise, the input is converted to a string in the format specified by the JSON.stringify in the ECMAScript
+ * Language Specification.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression<String> toString(@NonNull Expression input) {
+ return new Expression<>("to-string", input);
+ }
+
+ /**
+ * Converts the input value to a number, if possible.
+ * If the input is null or false, the result is 0.
+ * If the input is true, the result is 1.
+ * If the input is a string, it is converted to a number as specified by the ECMAScript Language Specification.
+ * If multiple values are provided, each one is evaluated in order until the first successful conversion is obtained.
+ * If none of the inputs can be converted, the expression is an error.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression<Number> toNumber(@NonNull Expression input) {
+ return new Expression<>("to-number", input);
+ }
+
+ /**
+ * "Converts the input value to a boolean. The result is `false` when then input is an empty string, 0, false,
+ * null, or NaN; otherwise it is true.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression<Boolean> toBool(@NonNull Expression input) {
+ return new Expression<>("to-boolean", input);
+ }
+
+ /**
+ * Converts the input value to a color. If multiple values are provided,
+ * each one is evaluated in order until the first successful conversion is obtained.
+ * If none of the inputs can be converted, the expression is an error.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression<Color> toColor(@NonNull Expression input) {
+ return new Expression<>("to-color", input);
+ }
+
+ //
+ // Variable binding
+ //
+
+ /**
+ * Binds input to named variables,
+ * which can then be referenced in the result expression using {@link #var(String)} or {@link #var(Expression)}.
+ *
+ * @param input expression input
+ * @return expression
+ */
+ public static Expression let(@Size(min = 1) Expression... input) {
+ return new Expression<>("let", input);
+ }
+
+ /**
+ * References variable bound using let.
+ *
+ * @param expression the variable naming expression that was bound with using let
+ * @return expression
+ */
+ public static Expression<Object> var(@NonNull Expression<String> expression) {
+ return new Expression<>("var", expression);
+ }
+
+ /**
+ * References variable bound using let.
+ *
+ * @param variableName the variable naming that was bound with using let
+ * @return expression
+ */
+ public static Expression var(@NonNull String variableName) {
+ return var(literal(variableName));
+ }
+
+ //
+ // Zoom
+ //
+
+ /**
+ * Gets the current zoom level.
+ * <p>
+ * Note that in style layout and paint properties,
+ * zoom may only appear as the input to a top-level step or interpolate expression.
+ * </p>
+ *
+ * @return expression
+ */
+ public static Expression<Number> zoom() {
+ return new Expression<>("zoom");
+ }
+
+ //
+ // Ramps, scales, curves
+ //
+
+ public static Stop stop(@NonNull Object stop, @NonNull Object value) {
+ return new Stop(stop, value);
+ }
+
+ /**
+ * Produces discrete, stepped results by evaluating a piecewise-constant function defined by pairs of
+ * input and output values (\"stops\"). The `input` may be any numeric expression (e.g., `[\"get\", \"population\"]`).
+ * Stop inputs must be numeric literals in strictly ascending order.
+ * Returns the output value of the stop just less than the input,
+ * or the first input if the input is less than the first stop.
+ *
+ * @param input the input value
+ * @param stops pair of input and output values
+ * @return expression
+ */
+ public static Expression step(@NonNull Number input, @NonNull Expression expression, Expression... stops) {
+ return step(literal(input), expression, stops);
+ }
+
+ /**
+ * Produces discrete, stepped results by evaluating a piecewise-constant function defined by pairs of
+ * input and output values (\"stops\"). The `input` may be any numeric expression (e.g., `[\"get\", \"population\"]`).
+ * Stop inputs must be numeric literals in strictly ascending order.
+ * Returns the output value of the stop just less than the input,
+ * or the first input if the input is less than the first stop.
+ *
+ * @param expression the input expression
+ * @param stops pair of input and output values
+ * @return expression
+ */
+ public static Expression step(@NonNull Expression<Number> input, @NonNull Expression expression, Expression... stops) {
+ return new Expression("step", join(new Expression[] {input, expression}, stops));
+ }
+
+ /**
+ * Produces discrete, stepped results by evaluating a piecewise-constant function defined by pairs of
+ * input and output values (\"stops\"). The `input` may be any numeric expression (e.g., `[\"get\", \"population\"]`).
+ * Stop inputs must be numeric literals in strictly ascending order.
+ * Returns the output value of the stop just less than the input,
+ * or the first input if the input is less than the first stop.
+ *
+ * @param input the input value
+ * @param stops pair of input and output values
+ * @return expression
+ */
+ public static Expression step(@NonNull Number input, @NonNull Expression expression, Stop... stops) {
+ Expression[] expressions = new Expression[stops.length * 2];
+ for (int i = 0; i < stops.length; i++) {
+ expressions[i * 2] = literal(stops[i].value);
+ expressions[i * 2 + 1] = literal(stops[i].output);
+ }
+ return step(literal(input), expression, expressions);
+ }
+
+ /**
+ * Produces discrete, stepped results by evaluating a piecewise-constant function defined by pairs of
+ * input and output values (\"stops\"). The `input` may be any numeric expression (e.g., `[\"get\", \"population\"]`).
+ * Stop inputs must be numeric literals in strictly ascending order.
+ * Returns the output value of the stop just less than the input,
+ * or the first input if the input is less than the first stop.
+ *
+ * @param input the input value
+ * @param stops pair of input and output values
+ * @return expression
+ */
+ public static Expression step(@NonNull Expression<Number> input, @NonNull Expression expression, Stop... stops) {
+ Expression[] expressions = new Expression[stops.length * 2];
+ for (int i = 0; i < stops.length; i++) {
+ expressions[i * 2] = literal(stops[i].value);
+ expressions[i * 2 + 1] = literal(stops[i].output);
+ }
+ return step(input, expression, expressions);
+ }
+
+ /**
+ * Produces continuous, smooth results by interpolating between pairs of input and output values (\"stops\").
+ * The `input` may be any numeric expression (e.g., `[\"get\", \"population\"]`).
+ * Stop inputs must be numeric literals in strictly ascending order.
+ * The output type must be `number`, `array&lt;number&gt;`, or `color`.
+ *
+ * @param interpolation type of interpolation
+ * @param number the input expression
+ * @param stops pair of input and output values
+ * @return expression
+ */
+ public static Expression interpolate(@NonNull Expression<Interpolator> interpolation,
+ @NonNull Expression<Number> number, Expression... stops) {
+ return new Expression("interpolate", join(new Expression[] {interpolation, number}, stops));
+ }
+
+ /**
+ * Produces continuous, smooth results by interpolating between pairs of input and output values (\"stops\").
+ * The `input` may be any numeric expression (e.g., `[\"get\", \"population\"]`).
+ * Stop inputs must be numeric literals in strictly ascending order.
+ * The output type must be `number`, `array&lt;number&gt;`, or `color`.
+ *
+ * @param interpolation type of interpolation
+ * @param number the input expression
+ * @param stops pair of input and output values
+ * @return expression
+ */
+ public static Expression interpolate(@NonNull Expression<Interpolator> interpolation,
+ @NonNull Expression<Number> number, Stop... stops) {
+ Expression[] expressions = new Expression[stops.length * 2];
+ for (int i = 0; i < stops.length; i++) {
+ expressions[i * 2] = literal(stops[i].value);
+ expressions[i * 2 + 1] = literal(stops[i].output);
+ }
+ return interpolate(interpolation, number, expressions);
+ }
+
+ /**
+ * interpolates linearly between the pair of stops just less than and just greater than the input.
+ *
+ * @return expression
+ */
+ public static Expression<Interpolator> linear() {
+ return new Expression<>("linear");
+ }
+
+ /**
+ * Interpolates exponentially between the stops just less than and just greater than the input.
+ * `base` controls the rate at which the output increases:
+ * higher values make the output increase more towards the high end of the range.
+ * With values close to 1 the output increases linearly.
+ *
+ * @param base value controlling the route at which the output increases
+ * @return expression
+ */
+ public static Expression<Interpolator> exponential(@NonNull Number base) {
+ return exponential(literal(base));
+ }
+
+ /**
+ * Interpolates exponentially between the stops just less than and just greater than the input.
+ * The parameter controls the rate at which the output increases:
+ * higher values make the output increase more towards the high end of the range.
+ * With values close to 1 the output increases linearly.
+ *
+ * @param expression base number expression
+ * @return expression
+ */
+ public static Expression<Interpolator> exponential(@NonNull Expression<Number> expression) {
+ return new Expression<>("exponential", expression);
+ }
+
+ /**
+ * Interpolates using the cubic bezier curve defined by the given control points.
+ *
+ * @param x1 x value of the first point of a cubic bezier, ranges from 0 to 1
+ * @param y1 y value of the first point of a cubic bezier, ranges from 0 to 1
+ * @param x2 x value of the second point of a cubic bezier, ranges from 0 to 1
+ * @param y2 y value fo the second point of a cubic bezier, ranges from 0 to 1
+ * @return expression
+ */
+ public static Expression<Interpolator> cubicBezier(@NonNull Expression<Number> x1, @NonNull Expression<Number> y1,
+ @NonNull Expression<Number> x2, @NonNull Expression<Number> y2) {
+ return new Expression<>("cubic-bezier", x1, y1, x2, y2);
+ }
+
+ /**
+ * Interpolates using the cubic bezier curve defined by the given control points.
+ *
+ * @param x1 x value of the first point of a cubic bezier, ranges from 0 to 1
+ * @param y1 y value of the first point of a cubic bezier, ranges from 0 to 1
+ * @param x2 x value of the second point of a cubic bezier, ranges from 0 to 1
+ * @param y2 y value fo the second point of a cubic bezier, ranges from 0 to 1
+ * @return expression
+ */
+ public static Expression<Interpolator> cubicBezier(@NonNull Number x1, @NonNull Number y1,
+ @NonNull Number x2, @NonNull Number y2) {
+ return cubicBezier(literal(x1), literal(y1), literal(x2), literal(y2));
+ }
+
+ /**
+ * Joins two expressions arrays.
+ * <p>
+ * This flattens the object array output of an expression from a nested expression hierarchy.
+ * </p>
+ *
+ * @param left the left part of an expression
+ * @param right the right part of an expression
+ * @return the joined expression
+ */
+ private static Expression[] join(Expression[] left, Expression[] right) {
+ Expression[] output = new Expression[left.length + right.length];
+ System.arraycopy(left, 0, output, 0, left.length);
+ System.arraycopy(right, 0, output, left.length, right.length);
+ return output;
+ }
+
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/BackgroundLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/BackgroundLayer.java
index 978fa29ef8..324b845dda 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/BackgroundLayer.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/BackgroundLayer.java
@@ -8,8 +8,6 @@ import android.support.annotation.UiThread;
import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor;
-import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
-
/**
* The background color or pattern of the map.
*
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CircleLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CircleLayer.java
index 10663142b5..ea96e4e9c3 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CircleLayer.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CircleLayer.java
@@ -8,8 +8,6 @@ import android.support.annotation.UiThread;
import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor;
-import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
-
/**
* A filled circle.
*
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/FillExtrusionLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/FillExtrusionLayer.java
index 6772da73b1..d4cdb2a425 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/FillExtrusionLayer.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/FillExtrusionLayer.java
@@ -8,8 +8,6 @@ import android.support.annotation.UiThread;
import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor;
-import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
-
/**
* An extruded (3D) polygon.
*
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/FillLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/FillLayer.java
index 3719ae9e1b..e639823ee1 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/FillLayer.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/FillLayer.java
@@ -8,8 +8,6 @@ import android.support.annotation.UiThread;
import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor;
-import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
-
/**
* A filled polygon with an optional stroked border.
*
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Layer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Layer.java
index 5015dd009d..5400e04589 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Layer.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Layer.java
@@ -2,6 +2,7 @@ package com.mapbox.mapboxsdk.style.layers;
import android.support.annotation.NonNull;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.functions.Function;
/**
@@ -88,6 +89,14 @@ public abstract class Layer {
}
private Object convertValue(Object value) {
- return value != null && value instanceof Function ? ((Function) value).toValueObject() : value;
+ if (value != null) {
+ if (value instanceof Function) {
+ return ((Function) value).toValueObject();
+ } else if (value instanceof Expression) {
+ return ((Expression) value).toArray();
+ }
+ }
+ return value;
}
-}
+
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/LineLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/LineLayer.java
index ca106cc106..bbcfb98f07 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/LineLayer.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/LineLayer.java
@@ -8,8 +8,6 @@ import android.support.annotation.UiThread;
import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor;
-import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
-
/**
* A stroked line.
*
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 8d5858217b..8d6c7dd055 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
@@ -402,7 +402,7 @@ public final class Property {
@Retention(RetentionPolicy.SOURCE)
public @interface TEXT_TRANSFORM {}
- // FILL_TRANSLATE_ANCHOR: Controls the translation reference point.
+ // FILL_TRANSLATE_ANCHOR: Controls the frame of reference for `fill-translate`.
/**
* The fill is translated relative to the map.
@@ -414,7 +414,7 @@ public final class Property {
public static final String FILL_TRANSLATE_ANCHOR_VIEWPORT = "viewport";
/**
- * Controls the translation reference point.
+ * Controls the frame of reference for `fill-translate`.
*/
@StringDef({
FILL_TRANSLATE_ANCHOR_MAP,
@@ -423,7 +423,7 @@ public final class Property {
@Retention(RetentionPolicy.SOURCE)
public @interface FILL_TRANSLATE_ANCHOR {}
- // LINE_TRANSLATE_ANCHOR: Controls the translation reference point.
+ // LINE_TRANSLATE_ANCHOR: Controls the frame of reference for `line-translate`.
/**
* The line is translated relative to the map.
@@ -435,7 +435,7 @@ public final class Property {
public static final String LINE_TRANSLATE_ANCHOR_VIEWPORT = "viewport";
/**
- * Controls the translation reference point.
+ * Controls the frame of reference for `line-translate`.
*/
@StringDef({
LINE_TRANSLATE_ANCHOR_MAP,
@@ -444,7 +444,7 @@ public final class Property {
@Retention(RetentionPolicy.SOURCE)
public @interface LINE_TRANSLATE_ANCHOR {}
- // ICON_TRANSLATE_ANCHOR: Controls the translation reference point.
+ // ICON_TRANSLATE_ANCHOR: Controls the frame of reference for `icon-translate`.
/**
* Icons are translated relative to the map.
@@ -456,7 +456,7 @@ public final class Property {
public static final String ICON_TRANSLATE_ANCHOR_VIEWPORT = "viewport";
/**
- * Controls the translation reference point.
+ * Controls the frame of reference for `icon-translate`.
*/
@StringDef({
ICON_TRANSLATE_ANCHOR_MAP,
@@ -465,7 +465,7 @@ public final class Property {
@Retention(RetentionPolicy.SOURCE)
public @interface ICON_TRANSLATE_ANCHOR {}
- // TEXT_TRANSLATE_ANCHOR: Controls the translation reference point.
+ // TEXT_TRANSLATE_ANCHOR: Controls the frame of reference for `text-translate`.
/**
* The text is translated relative to the map.
@@ -477,7 +477,7 @@ public final class Property {
public static final String TEXT_TRANSLATE_ANCHOR_VIEWPORT = "viewport";
/**
- * Controls the translation reference point.
+ * Controls the frame of reference for `text-translate`.
*/
@StringDef({
TEXT_TRANSLATE_ANCHOR_MAP,
@@ -486,7 +486,7 @@ public final class Property {
@Retention(RetentionPolicy.SOURCE)
public @interface TEXT_TRANSLATE_ANCHOR {}
- // CIRCLE_TRANSLATE_ANCHOR: Controls the translation reference point.
+ // CIRCLE_TRANSLATE_ANCHOR: Controls the frame of reference for `circle-translate`.
/**
* The circle is translated relative to the map.
@@ -498,7 +498,7 @@ public final class Property {
public static final String CIRCLE_TRANSLATE_ANCHOR_VIEWPORT = "viewport";
/**
- * Controls the translation reference point.
+ * Controls the frame of reference for `circle-translate`.
*/
@StringDef({
CIRCLE_TRANSLATE_ANCHOR_MAP,
@@ -549,7 +549,7 @@ public final class Property {
@Retention(RetentionPolicy.SOURCE)
public @interface CIRCLE_PITCH_ALIGNMENT {}
- // FILL_EXTRUSION_TRANSLATE_ANCHOR: Controls the translation reference point.
+ // FILL_EXTRUSION_TRANSLATE_ANCHOR: Controls the frame of reference for `fill-extrusion-translate`.
/**
* The fill extrusion is translated relative to the map.
@@ -561,7 +561,7 @@ public final class Property {
public static final String FILL_EXTRUSION_TRANSLATE_ANCHOR_VIEWPORT = "viewport";
/**
- * Controls the translation reference point.
+ * Controls the frame of reference for `fill-extrusion-translate`.
*/
@StringDef({
FILL_EXTRUSION_TRANSLATE_ANCHOR_MAP,
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 d4ddbe48ef..fe164343b5 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
@@ -5,8 +5,11 @@ package com.mapbox.mapboxsdk.style.layers;
import android.annotation.SuppressLint;
import android.support.annotation.ColorInt;
-import com.mapbox.mapboxsdk.style.functions.Function;
import com.mapbox.mapboxsdk.style.functions.CameraFunction;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
+import com.mapbox.mapboxsdk.style.functions.Function;
+
+import java.util.Locale;
/**
* Constructs paint/layout properties for Layers
@@ -32,6 +35,7 @@ public class PropertyFactory {
* @param function the visibility function
* @return property wrapper around a String function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, String>> visibility(Function<T, String> function) {
return new LayoutPropertyValue<>("visibility", function);
}
@@ -46,6 +50,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-antialias", value);
}
+ /**
+ * Whether or not the fill should be antialiased.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> fillAntialias(Expression expression) {
+ return new PaintPropertyValue<>("fill-antialias", expression);
+ }
+
/**
* Whether or not the fill should be antialiased.
@@ -54,6 +68,7 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for Boolean
* @return property wrapper around a Boolean function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, Boolean>> fillAntialias(CameraFunction<Z, Boolean> function) {
return new PaintPropertyValue<>("fill-antialias", function);
}
@@ -68,6 +83,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-opacity", value);
}
+ /**
+ * The opacity of the entire fill layer. In contrast to the {@link PropertyFactory#fillColor}, this value will also affect the 1px stroke around the fill, if the stroke is used.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> fillOpacity(Expression expression) {
+ return new PaintPropertyValue<>("fill-opacity", expression);
+ }
+
/**
* The opacity of the entire fill layer. In contrast to the {@link PropertyFactory#fillColor}, this value will also affect the 1px stroke around the fill, if the stroke is used.
@@ -76,6 +101,7 @@ public class PropertyFactory {
* @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, Float>> fillOpacity(Function<T, Float> function) {
return new PaintPropertyValue<>("fill-opacity", function);
}
@@ -100,6 +126,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-color", value);
}
+ /**
+ * The color of the filled part of this layer. This color can be specified as `rgba` with an alpha component and the color's opacity will not affect the opacity of the 1px stroke, if it is used.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> fillColor(Expression expression) {
+ return new PaintPropertyValue<>("fill-color", expression);
+ }
+
/**
* The color of the filled part of this layer. This color can be specified as `rgba` with an alpha component and the color's opacity will not affect the opacity of the 1px stroke, if it is used.
@@ -108,6 +144,7 @@ public class PropertyFactory {
* @param function a wrapper function for String
* @return property wrapper around a String function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, String>> fillColor(Function<T, String> function) {
return new PaintPropertyValue<>("fill-color", function);
}
@@ -132,6 +169,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-outline-color", value);
}
+ /**
+ * The outline color of the fill. Matches the value of {@link PropertyFactory#fillColor} if unspecified.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> fillOutlineColor(Expression expression) {
+ return new PaintPropertyValue<>("fill-outline-color", expression);
+ }
+
/**
* The outline color of the fill. Matches the value of {@link PropertyFactory#fillColor} if unspecified.
@@ -140,6 +187,7 @@ public class PropertyFactory {
* @param function a wrapper function for String
* @return property wrapper around a String function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, String>> fillOutlineColor(Function<T, String> function) {
return new PaintPropertyValue<>("fill-outline-color", function);
}
@@ -154,6 +202,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-translate", value);
}
+ /**
+ * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> fillTranslate(Expression expression) {
+ return new PaintPropertyValue<>("fill-translate", expression);
+ }
+
/**
* The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively.
@@ -162,12 +220,13 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for Float[]
* @return property wrapper around a Float[] function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, Float[]>> fillTranslate(CameraFunction<Z, Float[]> function) {
return new PaintPropertyValue<>("fill-translate", function);
}
/**
- * Controls the translation reference point.
+ * Controls the frame of reference for {@link PropertyFactory#fillTranslate}.
*
* @param value a String value
* @return property wrapper around String
@@ -176,14 +235,25 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-translate-anchor", value);
}
+ /**
+ * Controls the frame of reference for {@link PropertyFactory#fillTranslate}.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> fillTranslateAnchor(Expression expression) {
+ return new PaintPropertyValue<>("fill-translate-anchor", expression);
+ }
+
/**
- * Controls the translation reference point.
+ * Controls the frame of reference for {@link PropertyFactory#fillTranslate}.
*
* @param <Z> the zoom parameter type
* @param function a wrapper {@link CameraFunction} for String
* @return property wrapper around a String function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> fillTranslateAnchor(CameraFunction<Z, String> function) {
return new PaintPropertyValue<>("fill-translate-anchor", function);
}
@@ -198,6 +268,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-pattern", value);
}
+ /**
+ * Name of image in sprite to use for drawing image fills. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512).
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> fillPattern(Expression expression) {
+ return new PaintPropertyValue<>("fill-pattern", expression);
+ }
+
/**
* Name of image in sprite to use for drawing image fills. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512).
@@ -206,6 +286,7 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for String
* @return property wrapper around a String function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> fillPattern(CameraFunction<Z, String> function) {
return new PaintPropertyValue<>("fill-pattern", function);
}
@@ -220,6 +301,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-opacity", value);
}
+ /**
+ * The opacity at which the line will be drawn.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> lineOpacity(Expression expression) {
+ return new PaintPropertyValue<>("line-opacity", expression);
+ }
+
/**
* The opacity at which the line will be drawn.
@@ -228,6 +319,7 @@ public class PropertyFactory {
* @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, Float>> lineOpacity(Function<T, Float> function) {
return new PaintPropertyValue<>("line-opacity", function);
}
@@ -252,6 +344,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-color", value);
}
+ /**
+ * The color with which the line will be drawn.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> lineColor(Expression expression) {
+ return new PaintPropertyValue<>("line-color", expression);
+ }
+
/**
* The color with which the line will be drawn.
@@ -260,6 +362,7 @@ public class PropertyFactory {
* @param function a wrapper function for String
* @return property wrapper around a String function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, String>> lineColor(Function<T, String> function) {
return new PaintPropertyValue<>("line-color", function);
}
@@ -274,6 +377,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-translate", value);
}
+ /**
+ * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> lineTranslate(Expression expression) {
+ return new PaintPropertyValue<>("line-translate", expression);
+ }
+
/**
* The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively.
@@ -282,12 +395,13 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for Float[]
* @return property wrapper around a Float[] function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, Float[]>> lineTranslate(CameraFunction<Z, Float[]> function) {
return new PaintPropertyValue<>("line-translate", function);
}
/**
- * Controls the translation reference point.
+ * Controls the frame of reference for {@link PropertyFactory#lineTranslate}.
*
* @param value a String value
* @return property wrapper around String
@@ -296,14 +410,25 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-translate-anchor", value);
}
+ /**
+ * Controls the frame of reference for {@link PropertyFactory#lineTranslate}.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> lineTranslateAnchor(Expression expression) {
+ return new PaintPropertyValue<>("line-translate-anchor", expression);
+ }
+
/**
- * Controls the translation reference point.
+ * Controls the frame of reference for {@link PropertyFactory#lineTranslate}.
*
* @param <Z> the zoom parameter type
* @param function a wrapper {@link CameraFunction} for String
* @return property wrapper around a String function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> lineTranslateAnchor(CameraFunction<Z, String> function) {
return new PaintPropertyValue<>("line-translate-anchor", function);
}
@@ -318,6 +443,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-width", value);
}
+ /**
+ * Stroke thickness.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> lineWidth(Expression expression) {
+ return new PaintPropertyValue<>("line-width", expression);
+ }
+
/**
* Stroke thickness.
@@ -326,6 +461,7 @@ public class PropertyFactory {
* @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, Float>> lineWidth(Function<T, Float> function) {
return new PaintPropertyValue<>("line-width", function);
}
@@ -340,6 +476,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-gap-width", value);
}
+ /**
+ * Draws a line casing outside of a line's actual path. Value indicates the width of the inner gap.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> lineGapWidth(Expression expression) {
+ return new PaintPropertyValue<>("line-gap-width", expression);
+ }
+
/**
* Draws a line casing outside of a line's actual path. Value indicates the width of the inner gap.
@@ -348,6 +494,7 @@ public class PropertyFactory {
* @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, Float>> lineGapWidth(Function<T, Float> function) {
return new PaintPropertyValue<>("line-gap-width", function);
}
@@ -362,6 +509,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-offset", value);
}
+ /**
+ * The line's offset. For linear features, a positive value offsets the line to the right, relative to the direction of the line, and a negative value to the left. For polygon features, a positive value results in an inset, and a negative value results in an outset.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> lineOffset(Expression expression) {
+ return new PaintPropertyValue<>("line-offset", expression);
+ }
+
/**
* The line's offset. For linear features, a positive value offsets the line to the right, relative to the direction of the line, and a negative value to the left. For polygon features, a positive value results in an inset, and a negative value results in an outset.
@@ -370,6 +527,7 @@ public class PropertyFactory {
* @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, Float>> lineOffset(Function<T, Float> function) {
return new PaintPropertyValue<>("line-offset", function);
}
@@ -384,6 +542,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-blur", value);
}
+ /**
+ * Blur applied to the line, in density-independent pixels.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> lineBlur(Expression expression) {
+ return new PaintPropertyValue<>("line-blur", expression);
+ }
+
/**
* Blur applied to the line, in density-independent pixels.
@@ -392,6 +560,7 @@ public class PropertyFactory {
* @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, Float>> lineBlur(Function<T, Float> function) {
return new PaintPropertyValue<>("line-blur", function);
}
@@ -406,6 +575,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-dasharray", value);
}
+ /**
+ * Specifies the lengths of the alternating dashes and gaps that form the dash pattern. The lengths are later scaled by the line width. To convert a dash length to density-independent pixels, multiply the length by the current line width.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> lineDasharray(Expression expression) {
+ return new PaintPropertyValue<>("line-dasharray", expression);
+ }
+
/**
* Specifies the lengths of the alternating dashes and gaps that form the dash pattern. The lengths are later scaled by the line width. To convert a dash length to density-independent pixels, multiply the length by the current line width.
@@ -414,6 +593,7 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for Float[]
* @return property wrapper around a Float[] function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, Float[]>> lineDasharray(CameraFunction<Z, Float[]> function) {
return new PaintPropertyValue<>("line-dasharray", function);
}
@@ -428,6 +608,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-pattern", value);
}
+ /**
+ * Name of image in sprite to use for drawing image lines. For seamless patterns, image width must be a factor of two (2, 4, 8, ..., 512).
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> linePattern(Expression expression) {
+ return new PaintPropertyValue<>("line-pattern", expression);
+ }
+
/**
* Name of image in sprite to use for drawing image lines. For seamless patterns, image width must be a factor of two (2, 4, 8, ..., 512).
@@ -436,6 +626,7 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for String
* @return property wrapper around a String function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> linePattern(CameraFunction<Z, String> function) {
return new PaintPropertyValue<>("line-pattern", function);
}
@@ -450,6 +641,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("icon-opacity", value);
}
+ /**
+ * The opacity at which the icon will be drawn.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> iconOpacity(Expression expression) {
+ return new PaintPropertyValue<>("icon-opacity", expression);
+ }
+
/**
* The opacity at which the icon will be drawn.
@@ -458,6 +659,7 @@ public class PropertyFactory {
* @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, Float>> iconOpacity(Function<T, Float> function) {
return new PaintPropertyValue<>("icon-opacity", function);
}
@@ -482,6 +684,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("icon-color", value);
}
+ /**
+ * The color of the icon. This can only be used with sdf icons.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> iconColor(Expression expression) {
+ return new PaintPropertyValue<>("icon-color", expression);
+ }
+
/**
* The color of the icon. This can only be used with sdf icons.
@@ -490,6 +702,7 @@ public class PropertyFactory {
* @param function a wrapper function for String
* @return property wrapper around a String function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, String>> iconColor(Function<T, String> function) {
return new PaintPropertyValue<>("icon-color", function);
}
@@ -514,6 +727,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("icon-halo-color", value);
}
+ /**
+ * The color of the icon's halo. Icon halos can only be used with SDF icons.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> iconHaloColor(Expression expression) {
+ return new PaintPropertyValue<>("icon-halo-color", expression);
+ }
+
/**
* The color of the icon's halo. Icon halos can only be used with SDF icons.
@@ -522,6 +745,7 @@ public class PropertyFactory {
* @param function a wrapper function for String
* @return property wrapper around a String function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, String>> iconHaloColor(Function<T, String> function) {
return new PaintPropertyValue<>("icon-halo-color", function);
}
@@ -536,6 +760,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("icon-halo-width", value);
}
+ /**
+ * Distance of halo to the icon outline.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> iconHaloWidth(Expression expression) {
+ return new PaintPropertyValue<>("icon-halo-width", expression);
+ }
+
/**
* Distance of halo to the icon outline.
@@ -544,6 +778,7 @@ public class PropertyFactory {
* @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, Float>> iconHaloWidth(Function<T, Float> function) {
return new PaintPropertyValue<>("icon-halo-width", function);
}
@@ -558,6 +793,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("icon-halo-blur", value);
}
+ /**
+ * Fade out the halo towards the outside.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> iconHaloBlur(Expression expression) {
+ return new PaintPropertyValue<>("icon-halo-blur", expression);
+ }
+
/**
* Fade out the halo towards the outside.
@@ -566,6 +811,7 @@ public class PropertyFactory {
* @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, Float>> iconHaloBlur(Function<T, Float> function) {
return new PaintPropertyValue<>("icon-halo-blur", function);
}
@@ -580,6 +826,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("icon-translate", value);
}
+ /**
+ * Distance that the icon's anchor is moved from its original placement. Positive values indicate right and down, while negative values indicate left and up.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> iconTranslate(Expression expression) {
+ return new PaintPropertyValue<>("icon-translate", expression);
+ }
+
/**
* Distance that the icon's anchor is moved from its original placement. Positive values indicate right and down, while negative values indicate left and up.
@@ -588,12 +844,13 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for Float[]
* @return property wrapper around a Float[] function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, Float[]>> iconTranslate(CameraFunction<Z, Float[]> function) {
return new PaintPropertyValue<>("icon-translate", function);
}
/**
- * Controls the translation reference point.
+ * Controls the frame of reference for {@link PropertyFactory#iconTranslate}.
*
* @param value a String value
* @return property wrapper around String
@@ -602,14 +859,25 @@ public class PropertyFactory {
return new PaintPropertyValue<>("icon-translate-anchor", value);
}
+ /**
+ * Controls the frame of reference for {@link PropertyFactory#iconTranslate}.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> iconTranslateAnchor(Expression expression) {
+ return new PaintPropertyValue<>("icon-translate-anchor", expression);
+ }
+
/**
- * Controls the translation reference point.
+ * Controls the frame of reference for {@link PropertyFactory#iconTranslate}.
*
* @param <Z> the zoom parameter type
* @param function a wrapper {@link CameraFunction} for String
* @return property wrapper around a String function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> iconTranslateAnchor(CameraFunction<Z, String> function) {
return new PaintPropertyValue<>("icon-translate-anchor", function);
}
@@ -624,6 +892,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("text-opacity", value);
}
+ /**
+ * The opacity at which the text will be drawn.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> textOpacity(Expression expression) {
+ return new PaintPropertyValue<>("text-opacity", expression);
+ }
+
/**
* The opacity at which the text will be drawn.
@@ -632,6 +910,7 @@ public class PropertyFactory {
* @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, Float>> textOpacity(Function<T, Float> function) {
return new PaintPropertyValue<>("text-opacity", function);
}
@@ -656,6 +935,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("text-color", value);
}
+ /**
+ * The color with which the text will be drawn.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> textColor(Expression expression) {
+ return new PaintPropertyValue<>("text-color", expression);
+ }
+
/**
* The color with which the text will be drawn.
@@ -664,6 +953,7 @@ public class PropertyFactory {
* @param function a wrapper function for String
* @return property wrapper around a String function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, String>> textColor(Function<T, String> function) {
return new PaintPropertyValue<>("text-color", function);
}
@@ -688,6 +978,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("text-halo-color", value);
}
+ /**
+ * The color of the text's halo, which helps it stand out from backgrounds.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> textHaloColor(Expression expression) {
+ return new PaintPropertyValue<>("text-halo-color", expression);
+ }
+
/**
* The color of the text's halo, which helps it stand out from backgrounds.
@@ -696,6 +996,7 @@ public class PropertyFactory {
* @param function a wrapper function for String
* @return property wrapper around a String function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, String>> textHaloColor(Function<T, String> function) {
return new PaintPropertyValue<>("text-halo-color", function);
}
@@ -710,6 +1011,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("text-halo-width", value);
}
+ /**
+ * Distance of halo to the font outline. Max text halo width is 1/4 of the font-size.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> textHaloWidth(Expression expression) {
+ return new PaintPropertyValue<>("text-halo-width", expression);
+ }
+
/**
* Distance of halo to the font outline. Max text halo width is 1/4 of the font-size.
@@ -718,6 +1029,7 @@ public class PropertyFactory {
* @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, Float>> textHaloWidth(Function<T, Float> function) {
return new PaintPropertyValue<>("text-halo-width", function);
}
@@ -732,6 +1044,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("text-halo-blur", value);
}
+ /**
+ * The halo's fadeout distance towards the outside.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> textHaloBlur(Expression expression) {
+ return new PaintPropertyValue<>("text-halo-blur", expression);
+ }
+
/**
* The halo's fadeout distance towards the outside.
@@ -740,6 +1062,7 @@ public class PropertyFactory {
* @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, Float>> textHaloBlur(Function<T, Float> function) {
return new PaintPropertyValue<>("text-halo-blur", function);
}
@@ -754,6 +1077,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("text-translate", value);
}
+ /**
+ * Distance that the text's anchor is moved from its original placement. Positive values indicate right and down, while negative values indicate left and up.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> textTranslate(Expression expression) {
+ return new PaintPropertyValue<>("text-translate", expression);
+ }
+
/**
* Distance that the text's anchor is moved from its original placement. Positive values indicate right and down, while negative values indicate left and up.
@@ -762,12 +1095,13 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for Float[]
* @return property wrapper around a Float[] function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, Float[]>> textTranslate(CameraFunction<Z, Float[]> function) {
return new PaintPropertyValue<>("text-translate", function);
}
/**
- * Controls the translation reference point.
+ * Controls the frame of reference for {@link PropertyFactory#textTranslate}.
*
* @param value a String value
* @return property wrapper around String
@@ -776,14 +1110,25 @@ public class PropertyFactory {
return new PaintPropertyValue<>("text-translate-anchor", value);
}
+ /**
+ * Controls the frame of reference for {@link PropertyFactory#textTranslate}.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> textTranslateAnchor(Expression expression) {
+ return new PaintPropertyValue<>("text-translate-anchor", expression);
+ }
+
/**
- * Controls the translation reference point.
+ * Controls the frame of reference for {@link PropertyFactory#textTranslate}.
*
* @param <Z> the zoom parameter type
* @param function a wrapper {@link CameraFunction} for String
* @return property wrapper around a String function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> textTranslateAnchor(CameraFunction<Z, String> function) {
return new PaintPropertyValue<>("text-translate-anchor", function);
}
@@ -798,6 +1143,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("circle-radius", value);
}
+ /**
+ * Circle radius.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> circleRadius(Expression expression) {
+ return new PaintPropertyValue<>("circle-radius", expression);
+ }
+
/**
* Circle radius.
@@ -806,6 +1161,7 @@ public class PropertyFactory {
* @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, Float>> circleRadius(Function<T, Float> function) {
return new PaintPropertyValue<>("circle-radius", function);
}
@@ -830,6 +1186,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("circle-color", value);
}
+ /**
+ * The fill color of the circle.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> circleColor(Expression expression) {
+ return new PaintPropertyValue<>("circle-color", expression);
+ }
+
/**
* The fill color of the circle.
@@ -838,6 +1204,7 @@ public class PropertyFactory {
* @param function a wrapper function for String
* @return property wrapper around a String function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, String>> circleColor(Function<T, String> function) {
return new PaintPropertyValue<>("circle-color", function);
}
@@ -852,6 +1219,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("circle-blur", value);
}
+ /**
+ * Amount to blur the circle. 1 blurs the circle such that only the centerpoint is full opacity.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> circleBlur(Expression expression) {
+ return new PaintPropertyValue<>("circle-blur", expression);
+ }
+
/**
* Amount to blur the circle. 1 blurs the circle such that only the centerpoint is full opacity.
@@ -860,6 +1237,7 @@ public class PropertyFactory {
* @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, Float>> circleBlur(Function<T, Float> function) {
return new PaintPropertyValue<>("circle-blur", function);
}
@@ -874,6 +1252,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("circle-opacity", value);
}
+ /**
+ * The opacity at which the circle will be drawn.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> circleOpacity(Expression expression) {
+ return new PaintPropertyValue<>("circle-opacity", expression);
+ }
+
/**
* The opacity at which the circle will be drawn.
@@ -882,6 +1270,7 @@ public class PropertyFactory {
* @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, Float>> circleOpacity(Function<T, Float> function) {
return new PaintPropertyValue<>("circle-opacity", function);
}
@@ -896,6 +1285,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("circle-translate", value);
}
+ /**
+ * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> circleTranslate(Expression expression) {
+ return new PaintPropertyValue<>("circle-translate", expression);
+ }
+
/**
* The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively.
@@ -904,12 +1303,13 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for Float[]
* @return property wrapper around a Float[] function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, Float[]>> circleTranslate(CameraFunction<Z, Float[]> function) {
return new PaintPropertyValue<>("circle-translate", function);
}
/**
- * Controls the translation reference point.
+ * Controls the frame of reference for {@link PropertyFactory#circleTranslate}.
*
* @param value a String value
* @return property wrapper around String
@@ -918,14 +1318,25 @@ public class PropertyFactory {
return new PaintPropertyValue<>("circle-translate-anchor", value);
}
+ /**
+ * Controls the frame of reference for {@link PropertyFactory#circleTranslate}.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> circleTranslateAnchor(Expression expression) {
+ return new PaintPropertyValue<>("circle-translate-anchor", expression);
+ }
+
/**
- * Controls the translation reference point.
+ * Controls the frame of reference for {@link PropertyFactory#circleTranslate}.
*
* @param <Z> the zoom parameter type
* @param function a wrapper {@link CameraFunction} for String
* @return property wrapper around a String function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> circleTranslateAnchor(CameraFunction<Z, String> function) {
return new PaintPropertyValue<>("circle-translate-anchor", function);
}
@@ -940,6 +1351,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("circle-pitch-scale", value);
}
+ /**
+ * Controls the scaling behavior of the circle when the map is pitched.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> circlePitchScale(Expression expression) {
+ return new PaintPropertyValue<>("circle-pitch-scale", expression);
+ }
+
/**
* Controls the scaling behavior of the circle when the map is pitched.
@@ -948,6 +1369,7 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for String
* @return property wrapper around a String function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> circlePitchScale(CameraFunction<Z, String> function) {
return new PaintPropertyValue<>("circle-pitch-scale", function);
}
@@ -962,6 +1384,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("circle-pitch-alignment", value);
}
+ /**
+ * Orientation of circle when map is pitched.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> circlePitchAlignment(Expression expression) {
+ return new PaintPropertyValue<>("circle-pitch-alignment", expression);
+ }
+
/**
* Orientation of circle when map is pitched.
@@ -970,6 +1402,7 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for String
* @return property wrapper around a String function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> circlePitchAlignment(CameraFunction<Z, String> function) {
return new PaintPropertyValue<>("circle-pitch-alignment", function);
}
@@ -984,6 +1417,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("circle-stroke-width", value);
}
+ /**
+ * The width of the circle's stroke. Strokes are placed outside of the {@link PropertyFactory#circleRadius}.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> circleStrokeWidth(Expression expression) {
+ return new PaintPropertyValue<>("circle-stroke-width", expression);
+ }
+
/**
* The width of the circle's stroke. Strokes are placed outside of the {@link PropertyFactory#circleRadius}.
@@ -992,6 +1435,7 @@ public class PropertyFactory {
* @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, Float>> circleStrokeWidth(Function<T, Float> function) {
return new PaintPropertyValue<>("circle-stroke-width", function);
}
@@ -1016,6 +1460,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("circle-stroke-color", value);
}
+ /**
+ * The stroke color of the circle.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> circleStrokeColor(Expression expression) {
+ return new PaintPropertyValue<>("circle-stroke-color", expression);
+ }
+
/**
* The stroke color of the circle.
@@ -1024,6 +1478,7 @@ public class PropertyFactory {
* @param function a wrapper function for String
* @return property wrapper around a String function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, String>> circleStrokeColor(Function<T, String> function) {
return new PaintPropertyValue<>("circle-stroke-color", function);
}
@@ -1038,6 +1493,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("circle-stroke-opacity", value);
}
+ /**
+ * The opacity of the circle's stroke.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> circleStrokeOpacity(Expression expression) {
+ return new PaintPropertyValue<>("circle-stroke-opacity", expression);
+ }
+
/**
* The opacity of the circle's stroke.
@@ -1046,6 +1511,7 @@ public class PropertyFactory {
* @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, Float>> circleStrokeOpacity(Function<T, Float> function) {
return new PaintPropertyValue<>("circle-stroke-opacity", function);
}
@@ -1060,6 +1526,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-extrusion-opacity", value);
}
+ /**
+ * The opacity of the entire fill extrusion layer. This is rendered on a per-layer, not per-feature, basis, and data-driven styling is not available.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> fillExtrusionOpacity(Expression expression) {
+ return new PaintPropertyValue<>("fill-extrusion-opacity", expression);
+ }
+
/**
* The opacity of the entire fill extrusion layer. This is rendered on a per-layer, not per-feature, basis, and data-driven styling is not available.
@@ -1068,6 +1544,7 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> fillExtrusionOpacity(CameraFunction<Z, Float> function) {
return new PaintPropertyValue<>("fill-extrusion-opacity", function);
}
@@ -1092,6 +1569,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-extrusion-color", value);
}
+ /**
+ * The base color of the extruded fill. The extrusion's surfaces will be shaded differently based on this color in combination with the root `light` settings. If this color is specified as `rgba` with an alpha component, the alpha component will be ignored; use {@link PropertyFactory#fillExtrusionOpacity} to set layer opacity.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> fillExtrusionColor(Expression expression) {
+ return new PaintPropertyValue<>("fill-extrusion-color", expression);
+ }
+
/**
* The base color of the extruded fill. The extrusion's surfaces will be shaded differently based on this color in combination with the root `light` settings. If this color is specified as `rgba` with an alpha component, the alpha component will be ignored; use {@link PropertyFactory#fillExtrusionOpacity} to set layer opacity.
@@ -1100,6 +1587,7 @@ public class PropertyFactory {
* @param function a wrapper function for String
* @return property wrapper around a String function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, String>> fillExtrusionColor(Function<T, String> function) {
return new PaintPropertyValue<>("fill-extrusion-color", function);
}
@@ -1114,6 +1602,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-extrusion-translate", value);
}
+ /**
+ * The geometry's offset. Values are [x, y] where negatives indicate left and up (on the flat plane), respectively.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> fillExtrusionTranslate(Expression expression) {
+ return new PaintPropertyValue<>("fill-extrusion-translate", expression);
+ }
+
/**
* The geometry's offset. Values are [x, y] where negatives indicate left and up (on the flat plane), respectively.
@@ -1122,12 +1620,13 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for Float[]
* @return property wrapper around a Float[] function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, Float[]>> fillExtrusionTranslate(CameraFunction<Z, Float[]> function) {
return new PaintPropertyValue<>("fill-extrusion-translate", function);
}
/**
- * Controls the translation reference point.
+ * Controls the frame of reference for {@link PropertyFactory#fillExtrusionTranslate}.
*
* @param value a String value
* @return property wrapper around String
@@ -1136,14 +1635,25 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-extrusion-translate-anchor", value);
}
+ /**
+ * Controls the frame of reference for {@link PropertyFactory#fillExtrusionTranslate}.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> fillExtrusionTranslateAnchor(Expression expression) {
+ return new PaintPropertyValue<>("fill-extrusion-translate-anchor", expression);
+ }
+
/**
- * Controls the translation reference point.
+ * Controls the frame of reference for {@link PropertyFactory#fillExtrusionTranslate}.
*
* @param <Z> the zoom parameter type
* @param function a wrapper {@link CameraFunction} for String
* @return property wrapper around a String function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> fillExtrusionTranslateAnchor(CameraFunction<Z, String> function) {
return new PaintPropertyValue<>("fill-extrusion-translate-anchor", function);
}
@@ -1158,6 +1668,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-extrusion-pattern", value);
}
+ /**
+ * Name of image in sprite to use for drawing images on extruded fills. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512).
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> fillExtrusionPattern(Expression expression) {
+ return new PaintPropertyValue<>("fill-extrusion-pattern", expression);
+ }
+
/**
* Name of image in sprite to use for drawing images on extruded fills. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512).
@@ -1166,6 +1686,7 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for String
* @return property wrapper around a String function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> fillExtrusionPattern(CameraFunction<Z, String> function) {
return new PaintPropertyValue<>("fill-extrusion-pattern", function);
}
@@ -1180,6 +1701,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-extrusion-height", value);
}
+ /**
+ * The height with which to extrude this layer.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> fillExtrusionHeight(Expression expression) {
+ return new PaintPropertyValue<>("fill-extrusion-height", expression);
+ }
+
/**
* The height with which to extrude this layer.
@@ -1188,6 +1719,7 @@ public class PropertyFactory {
* @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, Float>> fillExtrusionHeight(Function<T, Float> function) {
return new PaintPropertyValue<>("fill-extrusion-height", function);
}
@@ -1202,6 +1734,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-extrusion-base", value);
}
+ /**
+ * The height with which to extrude the base of this layer. Must be less than or equal to {@link PropertyFactory#fillExtrusionHeight}.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> fillExtrusionBase(Expression expression) {
+ return new PaintPropertyValue<>("fill-extrusion-base", expression);
+ }
+
/**
* The height with which to extrude the base of this layer. Must be less than or equal to {@link PropertyFactory#fillExtrusionHeight}.
@@ -1210,6 +1752,7 @@ public class PropertyFactory {
* @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, Float>> fillExtrusionBase(Function<T, Float> function) {
return new PaintPropertyValue<>("fill-extrusion-base", function);
}
@@ -1224,6 +1767,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("raster-opacity", value);
}
+ /**
+ * The opacity at which the image will be drawn.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> rasterOpacity(Expression expression) {
+ return new PaintPropertyValue<>("raster-opacity", expression);
+ }
+
/**
* The opacity at which the image will be drawn.
@@ -1232,6 +1785,7 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> rasterOpacity(CameraFunction<Z, Float> function) {
return new PaintPropertyValue<>("raster-opacity", function);
}
@@ -1246,6 +1800,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("raster-hue-rotate", value);
}
+ /**
+ * Rotates hues around the color wheel.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> rasterHueRotate(Expression expression) {
+ return new PaintPropertyValue<>("raster-hue-rotate", expression);
+ }
+
/**
* Rotates hues around the color wheel.
@@ -1254,6 +1818,7 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> rasterHueRotate(CameraFunction<Z, Float> function) {
return new PaintPropertyValue<>("raster-hue-rotate", function);
}
@@ -1268,6 +1833,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("raster-brightness-min", value);
}
+ /**
+ * Increase or reduce the brightness of the image. The value is the minimum brightness.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> rasterBrightnessMin(Expression expression) {
+ return new PaintPropertyValue<>("raster-brightness-min", expression);
+ }
+
/**
* Increase or reduce the brightness of the image. The value is the minimum brightness.
@@ -1276,6 +1851,7 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> rasterBrightnessMin(CameraFunction<Z, Float> function) {
return new PaintPropertyValue<>("raster-brightness-min", function);
}
@@ -1290,6 +1866,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("raster-brightness-max", value);
}
+ /**
+ * Increase or reduce the brightness of the image. The value is the maximum brightness.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> rasterBrightnessMax(Expression expression) {
+ return new PaintPropertyValue<>("raster-brightness-max", expression);
+ }
+
/**
* Increase or reduce the brightness of the image. The value is the maximum brightness.
@@ -1298,6 +1884,7 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> rasterBrightnessMax(CameraFunction<Z, Float> function) {
return new PaintPropertyValue<>("raster-brightness-max", function);
}
@@ -1312,6 +1899,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("raster-saturation", value);
}
+ /**
+ * Increase or reduce the saturation of the image.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> rasterSaturation(Expression expression) {
+ return new PaintPropertyValue<>("raster-saturation", expression);
+ }
+
/**
* Increase or reduce the saturation of the image.
@@ -1320,6 +1917,7 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> rasterSaturation(CameraFunction<Z, Float> function) {
return new PaintPropertyValue<>("raster-saturation", function);
}
@@ -1334,6 +1932,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("raster-contrast", value);
}
+ /**
+ * Increase or reduce the contrast of the image.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> rasterContrast(Expression expression) {
+ return new PaintPropertyValue<>("raster-contrast", expression);
+ }
+
/**
* Increase or reduce the contrast of the image.
@@ -1342,6 +1950,7 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> rasterContrast(CameraFunction<Z, Float> function) {
return new PaintPropertyValue<>("raster-contrast", function);
}
@@ -1356,6 +1965,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("raster-fade-duration", value);
}
+ /**
+ * Fade duration when a new tile is added.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> rasterFadeDuration(Expression expression) {
+ return new PaintPropertyValue<>("raster-fade-duration", expression);
+ }
+
/**
* Fade duration when a new tile is added.
@@ -1364,6 +1983,7 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> rasterFadeDuration(CameraFunction<Z, Float> function) {
return new PaintPropertyValue<>("raster-fade-duration", function);
}
@@ -1388,6 +2008,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("background-color", value);
}
+ /**
+ * The color with which the background will be drawn.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> backgroundColor(Expression expression) {
+ return new PaintPropertyValue<>("background-color", expression);
+ }
+
/**
* The color with which the background will be drawn.
@@ -1396,6 +2026,7 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for String
* @return property wrapper around a String function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> backgroundColor(CameraFunction<Z, String> function) {
return new PaintPropertyValue<>("background-color", function);
}
@@ -1410,6 +2041,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("background-pattern", value);
}
+ /**
+ * Name of image in sprite to use for drawing an image background. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512).
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> backgroundPattern(Expression expression) {
+ return new PaintPropertyValue<>("background-pattern", expression);
+ }
+
/**
* Name of image in sprite to use for drawing an image background. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512).
@@ -1418,6 +2059,7 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for String
* @return property wrapper around a String function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> backgroundPattern(CameraFunction<Z, String> function) {
return new PaintPropertyValue<>("background-pattern", function);
}
@@ -1432,6 +2074,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("background-opacity", value);
}
+ /**
+ * The opacity at which the background will be drawn.
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> backgroundOpacity(Expression expression) {
+ return new PaintPropertyValue<>("background-opacity", expression);
+ }
+
/**
* The opacity at which the background will be drawn.
@@ -1440,6 +2092,7 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for Float
* @return property wrapper around a Float function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> backgroundOpacity(CameraFunction<Z, Float> function) {
return new PaintPropertyValue<>("background-opacity", function);
}
@@ -1454,6 +2107,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("line-cap", value);
}
+ /**
+ * The display of line endings.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static PropertyValue<Expression> lineCap(Expression value) {
+ return new LayoutPropertyValue<>("line-cap", value);
+ }
/**
@@ -1477,6 +2139,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("line-join", value);
}
+ /**
+ * The display of lines when joining.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static PropertyValue<Expression> lineJoin(Expression value) {
+ return new LayoutPropertyValue<>("line-join", value);
+ }
/**
@@ -1500,6 +2171,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("line-miter-limit", value);
}
+ /**
+ * Used to automatically convert miter joins to bevel joins for sharp angles.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static PropertyValue<Expression> lineMiterLimit(Expression value) {
+ return new LayoutPropertyValue<>("line-miter-limit", value);
+ }
/**
@@ -1523,6 +2203,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("line-round-limit", value);
}
+ /**
+ * Used to automatically convert round joins to miter joins for shallow angles.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static PropertyValue<Expression> lineRoundLimit(Expression value) {
+ return new LayoutPropertyValue<>("line-round-limit", value);
+ }
/**
@@ -1546,6 +2235,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("symbol-placement", value);
}
+ /**
+ * Label placement relative to its geometry.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static PropertyValue<Expression> symbolPlacement(Expression value) {
+ return new LayoutPropertyValue<>("symbol-placement", value);
+ }
/**
@@ -1569,6 +2267,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("symbol-spacing", value);
}
+ /**
+ * Distance between two symbol anchors.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static PropertyValue<Expression> symbolSpacing(Expression value) {
+ return new LayoutPropertyValue<>("symbol-spacing", value);
+ }
/**
@@ -1592,6 +2299,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("symbol-avoid-edges", value);
}
+ /**
+ * If true, the symbols will not cross tile edges to avoid mutual collisions. Recommended in layers that don't have enough padding in the vector tile to prevent collisions, or if it is a point symbol layer placed after a line symbol layer.
+ *
+ * @param value a Boolean value
+ * @return property wrapper around Boolean
+ */
+ public static PropertyValue<Expression> symbolAvoidEdges(Expression value) {
+ return new LayoutPropertyValue<>("symbol-avoid-edges", value);
+ }
/**
@@ -1615,6 +2331,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("icon-allow-overlap", value);
}
+ /**
+ * If true, the icon will be visible even if it collides with other previously drawn symbols.
+ *
+ * @param value a Boolean value
+ * @return property wrapper around Boolean
+ */
+ public static PropertyValue<Expression> iconAllowOverlap(Expression value) {
+ return new LayoutPropertyValue<>("icon-allow-overlap", value);
+ }
/**
@@ -1638,6 +2363,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("icon-ignore-placement", value);
}
+ /**
+ * If true, other symbols can be visible even if they collide with the icon.
+ *
+ * @param value a Boolean value
+ * @return property wrapper around Boolean
+ */
+ public static PropertyValue<Expression> iconIgnorePlacement(Expression value) {
+ return new LayoutPropertyValue<>("icon-ignore-placement", value);
+ }
/**
@@ -1661,6 +2395,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("icon-optional", value);
}
+ /**
+ * If true, text will display without their corresponding icons when the icon collides with other symbols and the text does not.
+ *
+ * @param value a Boolean value
+ * @return property wrapper around Boolean
+ */
+ public static PropertyValue<Expression> iconOptional(Expression value) {
+ return new LayoutPropertyValue<>("icon-optional", value);
+ }
/**
@@ -1684,6 +2427,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("icon-rotation-alignment", value);
}
+ /**
+ * In combination with {@link Property.SYMBOL_PLACEMENT}, determines the rotation behavior of icons.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static PropertyValue<Expression> iconRotationAlignment(Expression value) {
+ return new LayoutPropertyValue<>("icon-rotation-alignment", value);
+ }
/**
@@ -1707,6 +2459,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("icon-size", value);
}
+ /**
+ * Scales the original size of the icon by the provided factor. The new pixel size of the image will be the original pixel size multiplied by {@link PropertyFactory#iconSize}. 1 is the original size; 3 triples the size of the image.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static PropertyValue<Expression> iconSize(Expression value) {
+ return new LayoutPropertyValue<>("icon-size", value);
+ }
/**
@@ -1730,6 +2491,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("icon-text-fit", value);
}
+ /**
+ * Scales the icon to fit around the associated text.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static PropertyValue<Expression> iconTextFit(Expression value) {
+ return new LayoutPropertyValue<>("icon-text-fit", value);
+ }
/**
@@ -1753,6 +2523,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("icon-text-fit-padding", value);
}
+ /**
+ * Size of the additional area added to dimensions determined by {@link Property.ICON_TEXT_FIT}, in clockwise order: top, right, bottom, left.
+ *
+ * @param value a Float[] value
+ * @return property wrapper around Float[]
+ */
+ public static PropertyValue<Expression> iconTextFitPadding(Expression value) {
+ return new LayoutPropertyValue<>("icon-text-fit-padding", value);
+ }
/**
@@ -1767,7 +2546,7 @@ public class PropertyFactory {
}
/**
- * Name of image in sprite to use for drawing an image background. A string with {tokens} replaced, referencing the data property to pull from.
+ * Name of image in sprite to use for drawing an image background. A string with `{tokens}` replaced, referencing the data property to pull from. (`{token}` replacement is only supported for literal {@link PropertyFactory#iconImage} values; not for property functions.)
*
* @param value a String value
* @return property wrapper around String
@@ -1776,10 +2555,19 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("icon-image", value);
}
+ /**
+ * Name of image in sprite to use for drawing an image background. A string with `{tokens}` replaced, referencing the data property to pull from. (`{token}` replacement is only supported for literal {@link PropertyFactory#iconImage} values; not for property functions.)
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static PropertyValue<Expression> iconImage(Expression value) {
+ return new LayoutPropertyValue<>("icon-image", value);
+ }
/**
- * Name of image in sprite to use for drawing an image background. A string with {tokens} replaced, referencing the data property to pull from.
+ * Name of image in sprite to use for drawing an image background. A string with `{tokens}` replaced, referencing the data property to pull from. (`{token}` replacement is only supported for literal {@link PropertyFactory#iconImage} values; not for property functions.)
*
* @param <T> the function input type
* @param function a wrapper function for String
@@ -1799,6 +2587,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("icon-rotate", value);
}
+ /**
+ * Rotates the icon clockwise.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static PropertyValue<Expression> iconRotate(Expression value) {
+ return new LayoutPropertyValue<>("icon-rotate", value);
+ }
/**
@@ -1822,6 +2619,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("icon-padding", value);
}
+ /**
+ * Size of the additional area around the icon bounding box used for detecting symbol collisions.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static PropertyValue<Expression> iconPadding(Expression value) {
+ return new LayoutPropertyValue<>("icon-padding", value);
+ }
/**
@@ -1845,6 +2651,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("icon-keep-upright", value);
}
+ /**
+ * If true, the icon may be flipped to prevent it from being rendered upside-down.
+ *
+ * @param value a Boolean value
+ * @return property wrapper around Boolean
+ */
+ public static PropertyValue<Expression> iconKeepUpright(Expression value) {
+ return new LayoutPropertyValue<>("icon-keep-upright", value);
+ }
/**
@@ -1868,6 +2683,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("icon-offset", value);
}
+ /**
+ * Offset distance of icon from its anchor. Positive values indicate right and down, while negative values indicate left and up. When combined with {@link PropertyFactory#iconRotate} the offset will be as if the rotated direction was up.
+ *
+ * @param value a Float[] value
+ * @return property wrapper around Float[]
+ */
+ public static PropertyValue<Expression> iconOffset(Expression value) {
+ return new LayoutPropertyValue<>("icon-offset", value);
+ }
/**
@@ -1891,6 +2715,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("icon-anchor", value);
}
+ /**
+ * Part of the icon placed closest to the anchor.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static PropertyValue<Expression> iconAnchor(Expression value) {
+ return new LayoutPropertyValue<>("icon-anchor", value);
+ }
/**
@@ -1914,6 +2747,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("icon-pitch-alignment", value);
}
+ /**
+ * Orientation of icon when map is pitched.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static PropertyValue<Expression> iconPitchAlignment(Expression value) {
+ return new LayoutPropertyValue<>("icon-pitch-alignment", value);
+ }
/**
@@ -1937,6 +2779,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-pitch-alignment", value);
}
+ /**
+ * Orientation of text when map is pitched.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static PropertyValue<Expression> textPitchAlignment(Expression value) {
+ return new LayoutPropertyValue<>("text-pitch-alignment", value);
+ }
/**
@@ -1960,6 +2811,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-rotation-alignment", value);
}
+ /**
+ * In combination with {@link Property.SYMBOL_PLACEMENT}, determines the rotation behavior of the individual glyphs forming the text.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static PropertyValue<Expression> textRotationAlignment(Expression value) {
+ return new LayoutPropertyValue<>("text-rotation-alignment", value);
+ }
/**
@@ -1974,7 +2834,7 @@ public class PropertyFactory {
}
/**
- * Value to use for a text label. Feature properties are specified using tokens like {field_name}. (Token replacement is only supported for literal {@link PropertyFactory#textField} values--not for property functions.)
+ * Value to use for a text label. Feature properties are specified using tokens like `{field_name}`. (`{token}` replacement is only supported for literal {@link PropertyFactory#textField} values; not for property functions.)
*
* @param value a String value
* @return property wrapper around String
@@ -1983,10 +2843,19 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-field", value);
}
+ /**
+ * Value to use for a text label. Feature properties are specified using tokens like `{field_name}`. (`{token}` replacement is only supported for literal {@link PropertyFactory#textField} values; not for property functions.)
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static PropertyValue<Expression> textField(Expression value) {
+ return new LayoutPropertyValue<>("text-field", value);
+ }
/**
- * Value to use for a text label. Feature properties are specified using tokens like {field_name}. (Token replacement is only supported for literal {@link PropertyFactory#textField} values--not for property functions.)
+ * Value to use for a text label. Feature properties are specified using tokens like `{field_name}`. (`{token}` replacement is only supported for literal {@link PropertyFactory#textField} values; not for property functions.)
*
* @param <T> the function input type
* @param function a wrapper function for String
@@ -2006,16 +2875,25 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-font", value);
}
+ /**
+ * Font stack to use for displaying text.
+ *
+ * @param value a String[] value
+ * @return property wrapper around String[]
+ */
+ public static PropertyValue<Expression> textFont(Expression value) {
+ return new LayoutPropertyValue<>("text-font", value);
+ }
/**
* Font stack to use for displaying text.
*
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for String[]
+ * @param <T> the function input type
+ * @param function a wrapper function for String[]
* @return property wrapper around a String[] function
*/
- public static <Z extends Number> PropertyValue<CameraFunction<Z, String[]>> textFont(CameraFunction<Z, String[]> function) {
+ public static <T> PropertyValue<Function<T, String[]>> textFont(Function<T, String[]> function) {
return new LayoutPropertyValue<>("text-font", function);
}
@@ -2029,6 +2907,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-size", value);
}
+ /**
+ * Font size.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static PropertyValue<Expression> textSize(Expression value) {
+ return new LayoutPropertyValue<>("text-size", value);
+ }
/**
@@ -2052,6 +2939,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-max-width", value);
}
+ /**
+ * The maximum line width for text wrapping.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static PropertyValue<Expression> textMaxWidth(Expression value) {
+ return new LayoutPropertyValue<>("text-max-width", value);
+ }
/**
@@ -2075,6 +2971,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-line-height", value);
}
+ /**
+ * Text leading value for multi-line text.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static PropertyValue<Expression> textLineHeight(Expression value) {
+ return new LayoutPropertyValue<>("text-line-height", value);
+ }
/**
@@ -2098,6 +3003,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-letter-spacing", value);
}
+ /**
+ * Text tracking amount.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static PropertyValue<Expression> textLetterSpacing(Expression value) {
+ return new LayoutPropertyValue<>("text-letter-spacing", value);
+ }
/**
@@ -2121,6 +3035,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-justify", value);
}
+ /**
+ * Text justification options.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static PropertyValue<Expression> textJustify(Expression value) {
+ return new LayoutPropertyValue<>("text-justify", value);
+ }
/**
@@ -2144,6 +3067,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-anchor", value);
}
+ /**
+ * Part of the text placed closest to the anchor.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static PropertyValue<Expression> textAnchor(Expression value) {
+ return new LayoutPropertyValue<>("text-anchor", value);
+ }
/**
@@ -2167,6 +3099,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-max-angle", value);
}
+ /**
+ * Maximum angle change between adjacent characters.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static PropertyValue<Expression> textMaxAngle(Expression value) {
+ return new LayoutPropertyValue<>("text-max-angle", value);
+ }
/**
@@ -2190,6 +3131,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-rotate", value);
}
+ /**
+ * Rotates the text clockwise.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static PropertyValue<Expression> textRotate(Expression value) {
+ return new LayoutPropertyValue<>("text-rotate", value);
+ }
/**
@@ -2213,6 +3163,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-padding", value);
}
+ /**
+ * Size of the additional area around the text bounding box used for detecting symbol collisions.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static PropertyValue<Expression> textPadding(Expression value) {
+ return new LayoutPropertyValue<>("text-padding", value);
+ }
/**
@@ -2236,6 +3195,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-keep-upright", value);
}
+ /**
+ * If true, the text may be flipped vertically to prevent it from being rendered upside-down.
+ *
+ * @param value a Boolean value
+ * @return property wrapper around Boolean
+ */
+ public static PropertyValue<Expression> textKeepUpright(Expression value) {
+ return new LayoutPropertyValue<>("text-keep-upright", value);
+ }
/**
@@ -2259,6 +3227,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-transform", value);
}
+ /**
+ * Specifies how to capitalize text, similar to the CSS {@link PropertyFactory#textTransform} property.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static PropertyValue<Expression> textTransform(Expression value) {
+ return new LayoutPropertyValue<>("text-transform", value);
+ }
/**
@@ -2282,6 +3259,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-offset", value);
}
+ /**
+ * Offset distance of text from its anchor. Positive values indicate right and down, while negative values indicate left and up.
+ *
+ * @param value a Float[] value
+ * @return property wrapper around Float[]
+ */
+ public static PropertyValue<Expression> textOffset(Expression value) {
+ return new LayoutPropertyValue<>("text-offset", value);
+ }
/**
@@ -2305,6 +3291,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-allow-overlap", value);
}
+ /**
+ * If true, the text will be visible even if it collides with other previously drawn symbols.
+ *
+ * @param value a Boolean value
+ * @return property wrapper around Boolean
+ */
+ public static PropertyValue<Expression> textAllowOverlap(Expression value) {
+ return new LayoutPropertyValue<>("text-allow-overlap", value);
+ }
/**
@@ -2328,6 +3323,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-ignore-placement", value);
}
+ /**
+ * If true, other symbols can be visible even if they collide with the text.
+ *
+ * @param value a Boolean value
+ * @return property wrapper around Boolean
+ */
+ public static PropertyValue<Expression> textIgnorePlacement(Expression value) {
+ return new LayoutPropertyValue<>("text-ignore-placement", value);
+ }
/**
@@ -2351,7 +3355,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-optional", value);
}
-
+ /**
+ * If true, icons will display without their corresponding text when the text collides with other symbols and the icon does not.
+ *
+ * @param value a Boolean value
+ * @return property wrapper around Boolean
+ */
+ public static PropertyValue<Expression> textOptional(Expression value) {
+ return new LayoutPropertyValue<>("text-optional", value);
+ }
/**
* If true, icons will display without their corresponding text when the text collides with other symbols and the icon does not.
@@ -2364,9 +3376,9 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-optional", function);
}
- @SuppressLint("DefaultLocale")
public static String colorToRgbaString(@ColorInt int value) {
- return String.format("rgba(%d, %d, %d, %d)", (value >> 16) & 0xFF, (value >> 8) & 0xFF, value & 0xFF, (value >> 24) & 0xFF);
+ return String.format(Locale.US,"rgba(%d, %d, %d, %d)",
+ (value >> 16) & 0xFF, (value >> 8) & 0xFF, value & 0xFF, (value >> 24) & 0xFF);
}
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/RasterLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/RasterLayer.java
index e67e71b61d..0a056d8fac 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/RasterLayer.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/RasterLayer.java
@@ -2,14 +2,9 @@
package com.mapbox.mapboxsdk.style.layers;
-import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.UiThread;
-import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor;
-
-import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
-
/**
* Raster map textures such as satellite imagery.
*
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 d0fb82dce5..3d2c3881b2 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
@@ -8,8 +8,6 @@ import android.support.annotation.UiThread;
import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor;
-import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
-
/**
* An icon or a text label.
*
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/property_factory.java.ejs b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/property_factory.java.ejs
index 2d3421d1d9..ed138e557a 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/property_factory.java.ejs
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/property_factory.java.ejs
@@ -11,6 +11,7 @@ import android.support.annotation.ColorInt;
import com.mapbox.mapboxsdk.style.functions.Function;
import com.mapbox.mapboxsdk.style.functions.CameraFunction;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
/**
* Constructs paint/layout properties for Layers
@@ -36,6 +37,7 @@ public class PropertyFactory {
* @param function the visibility function
* @return property wrapper around a String function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, String>> visibility(Function<T, String> function) {
return new LayoutPropertyValue<>("visibility", function);
}
@@ -63,6 +65,16 @@ public class PropertyFactory {
return new PaintPropertyValue<>("<%- property.name %>", value);
}
+ /**
+ * <%- propertyFactoryMethodDoc(property) %>
+ *
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
+ */
+ public static PropertyValue<Expression> <%- camelizeWithLeadingLowercase(property.name) %>(Expression expression) {
+ return new PaintPropertyValue<>("<%- property.name %>", expression);
+ }
+
<% if (supportsPropertyFunction(property)) { -%>
/**
@@ -72,6 +84,7 @@ public class PropertyFactory {
* @param function a wrapper function for <%- propertyType(property) %>
* @return property wrapper around a <%- propertyType(property) %> function
*/
+ @Deprecated
public static <T> PropertyValue<Function<T, <%- propertyType(property) %>>> <%- camelizeWithLeadingLowercase(property.name) %>(Function<T, <%- propertyType(property) %>> function) {
return new PaintPropertyValue<>("<%- property.name %>", function);
}
@@ -85,6 +98,7 @@ public class PropertyFactory {
* @param function a wrapper {@link CameraFunction} for <%- propertyType(property) %>
* @return property wrapper around a <%- propertyType(property) %> function
*/
+ @Deprecated
public static <Z extends Number> PropertyValue<CameraFunction<Z, <%- propertyType(property) %>>> <%- camelizeWithLeadingLowercase(property.name) %>(CameraFunction<Z, <%- propertyType(property) %>> function) {
return new PaintPropertyValue<>("<%- property.name %>", function);
}
@@ -102,6 +116,15 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("<%- property.name %>", value);
}
+ /**
+ * <%- propertyFactoryMethodDoc(property) %>
+ *
+ * @param value a <%- propertyType(property) %> value
+ * @return property wrapper around <%- propertyType(property) %>
+ */
+ public static PropertyValue<Expression> <%- camelizeWithLeadingLowercase(property.name) %>(Expression value) {
+ return new LayoutPropertyValue<>("<%- property.name %>", value);
+ }
<% if (supportsPropertyFunction(property)) { -%>
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CustomGeometrySource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CustomGeometrySource.java
new file mode 100644
index 0000000000..62f1719ddf
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CustomGeometrySource.java
@@ -0,0 +1,203 @@
+package com.mapbox.mapboxsdk.style.sources;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.annotation.UiThread;
+import android.support.annotation.WorkerThread;
+
+import com.mapbox.mapboxsdk.geometry.LatLngBounds;
+import com.mapbox.mapboxsdk.style.layers.Filter;
+import com.mapbox.services.commons.geojson.Feature;
+import com.mapbox.services.commons.geojson.FeatureCollection;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Custom Vector Source, allows using FeatureCollections.
+ *
+ */
+@UiThread
+public class CustomGeometrySource extends Source {
+ private ExecutorService executor;
+ private GeometryTileProvider provider;
+ private final Map<TileID, AtomicBoolean> cancelledTileRequests = new ConcurrentHashMap<>();
+
+ /**
+ * Create a CustomGeometrySource
+ *
+ * @param id The source id.
+ * @param provider The tile provider that returns geometry data for this source.
+ */
+ public CustomGeometrySource(String id, GeometryTileProvider provider) {
+ this(id, provider, new GeoJsonOptions());
+ }
+
+ /**
+ * Create a CustomGeometrySource with non-default GeoJsonOptions.
+ * <p>Supported options are minZoom, maxZoom, buffer, and tolerance.</p>
+ *
+ * @param id The source id.
+ * @param provider The tile provider that returns geometry data for this source.
+ * @param options GeoJsonOptions.
+ */
+ public CustomGeometrySource(String id, GeometryTileProvider provider, GeoJsonOptions options) {
+ this.provider = provider;
+ executor = Executors.newFixedThreadPool(4);
+ initialize(id, options);
+ }
+
+ /**
+ * Invalidate previously provided features within a given bounds at all zoom levels.
+ * Invoking this method will result in new requests to `GeometryTileProvider` for regions
+ * that contain, include, or intersect with the provided bounds.
+ *
+ * @param bounds The region in which features should be invalidated at all zoom levels
+ */
+ public void invalidateRegion(LatLngBounds bounds) {
+ nativeInvalidateBounds(bounds);
+ }
+
+ /**
+ * Invalidate the geometry contents of a specific tile. Invoking this method will result
+ * in new requests to `GeometryTileProvider` for visible tiles.
+ *
+ * @param zoomLevel Tile zoom level.
+ * @param x Tile X coordinate.
+ * @param y Tile Y coordinate.
+ */
+ public void invalidateTile(int zoomLevel, int x, int y) {
+ nativeInvalidateTile(zoomLevel, x, y);
+ }
+
+ /**
+ * Set or update geometry contents of a specific tile. Use this method to update tiles
+ * for which `GeometryTileProvider` was previously invoked. This method can be called from
+ * background threads.
+ *
+ * @param zoomLevel Tile zoom level.
+ * @param x Tile X coordinate.
+ * @param y Tile Y coordinate.
+ * @param data Feature collection for the tile.
+ */
+ public void setTileData(int zoomLevel, int x, int y, FeatureCollection data) {
+ nativeSetTileData(zoomLevel, x, y, data);
+ }
+
+ /**
+ * Queries the source for features.
+ *
+ * @param filter an optional filter statement to filter the returned Features
+ * @return the features
+ */
+ @NonNull
+ public List<Feature> querySourceFeatures(@Nullable Filter.Statement filter) {
+ Feature[] features = querySourceFeatures(filter != null ? filter.toArray() : null);
+ return features != null ? Arrays.asList(features) : new ArrayList<Feature>();
+ }
+
+ protected native void initialize(String sourceId, Object options);
+
+ private native Feature[] querySourceFeatures(Object[] filter);
+
+ private native void nativeSetTileData(int z, int x, int y, FeatureCollection data);
+
+ private native void nativeInvalidateTile(int z, int x, int y);
+
+ private native void nativeInvalidateBounds(LatLngBounds bounds);
+
+ @Override
+ protected native void finalize() throws Throwable;
+
+ private void setTileData(TileID tileId, FeatureCollection data) {
+ cancelledTileRequests.remove(tileId);
+ nativeSetTileData(tileId.z, tileId.x, tileId.y, data);
+ }
+
+ @WorkerThread
+ private void fetchTile(int z, int x, int y) {
+ AtomicBoolean cancelFlag = new AtomicBoolean(false);
+ TileID tileID = new TileID(z, x, y);
+ cancelledTileRequests.put(tileID, cancelFlag);
+ GeometryTileRequest request = new GeometryTileRequest(tileID, provider, this, cancelFlag);
+ executor.execute(request);
+ }
+
+ @WorkerThread
+ private void cancelTile(int z, int x, int y) {
+ AtomicBoolean cancelFlag = cancelledTileRequests.get(new TileID(z, x, y));
+ if (cancelFlag != null) {
+ cancelFlag.compareAndSet(false, true);
+ }
+ }
+
+ private static class TileID {
+ public int z;
+ public int x;
+ public int y;
+
+ public TileID(int _z, int _x, int _y) {
+ z = _z;
+ x = _x;
+ y = _y;
+ }
+
+ public int hashCode() {
+ return Arrays.hashCode(new int[]{z, x, y});
+ }
+
+ public boolean equals(Object object) {
+ if (object == this) {
+ return true;
+ }
+
+ if (object == null || getClass() != object.getClass()) {
+ return false;
+ }
+
+ if (object instanceof TileID) {
+ TileID other = (TileID)object;
+ return this.z == other.z && this.x == other.x && this.y == other.y;
+ }
+ return false;
+ }
+ }
+
+ private static class GeometryTileRequest implements Runnable {
+ private TileID id;
+ private GeometryTileProvider provider;
+ private WeakReference<CustomGeometrySource> sourceRef;
+ private AtomicBoolean cancelled;
+
+ public GeometryTileRequest(TileID _id, GeometryTileProvider p,
+ CustomGeometrySource _source, AtomicBoolean _cancelled) {
+ id = _id;
+ provider = p;
+ sourceRef = new WeakReference<>(_source);
+ cancelled = _cancelled;
+ }
+
+ public void run() {
+ if (isCancelled()) {
+ return;
+ }
+
+ FeatureCollection data = provider.getFeaturesForBounds(LatLngBounds.from(id.z, id.x, id.y), id.z);
+ CustomGeometrySource source = sourceRef.get();
+ if (!isCancelled() && source != null && data != null) {
+ source.setTileData(id, data);
+ }
+ }
+
+ private Boolean isCancelled() {
+ return cancelled.get();
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonOptions.java
index 1a1711e547..81f7255b86 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonOptions.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonOptions.java
@@ -16,6 +16,17 @@ public class GeoJsonOptions extends HashMap<String, Object> {
* @param maxZoom the maximum zoom - Defaults to 18.
* @return the current instance for chaining
*/
+ public GeoJsonOptions withMinZoom(int minZoom) {
+ this.put("minzoom", minZoom);
+ return this;
+ }
+
+ /**
+ * Maximum zoom level at which to create vector tiles (higher means greater detail at high zoom levels).
+ *
+ * @param maxZoom the maximum zoom - Defaults to 18.
+ * @return the current instance for chaining
+ */
public GeoJsonOptions withMaxZoom(int maxZoom) {
this.put("maxzoom", maxZoom);
return this;
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeometryTileProvider.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeometryTileProvider.java
new file mode 100644
index 0000000000..3f1eb315d3
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeometryTileProvider.java
@@ -0,0 +1,22 @@
+package com.mapbox.mapboxsdk.style.sources;
+
+import android.support.annotation.WorkerThread;
+
+import com.mapbox.mapboxsdk.geometry.LatLngBounds;
+import com.mapbox.services.commons.geojson.FeatureCollection;
+
+/**
+ * Interface that defines methods for working with {@link CustomGeometrySource}.
+ */
+public interface GeometryTileProvider {
+
+ /***
+ * Interface method called by {@link CustomGeometrySource} to request features for a tile.
+ *
+ * @param bounds {@link LatLngBounds} of the tile.
+ * @param zoomLevel Tile zoom level.
+ * @return Return a @{link FeatureCollection} to be displayed in the requested tile.
+ */
+ @WorkerThread
+ FeatureCollection getFeaturesForBounds(LatLngBounds bounds, int zoomLevel);
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/BitmapUtils.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/BitmapUtils.java
index 765ca431dd..78503f9dfe 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/BitmapUtils.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/BitmapUtils.java
@@ -54,13 +54,25 @@ public class BitmapUtils {
/**
* Extract an underlying bitmap from a drawable
- * @param drawable The source drawable
+ *
+ * @param sourceDrawable The source drawable
* @return The underlying bitmap
*/
- public static Bitmap getBitmapFromDrawable(Drawable drawable) {
- if (drawable instanceof BitmapDrawable) {
- return ((BitmapDrawable) drawable).getBitmap();
+ public static Bitmap getBitmapFromDrawable(Drawable sourceDrawable) {
+ if (sourceDrawable == null) {
+ return null;
+ }
+
+ if (sourceDrawable instanceof BitmapDrawable) {
+ return ((BitmapDrawable) sourceDrawable).getBitmap();
} else {
+ //copying drawable object to not manipulate on the same reference
+ Drawable.ConstantState constantState = sourceDrawable.getConstantState();
+ if (constantState == null) {
+ return null;
+ }
+ Drawable drawable = constantState.newDrawable().mutate();
+
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
@@ -72,6 +84,7 @@ public class BitmapUtils {
/**
* Create a byte array out of drawable
+ *
* @param drawable The source drawable
* @return The byte array of source drawable
*/
@@ -79,7 +92,11 @@ public class BitmapUtils {
if (drawable == null) {
return null;
}
+
Bitmap bitmap = getBitmapFromDrawable(drawable);
+ if (bitmap == null) {
+ return null;
+ }
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
return stream.toByteArray();
@@ -87,8 +104,9 @@ public class BitmapUtils {
/**
* Decode byte array to drawable object
+ *
* @param context Context to obtain {@link android.content.res.Resources}
- * @param array The source byte array
+ * @param array The source byte array
* @return The drawable created from source byte array
*/
public static Drawable getDrawableFromByteArray(Context context, byte[] array) {
diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java
index bb96c9939d..c3d13f0c66 100644
--- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java
+++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java
@@ -2,6 +2,7 @@ package com.mapbox.mapboxsdk.geometry;
import android.os.Parcelable;
+import com.mapbox.mapboxsdk.constants.GeometryConstants;
import com.mapbox.mapboxsdk.exceptions.InvalidLatLngBoundsException;
import com.mapbox.mapboxsdk.utils.MockParcel;
@@ -272,4 +273,20 @@ public class LatLngBoundsTest {
Parcelable parcel = MockParcel.obtain(latLngBounds);
assertEquals("Parcel should match original object", parcel, latLngBounds);
}
+
+ @Test
+ public void fromTileID() {
+ LatLngBounds bounds = LatLngBounds.from(0, 0, 0);
+ assertEquals(GeometryConstants.MIN_LONGITUDE, bounds.getLonWest(), DELTA);
+ assertEquals(GeometryConstants.MIN_MERCATOR_LATITUDE, bounds.getLatSouth(), DELTA);
+ assertEquals(GeometryConstants.MAX_LONGITUDE, bounds.getLonEast(), DELTA);
+ assertEquals(GeometryConstants.MAX_MERCATOR_LATITUDE, bounds.getLatNorth(), DELTA);
+
+ bounds = LatLngBounds.from(10, 288, 385);
+ assertEquals(-78.75, bounds.getLonWest(), DELTA);
+ assertEquals(40.446947059600497, bounds.getLatSouth(), DELTA);
+ assertEquals(-78.3984375, bounds.getLonEast(), DELTA);
+ assertEquals(40.713955826286039, bounds.getLatNorth(), DELTA);
+
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java
index 06e93b9d2f..8e47f069c3 100644
--- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java
+++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java
@@ -12,6 +12,7 @@ import org.junit.rules.ExpectedException;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -255,8 +256,17 @@ public class LatLngTest {
@Test
public void testWrapped() {
- LatLng latLng = new LatLng(45.0, -185.0).wrap();
- assertEquals("longitude wrapped value", latLng.getLongitude(), 175.0, DELTA);
+ LatLng originalLatLng = new LatLng(45.0, -185.0);
+ LatLng newLatlng = originalLatLng.wrap();
+ assertNotSame(" new wrapped LatLng is created", originalLatLng, newLatlng);
+ assertEquals("longitude wrapped value", originalLatLng.getLongitude(), -185.0, DELTA);
+ assertEquals("longitude wrapped value", newLatlng.getLongitude(), 175.0, DELTA);
+
+ newLatlng = new LatLng(45.0, 180.0).wrap();
+ assertEquals("longitude wrapped max value", newLatlng.getLongitude(), 180.0, DELTA);
+
+ newLatlng = new LatLng(45.0, -180.0).wrap();
+ assertEquals("longitude wrapped min value", newLatlng.getLongitude(), -180.0, DELTA);
}
@Test
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
new file mode 100644
index 0000000000..eb1ce8bfaa
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/style/expressions/ExpressionTest.java
@@ -0,0 +1,1010 @@
+package com.mapbox.mapboxsdk.style.expressions;
+
+import android.graphics.Color;
+
+import com.mapbox.mapboxsdk.style.layers.PropertyFactory;
+
+import org.junit.Test;
+
+import java.util.Arrays;
+
+import static com.mapbox.mapboxsdk.style.expressions.Expression.acos;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.all;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.any;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.array;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.asin;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.at;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.atan;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.bool;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.coalesce;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.color;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.concat;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.cos;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.cubicBezier;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.division;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.downcase;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.e;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.eq;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.exponential;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.geometryType;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.gt;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.gte;
+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.length;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.let;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.linear;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.literal;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.ln;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.ln2;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.log10;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.log2;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.lt;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.lte;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.match;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.max;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.min;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.mod;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.neq;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.not;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.number;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.object;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.pi;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.pow;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.product;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.properties;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.rgb;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.rgba;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.sin;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.sqrt;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.step;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.stop;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.string;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.subtract;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.sum;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.switchCase;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.tan;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.toBool;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.toColor;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.toNumber;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.toRgba;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.typeOf;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.upcase;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.var;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.zoom;
+import static junit.framework.Assert.assertTrue;
+
+/**
+ * Expression unit tests that validate the expression output with the expected Object[]array representation.
+ */
+public class ExpressionTest {
+
+ @Test
+ public void testRgb() throws Exception {
+ Object[] expected = new Object[] {"rgb", 0, 0, 0};
+ Object[] actual = rgb(literal(0), literal(0), literal(0)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testRgbLiteral() throws Exception {
+ Object[] expected = new Object[] {"rgb", 0, 0, 0};
+ Object[] actual = rgb(0, 0, 0).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testRgba() throws Exception {
+ Object[] expected = new Object[] {"rgba", 0, 0, 0, 1};
+ Object[] actual = rgba(literal(0), literal(0), literal(0), literal(1)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testRgbaLiteral() throws Exception {
+ Object[] expected = new Object[] {"rgba", 0, 0, 0, 1};
+ Object[] actual = rgba(0, 0, 0, 1).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testToRgba() throws Exception {
+ Object[] expected = new Object[] {"to-rgba", PropertyFactory.colorToRgbaString(Color.RED)};
+ Object[] actual = toRgba(color(Color.RED)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testEq() throws Exception {
+ Object[] expected = new Object[] {"==", 1, 1};
+ Object[] actual = eq(literal(1), literal(1)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testEqLiteral() throws Exception {
+ Object[] expected = new Object[] {"==", 1, 1};
+ Object[] actual = eq(1, 1).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testNeq() throws Exception {
+ Object[] expected = new Object[] {"!=", 0, 1};
+ Object[] actual = neq(literal(0), literal(1)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testNeqLiteral() throws Exception {
+ Object[] expected = new Object[] {"!=", 0, 1};
+ Object[] actual = neq(0, 1).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testGt() throws Exception {
+ Object[] expected = new Object[] {">", 0, 1};
+ Object[] actual = gt(literal(0), literal(1)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testGtLiteral() throws Exception {
+ Object[] expected = new Object[] {">", 0, 1};
+ Object[] actual = gt(0, 1).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testLt() throws Exception {
+ Object[] expected = new Object[] {"<", 1, 0};
+ Object[] actual = lt(literal(1), literal(0)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testLtLiteral() throws Exception {
+ Object[] expected = new Object[] {"<", 1, 0};
+ Object[] actual = lt(1, 0).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testGte() throws Exception {
+ Object[] expected = new Object[] {">=", 1, 1};
+ Object[] actual = gte(literal(1), literal(1)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testGteLiteral() throws Exception {
+ Object[] expected = new Object[] {">=", 1, 1};
+ Object[] actual = gte(1, 1).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testLte() throws Exception {
+ Object[] expected = new Object[] {"<=", 1, 1};
+ Object[] actual = lte(literal(1), literal(1)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testLteLiteral() throws Exception {
+ Object[] expected = new Object[] {"<=", 1, 1};
+ Object[] actual = lte(1, 1).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testAll() throws Exception {
+ Object[] expected = new Object[] {"all", true, true, true};
+ Object[] actual = all(literal(true), literal(true), literal(true)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testAny() throws Exception {
+ Object[] expected = new Object[] {"any", true, false, false};
+ Object[] actual = any(literal(true), literal(false), literal(false)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testNot() throws Exception {
+ Object[] expected = new Object[] {"!", false};
+ Object[] actual = not(literal(false)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testNotLiteral() throws Exception {
+ Object[] expected = new Object[] {"!", false};
+ Object[] actual = not(false).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testSwitchCase() throws Exception {
+ Object[] expectedCaseOneGet = new Object[] {"get", "key1"};
+ Object[] expectedCaseOne = new Object[] {"==", expectedCaseOneGet, "value1"};
+ Object[] expectedCaseTwoGet = new Object[] {"get", "key2"};
+ Object[] expectedCaseTwo = new Object[] {"!=", expectedCaseTwoGet, "value2"};
+ Object[] expected = new Object[] {"case", expectedCaseOne, expectedCaseTwo};
+
+ Object[] actual = switchCase(
+ eq(get(literal("key1")), literal("value1")),
+ neq(get(literal("key2")), literal("value2"))
+ ).toArray();
+
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testSwitchCaseLiteral() throws Exception {
+ Object[] expectedCaseOneGet = new Object[] {"get", "key1"};
+ Object[] expectedCaseOne = new Object[] {"==", expectedCaseOneGet, "value1"};
+ Object[] expectedCaseTwoGet = new Object[] {"get", "key2"};
+ Object[] expectedCaseTwo = new Object[] {"!=", expectedCaseTwoGet, "value2"};
+ Object[] expected = new Object[] {"case", expectedCaseOne, expectedCaseTwo};
+
+ Object[] actual = switchCase(
+ eq(get("key1"), literal("value1")),
+ neq(get("key2"), literal("value2"))
+ ).toArray();
+
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testMatch() throws Exception {
+ Object[] labelZero = new Object[] {"a", "output"};
+ Object[] labelOne = new Object[] {"b", "output2"};
+ Object[] labelTwo = new Object[] {"c", "output3"};
+
+ Object[] expected = new Object[] {"match", labelZero, labelOne, labelTwo};
+ Object[] actual = match(literal(labelZero), literal(labelOne), literal(labelTwo)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testCoalesce() throws Exception {
+ Object[] expectedGetOne = new Object[] {"get", "invalidKey"};
+ Object[] expectedGetTwo = new Object[] {"get", "validKey"};
+ Object[] expected = new Object[] {"coalesce", expectedGetOne, expectedGetTwo};
+
+ Object[] actual = coalesce(
+ get(literal("invalidKey")),
+ get(literal("validKey"))
+ ).toArray();
+
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testCoalesceLiteral() throws Exception {
+ Object[] expectedGetOne = new Object[] {"get", "invalidKey"};
+ Object[] expectedGetTwo = new Object[] {"get", "validKey"};
+ Object[] expected = new Object[] {"coalesce", expectedGetOne, expectedGetTwo};
+
+ Object[] actual = coalesce(
+ get("invalidKey"),
+ get("validKey")
+ ).toArray();
+
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testProperties() throws Exception {
+ Object[] expected = new Object[] {"properties"};
+ Object[] actual = properties().toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testGeometryType() throws Exception {
+ Object[] expected = new Object[] {"geometry-type"};
+ Object[] actual = geometryType().toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testId() throws Exception {
+ Object[] expected = new Object[] {"id"};
+ Object[] actual = id().toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testHeatmapDensity() throws Exception {
+ Object[] expected = new Object[] {"heatmap-density"};
+ Object[] actual = heatmapDensity().toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testAt() throws Exception {
+ Object[] expected = new Object[] {"at", 3, new Object[] {"one", "two"}};
+ Object[] actual = at(literal(3), literal(new Object[] {"one", "two"})).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testAtLiteral() throws Exception {
+ Object[] expected = new Object[] {"at", 3, new Object[] {"one", "two"}};
+ Object[] actual = at(3, literal(new Object[] {"one", "two"})).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testAtExpression() throws Exception {
+ Object[] expected = new Object[] {"at", 3, new Object[] {"properties"}};
+ Object[] actual = at(literal(3), properties()).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testGet() throws Exception {
+ Object[] expected = new Object[] {"get", "key"};
+ Object[] actual = get(literal("key")).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testGetLiteral() throws Exception {
+ Object[] expected = new Object[] {"get", "key"};
+ Object[] actual = get("key").toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testGetObject() throws Exception {
+ Object[] expected = new Object[] {"get", "key", new Object[] {"properties"}};
+ Object[] actual = get(literal("key"), properties()).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testGetObjectLiteral() throws Exception {
+ Object[] expected = new Object[] {"get", "key", new Object[] {"properties"}};
+ Object[] actual = get("key", properties()).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testHas() throws Exception {
+ Object[] expected = new Object[] {"has", "key"};
+ Object[] actual = has(literal("key")).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testHasLiteral() throws Exception {
+ Object[] expected = new Object[] {"has", "key"};
+ Object[] actual = has("key").toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testHasObject() throws Exception {
+ Object[] expected = new Object[] {"has", "key", new Object[] {"properties"}};
+ Object[] actual = has(literal("key"), properties()).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testHasObjectLiteral() throws Exception {
+ Object[] expected = new Object[] {"has", "key", new Object[] {"properties"}};
+ Object[] actual = has("key", properties()).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testHasExpression() throws Exception {
+ Object[] expected = new Object[] {"has", new Object[] {"get", "key"}, new Object[] {"properties"}};
+ Object[] actual = has(get(literal("key")), properties()).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testHasExpressionLiteral() throws Exception {
+ Object[] expected = new Object[] {"has", new Object[] {"get", "key"}, new Object[] {"properties"}};
+ Object[] actual = has(get("key"), properties()).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testLength() throws Exception {
+ Object[] expected = new Object[] {"length", "key"};
+ Object[] actual = length(literal("key")).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testLengthLiteral() throws Exception {
+ Object[] expected = new Object[] {"length", "key"};
+ Object[] actual = length("key").toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testLengthExpression() throws Exception {
+ Object[] expected = new Object[] {"length", new Object[] {"get", "key"}};
+ Object[] actual = length(get(literal("key"))).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testLn2() throws Exception {
+ Object[] expected = new Object[] {"ln2"};
+ Object[] actual = ln2().toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testPi() throws Exception {
+ Object[] expected = new Object[] {"pi"};
+ Object[] actual = pi().toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testE() throws Exception {
+ Object[] expected = new Object[] {"e"};
+ Object[] actual = e().toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testSum() throws Exception {
+ Object[] expected = new Object[] {"+", 1, 2};
+ Object[] actual = sum(literal(1), literal(2)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testSumLiteral() throws Exception {
+ Object[] expected = new Object[] {"+", 1, 2};
+ Object[] actual = sum(1, 2).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testProduct() throws Exception {
+ Object[] expected = new Object[] {"*", 1, 2};
+ Object[] actual = product(literal(1), literal(2)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testProductLiteral() throws Exception {
+ Object[] expected = new Object[] {"*", 1, 2};
+ Object[] actual = product(1, 2).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testSubtract() throws Exception {
+ Object[] expected = new Object[] {"-", 2, 1};
+ Object[] actual = subtract(literal(2), literal(1)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testSubtractLiteral() throws Exception {
+ Object[] expected = new Object[] {"-", 2, 1};
+ Object[] actual = subtract(2, 1).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testDivision() throws Exception {
+ Object[] expected = new Object[] {"/", 2, 1};
+ Object[] actual = division(literal(2), literal(1)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testDivisionLiteral() throws Exception {
+ Object[] expected = new Object[] {"/", 2, 1};
+ Object[] actual = division(2, 1).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testDivisionWithNestedGet() throws Exception {
+ Object nestedGet = new Object[] {"get", "key"};
+ Object[] expected = new Object[] {"/", 2, nestedGet};
+ Object[] actual = division(literal(2), get(literal("key"))).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testMod() throws Exception {
+ Object[] expected = new Object[] {"%", 1, 3};
+ Object[] actual = mod(literal(1), literal(3)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testModLiteral() throws Exception {
+ Object[] expected = new Object[] {"%", 1, 3};
+ Object[] actual = mod(1, 3).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testPow() throws Exception {
+ Object[] expected = new Object[] {"^", 2, 3};
+ Object[] actual = pow(literal(2), literal(3)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testPowLiteral() throws Exception {
+ Object[] expected = new Object[] {"^", 2, 3};
+ Object[] actual = pow(2, 3).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testSqrt() throws Exception {
+ Object[] expected = new Object[] {"sqrt", 4};
+ Object[] actual = sqrt(literal(4)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testSqrtLiteral() throws Exception {
+ Object[] expected = new Object[] {"sqrt", 4};
+ Object[] actual = sqrt(4).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testLog10() throws Exception {
+ Object[] expected = new Object[] {"log10", 10};
+ Object[] actual = log10(literal(10)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testLog10Literal() throws Exception {
+ Object[] expected = new Object[] {"log10", 10};
+ Object[] actual = log10(10).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testLn() throws Exception {
+ Object[] expected = new Object[] {"ln", 2};
+ Object[] actual = ln(literal(2)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testLnLiteral() throws Exception {
+ Object[] expected = new Object[] {"ln", 2};
+ Object[] actual = ln(2).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testLog2() throws Exception {
+ Object[] expected = new Object[] {"log2", 16};
+ Object[] actual = log2(literal(16)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testLog2Literal() throws Exception {
+ Object[] expected = new Object[] {"log2", 16};
+ Object[] actual = log2(16).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testSin() throws Exception {
+ Object[] expected = new Object[] {"sin", 45};
+ Object[] actual = sin(literal(45)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testSinLiteral() throws Exception {
+ Object[] expected = new Object[] {"sin", 45};
+ Object[] actual = sin(45).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testCos() throws Exception {
+ Object[] expected = new Object[] {"cos", 45};
+ Object[] actual = cos(literal(45)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testCosLiteral() throws Exception {
+ Object[] expected = new Object[] {"cos", 45};
+ Object[] actual = cos(45).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testTan() throws Exception {
+ Object[] expected = new Object[] {"tan", 45};
+ Object[] actual = tan(literal(45)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testTanLiteral() throws Exception {
+ Object[] expected = new Object[] {"tan", 45};
+ Object[] actual = tan(45).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testAsin() throws Exception {
+ Object[] expected = new Object[] {"asin", 45};
+ Object[] actual = asin(literal(45)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testAsinLiteral() throws Exception {
+ Object[] expected = new Object[] {"asin", 45};
+ Object[] actual = asin(45).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testAcos() throws Exception {
+ Object[] expected = new Object[] {"acos", 45};
+ Object[] actual = acos(literal(45)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testAcosLiteral() throws Exception {
+ Object[] expected = new Object[] {"acos", 45};
+ Object[] actual = acos(45).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testAtan() throws Exception {
+ Object[] expected = new Object[] {"atan", 45};
+ Object[] actual = atan(literal(45)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testAtanLiteral() throws Exception {
+ Object[] expected = new Object[] {"atan", 45};
+ Object[] actual = atan(45).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testMin() throws Exception {
+ Object[] expected = new Object[] {"min", 0, 1, 2, 3};
+ Object[] actual = min(literal(0), literal(1), literal(2), literal(3)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testMinLiteral() throws Exception {
+ Object[] expected = new Object[] {"min", 0, 1, 2, 3};
+ Object[] actual = min(0, 1, 2, 3).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testMax() throws Exception {
+ Object[] expected = new Object[] {"max", 0, 1, 2, 3};
+ Object[] actual = max(literal(0), literal(1), literal(2), literal(3)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testMaxLiteral() throws Exception {
+ Object[] expected = new Object[] {"max", 0, 1, 2, 3};
+ Object[] actual = max(0, 1, 2, 3).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testUpcase() throws Exception {
+ Object[] expected = new Object[] {"upcase", "string"};
+ Object[] actual = upcase(literal("string")).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testUpcaseLiteral() throws Exception {
+ Object[] expected = new Object[] {"upcase", "string"};
+ Object[] actual = upcase("string").toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testDowncase() throws Exception {
+ Object[] expected = new Object[] {"downcase", "string"};
+ Object[] actual = downcase(literal("string")).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testDowncaseLiteral() throws Exception {
+ Object[] expected = new Object[] {"downcase", "string"};
+ Object[] actual = downcase("string").toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testConcat() throws Exception {
+ Object[] expected = new Object[] {"concat", "foo", "bar"};
+ Object[] actual = concat(literal("foo"), literal("bar")).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testConcatLiteral() throws Exception {
+ Object[] expected = new Object[] {"concat", "foo", "bar"};
+ Object[] actual = concat("foo", "bar").toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testArray() throws Exception {
+ Object[] get = new Object[] {"get", "keyToArray"};
+ Object[] expected = new Object[] {"array", get};
+ Object[] actual = array(get(literal("keyToArray"))).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testArrayLiteral() throws Exception {
+ Object[] get = new Object[] {"get", "keyToArray"};
+ Object[] expected = new Object[] {"array", get};
+ Object[] actual = array(get("keyToArray")).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testTypeOf() throws Exception {
+ Object[] expected = new Object[] {"typeof", "value"};
+ Object[] actual = typeOf(literal("value")).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testString() throws Exception {
+ Object[] expected = new Object[] {"string", "value"};
+ Object[] actual = string(literal("value")).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testNumber() throws Exception {
+ Object[] expected = new Object[] {"number", 1};
+ Object[] actual = number(literal(1)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testBool() throws Exception {
+ Object[] expected = new Object[] {"boolean", true};
+ Object[] actual = bool(literal(true)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testObject() throws Exception {
+ Object object = new Object();
+ Object[] expected = new Object[] {"object", object};
+ Object[] actual = object(literal(object)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testToString() throws Exception {
+ Object[] expected = new Object[] {"to-string", 3};
+ Object[] actual = Expression.toString(literal(3)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testToNumber() throws Exception {
+ Object[] expected = new Object[] {"to-number", "3"};
+ Object[] actual = toNumber(literal("3")).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testToBool() throws Exception {
+ Object[] expected = new Object[] {"to-boolean", "true"};
+ Object[] actual = toBool(literal("true")).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testToColor() throws Exception {
+ Object[] expected = new Object[] {"to-color", "value"};
+ Object[] actual = toColor(literal("value")).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testLet() throws Exception {
+ Object[] expected = new Object[] {"let", "letName", "value"};
+ Object[] actual = let(literal("letName"), literal("value")).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testVar() throws Exception {
+ Object[] expected = new Object[] {"var", "letName"};
+ Object[] actual = var(literal("letName")).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testVarLiteral() throws Exception {
+ Object[] expected = new Object[] {"var", "letName"};
+ Object[] actual = var("letName").toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testVarExpression() throws Exception {
+ Object[] expected = new Object[] {"var", new Object[] {"get", "letName"}};
+ Object[] actual = var(get(literal("letName"))).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testVarExpressionLiteral() throws Exception {
+ Object[] expected = new Object[] {"var", new Object[] {"get", "letName"}};
+ Object[] actual = var(get("letName")).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testZoom() throws Exception {
+ Object[] expected = new Object[] {"zoom"};
+ Object[] actual = zoom().toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testStepBasic() throws Exception {
+ Object[] expected = new Object[] {"step", 12, 11, 0, 111, 1, 1111};
+ Object[] actual = step(literal(12), literal(11), literal(0), literal(111), literal(1), literal(1111)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testStepBasicLiteral() throws Exception {
+ Object[] expected = new Object[] {"step", new Object[] {"get", "line-width"}, 11, 0, 111, 1, 1111};
+ Object[] actual = step(get("line-width"), literal(11), stop(0, 111), stop(1, 1111)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testStepExpression() throws Exception {
+ Object[] input = new Object[] {"get", "key"};
+ Object[] number = new Object[] {"to-number", input};
+ Object[] expected = new Object[] {"step", number, 11, 0, 111, 1, 1111};
+ Object[] actual = step(toNumber(get(literal("key"))),
+ literal(11), literal(0), literal(111), literal(1), literal(1111)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testStepExpressionLiteral() throws Exception {
+ Object[] input = new Object[] {"get", "key"};
+ Object[] number = new Object[] {"to-number", input};
+ Object[] expected = new Object[] {"step", number, 11, 0, 111, 1, 1111};
+ Object[] actual = step(toNumber(get("key")), literal(11), stop(0, 111), stop(1, 1111)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testLinear() throws Exception {
+ Object[] stopZero = new Object[] {0, 1};
+ Object[] stopOne = new Object[] {1, 2};
+ Object[] stopTwo = new Object[] {2, 3};
+ Object[] expected = new Object[] {"interpolate", new Object[] {"linear"}, 12, stopZero, stopOne, stopTwo};
+ Object[] actual = interpolate(linear(), literal(12),
+ literal(stopZero), literal(stopOne), literal(stopTwo)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testLinearStops() throws Exception {
+ Object[] expected = new Object[] {"interpolate", new Object[] {"linear"}, 12, 0, 1, 1, 2, 2, 3};
+ Object[] actual = interpolate(linear(), literal(12), stop(0, 1), stop(1, 2), stop(2, 3)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testExponential() throws Exception {
+ Object[] exponential = new Object[] {"exponential", 12};
+ Object[] get = new Object[] {"get", "x"};
+ Object[] expected = new Object[] {"interpolate", exponential, get, 0, 100, 200};
+ Object[] actual = interpolate(exponential(literal(12)),
+ get(literal("x")), literal(0), literal(100), literal(200)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testExponentialLiteral() throws Exception {
+ Object[] exponential = new Object[] {"exponential", 12};
+ Object[] get = new Object[] {"get", "x"};
+ Object[] expected = new Object[] {"interpolate", exponential, get, 0, 100, 100, 200};
+ Object[] actual = interpolate(exponential(12), get("x"), stop(0, 100), stop(100, 200)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testExponentialExpressionLiteral() throws Exception {
+ Object[] getX = new Object[] {"get", "x"};
+ Object[] exponential = new Object[] {"exponential", getX};
+ Object[] getY = new Object[] {"get", "y"};
+ Object[] expected = new Object[] {"interpolate", exponential, getY, 0, 100, 100, 200};
+ Object[] actual = interpolate(exponential(get("x")), get("y"), stop(0, 100), stop(100, 200)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testCubicBezier() throws Exception {
+ Object[] cubicBezier = new Object[] {"cubic-bezier", 1, 1, 1, 1};
+ Object[] get = new Object[] {"get", "x"};
+ Object[] expected = new Object[] {"interpolate", cubicBezier, get, 0, 100, 100, 200};
+ Object[] actual = interpolate(cubicBezier(literal(1), literal(1), literal(1), literal(1)),
+ get(literal("x")), literal(0), literal(100), literal(100), literal(200)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testCubicBezierLiteral() throws Exception {
+ Object[] cubicBezier = new Object[] {"cubic-bezier", 1, 1, 1, 1};
+ Object[] get = new Object[] {"get", "x"};
+ Object[] expected = new Object[] {"interpolate", cubicBezier, get, 0, 100, 100, 200};
+ Object[] actual = interpolate(cubicBezier(1, 1, 1, 1), get("x"), stop(0, 100), stop(100, 200)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testCubicBezierExpression() throws Exception {
+ Object[] getX = new Object[] {"get", "x"};
+ Object[] getY = new Object[] {"get", "y"};
+ Object[] getZ = new Object[] {"get", "z"};
+ Object[] cubicBezier = new Object[] {"cubic-bezier", getZ, 1, getY, 1};
+ Object[] expected = new Object[] {"interpolate", cubicBezier, getX, 0, 100, 200};
+ Object[] actual = interpolate(cubicBezier(get(literal("z")), literal(1),
+ get(literal("y")), literal(1)), get(literal("x")), literal(0), literal(100), literal(200)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testCubicBezierExpressionLiteral() throws Exception {
+ Object[] getX = new Object[] {"get", "x"};
+ Object[] getY = new Object[] {"get", "y"};
+ Object[] getZ = new Object[] {"get", "z"};
+ Object[] cubicBezier = new Object[] {"cubic-bezier", getZ, 1, getY, 1};
+ Object[] expected = new Object[] {"interpolate", cubicBezier, getX, 0, 100, 100, 200};
+ Object[] actual = interpolate(cubicBezier(get("z"), literal(1), get("y"),
+ literal(1)), get("x"), stop(0, 100), stop(100, 200)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/build.gradle b/platform/android/MapboxGLAndroidSDKTestApp/build.gradle
index f45ad3dc3a..765b346669 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/build.gradle
+++ b/platform/android/MapboxGLAndroidSDKTestApp/build.gradle
@@ -14,8 +14,8 @@ android {
}
compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_7
- targetCompatibility JavaVersion.VERSION_1_7
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
}
packagingOptions {
@@ -28,7 +28,7 @@ android {
baseline file("lint-baseline-local.xml")
checkAllWarnings true
warningsAsErrors true
- disable 'MissingTranslation', 'GoogleAppIndexingWarning', 'UnpackedNativeCode', 'IconDipSize', 'TypographyQuotes'
+ disable 'MissingTranslation', 'GoogleAppIndexingWarning', 'UnpackedNativeCode', 'IconDipSize', 'TypographyQuotes'
abortOnError false
}
@@ -52,31 +52,32 @@ android {
}
dependencies {
- compile(project(':MapboxGLAndroidSDK')) {
- transitive = true
- }
+ implementation(project(':MapboxGLAndroidSDK'))
// Support libraries
- compile rootProject.ext.dep.supportAppcompatV7
- compile rootProject.ext.dep.supportRecyclerView
- compile rootProject.ext.dep.supportDesign
+ implementation rootProject.ext.dep.supportAppcompatV7
+ implementation rootProject.ext.dep.supportRecyclerView
+ implementation rootProject.ext.dep.supportDesign
// Leak Canary
- debugCompile rootProject.ext.dep.leakCanaryDebug
- releaseCompile rootProject.ext.dep.leakCanaryRelease
+ debugImplementation rootProject.ext.dep.leakCanaryDebug
+ releaseImplementation rootProject.ext.dep.leakCanaryRelease
+
+ // Timber
+ implementation rootProject.ext.dep.timber
// Mapbox Android Services (Java component)
- compile(rootProject.ext.dep.mapboxJavaServices) {
+ implementation(rootProject.ext.dep.mapboxJavaServices) {
transitive = true
}
- compile rootProject.ext.dep.lost
+ implementation rootProject.ext.dep.lost
// Testing dependencies
- androidTestCompile rootProject.ext.dep.supportAnnotations
- androidTestCompile rootProject.ext.dep.testRunner
- androidTestCompile rootProject.ext.dep.testRules
- androidTestCompile rootProject.ext.dep.testEspressoCore
- androidTestCompile rootProject.ext.dep.testEspressoIntents
+ androidTestImplementation rootProject.ext.dep.supportAnnotations
+ androidTestImplementation rootProject.ext.dep.testRunner
+ androidTestImplementation rootProject.ext.dep.testRules
+ androidTestImplementation rootProject.ext.dep.testEspressoCore
+ androidTestImplementation rootProject.ext.dep.testEspressoIntents
}
apply from: 'gradle-make.gradle'
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java
index 3dbbaceb1a..b4bc118129 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java
@@ -1,8 +1,6 @@
package com.mapbox.mapboxsdk.maps;
import android.graphics.Color;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
import android.support.test.espresso.UiController;
import android.support.test.espresso.ViewAction;
import android.view.View;
@@ -70,26 +68,24 @@ public class MapboxMapTest extends BaseActivityTest {
@Test
public void testTransitionDuration() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- long transitionDuration = 600;
- mapboxMap.setTransitionDuration(transitionDuration);
- assertEquals("TransitionDuration should match", transitionDuration, mapboxMap.getTransitionDuration(), 0);
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ long transitionDuration = 600;
+ mapboxMap.setTransitionDuration(transitionDuration);
+ assertEquals(
+ "TransitionDuration should match", transitionDuration, mapboxMap.getTransitionDuration(), 0
+ );
}));
}
@Test
public void testTransitionDelay() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- long transitionDelay = 50;
- mapboxMap.setTransitionDelay(transitionDelay);
- assertEquals("TransitionDelay should match", transitionDelay, mapboxMap.getTransitionDelay(), 0);
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ long transitionDelay = 50;
+ mapboxMap.setTransitionDelay(transitionDelay);
+ assertEquals(
+ "TransitionDelay should match", transitionDelay, mapboxMap.getTransitionDelay(), 0
+ );
}));
}
@@ -99,40 +95,34 @@ public class MapboxMapTest extends BaseActivityTest {
@Test
public void testCameraPositionOnFinish() {
ViewUtils.checkViewIsDisplayed(R.id.mapView);
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
- final LatLng latLng = new LatLng(30.0, 30.0);
- mapboxMap.moveCamera(CameraUpdateFactory.newLatLng(latLng), new MapboxMap.CancelableCallback() {
- @Override
- public void onCancel() {
- }
+ final LatLng latLng = new LatLng(30.0, 30.0);
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLng(latLng), new MapboxMap.CancelableCallback() {
+ @Override
+ public void onCancel() {
+ }
- @Override
- public void onFinish() {
- LatLng cameraPositionLatLng = mapboxMap.getCameraPosition().target;
- Timber.d(cameraPositionLatLng.toString());
- assertEquals(cameraPositionLatLng.getLatitude(), latLng.getLatitude(), LAT_LNG_DELTA);
- assertEquals(cameraPositionLatLng.getLongitude(), latLng.getLongitude(), LAT_LNG_DELTA);
- }
- });
- }
+ @Override
+ public void onFinish() {
+ LatLng cameraPositionLatLng = mapboxMap.getCameraPosition().target;
+ Timber.d(cameraPositionLatLng.toString());
+ assertEquals(cameraPositionLatLng.getLatitude(), latLng.getLatitude(), LAT_LNG_DELTA);
+ assertEquals(cameraPositionLatLng.getLongitude(), latLng.getLongitude(), LAT_LNG_DELTA);
+ }
+ });
}));
}
@Test
public void testCameraForLatLngBounds() {
ViewUtils.checkViewIsDisplayed(R.id.mapView);
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- // set
- mapboxMap.setLatLngBoundsForCameraTarget(
- new LatLngBounds.Builder().include(new LatLng()).include(new LatLng(1, 1)).build());
- // reset
- mapboxMap.setLatLngBoundsForCameraTarget(null);
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ // set
+ mapboxMap.setLatLngBoundsForCameraTarget(
+ new LatLngBounds.Builder().include(new LatLng()).include(new LatLng(1, 1)).build());
+ // reset
+ mapboxMap.setLatLngBoundsForCameraTarget(null);
}));
}
@@ -143,12 +133,9 @@ public class MapboxMapTest extends BaseActivityTest {
@Test
public void testMinZoom() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- mapboxMap.setMinZoomPreference(10);
- assertEquals("MinZoom should match", 10, mapboxMap.getMinZoomLevel(), 10);
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ mapboxMap.setMinZoomPreference(10);
+ assertEquals("MinZoom should match", 10, mapboxMap.getMinZoomLevel(), 10);
}));
}
@@ -156,12 +143,9 @@ public class MapboxMapTest extends BaseActivityTest {
public void testMaxZoom() {
validateTestSetup();
final double zoom = 10;
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- mapboxMap.setMaxZoomPreference(zoom);
- assertEquals("MaxZoom should match", zoom, mapboxMap.getMaxZoomLevel(), 10);
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ mapboxMap.setMaxZoomPreference(zoom);
+ assertEquals("MaxZoom should match", zoom, mapboxMap.getMaxZoomLevel(), 10);
}));
}
@@ -169,14 +153,11 @@ public class MapboxMapTest extends BaseActivityTest {
@Ignore
public void testInitialZoomLevels() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- assertEquals("MaxZoom should match", MapboxConstants.MAXIMUM_ZOOM, mapboxMap.getMaxZoomLevel(),
- TestConstants.ZOOM_DELTA);
- assertEquals("MinZoom should match", MapboxConstants.MINIMUM_ZOOM, mapboxMap.getMinZoomLevel(),
- TestConstants.ZOOM_DELTA);
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ assertEquals("MaxZoom should match", MapboxConstants.MAXIMUM_ZOOM, mapboxMap.getMaxZoomLevel(),
+ TestConstants.ZOOM_DELTA);
+ assertEquals("MinZoom should match", MapboxConstants.MINIMUM_ZOOM, mapboxMap.getMinZoomLevel(),
+ TestConstants.ZOOM_DELTA);
}));
}
@@ -197,43 +178,28 @@ public class MapboxMapTest extends BaseActivityTest {
@Test
public void testConcurrentInfoWindowEnabled() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- mapboxMap.setAllowConcurrentMultipleOpenInfoWindows(true);
- assertTrue("ConcurrentWindows should be true", mapboxMap.isAllowConcurrentMultipleOpenInfoWindows());
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ mapboxMap.setAllowConcurrentMultipleOpenInfoWindows(true);
+ assertTrue("ConcurrentWindows should be true", mapboxMap.isAllowConcurrentMultipleOpenInfoWindows());
}));
}
@Test
public void testConcurrentInfoWindowDisabled() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- mapboxMap.setAllowConcurrentMultipleOpenInfoWindows(false);
- assertFalse("ConcurrentWindows should be false", mapboxMap.isAllowConcurrentMultipleOpenInfoWindows());
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ mapboxMap.setAllowConcurrentMultipleOpenInfoWindows(false);
+ assertFalse("ConcurrentWindows should be false", mapboxMap.isAllowConcurrentMultipleOpenInfoWindows());
}));
}
@Test
public void testInfoWindowAdapter() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- MapboxMap.InfoWindowAdapter infoWindowAdapter = new MapboxMap.InfoWindowAdapter() {
- @Nullable
- @Override
- public View getInfoWindow(@NonNull Marker marker) {
- return null;
- }
- };
- mapboxMap.setInfoWindowAdapter(infoWindowAdapter);
- assertEquals("InfoWindowAdpter should be the same", infoWindowAdapter, mapboxMap.getInfoWindowAdapter());
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ MapboxMap.InfoWindowAdapter infoWindowAdapter = marker -> null;
+ mapboxMap.setInfoWindowAdapter(infoWindowAdapter);
+ assertEquals("InfoWindowAdpter should be the same", infoWindowAdapter, mapboxMap.getInfoWindowAdapter());
}));
}
@@ -245,12 +211,9 @@ public class MapboxMapTest extends BaseActivityTest {
@Ignore /* disabled due to enabling permissions during test #7177 */
public void testMyLocationEnabled() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- mapboxMap.setMyLocationEnabled(true);
- assertTrue("MyLocationEnabled should be true", mapboxMap.isMyLocationEnabled());
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ mapboxMap.setMyLocationEnabled(true);
+ assertTrue("MyLocationEnabled should be true", mapboxMap.isMyLocationEnabled());
}));
}
@@ -258,12 +221,9 @@ public class MapboxMapTest extends BaseActivityTest {
@Ignore /* can't create handler inside thread that not called Looper.prepare() */
public void testMyLocationDisabled() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- mapboxMap.setMyLocationEnabled(false);
- assertFalse("MyLocationEnabled should be false", mapboxMap.isMyLocationEnabled());
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ mapboxMap.setMyLocationEnabled(false);
+ assertFalse("MyLocationEnabled should be false", mapboxMap.isMyLocationEnabled());
}));
}
@@ -274,73 +234,49 @@ public class MapboxMapTest extends BaseActivityTest {
@Test
public void testFpsListener() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- MapboxMap.OnFpsChangedListener fpsChangedListener = new MapboxMap.OnFpsChangedListener() {
- @Override
- public void onFpsChanged(double fps) {
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ MapboxMap.OnFpsChangedListener fpsChangedListener = fps -> {
- }
- };
- mapboxMap.setOnFpsChangedListener(fpsChangedListener);
- assertEquals("FpsListener should match", fpsChangedListener, mapboxMap.getOnFpsChangedListener());
- }
+ };
+ mapboxMap.setOnFpsChangedListener(fpsChangedListener);
+ assertEquals("FpsListener should match", fpsChangedListener, mapboxMap.getOnFpsChangedListener());
}));
}
@Test
public void testInfoWindowClickListener() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- MapboxMap.OnInfoWindowClickListener clickListener = new MapboxMap.OnInfoWindowClickListener() {
- @Override
- public boolean onInfoWindowClick(@NonNull Marker marker) {
- return false;
- }
- };
- mapboxMap.setOnInfoWindowClickListener(clickListener);
- assertEquals("InfoWidowClickListener should match", clickListener, mapboxMap.getOnInfoWindowClickListener());
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ MapboxMap.OnInfoWindowClickListener clickListener = marker -> false;
+ mapboxMap.setOnInfoWindowClickListener(clickListener);
+ assertEquals(
+ "InfoWidowClickListener should match", clickListener, mapboxMap.getOnInfoWindowClickListener()
+ );
}));
}
@Test
public void testInfoWindowCloseListener() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- MapboxMap.OnInfoWindowCloseListener listener = new MapboxMap.OnInfoWindowCloseListener() {
- @Override
- public void onInfoWindowClose(Marker marker) {
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ MapboxMap.OnInfoWindowCloseListener listener = marker -> {
- }
- };
- mapboxMap.setOnInfoWindowCloseListener(listener);
- assertEquals("InfoWindowCloseListener should match", listener, mapboxMap.getOnInfoWindowCloseListener());
- }
+ };
+ mapboxMap.setOnInfoWindowCloseListener(listener);
+ assertEquals("InfoWindowCloseListener should match", listener, mapboxMap.getOnInfoWindowCloseListener());
}));
}
@Test
public void testInfoWindowLongClickListener() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- MapboxMap.OnInfoWindowLongClickListener listener = new MapboxMap.OnInfoWindowLongClickListener() {
- @Override
- public void onInfoWindowLongClick(Marker marker) {
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ MapboxMap.OnInfoWindowLongClickListener listener = marker -> {
- }
- };
- mapboxMap.setOnInfoWindowLongClickListener(listener);
- assertEquals("InfoWindowLongClickListener should match", listener,
- mapboxMap.getOnInfoWindowLongClickListener());
- }
+ };
+ mapboxMap.setOnInfoWindowLongClickListener(listener);
+ assertEquals("InfoWindowLongClickListener should match", listener,
+ mapboxMap.getOnInfoWindowLongClickListener());
}));
}
@@ -351,13 +287,10 @@ public class MapboxMapTest extends BaseActivityTest {
@Test
public void testAddMarker() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
- Marker marker = mapboxMap.addMarker(markerOptions);
- assertTrue("Marker should be contained", mapboxMap.getMarkers().contains(marker));
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
+ Marker marker = mapboxMap.addMarker(markerOptions);
+ assertTrue("Marker should be contained", mapboxMap.getMarkers().contains(marker));
}));
}
@@ -369,442 +302,356 @@ public class MapboxMapTest extends BaseActivityTest {
@Test
public void testAddMarkers() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- List<BaseMarkerOptions> markerList = new ArrayList<>();
- MarkerOptions markerOptions1 = new MarkerOptions().position(new LatLng()).title("a");
- MarkerOptions markerOptions2 = new MarkerOptions().position(new LatLng()).title("b");
- markerList.add(markerOptions1);
- markerList.add(markerOptions2);
- List<Marker> markers = mapboxMap.addMarkers(markerList);
- assertEquals("Markers size should be 2", 2, mapboxMap.getMarkers().size());
- assertTrue(mapboxMap.getMarkers().contains(markers.get(0)));
- assertTrue(mapboxMap.getMarkers().contains(markers.get(1)));
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ List<BaseMarkerOptions> markerList = new ArrayList<>();
+ MarkerOptions markerOptions1 = new MarkerOptions().position(new LatLng()).title("a");
+ MarkerOptions markerOptions2 = new MarkerOptions().position(new LatLng()).title("b");
+ markerList.add(markerOptions1);
+ markerList.add(markerOptions2);
+ List<Marker> markers = mapboxMap.addMarkers(markerList);
+ assertEquals("Markers size should be 2", 2, mapboxMap.getMarkers().size());
+ assertTrue(mapboxMap.getMarkers().contains(markers.get(0)));
+ assertTrue(mapboxMap.getMarkers().contains(markers.get(1)));
}));
}
@Test
public void testAddMarkersEmpty() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- List<BaseMarkerOptions> markerList = new ArrayList<>();
- mapboxMap.addMarkers(markerList);
- assertEquals("Markers size should be 0", 0, mapboxMap.getMarkers().size());
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ List<BaseMarkerOptions> markerList = new ArrayList<>();
+ mapboxMap.addMarkers(markerList);
+ assertEquals("Markers size should be 0", 0, mapboxMap.getMarkers().size());
}));
}
@Test
public void testAddMarkersSingleMarker() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- List<BaseMarkerOptions> markerList = new ArrayList<>();
- MarkerOptions markerOptions = new MarkerOptions().title("a").position(new LatLng());
- markerList.add(markerOptions);
- List<Marker> markers = mapboxMap.addMarkers(markerList);
- assertEquals("Markers size should be 1", 1, mapboxMap.getMarkers().size());
- assertTrue(mapboxMap.getMarkers().contains(markers.get(0)));
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ List<BaseMarkerOptions> markerList = new ArrayList<>();
+ MarkerOptions markerOptions = new MarkerOptions().title("a").position(new LatLng());
+ markerList.add(markerOptions);
+ List<Marker> markers = mapboxMap.addMarkers(markerList);
+ assertEquals("Markers size should be 1", 1, mapboxMap.getMarkers().size());
+ assertTrue(mapboxMap.getMarkers().contains(markers.get(0)));
}));
}
@Test
public void testAddPolygon() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- PolygonOptions polygonOptions = new PolygonOptions().add(new LatLng());
- Polygon polygon = mapboxMap.addPolygon(polygonOptions);
- assertTrue("Polygon should be contained", mapboxMap.getPolygons().contains(polygon));
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ PolygonOptions polygonOptions = new PolygonOptions().add(new LatLng());
+ Polygon polygon = mapboxMap.addPolygon(polygonOptions);
+ assertTrue("Polygon should be contained", mapboxMap.getPolygons().contains(polygon));
}));
}
@Test
public void testAddEmptyPolygon() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- PolygonOptions polygonOptions = new PolygonOptions();
- Polygon polygon = mapboxMap.addPolygon(polygonOptions);
- assertTrue("Polygon should be ignored", !mapboxMap.getPolygons().contains(polygon));
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ PolygonOptions polygonOptions = new PolygonOptions();
+ Polygon polygon = mapboxMap.addPolygon(polygonOptions);
+ assertTrue("Polygon should be ignored", !mapboxMap.getPolygons().contains(polygon));
}));
}
@Test
public void testAddPolygons() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- List<PolygonOptions> polygonList = new ArrayList<>();
- PolygonOptions polygonOptions1 = new PolygonOptions().fillColor(Color.BLACK).add(new LatLng());
- PolygonOptions polygonOptions2 = new PolygonOptions().fillColor(Color.WHITE).add(new LatLng());
- PolygonOptions polygonOptions3 = new PolygonOptions();
- polygonList.add(polygonOptions1);
- polygonList.add(polygonOptions2);
- polygonList.add(polygonOptions3);
- mapboxMap.addPolygons(polygonList);
- assertEquals("Polygons size should be 2", 2, mapboxMap.getPolygons().size());
- assertTrue(mapboxMap.getPolygons().contains(polygonOptions1.getPolygon()));
- assertTrue(mapboxMap.getPolygons().contains(polygonOptions2.getPolygon()));
- assertTrue("Polygon should be ignored", !mapboxMap.getPolygons().contains(polygonOptions3.getPolygon()));
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ List<PolygonOptions> polygonList = new ArrayList<>();
+ PolygonOptions polygonOptions1 = new PolygonOptions().fillColor(Color.BLACK).add(new LatLng());
+ PolygonOptions polygonOptions2 = new PolygonOptions().fillColor(Color.WHITE).add(new LatLng());
+ PolygonOptions polygonOptions3 = new PolygonOptions();
+ polygonList.add(polygonOptions1);
+ polygonList.add(polygonOptions2);
+ polygonList.add(polygonOptions3);
+ mapboxMap.addPolygons(polygonList);
+ assertEquals("Polygons size should be 2", 2, mapboxMap.getPolygons().size());
+ assertTrue(mapboxMap.getPolygons().contains(polygonOptions1.getPolygon()));
+ assertTrue(mapboxMap.getPolygons().contains(polygonOptions2.getPolygon()));
+ assertTrue("Polygon should be ignored", !mapboxMap.getPolygons().contains(polygonOptions3.getPolygon()));
}));
}
@Test
public void addPolygonsEmpty() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- mapboxMap.addPolygons(new ArrayList<PolygonOptions>());
- assertEquals("Polygons size should be 0", 0, mapboxMap.getPolygons().size());
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ mapboxMap.addPolygons(new ArrayList<PolygonOptions>());
+ assertEquals("Polygons size should be 0", 0, mapboxMap.getPolygons().size());
}));
}
@Test
public void addPolygonsSingle() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- List<PolygonOptions> polygonList = new ArrayList<>();
- PolygonOptions polygonOptions = new PolygonOptions().fillColor(Color.BLACK).add(new LatLng());
- polygonList.add(polygonOptions);
- mapboxMap.addPolygons(polygonList);
- assertEquals("Polygons size should be 1", 1, mapboxMap.getPolygons().size());
- assertTrue(mapboxMap.getPolygons().contains(polygonOptions.getPolygon()));
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ List<PolygonOptions> polygonList = new ArrayList<>();
+ PolygonOptions polygonOptions = new PolygonOptions().fillColor(Color.BLACK).add(new LatLng());
+ polygonList.add(polygonOptions);
+ mapboxMap.addPolygons(polygonList);
+ assertEquals("Polygons size should be 1", 1, mapboxMap.getPolygons().size());
+ assertTrue(mapboxMap.getPolygons().contains(polygonOptions.getPolygon()));
}));
}
@Test
public void testAddPolyline() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- PolylineOptions polylineOptions = new PolylineOptions().add(new LatLng());
- Polyline polyline = mapboxMap.addPolyline(polylineOptions);
- assertTrue("Polyline should be contained", mapboxMap.getPolylines().contains(polyline));
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ PolylineOptions polylineOptions = new PolylineOptions().add(new LatLng());
+ Polyline polyline = mapboxMap.addPolyline(polylineOptions);
+ assertTrue("Polyline should be contained", mapboxMap.getPolylines().contains(polyline));
}));
}
@Test
public void testAddEmptyPolyline() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- PolylineOptions polylineOptions = new PolylineOptions();
- Polyline polyline = mapboxMap.addPolyline(polylineOptions);
- assertTrue("Polyline should be ignored", !mapboxMap.getPolylines().contains(polyline));
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ PolylineOptions polylineOptions = new PolylineOptions();
+ Polyline polyline = mapboxMap.addPolyline(polylineOptions);
+ assertTrue("Polyline should be ignored", !mapboxMap.getPolylines().contains(polyline));
}));
}
@Test
public void testAddPolylines() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- List<PolylineOptions> polylineList = new ArrayList<>();
- PolylineOptions polygonOptions1 = new PolylineOptions().color(Color.BLACK).add(new LatLng());
- PolylineOptions polygonOptions2 = new PolylineOptions().color(Color.WHITE).add(new LatLng());
- PolylineOptions polygonOptions3 = new PolylineOptions();
- polylineList.add(polygonOptions1);
- polylineList.add(polygonOptions2);
- polylineList.add(polygonOptions3);
- mapboxMap.addPolylines(polylineList);
- assertEquals("Polygons size should be 2", 2, mapboxMap.getPolylines().size());
- assertTrue(mapboxMap.getPolylines().contains(polygonOptions1.getPolyline()));
- assertTrue(mapboxMap.getPolylines().contains(polygonOptions2.getPolyline()));
- assertTrue("Polyline should be ignored", !mapboxMap.getPolylines().contains(polygonOptions3.getPolyline()));
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ List<PolylineOptions> polylineList = new ArrayList<>();
+ PolylineOptions polygonOptions1 = new PolylineOptions().color(Color.BLACK).add(new LatLng());
+ PolylineOptions polygonOptions2 = new PolylineOptions().color(Color.WHITE).add(new LatLng());
+ PolylineOptions polygonOptions3 = new PolylineOptions();
+ polylineList.add(polygonOptions1);
+ polylineList.add(polygonOptions2);
+ polylineList.add(polygonOptions3);
+ mapboxMap.addPolylines(polylineList);
+ assertEquals("Polygons size should be 2", 2, mapboxMap.getPolylines().size());
+ assertTrue(mapboxMap.getPolylines().contains(polygonOptions1.getPolyline()));
+ assertTrue(mapboxMap.getPolylines().contains(polygonOptions2.getPolyline()));
+ assertTrue(
+ "Polyline should be ignored", !mapboxMap.getPolylines().contains(polygonOptions3.getPolyline())
+ );
}));
}
@Test
public void testAddPolylinesEmpty() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- mapboxMap.addPolylines(new ArrayList<PolylineOptions>());
- assertEquals("Polygons size should be 0", 0, mapboxMap.getPolylines().size());
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ mapboxMap.addPolylines(new ArrayList<PolylineOptions>());
+ assertEquals("Polygons size should be 0", 0, mapboxMap.getPolylines().size());
}));
}
@Test
public void testAddPolylinesSingle() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- List<PolylineOptions> polylineList = new ArrayList<>();
- PolylineOptions polygonOptions = new PolylineOptions().color(Color.BLACK).add(new LatLng());
- polylineList.add(polygonOptions);
- mapboxMap.addPolylines(polylineList);
- assertEquals("Polygons size should be 1", 1, mapboxMap.getPolylines().size());
- assertTrue(mapboxMap.getPolylines().contains(polygonOptions.getPolyline()));
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ List<PolylineOptions> polylineList = new ArrayList<>();
+ PolylineOptions polygonOptions = new PolylineOptions().color(Color.BLACK).add(new LatLng());
+ polylineList.add(polygonOptions);
+ mapboxMap.addPolylines(polylineList);
+ assertEquals("Polygons size should be 1", 1, mapboxMap.getPolylines().size());
+ assertTrue(mapboxMap.getPolylines().contains(polygonOptions.getPolyline()));
}));
}
@Test
public void testRemoveMarker() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
- Marker marker = mapboxMap.addMarker(markerOptions);
- mapboxMap.removeMarker(marker);
- assertTrue("Markers should be empty", mapboxMap.getMarkers().isEmpty());
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
+ Marker marker = mapboxMap.addMarker(markerOptions);
+ mapboxMap.removeMarker(marker);
+ assertTrue("Markers should be empty", mapboxMap.getMarkers().isEmpty());
}));
}
@Test
public void testRemovePolygon() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- PolygonOptions polygonOptions = new PolygonOptions();
- Polygon polygon = mapboxMap.addPolygon(polygonOptions);
- mapboxMap.removePolygon(polygon);
- assertTrue("Polygons should be empty", mapboxMap.getPolylines().isEmpty());
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ PolygonOptions polygonOptions = new PolygonOptions();
+ Polygon polygon = mapboxMap.addPolygon(polygonOptions);
+ mapboxMap.removePolygon(polygon);
+ assertTrue("Polygons should be empty", mapboxMap.getPolylines().isEmpty());
}));
}
@Test
public void testRemovePolyline() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- PolylineOptions polylineOptions = new PolylineOptions();
- Polyline polyline = mapboxMap.addPolyline(polylineOptions);
- mapboxMap.removePolyline(polyline);
- assertTrue("Polylines should be empty", mapboxMap.getPolylines().isEmpty());
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ PolylineOptions polylineOptions = new PolylineOptions();
+ Polyline polyline = mapboxMap.addPolyline(polylineOptions);
+ mapboxMap.removePolyline(polyline);
+ assertTrue("Polylines should be empty", mapboxMap.getPolylines().isEmpty());
}));
}
@Test
public void testRemoveAnnotation() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
- Marker marker = mapboxMap.addMarker(markerOptions);
- mapboxMap.removeAnnotation(marker);
- assertTrue("Annotations should be empty", mapboxMap.getAnnotations().isEmpty());
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
+ Marker marker = mapboxMap.addMarker(markerOptions);
+ mapboxMap.removeAnnotation(marker);
+ assertTrue("Annotations should be empty", mapboxMap.getAnnotations().isEmpty());
}));
}
@Test
public void testRemoveAnnotationById() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
- mapboxMap.addMarker(markerOptions);
- // id will always be 0 in unit tests
- mapboxMap.removeAnnotation(0);
- assertTrue("Annotations should be empty", mapboxMap.getAnnotations().isEmpty());
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
+ mapboxMap.addMarker(markerOptions);
+ // id will always be 0 in unit tests
+ mapboxMap.removeAnnotation(0);
+ assertTrue("Annotations should be empty", mapboxMap.getAnnotations().isEmpty());
}));
}
@Test
public void testRemoveAnnotations() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- List<BaseMarkerOptions> markerList = new ArrayList<>();
- MarkerOptions markerOptions1 = new MarkerOptions().title("a").position(new LatLng());
- MarkerOptions markerOptions2 = new MarkerOptions().title("b").position(new LatLng());
- markerList.add(markerOptions1);
- markerList.add(markerOptions2);
- mapboxMap.addMarkers(markerList);
- mapboxMap.removeAnnotations();
- assertTrue("Annotations should be empty", mapboxMap.getAnnotations().isEmpty());
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ List<BaseMarkerOptions> markerList = new ArrayList<>();
+ MarkerOptions markerOptions1 = new MarkerOptions().title("a").position(new LatLng());
+ MarkerOptions markerOptions2 = new MarkerOptions().title("b").position(new LatLng());
+ markerList.add(markerOptions1);
+ markerList.add(markerOptions2);
+ mapboxMap.addMarkers(markerList);
+ mapboxMap.removeAnnotations();
+ assertTrue("Annotations should be empty", mapboxMap.getAnnotations().isEmpty());
}));
}
@Test
public void testClear() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- List<BaseMarkerOptions> markerList = new ArrayList<>();
- MarkerOptions markerOptions1 = new MarkerOptions().title("a").position(new LatLng());
- MarkerOptions markerOptions2 = new MarkerOptions().title("b").position(new LatLng());
- markerList.add(markerOptions1);
- markerList.add(markerOptions2);
- mapboxMap.addMarkers(markerList);
- mapboxMap.clear();
- assertTrue("Annotations should be empty", mapboxMap.getAnnotations().isEmpty());
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ List<BaseMarkerOptions> markerList = new ArrayList<>();
+ MarkerOptions markerOptions1 = new MarkerOptions().title("a").position(new LatLng());
+ MarkerOptions markerOptions2 = new MarkerOptions().title("b").position(new LatLng());
+ markerList.add(markerOptions1);
+ markerList.add(markerOptions2);
+ mapboxMap.addMarkers(markerList);
+ mapboxMap.clear();
+ assertTrue("Annotations should be empty", mapboxMap.getAnnotations().isEmpty());
}));
}
@Test
public void testRemoveAnnotationsByList() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- List<BaseMarkerOptions> markerList = new ArrayList<>();
- MarkerOptions markerOptions1 = new MarkerOptions().title("a").position(new LatLng());
- MarkerOptions markerOptions2 = new MarkerOptions().title("b").position(new LatLng());
- markerList.add(markerOptions1);
- markerList.add(markerOptions2);
- List<Marker> markers = mapboxMap.addMarkers(markerList);
- Marker marker = mapboxMap.addMarker(new MarkerOptions().position(new LatLng()).title("c"));
- mapboxMap.removeAnnotations(markers);
- assertTrue("Annotations should not be empty", mapboxMap.getAnnotations().size() == 1);
- assertTrue("Marker should be contained", mapboxMap.getAnnotations().contains(marker));
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ List<BaseMarkerOptions> markerList = new ArrayList<>();
+ MarkerOptions markerOptions1 = new MarkerOptions().title("a").position(new LatLng());
+ MarkerOptions markerOptions2 = new MarkerOptions().title("b").position(new LatLng());
+ markerList.add(markerOptions1);
+ markerList.add(markerOptions2);
+ List<Marker> markers = mapboxMap.addMarkers(markerList);
+ Marker marker = mapboxMap.addMarker(new MarkerOptions().position(new LatLng()).title("c"));
+ mapboxMap.removeAnnotations(markers);
+ assertTrue("Annotations should not be empty", mapboxMap.getAnnotations().size() == 1);
+ assertTrue("Marker should be contained", mapboxMap.getAnnotations().contains(marker));
}));
}
@Test
public void testGetAnnotationById() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
- Marker initialMarker = mapboxMap.addMarker(markerOptions);
- Marker retrievedMarker = (Marker) mapboxMap.getAnnotation(0);
- assertEquals("Markers should match", initialMarker, retrievedMarker);
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
+ Marker initialMarker = mapboxMap.addMarker(markerOptions);
+ Marker retrievedMarker = (Marker) mapboxMap.getAnnotation(0);
+ assertEquals("Markers should match", initialMarker, retrievedMarker);
}));
}
@Test
public void testGetAnnotations() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- assertNotNull("Annotations should be non null", mapboxMap.getAnnotations());
- }
- }));
+ onView(withId(R.id.mapView)).perform(
+ new MapboxMapAction((uiController, view) ->
+ assertNotNull("Annotations should be non null", mapboxMap.getAnnotations()))
+ );
}
@Test
public void testGetMarkers() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- assertNotNull("Markers should be non null", mapboxMap.getMarkers());
- }
- }));
+ onView(withId(R.id.mapView)).perform(
+ new MapboxMapAction((uiController, view) ->
+ assertNotNull("Markers should be non null", mapboxMap.getMarkers()))
+ );
}
@Test
public void testGetPolygons() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- assertNotNull("Polygons should be non null", mapboxMap.getPolygons());
- }
- }));
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) ->
+ assertNotNull("Polygons should be non null", mapboxMap.getPolygons()))
+ );
}
@Test
public void testGetPolylines() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- assertNotNull("Polylines should be non null", mapboxMap.getPolylines());
- }
- }));
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) ->
+ assertNotNull("Polylines should be non null", mapboxMap.getPolylines()))
+ );
}
@Test
public void testGetSelectedMarkers() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- assertNotNull("Selected markers should be non null", mapboxMap.getSelectedMarkers());
- }
- }));
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) ->
+ assertNotNull("Selected markers should be non null", mapboxMap.getSelectedMarkers()))
+ );
}
@Test
public void testSelectMarker() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
- Marker marker = mapboxMap.addMarker(markerOptions);
- mapboxMap.selectMarker(marker);
- assertTrue("Marker should be contained", mapboxMap.getSelectedMarkers().contains(marker));
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
+ Marker marker = mapboxMap.addMarker(markerOptions);
+ mapboxMap.selectMarker(marker);
+ assertTrue("Marker should be contained", mapboxMap.getSelectedMarkers().contains(marker));
}));
}
@Test
public void testDeselectMarker() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
- Marker marker = mapboxMap.addMarker(markerOptions);
- mapboxMap.selectMarker(marker);
- mapboxMap.deselectMarker(marker);
- assertTrue("Selected markers should be empty", mapboxMap.getSelectedMarkers().isEmpty());
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
+ Marker marker = mapboxMap.addMarker(markerOptions);
+ mapboxMap.selectMarker(marker);
+ mapboxMap.deselectMarker(marker);
+ assertTrue("Selected markers should be empty", mapboxMap.getSelectedMarkers().isEmpty());
}));
}
@Test
public void testDeselectMarkers() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
- Marker marker1 = mapboxMap.addMarker(markerOptions);
- Marker marker2 = mapboxMap.addMarker(markerOptions);
- mapboxMap.selectMarker(marker1);
- mapboxMap.selectMarker(marker2);
- mapboxMap.deselectMarkers();
- assertTrue("Selected markers should be empty", mapboxMap.getSelectedMarkers().isEmpty());
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
+ Marker marker1 = mapboxMap.addMarker(markerOptions);
+ Marker marker2 = mapboxMap.addMarker(markerOptions);
+ mapboxMap.selectMarker(marker1);
+ mapboxMap.selectMarker(marker2);
+ mapboxMap.deselectMarkers();
+ assertTrue("Selected markers should be empty", mapboxMap.getSelectedMarkers().isEmpty());
}));
}
@@ -813,14 +660,11 @@ public class MapboxMapTest extends BaseActivityTest {
@Test
public void testTilePrefetch() {
validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- mapboxMap.setPrefetchesTiles(true);
- assertTrue(mapboxMap.getPrefetchesTiles());
- mapboxMap.setPrefetchesTiles(false);
- assertFalse(mapboxMap.getPrefetchesTiles());
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ mapboxMap.setPrefetchesTiles(true);
+ assertTrue(mapboxMap.getPrefetchesTiles());
+ mapboxMap.setPrefetchesTiles(false);
+ assertFalse(mapboxMap.getPrefetchesTiles());
}));
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/OrientationTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/OrientationTest.java
new file mode 100644
index 0000000000..7a1fcbf5f3
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/OrientationTest.java
@@ -0,0 +1,41 @@
+package com.mapbox.mapboxsdk.maps;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.activity.camera.CameraAnimationTypeActivity;
+import org.junit.Test;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.matcher.ViewMatchers.isRoot;
+import static com.mapbox.mapboxsdk.testapp.action.OrientationChangeAction.orientationLandscape;
+import static com.mapbox.mapboxsdk.testapp.action.OrientationChangeAction.orientationLandscapeReverse;
+import static com.mapbox.mapboxsdk.testapp.action.OrientationChangeAction.orientationPortrait;
+import static com.mapbox.mapboxsdk.testapp.action.OrientationChangeAction.orientationPortraitReverse;
+
+public class OrientationTest extends BaseActivityTest {
+
+ @Test
+ public void testChangeDeviceOrientation() {
+ onView(isRoot()).perform(orientationLandscape());
+ waitLoop(2200);
+ onView(isRoot()).perform(orientationPortrait());
+ waitLoop(2500);
+ onView(isRoot()).perform(orientationLandscapeReverse());
+ waitLoop(500);
+ onView(isRoot()).perform(orientationPortraitReverse());
+ waitLoop(1250);
+ onView(isRoot()).perform(orientationLandscape());
+ waitLoop(750);
+ onView(isRoot()).perform(orientationPortrait());
+ waitLoop(950);
+ onView(isRoot()).perform(orientationLandscapeReverse());
+ onView(isRoot()).perform(orientationPortraitReverse());
+ onView(isRoot()).perform(orientationLandscape());
+ onView(isRoot()).perform(orientationPortrait());
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return CameraAnimationTypeActivity.class;
+ }
+
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/action/OrientationChangeAction.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/action/OrientationChangeAction.java
new file mode 100644
index 0000000000..7f73d6a7f3
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/action/OrientationChangeAction.java
@@ -0,0 +1,74 @@
+package com.mapbox.mapboxsdk.testapp.action;
+
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.pm.ActivityInfo;
+import android.support.test.espresso.UiController;
+import android.support.test.espresso.ViewAction;
+import android.view.View;
+import android.view.ViewGroup;
+import org.hamcrest.Matcher;
+
+import static android.support.test.espresso.matcher.ViewMatchers.isRoot;
+
+public class OrientationChangeAction implements ViewAction {
+
+ private final int orientation;
+
+ private OrientationChangeAction(int orientation) {
+ this.orientation = orientation;
+ }
+
+ public static ViewAction orientationLandscape() {
+ return new OrientationChangeAction(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+ }
+
+ public static ViewAction orientationPortrait() {
+ return new OrientationChangeAction(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ }
+
+ public static ViewAction orientationLandscapeReverse() {
+ return new OrientationChangeAction(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
+ }
+
+ public static ViewAction orientationPortraitReverse() {
+ return new OrientationChangeAction(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
+ }
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return isRoot();
+ }
+
+ @Override
+ public String getDescription() {
+ return "change orientation to " + orientation;
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ uiController.loopMainThreadUntilIdle();
+ Activity activity = getActivity(view.getContext());
+ if (activity == null && view instanceof ViewGroup) {
+ ViewGroup v = (ViewGroup) view;
+ int c = v.getChildCount();
+ for (int i = 0; i < c && activity == null; ++i) {
+ activity = getActivity(v.getChildAt(i).getContext());
+ }
+ }
+ activity.setRequestedOrientation(orientation);
+ }
+
+ private Activity getActivity(Context context) {
+ while (context instanceof ContextWrapper) {
+ if (context instanceof Activity) {
+ return (Activity) context;
+ }
+ context = ((ContextWrapper) context).getBaseContext();
+ }
+ return null;
+ }
+
+}
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 61bff1f113..3f32443021 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
@@ -10,18 +10,14 @@ import android.support.test.espresso.UiController;
import android.support.test.espresso.ViewAction;
import android.support.test.rule.ActivityTestRule;
import android.view.View;
-
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
-
import junit.framework.Assert;
-
import org.hamcrest.Matcher;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
-
import timber.log.Timber;
import static android.support.test.espresso.Espresso.onView;
@@ -72,7 +68,11 @@ public abstract class BaseActivityTest {
}
protected void waitLoop() {
- onView(withId(R.id.mapView)).perform(new LoopAction(500));
+ waitLoop(500);
+ }
+
+ protected void waitLoop(long waitTime) {
+ onView(withId(R.id.mapView)).perform(new LoopAction(waitTime));
}
static boolean isConnected(Context context) {
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/MarkerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/MarkerTest.java
index e511135b99..11756d3d32 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/MarkerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/MarkerTest.java
@@ -1,11 +1,8 @@
package com.mapbox.mapboxsdk.testapp.annotations;
-import android.support.test.espresso.UiController;
-
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
import com.mapbox.mapboxsdk.geometry.LatLng;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
@@ -34,25 +31,22 @@ public class MarkerTest extends BaseActivityTest {
@Ignore
public void addMarkerTest() {
validateTestSetup();
- MapboxMapAction.invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertEquals("Markers should be empty", 0, mapboxMap.getMarkers().size());
+ MapboxMapAction.invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertEquals("Markers should be empty", 0, mapboxMap.getMarkers().size());
- MarkerOptions options = new MarkerOptions();
- options.setPosition(new LatLng());
- options.setSnippet(TestConstants.TEXT_MARKER_SNIPPET);
- options.setTitle(TestConstants.TEXT_MARKER_TITLE);
- marker = mapboxMap.addMarker(options);
+ MarkerOptions options = new MarkerOptions();
+ options.setPosition(new LatLng());
+ options.setSnippet(TestConstants.TEXT_MARKER_SNIPPET);
+ options.setTitle(TestConstants.TEXT_MARKER_TITLE);
+ marker = mapboxMap.addMarker(options);
- assertEquals("Markers size should be 1, ", 1, mapboxMap.getMarkers().size());
- assertEquals("Marker id should be 0", 0, marker.getId());
- assertEquals("Marker target should match", new LatLng(), marker.getPosition());
- assertEquals("Marker snippet should match", TestConstants.TEXT_MARKER_SNIPPET, marker.getSnippet());
- assertEquals("Marker target should match", TestConstants.TEXT_MARKER_TITLE, marker.getTitle());
- mapboxMap.clear();
- assertEquals("Markers should be empty", 0, mapboxMap.getMarkers().size());
- }
+ assertEquals("Markers size should be 1, ", 1, mapboxMap.getMarkers().size());
+ assertEquals("Marker id should be 0", 0, marker.getId());
+ assertEquals("Marker target should match", new LatLng(), marker.getPosition());
+ assertEquals("Marker snippet should match", TestConstants.TEXT_MARKER_SNIPPET, marker.getSnippet());
+ assertEquals("Marker target should match", TestConstants.TEXT_MARKER_TITLE, marker.getTitle());
+ mapboxMap.clear();
+ assertEquals("Markers should be empty", 0, mapboxMap.getMarkers().size());
});
}
@@ -60,16 +54,13 @@ public class MarkerTest extends BaseActivityTest {
@Ignore
public void showInfoWindowTest() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- final MarkerOptions options = new MarkerOptions();
- options.setPosition(new LatLng());
- options.setSnippet(TestConstants.TEXT_MARKER_SNIPPET);
- options.setTitle(TestConstants.TEXT_MARKER_TITLE);
- marker = mapboxMap.addMarker(options);
- mapboxMap.selectMarker(marker);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ final MarkerOptions options = new MarkerOptions();
+ options.setPosition(new LatLng());
+ options.setSnippet(TestConstants.TEXT_MARKER_SNIPPET);
+ options.setTitle(TestConstants.TEXT_MARKER_TITLE);
+ marker = mapboxMap.addMarker(options);
+ mapboxMap.selectMarker(marker);
});
onView(withText(TestConstants.TEXT_MARKER_TITLE)).check(matches(isDisplayed()));
onView(withText(TestConstants.TEXT_MARKER_SNIPPET)).check(matches(isDisplayed()));
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/MarkerViewTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/MarkerViewTest.java
index 8bf847c2e7..ad153336a4 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/MarkerViewTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/MarkerViewTest.java
@@ -1,11 +1,7 @@
package com.mapbox.mapboxsdk.testapp.annotations;
-import android.support.test.espresso.UiController;
-
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.geometry.LatLng;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
import com.mapbox.mapboxsdk.testapp.activity.annotation.MarkerViewActivity;
import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
@@ -36,24 +32,21 @@ public class MarkerViewTest extends BaseActivityTest {
public void addMarkerViewTest() {
validateTestSetup();
addAdapter();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertEquals("Markers should be empty", 0, mapboxMap.getMarkers().size());
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertEquals("Markers should be empty", 0, mapboxMap.getMarkers().size());
- TextMarkerViewOptions options = new TextMarkerViewOptions();
- options.text(TestConstants.TEXT_MARKER_TEXT);
- options.position(new LatLng());
- options.snippet(TestConstants.TEXT_MARKER_SNIPPET);
- options.title(TestConstants.TEXT_MARKER_TITLE);
- marker = mapboxMap.addMarker(options);
- assertEquals("Markers size should be 1, ", 1, mapboxMap.getMarkers().size());
- assertEquals("Marker id should be 0", 0, marker.getId());
- assertEquals("Marker target should match", new LatLng(), marker.getPosition());
- assertEquals("Marker snippet should match", TestConstants.TEXT_MARKER_SNIPPET, marker.getSnippet());
- assertEquals("Marker target should match", TestConstants.TEXT_MARKER_TITLE, marker.getTitle());
- uiController.loopMainThreadForAtLeast(500);
- }
+ TextMarkerViewOptions options = new TextMarkerViewOptions();
+ options.text(TestConstants.TEXT_MARKER_TEXT);
+ options.position(new LatLng());
+ options.snippet(TestConstants.TEXT_MARKER_SNIPPET);
+ options.title(TestConstants.TEXT_MARKER_TITLE);
+ marker = mapboxMap.addMarker(options);
+ assertEquals("Markers size should be 1, ", 1, mapboxMap.getMarkers().size());
+ assertEquals("Marker id should be 0", 0, marker.getId());
+ assertEquals("Marker target should match", new LatLng(), marker.getPosition());
+ assertEquals("Marker snippet should match", TestConstants.TEXT_MARKER_SNIPPET, marker.getSnippet());
+ assertEquals("Marker target should match", TestConstants.TEXT_MARKER_TITLE, marker.getTitle());
+ uiController.loopMainThreadForAtLeast(500);
});
onView(withText(TestConstants.TEXT_MARKER_TEXT)).check(matches(isDisplayed()));
}
@@ -63,18 +56,15 @@ public class MarkerViewTest extends BaseActivityTest {
public void showInfoWindowTest() {
validateTestSetup();
addAdapter();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- final TextMarkerViewOptions options = new TextMarkerViewOptions();
- options.position(new LatLng());
- options.text(TestConstants.TEXT_MARKER_TEXT);
- options.snippet(TestConstants.TEXT_MARKER_SNIPPET);
- options.title(TestConstants.TEXT_MARKER_TITLE);
- marker = mapboxMap.addMarker(options);
- uiController.loopMainThreadForAtLeast(500);
- mapboxMap.selectMarker(marker);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ final TextMarkerViewOptions options = new TextMarkerViewOptions();
+ options.position(new LatLng());
+ options.text(TestConstants.TEXT_MARKER_TEXT);
+ options.snippet(TestConstants.TEXT_MARKER_SNIPPET);
+ options.title(TestConstants.TEXT_MARKER_TITLE);
+ marker = mapboxMap.addMarker(options);
+ uiController.loopMainThreadForAtLeast(500);
+ mapboxMap.selectMarker(marker);
});
onView(withText(TestConstants.TEXT_MARKER_TEXT)).check(matches(isDisplayed()));
onView(withText(TestConstants.TEXT_MARKER_TITLE)).check(matches(isDisplayed()));
@@ -82,13 +72,8 @@ public class MarkerViewTest extends BaseActivityTest {
}
private void addAdapter() {
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- mapboxMap.getMarkerViewManager().addMarkerViewAdapter(
- new MarkerViewActivity.TextAdapter(rule.getActivity(), mapboxMap));
- }
- });
+ invoke(mapboxMap, (uiController, mapboxMap) -> mapboxMap.getMarkerViewManager().addMarkerViewAdapter(
+ new MarkerViewActivity.TextAdapter(rule.getActivity(), mapboxMap)));
}
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/PolygonTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/PolygonTest.java
index c90a5f60c6..be969f29c3 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/PolygonTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/PolygonTest.java
@@ -1,13 +1,10 @@
package com.mapbox.mapboxsdk.testapp.annotations;
import android.graphics.Color;
-import android.support.test.espresso.UiController;
import com.mapbox.mapboxsdk.annotations.Polygon;
import com.mapbox.mapboxsdk.annotations.PolygonOptions;
import com.mapbox.mapboxsdk.geometry.LatLng;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
@@ -28,31 +25,28 @@ public class PolygonTest extends BaseActivityTest {
@Ignore
public void addPolygonTest() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- LatLng latLngOne = new LatLng();
- LatLng latLngTwo = new LatLng(1, 0);
- LatLng latLngThree = new LatLng(1, 1);
-
- assertEquals("Polygons should be empty", 0, mapboxMap.getPolygons().size());
-
- final PolygonOptions options = new PolygonOptions();
- options.strokeColor(Color.BLUE);
- options.fillColor(Color.RED);
- options.add(latLngOne);
- options.add(latLngTwo);
- options.add(latLngThree);
- Polygon polygon = mapboxMap.addPolygon(options);
-
- assertEquals("Polygons should be 1", 1, mapboxMap.getPolygons().size());
- assertEquals("Polygon id should be 0", 0, polygon.getId());
- assertEquals("Polygon points size should match", 3, polygon.getPoints().size());
- assertEquals("Polygon stroke color should match", Color.BLUE, polygon.getStrokeColor());
- assertEquals("Polygon target should match", Color.RED, polygon.getFillColor());
- mapboxMap.clear();
- assertEquals("Polygons should be empty", 0, mapboxMap.getPolygons().size());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ LatLng latLngOne = new LatLng();
+ LatLng latLngTwo = new LatLng(1, 0);
+ LatLng latLngThree = new LatLng(1, 1);
+
+ assertEquals("Polygons should be empty", 0, mapboxMap.getPolygons().size());
+
+ final PolygonOptions options = new PolygonOptions();
+ options.strokeColor(Color.BLUE);
+ options.fillColor(Color.RED);
+ options.add(latLngOne);
+ options.add(latLngTwo);
+ options.add(latLngThree);
+ Polygon polygon = mapboxMap.addPolygon(options);
+
+ assertEquals("Polygons should be 1", 1, mapboxMap.getPolygons().size());
+ assertEquals("Polygon id should be 0", 0, polygon.getId());
+ assertEquals("Polygon points size should match", 3, polygon.getPoints().size());
+ assertEquals("Polygon stroke color should match", Color.BLUE, polygon.getStrokeColor());
+ assertEquals("Polygon target should match", Color.RED, polygon.getFillColor());
+ mapboxMap.clear();
+ assertEquals("Polygons should be empty", 0, mapboxMap.getPolygons().size());
});
}
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/PolylineTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/PolylineTest.java
index e6aa661729..b9c68ceab7 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/PolylineTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/PolylineTest.java
@@ -1,13 +1,10 @@
package com.mapbox.mapboxsdk.testapp.annotations;
import android.graphics.Color;
-import android.support.test.espresso.UiController;
import com.mapbox.mapboxsdk.annotations.Polyline;
import com.mapbox.mapboxsdk.annotations.PolylineOptions;
import com.mapbox.mapboxsdk.geometry.LatLng;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
@@ -28,27 +25,24 @@ public class PolylineTest extends BaseActivityTest {
@Ignore
public void addPolylineTest() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- LatLng latLngOne = new LatLng();
- LatLng latLngTwo = new LatLng(1, 0);
-
- assertEquals("Polygons should be empty", 0, mapboxMap.getPolygons().size());
-
- final PolylineOptions options = new PolylineOptions();
- options.color(Color.BLUE);
- options.add(latLngOne);
- options.add(latLngTwo);
- Polyline polyline = mapboxMap.addPolyline(options);
-
- assertEquals("Polylines should be 1", 1, mapboxMap.getPolylines().size());
- assertEquals("Polyline id should be 0", 0, polyline.getId());
- assertEquals("Polyline points size should match", 2, polyline.getPoints().size());
- assertEquals("Polyline stroke color should match", Color.BLUE, polyline.getColor());
- mapboxMap.clear();
- assertEquals("Polyline should be empty", 0, mapboxMap.getPolylines().size());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ LatLng latLngOne = new LatLng();
+ LatLng latLngTwo = new LatLng(1, 0);
+
+ assertEquals("Polygons should be empty", 0, mapboxMap.getPolygons().size());
+
+ final PolylineOptions options = new PolylineOptions();
+ options.color(Color.BLUE);
+ options.add(latLngOne);
+ options.add(latLngTwo);
+ Polyline polyline = mapboxMap.addPolyline(options);
+
+ assertEquals("Polylines should be 1", 1, mapboxMap.getPolylines().size());
+ assertEquals("Polyline id should be 0", 0, polyline.getId());
+ assertEquals("Polyline points size should match", 2, polyline.getPoints().size());
+ assertEquals("Polyline stroke color should match", Color.BLUE, polyline.getColor());
+ mapboxMap.clear();
+ assertEquals("Polyline should be empty", 0, mapboxMap.getPolylines().size());
});
}
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraAnimateTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraAnimateTest.java
index c16c8f05bb..94aec734a4 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraAnimateTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraAnimateTest.java
@@ -1,14 +1,11 @@
package com.mapbox.mapboxsdk.testapp.camera;
import android.graphics.PointF;
-import android.support.test.espresso.UiController;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
import com.mapbox.mapboxsdk.testapp.utils.TestConstants;
@@ -30,23 +27,20 @@ public class CameraAnimateTest extends BaseActivityTest {
@Ignore
public void testAnimateToCameraPositionTarget() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- float zoom = 1.0f;
- LatLng moveTarget = new LatLng(1, 1);
- CameraPosition initialPosition = new CameraPosition.Builder().target(
- new LatLng()).zoom(zoom).bearing(0).tilt(0).build();
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Default camera position should match default", cameraPosition, initialPosition);
- mapboxMap.animateCamera(CameraUpdateFactory.newLatLng(moveTarget));
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
- moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA);
- assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
- moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ float zoom = 1.0f;
+ LatLng moveTarget = new LatLng(1, 1);
+ CameraPosition initialPosition = new CameraPosition.Builder().target(
+ new LatLng()).zoom(zoom).bearing(0).tilt(0).build();
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Default camera position should match default", cameraPosition, initialPosition);
+ mapboxMap.animateCamera(CameraUpdateFactory.newLatLng(moveTarget));
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
+ moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
+ moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA);
});
}
@@ -54,20 +48,17 @@ public class CameraAnimateTest extends BaseActivityTest {
@Ignore
public void testAnimateToCameraPositionTargetZoom() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- final float moveZoom = 15.5f;
- final LatLng moveTarget = new LatLng(1.0000000001, 1.0000000003);
- mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(moveTarget, moveZoom));
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
- moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA);
- assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
- moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA);
- assertEquals("Moved zoom should match", cameraPosition.zoom, moveZoom, TestConstants.ZOOM_DELTA);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ final float moveZoom = 15.5f;
+ final LatLng moveTarget = new LatLng(1.0000000001, 1.0000000003);
+ mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(moveTarget, moveZoom));
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
+ moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
+ moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved zoom should match", cameraPosition.zoom, moveZoom, TestConstants.ZOOM_DELTA);
});
}
@@ -75,32 +66,29 @@ public class CameraAnimateTest extends BaseActivityTest {
@Ignore
public void testAnimateToCameraPosition() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- final LatLng moveTarget = new LatLng(1.0000000001, 1.0000000003);
- final float moveZoom = 15.5f;
- final float moveTilt = 45.5f;
- final float moveBearing = 12.5f;
-
- mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(
- new CameraPosition.Builder()
- .target(moveTarget)
- .zoom(moveZoom)
- .tilt(moveTilt)
- .bearing(moveBearing)
- .build())
- );
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
- moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA);
- assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
- moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA);
- assertEquals("Moved zoom should match", cameraPosition.zoom, moveZoom, TestConstants.ZOOM_DELTA);
- assertEquals("Moved zoom should match", cameraPosition.tilt, moveTilt, TestConstants.TILT_DELTA);
- assertEquals("Moved bearing should match", cameraPosition.bearing, moveBearing, TestConstants.BEARING_DELTA);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ final LatLng moveTarget = new LatLng(1.0000000001, 1.0000000003);
+ final float moveZoom = 15.5f;
+ final float moveTilt = 45.5f;
+ final float moveBearing = 12.5f;
+
+ mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(
+ new CameraPosition.Builder()
+ .target(moveTarget)
+ .zoom(moveZoom)
+ .tilt(moveTilt)
+ .bearing(moveBearing)
+ .build())
+ );
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
+ moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
+ moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved zoom should match", cameraPosition.zoom, moveZoom, TestConstants.ZOOM_DELTA);
+ assertEquals("Moved zoom should match", cameraPosition.tilt, moveTilt, TestConstants.TILT_DELTA);
+ assertEquals("Moved bearing should match", cameraPosition.bearing, moveBearing, TestConstants.BEARING_DELTA);
});
}
@@ -108,27 +96,24 @@ public class CameraAnimateTest extends BaseActivityTest {
@Ignore
public void testAnimateToBounds() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- final LatLng centerBounds = new LatLng(1, 1);
- LatLng cornerOne = new LatLng();
- LatLng cornerTwo = new LatLng(2, 2);
- final LatLngBounds.Builder builder = new LatLngBounds.Builder();
- builder.include(cornerOne);
- builder.include(cornerTwo);
- mapboxMap.animateCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), 0));
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Moved camera position latitude should match center bounds",
- cameraPosition.target.getLatitude(),
- centerBounds.getLatitude(),
- TestConstants.LAT_LNG_DELTA);
- assertEquals("Moved camera position longitude should match center bounds",
- cameraPosition.target.getLongitude(),
- centerBounds.getLongitude(),
- TestConstants.LAT_LNG_DELTA);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ final LatLng centerBounds = new LatLng(1, 1);
+ LatLng cornerOne = new LatLng();
+ LatLng cornerTwo = new LatLng(2, 2);
+ final LatLngBounds.Builder builder = new LatLngBounds.Builder();
+ builder.include(cornerOne);
+ builder.include(cornerTwo);
+ mapboxMap.animateCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), 0));
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match center bounds",
+ cameraPosition.target.getLatitude(),
+ centerBounds.getLatitude(),
+ TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved camera position longitude should match center bounds",
+ cameraPosition.target.getLongitude(),
+ centerBounds.getLongitude(),
+ TestConstants.LAT_LNG_DELTA);
});
}
@@ -136,21 +121,18 @@ public class CameraAnimateTest extends BaseActivityTest {
@Ignore
public void testAnimateToMoveBy() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- final PointF centerPoint = mapboxMap.getProjection().toScreenLocation(mapboxMap.getCameraPosition().target);
- final LatLng moveTarget = new LatLng(2, 2);
- final PointF moveTargetPoint = mapboxMap.getProjection().toScreenLocation(moveTarget);
- mapboxMap.animateCamera(CameraUpdateFactory.scrollBy(
- moveTargetPoint.x - centerPoint.x, moveTargetPoint.y - centerPoint.y));
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
- moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA_LARGE);
- assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
- moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA_LARGE);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ final PointF centerPoint = mapboxMap.getProjection().toScreenLocation(mapboxMap.getCameraPosition().target);
+ final LatLng moveTarget = new LatLng(2, 2);
+ final PointF moveTargetPoint = mapboxMap.getProjection().toScreenLocation(moveTarget);
+ mapboxMap.animateCamera(CameraUpdateFactory.scrollBy(
+ moveTargetPoint.x - centerPoint.x, moveTargetPoint.y - centerPoint.y));
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
+ moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA_LARGE);
+ assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
+ moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA_LARGE);
});
}
@@ -158,16 +140,13 @@ public class CameraAnimateTest extends BaseActivityTest {
@Ignore
public void testAnimateToZoomIn() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- float zoom = 1.0f;
- mapboxMap.animateCamera(CameraUpdateFactory.zoomIn());
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoom + 1,
- TestConstants.ZOOM_DELTA);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ float zoom = 1.0f;
+ mapboxMap.animateCamera(CameraUpdateFactory.zoomIn());
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoom + 1,
+ TestConstants.ZOOM_DELTA);
});
}
@@ -175,18 +154,15 @@ public class CameraAnimateTest extends BaseActivityTest {
@Ignore
public void testAnimateToZoomOut() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- float zoom = 10.0f;
- mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(), zoom));
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- mapboxMap.animateCamera(CameraUpdateFactory.zoomOut());
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoom - 1,
- TestConstants.ZOOM_DELTA);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ float zoom = 10.0f;
+ mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(), zoom));
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ mapboxMap.animateCamera(CameraUpdateFactory.zoomOut());
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoom - 1,
+ TestConstants.ZOOM_DELTA);
});
}
@@ -194,17 +170,14 @@ public class CameraAnimateTest extends BaseActivityTest {
@Ignore
public void testAnimateToZoomBy() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- float zoom = 1.0f;
- final float zoomBy = 2.45f;
- mapboxMap.animateCamera(CameraUpdateFactory.zoomBy(zoomBy));
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoom + zoomBy,
- TestConstants.ZOOM_DELTA);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ float zoom = 1.0f;
+ final float zoomBy = 2.45f;
+ mapboxMap.animateCamera(CameraUpdateFactory.zoomBy(zoomBy));
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoom + zoomBy,
+ TestConstants.ZOOM_DELTA);
});
}
@@ -212,16 +185,13 @@ public class CameraAnimateTest extends BaseActivityTest {
@Ignore
public void testAnimateToZoomTo() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- final float zoomTo = 2.45f;
- mapboxMap.animateCamera(CameraUpdateFactory.zoomTo(zoomTo));
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoomTo,
- TestConstants.ZOOM_DELTA);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ final float zoomTo = 2.45f;
+ mapboxMap.animateCamera(CameraUpdateFactory.zoomTo(zoomTo));
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoomTo,
+ TestConstants.ZOOM_DELTA);
});
}
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraEaseTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraEaseTest.java
index 8c67af7da3..e7c8d6b7bb 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraEaseTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraEaseTest.java
@@ -1,14 +1,11 @@
package com.mapbox.mapboxsdk.testapp.camera;
import android.graphics.PointF;
-import android.support.test.espresso.UiController;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
import com.mapbox.mapboxsdk.testapp.utils.TestConstants;
@@ -30,23 +27,20 @@ public class CameraEaseTest extends BaseActivityTest {
@Ignore
public void testEaseToCameraPositionTarget() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- float zoom = 1.0f;
- LatLng moveTarget = new LatLng(1, 1);
- CameraPosition initialPosition = new CameraPosition.Builder().target(
- new LatLng()).zoom(zoom).bearing(0).tilt(0).build();
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Default camera position should match default", cameraPosition, initialPosition);
- mapboxMap.easeCamera(CameraUpdateFactory.newLatLng(moveTarget));
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
- moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA);
- assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
- moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ float zoom = 1.0f;
+ LatLng moveTarget = new LatLng(1, 1);
+ CameraPosition initialPosition = new CameraPosition.Builder().target(
+ new LatLng()).zoom(zoom).bearing(0).tilt(0).build();
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Default camera position should match default", cameraPosition, initialPosition);
+ mapboxMap.easeCamera(CameraUpdateFactory.newLatLng(moveTarget));
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
+ moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
+ moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA);
});
}
@@ -54,20 +48,17 @@ public class CameraEaseTest extends BaseActivityTest {
@Ignore
public void testEaseToCameraPositionTargetZoom() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- final float moveZoom = 15.5f;
- final LatLng moveTarget = new LatLng(1.0000000001, 1.0000000003);
- mapboxMap.easeCamera(CameraUpdateFactory.newLatLngZoom(moveTarget, moveZoom));
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
- moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA);
- assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
- moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA);
- assertEquals("Moved zoom should match", cameraPosition.zoom, moveZoom, TestConstants.ZOOM_DELTA);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ final float moveZoom = 15.5f;
+ final LatLng moveTarget = new LatLng(1.0000000001, 1.0000000003);
+ mapboxMap.easeCamera(CameraUpdateFactory.newLatLngZoom(moveTarget, moveZoom));
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
+ moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
+ moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved zoom should match", cameraPosition.zoom, moveZoom, TestConstants.ZOOM_DELTA);
});
}
@@ -75,32 +66,29 @@ public class CameraEaseTest extends BaseActivityTest {
@Ignore
public void testEaseToCameraPosition() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- final LatLng moveTarget = new LatLng(1.0000000001, 1.0000000003);
- final float moveZoom = 15.5f;
- final float moveTilt = 45.5f;
- final float moveBearing = 12.5f;
-
- mapboxMap.easeCamera(CameraUpdateFactory.newCameraPosition(
- new CameraPosition.Builder()
- .target(moveTarget)
- .zoom(moveZoom)
- .tilt(moveTilt)
- .bearing(moveBearing)
- .build())
- );
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
- moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA);
- assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
- moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA);
- assertEquals("Moved zoom should match", cameraPosition.zoom, moveZoom, TestConstants.ZOOM_DELTA);
- assertEquals("Moved zoom should match", cameraPosition.tilt, moveTilt, TestConstants.TILT_DELTA);
- assertEquals("Moved bearing should match", cameraPosition.bearing, moveBearing, TestConstants.BEARING_DELTA);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ final LatLng moveTarget = new LatLng(1.0000000001, 1.0000000003);
+ final float moveZoom = 15.5f;
+ final float moveTilt = 45.5f;
+ final float moveBearing = 12.5f;
+
+ mapboxMap.easeCamera(CameraUpdateFactory.newCameraPosition(
+ new CameraPosition.Builder()
+ .target(moveTarget)
+ .zoom(moveZoom)
+ .tilt(moveTilt)
+ .bearing(moveBearing)
+ .build())
+ );
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
+ moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
+ moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved zoom should match", cameraPosition.zoom, moveZoom, TestConstants.ZOOM_DELTA);
+ assertEquals("Moved zoom should match", cameraPosition.tilt, moveTilt, TestConstants.TILT_DELTA);
+ assertEquals("Moved bearing should match", cameraPosition.bearing, moveBearing, TestConstants.BEARING_DELTA);
});
}
@@ -108,27 +96,24 @@ public class CameraEaseTest extends BaseActivityTest {
@Ignore
public void testEaseToBounds() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- final LatLng centerBounds = new LatLng(1, 1);
- LatLng cornerOne = new LatLng();
- LatLng cornerTwo = new LatLng(2, 2);
- final LatLngBounds.Builder builder = new LatLngBounds.Builder();
- builder.include(cornerOne);
- builder.include(cornerTwo);
- mapboxMap.easeCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), 0));
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Moved camera position latitude should match center bounds",
- cameraPosition.target.getLatitude(),
- centerBounds.getLatitude(),
- TestConstants.LAT_LNG_DELTA);
- assertEquals("Moved camera position longitude should match center bounds",
- cameraPosition.target.getLongitude(),
- centerBounds.getLongitude(),
- TestConstants.LAT_LNG_DELTA);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ final LatLng centerBounds = new LatLng(1, 1);
+ LatLng cornerOne = new LatLng();
+ LatLng cornerTwo = new LatLng(2, 2);
+ final LatLngBounds.Builder builder = new LatLngBounds.Builder();
+ builder.include(cornerOne);
+ builder.include(cornerTwo);
+ mapboxMap.easeCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), 0));
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match center bounds",
+ cameraPosition.target.getLatitude(),
+ centerBounds.getLatitude(),
+ TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved camera position longitude should match center bounds",
+ cameraPosition.target.getLongitude(),
+ centerBounds.getLongitude(),
+ TestConstants.LAT_LNG_DELTA);
});
}
@@ -136,21 +121,18 @@ public class CameraEaseTest extends BaseActivityTest {
@Ignore
public void testEaseToMoveBy() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- final PointF centerPoint = mapboxMap.getProjection().toScreenLocation(mapboxMap.getCameraPosition().target);
- final LatLng moveTarget = new LatLng(2, 2);
- final PointF moveTargetPoint = mapboxMap.getProjection().toScreenLocation(moveTarget);
- mapboxMap.easeCamera(CameraUpdateFactory.scrollBy(
- moveTargetPoint.x - centerPoint.x, moveTargetPoint.y - centerPoint.y));
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
- moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA_LARGE);
- assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
- moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA_LARGE);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ final PointF centerPoint = mapboxMap.getProjection().toScreenLocation(mapboxMap.getCameraPosition().target);
+ final LatLng moveTarget = new LatLng(2, 2);
+ final PointF moveTargetPoint = mapboxMap.getProjection().toScreenLocation(moveTarget);
+ mapboxMap.easeCamera(CameraUpdateFactory.scrollBy(
+ moveTargetPoint.x - centerPoint.x, moveTargetPoint.y - centerPoint.y));
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
+ moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA_LARGE);
+ assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
+ moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA_LARGE);
});
}
@@ -158,16 +140,13 @@ public class CameraEaseTest extends BaseActivityTest {
@Ignore
public void testEaseToZoomIn() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- float zoom = 1.0f;
- mapboxMap.easeCamera(CameraUpdateFactory.zoomIn());
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoom + 1,
- TestConstants.ZOOM_DELTA);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ float zoom = 1.0f;
+ mapboxMap.easeCamera(CameraUpdateFactory.zoomIn());
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoom + 1,
+ TestConstants.ZOOM_DELTA);
});
}
@@ -175,18 +154,15 @@ public class CameraEaseTest extends BaseActivityTest {
@Ignore
public void testEaseToZoomOut() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- float zoom = 10.0f;
- mapboxMap.easeCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(), zoom));
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- mapboxMap.easeCamera(CameraUpdateFactory.zoomOut());
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoom - 1,
- TestConstants.ZOOM_DELTA);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ float zoom = 10.0f;
+ mapboxMap.easeCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(), zoom));
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ mapboxMap.easeCamera(CameraUpdateFactory.zoomOut());
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoom - 1,
+ TestConstants.ZOOM_DELTA);
});
}
@@ -194,17 +170,14 @@ public class CameraEaseTest extends BaseActivityTest {
@Ignore
public void testEaseToZoomBy() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- float zoom = 1.0f;
- final float zoomBy = 2.45f;
- mapboxMap.easeCamera(CameraUpdateFactory.zoomBy(zoomBy));
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoom + zoomBy,
- TestConstants.ZOOM_DELTA);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ float zoom = 1.0f;
+ final float zoomBy = 2.45f;
+ mapboxMap.easeCamera(CameraUpdateFactory.zoomBy(zoomBy));
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoom + zoomBy,
+ TestConstants.ZOOM_DELTA);
});
}
@@ -212,16 +185,13 @@ public class CameraEaseTest extends BaseActivityTest {
@Ignore
public void testEaseToZoomTo() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- final float zoomTo = 2.45f;
- mapboxMap.easeCamera(CameraUpdateFactory.zoomTo(zoomTo));
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoomTo,
- TestConstants.ZOOM_DELTA);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ final float zoomTo = 2.45f;
+ mapboxMap.easeCamera(CameraUpdateFactory.zoomTo(zoomTo));
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoomTo,
+ TestConstants.ZOOM_DELTA);
});
}
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraMoveTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraMoveTest.java
index 54590981fa..37b9171a95 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraMoveTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraMoveTest.java
@@ -1,14 +1,12 @@
+
package com.mapbox.mapboxsdk.testapp.camera;
import android.graphics.PointF;
-import android.support.test.espresso.UiController;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
import com.mapbox.mapboxsdk.testapp.utils.TestConstants;
@@ -30,23 +28,20 @@ public class CameraMoveTest extends BaseActivityTest {
@Ignore
public void testMoveToCameraPositionTarget() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- float zoom = 1.0f;
- LatLng moveTarget = new LatLng(1, 1);
- CameraPosition initialPosition = new CameraPosition.Builder().target(
- new LatLng()).zoom(zoom).bearing(0).tilt(0).build();
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Default camera position should match default", cameraPosition, initialPosition);
- mapboxMap.moveCamera(CameraUpdateFactory.newLatLng(moveTarget));
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
- moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA);
- assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
- moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ float zoom = 1.0f;
+ LatLng moveTarget = new LatLng(1, 1);
+ CameraPosition initialPosition = new CameraPosition.Builder().target(
+ new LatLng()).zoom(zoom).bearing(0).tilt(0).build();
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Default camera position should match default", cameraPosition, initialPosition);
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLng(moveTarget));
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
+ moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
+ moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA);
});
}
@@ -54,20 +49,17 @@ public class CameraMoveTest extends BaseActivityTest {
@Ignore
public void testMoveToCameraPositionTargetZoom() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- final float moveZoom = 15.5f;
- final LatLng moveTarget = new LatLng(1.0000000001, 1.0000000003);
- mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(moveTarget, moveZoom));
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
- moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA);
- assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
- moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA);
- assertEquals("Moved zoom should match", cameraPosition.zoom, moveZoom, TestConstants.ZOOM_DELTA);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ final float moveZoom = 15.5f;
+ final LatLng moveTarget = new LatLng(1.0000000001, 1.0000000003);
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(moveTarget, moveZoom));
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
+ moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
+ moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved zoom should match", cameraPosition.zoom, moveZoom, TestConstants.ZOOM_DELTA);
});
}
@@ -75,32 +67,29 @@ public class CameraMoveTest extends BaseActivityTest {
@Ignore
public void testMoveToCameraPosition() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- final LatLng moveTarget = new LatLng(1.0000000001, 1.0000000003);
- final float moveZoom = 15.5f;
- final float moveTilt = 45.5f;
- final float moveBearing = 12.5f;
-
- mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(
- new CameraPosition.Builder()
- .target(moveTarget)
- .zoom(moveZoom)
- .tilt(moveTilt)
- .bearing(moveBearing)
- .build())
- );
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
- moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA);
- assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
- moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA);
- assertEquals("Moved zoom should match", cameraPosition.zoom, moveZoom, TestConstants.ZOOM_DELTA);
- assertEquals("Moved zoom should match", cameraPosition.tilt, moveTilt, TestConstants.TILT_DELTA);
- assertEquals("Moved bearing should match", cameraPosition.bearing, moveBearing, TestConstants.BEARING_DELTA);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ final LatLng moveTarget = new LatLng(1.0000000001, 1.0000000003);
+ final float moveZoom = 15.5f;
+ final float moveTilt = 45.5f;
+ final float moveBearing = 12.5f;
+
+ mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(
+ new CameraPosition.Builder()
+ .target(moveTarget)
+ .zoom(moveZoom)
+ .tilt(moveTilt)
+ .bearing(moveBearing)
+ .build())
+ );
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
+ moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
+ moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved zoom should match", cameraPosition.zoom, moveZoom, TestConstants.ZOOM_DELTA);
+ assertEquals("Moved zoom should match", cameraPosition.tilt, moveTilt, TestConstants.TILT_DELTA);
+ assertEquals("Moved bearing should match", cameraPosition.bearing, moveBearing, TestConstants.BEARING_DELTA);
});
}
@@ -108,27 +97,24 @@ public class CameraMoveTest extends BaseActivityTest {
@Ignore
public void testMoveToBounds() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- final LatLng centerBounds = new LatLng(1, 1);
- LatLng cornerOne = new LatLng();
- LatLng cornerTwo = new LatLng(2, 2);
- final LatLngBounds.Builder builder = new LatLngBounds.Builder();
- builder.include(cornerOne);
- builder.include(cornerTwo);
- mapboxMap.moveCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), 0));
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Moved camera position latitude should match center bounds",
- cameraPosition.target.getLatitude(),
- centerBounds.getLatitude(),
- TestConstants.LAT_LNG_DELTA);
- assertEquals("Moved camera position longitude should match center bounds",
- cameraPosition.target.getLongitude(),
- centerBounds.getLongitude(),
- TestConstants.LAT_LNG_DELTA);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ final LatLng centerBounds = new LatLng(1, 1);
+ LatLng cornerOne = new LatLng();
+ LatLng cornerTwo = new LatLng(2, 2);
+ final LatLngBounds.Builder builder = new LatLngBounds.Builder();
+ builder.include(cornerOne);
+ builder.include(cornerTwo);
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), 0));
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match center bounds",
+ cameraPosition.target.getLatitude(),
+ centerBounds.getLatitude(),
+ TestConstants.LAT_LNG_DELTA);
+ assertEquals("Moved camera position longitude should match center bounds",
+ cameraPosition.target.getLongitude(),
+ centerBounds.getLongitude(),
+ TestConstants.LAT_LNG_DELTA);
});
}
@@ -136,21 +122,18 @@ public class CameraMoveTest extends BaseActivityTest {
@Ignore
public void testMoveToMoveBy() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- final PointF centerPoint = mapboxMap.getProjection().toScreenLocation(mapboxMap.getCameraPosition().target);
- final LatLng moveTarget = new LatLng(2, 2);
- final PointF moveTargetPoint = mapboxMap.getProjection().toScreenLocation(moveTarget);
- mapboxMap.moveCamera(CameraUpdateFactory.scrollBy(
- moveTargetPoint.x - centerPoint.x, moveTargetPoint.y - centerPoint.y));
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
- moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA_LARGE);
- assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
- moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA_LARGE);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ final PointF centerPoint = mapboxMap.getProjection().toScreenLocation(mapboxMap.getCameraPosition().target);
+ final LatLng moveTarget = new LatLng(2, 2);
+ final PointF moveTargetPoint = mapboxMap.getProjection().toScreenLocation(moveTarget);
+ mapboxMap.moveCamera(CameraUpdateFactory.scrollBy(
+ moveTargetPoint.x - centerPoint.x, moveTargetPoint.y - centerPoint.y));
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera position latitude should match", cameraPosition.target.getLatitude(),
+ moveTarget.getLatitude(), TestConstants.LAT_LNG_DELTA_LARGE);
+ assertEquals("Moved camera position longitude should match", cameraPosition.target.getLongitude(),
+ moveTarget.getLongitude(), TestConstants.LAT_LNG_DELTA_LARGE);
});
}
@@ -158,16 +141,13 @@ public class CameraMoveTest extends BaseActivityTest {
@Ignore
public void testMoveToZoomIn() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- float zoom = 1.0f;
- mapboxMap.moveCamera(CameraUpdateFactory.zoomIn());
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoom + 1,
- TestConstants.ZOOM_DELTA);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ float zoom = 1.0f;
+ mapboxMap.moveCamera(CameraUpdateFactory.zoomIn());
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoom + 1,
+ TestConstants.ZOOM_DELTA);
});
}
@@ -175,18 +155,15 @@ public class CameraMoveTest extends BaseActivityTest {
@Ignore
public void testMoveToZoomOut() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- float zoom = 10.0f;
- mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(), zoom));
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- mapboxMap.moveCamera(CameraUpdateFactory.zoomOut());
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoom - 1,
- TestConstants.ZOOM_DELTA);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ float zoom = 10.0f;
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(), zoom));
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ mapboxMap.moveCamera(CameraUpdateFactory.zoomOut());
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoom - 1,
+ TestConstants.ZOOM_DELTA);
});
}
@@ -194,17 +171,14 @@ public class CameraMoveTest extends BaseActivityTest {
@Ignore
public void testMoveToZoomBy() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- float zoom = 1.0f;
- final float zoomBy = 2.45f;
- mapboxMap.moveCamera(CameraUpdateFactory.zoomBy(zoomBy));
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoom + zoomBy,
- TestConstants.ZOOM_DELTA);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ float zoom = 1.0f;
+ final float zoomBy = 2.45f;
+ mapboxMap.moveCamera(CameraUpdateFactory.zoomBy(zoomBy));
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoom + zoomBy,
+ TestConstants.ZOOM_DELTA);
});
}
@@ -212,16 +186,13 @@ public class CameraMoveTest extends BaseActivityTest {
@Ignore
public void testMoveToZoomTo() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- final float zoomTo = 2.45f;
- mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(zoomTo));
- uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoomTo,
- TestConstants.ZOOM_DELTA);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ final float zoomTo = 2.45f;
+ mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(zoomTo));
+ uiController.loopMainThreadForAtLeast(TestConstants.ANIMATION_TEST_TIME);
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Moved camera zoom should match moved camera zoom", cameraPosition.zoom, zoomTo,
+ TestConstants.ZOOM_DELTA);
});
}
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/feature/QueryRenderedFeaturesPropertiesTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/feature/QueryRenderedFeaturesPropertiesTest.java
index 8e6987b712..6e446ceda9 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/feature/QueryRenderedFeaturesPropertiesTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/feature/QueryRenderedFeaturesPropertiesTest.java
@@ -2,11 +2,9 @@ package com.mapbox.mapboxsdk.testapp.feature;
import android.graphics.PointF;
import android.support.test.espresso.ViewAction;
-import android.support.test.espresso.action.CoordinatesProvider;
import android.support.test.espresso.action.GeneralClickAction;
import android.support.test.espresso.action.Press;
import android.support.test.espresso.action.Tap;
-import android.view.View;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.testapp.R;
@@ -44,15 +42,12 @@ public class QueryRenderedFeaturesPropertiesTest extends BaseActivityTest {
private static ViewAction clickXY(final float x, final float y) {
return new GeneralClickAction(
Tap.SINGLE,
- new CoordinatesProvider() {
- @Override
- public float[] calculateCoordinates(View view) {
- final int[] screenPos = new int[2];
- view.getLocationOnScreen(screenPos);
- final float screenX = screenPos[0] + x;
- final float screenY = screenPos[1] + y;
- return new float[] {screenX, screenY};
- }
+ view -> {
+ final int[] screenPos = new int[2];
+ view.getLocationOnScreen(screenPos);
+ final float screenX = screenPos[0] + x;
+ final float screenY = screenPos[1] + y;
+ return new float[] {screenX, screenY};
},
Press.FINGER);
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/geometry/LatLngBoundsTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/geometry/LatLngBoundsTest.java
index f3ce9994a3..738f1e203f 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/geometry/LatLngBoundsTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/geometry/LatLngBoundsTest.java
@@ -1,11 +1,8 @@
package com.mapbox.mapboxsdk.testapp.geometry;
-import android.support.test.espresso.UiController;
-
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
import com.mapbox.mapboxsdk.testapp.activity.feature.QueryRenderedFeaturesBoxHighlightActivity;
@@ -26,15 +23,12 @@ public class LatLngBoundsTest extends BaseActivityTest {
public void testLatLngBounds() {
// regression test for #9322
validateTestSetup();
- MapboxMapAction.invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- LatLngBounds bounds = new LatLngBounds.Builder()
- .include(new LatLng(48.8589506, 2.2773457))
- .include(new LatLng(47.2383171, -1.6309316))
- .build();
- mapboxMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0));
- }
+ MapboxMapAction.invoke(mapboxMap, (uiController, mapboxMap) -> {
+ LatLngBounds bounds = new LatLngBounds.Builder()
+ .include(new LatLng(48.8589506, 2.2773457))
+ .include(new LatLng(47.2383171, -1.6309316))
+ .build();
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0));
});
}
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/AttributionTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/AttributionTest.java
index a20426c29c..09fbcb868c 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/AttributionTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/AttributionTest.java
@@ -150,15 +150,12 @@ public class AttributionTest extends BaseActivityTest {
}
private void buildUrlSpans() {
- onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
- @Override
- public void onViewAction(UiController uiController, View view) {
- for (Source source : mapboxMap.getSources()) {
- String attributionSource = source.getAttribution();
- if (!TextUtils.isEmpty(attributionSource)) {
- SpannableStringBuilder htmlBuilder = (SpannableStringBuilder) Html.fromHtml(attributionSource);
- urlSpans = htmlBuilder.getSpans(0, htmlBuilder.length(), URLSpan.class);
- }
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ for (Source source : mapboxMap.getSources()) {
+ String attributionSource = source.getAttribution();
+ if (!TextUtils.isEmpty(attributionSource)) {
+ SpannableStringBuilder htmlBuilder = (SpannableStringBuilder) Html.fromHtml(attributionSource);
+ urlSpans = htmlBuilder.getSpans(0, htmlBuilder.length(), URLSpan.class);
}
}
}));
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/CompassViewTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/CompassViewTest.java
index 28389a3386..2a510b4dc5 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/CompassViewTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/CompassViewTest.java
@@ -1,13 +1,9 @@
package com.mapbox.mapboxsdk.testapp.maps.widgets;
-import android.support.test.espresso.UiController;
-
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
import com.mapbox.mapboxsdk.testapp.utils.TestConstants;
@@ -41,18 +37,15 @@ public class CompassViewTest extends BaseActivityTest {
@Ignore
public void testVisible() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(
- new CameraPosition.Builder()
- .bearing(45)
- .zoom(1)
- .target(new LatLng())
- .build()
- ));
- uiController.loopMainThreadForAtLeast(500);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(
+ new CameraPosition.Builder()
+ .bearing(45)
+ .zoom(1)
+ .target(new LatLng())
+ .build()
+ ));
+ uiController.loopMainThreadForAtLeast(500);
});
onView(withId(R.id.compassView)).check(matches(isDisplayed()));
}
@@ -61,27 +54,19 @@ public class CompassViewTest extends BaseActivityTest {
@Ignore
public void testClick() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(
- new CameraPosition.Builder()
- .bearing(45)
- .zoom(1)
- .target(new LatLng())
- .build()
- ));
- }
- });
+ invoke(mapboxMap, (uiController, mapboxMap) -> mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(
+ new CameraPosition.Builder()
+ .bearing(45)
+ .zoom(1)
+ .target(new LatLng())
+ .build()
+ )));
onView(withId(R.id.compassView)).perform(click());
waitLoop();
onView(withId(R.id.compassView)).check(matches(not(isDisplayed())));
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- assertEquals("Camera bearing should face north, ", 0, cameraPosition.bearing, TestConstants.BEARING_DELTA);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ CameraPosition cameraPosition = mapboxMap.getCameraPosition();
+ assertEquals("Camera bearing should face north, ", 0, cameraPosition.bearing, TestConstants.BEARING_DELTA);
});
}
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/offline/OfflineUtilsTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/offline/OfflineUtilsTest.java
new file mode 100644
index 0000000000..84f84fdb90
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/offline/OfflineUtilsTest.java
@@ -0,0 +1,44 @@
+package com.mapbox.mapboxsdk.testapp.offline;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
+import com.mapbox.mapboxsdk.testapp.utils.OfflineUtils;
+
+import org.junit.Test;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+
+import static com.mapbox.mapboxsdk.testapp.activity.offline.OfflineActivity.JSON_CHARSET;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.TestCase.assertTrue;
+
+public class OfflineUtilsTest extends BaseActivityTest {
+
+ private static final String REGION_NAME = "hello world";
+ private static final String CONVERTED_REGION_NAME = "{\"FIELD_REGION_NAME\":\"hello world\"}";
+
+ @Override
+ protected Class getActivityClass() {
+ return EspressoTestActivity.class;
+ }
+
+ @Test
+ public void testOfflineUtilsConvertToBytes() throws UnsupportedEncodingException {
+ byte[] expected = CONVERTED_REGION_NAME.getBytes(JSON_CHARSET);
+ byte[] actual = OfflineUtils.convertRegionName(REGION_NAME);
+ assertTrue("Bytes arrays should match", Arrays.equals(expected, actual));
+ }
+
+ @Test
+ public void testOfflineUtilsConvertToString() throws UnsupportedEncodingException {
+ String actual = OfflineUtils.convertRegionName(CONVERTED_REGION_NAME.getBytes(JSON_CHARSET));
+ assertEquals("Strings should match", REGION_NAME, actual);
+ }
+
+ @Test
+ public void testOfflineUtilsConvertNoOp() {
+ String convertNoOp = OfflineUtils.convertRegionName(OfflineUtils.convertRegionName(REGION_NAME));
+ assertEquals("Strings should match", REGION_NAME, convertNoOp);
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BackgroundLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BackgroundLayerTest.java
index 0e4cf6a8ca..50f2fa7d62 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BackgroundLayerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BackgroundLayerTest.java
@@ -3,38 +3,34 @@
package com.mapbox.mapboxsdk.testapp.style;
import android.graphics.Color;
-import android.support.test.espresso.UiController;
import android.support.test.runner.AndroidJUnit4;
-import timber.log.Timber;
-
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.style.functions.CompositeFunction;
import com.mapbox.mapboxsdk.style.functions.CameraFunction;
-import com.mapbox.mapboxsdk.style.functions.SourceFunction;
-import com.mapbox.mapboxsdk.style.functions.stops.CategoricalStops;
import com.mapbox.mapboxsdk.style.functions.stops.ExponentialStops;
-import com.mapbox.mapboxsdk.style.functions.stops.IdentityStops;
import com.mapbox.mapboxsdk.style.functions.stops.IntervalStops;
-import com.mapbox.mapboxsdk.style.functions.stops.Stop;
-import com.mapbox.mapboxsdk.style.functions.stops.Stops;
import com.mapbox.mapboxsdk.style.layers.BackgroundLayer;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
+import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static com.mapbox.mapboxsdk.style.functions.Function.*;
+import timber.log.Timber;
+
+import static com.mapbox.mapboxsdk.style.functions.Function.zoom;
import static com.mapbox.mapboxsdk.style.functions.stops.Stop.stop;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stops.*;
+import static com.mapbox.mapboxsdk.style.functions.stops.Stops.exponential;
+import static com.mapbox.mapboxsdk.style.functions.stops.Stops.interval;
+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.backgroundColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.backgroundOpacity;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.backgroundPattern;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.visibility;
import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
-import static org.junit.Assert.*;
-import static com.mapbox.mapboxsdk.style.layers.Property.*;
-import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
-
-import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
-import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
/**
* Basic smoke tests for BackgroundLayer
@@ -51,12 +47,7 @@ public class BackgroundLayerTest extends BaseActivityTest {
private void setupLayer() {
Timber.i("Retrieving layer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- layer = mapboxMap.getLayerAs("background");
- }
- });
+ invoke(mapboxMap, (uiController, mapboxMap) -> layer = mapboxMap.getLayerAs("background"));
}
@Test
@@ -64,18 +55,15 @@ public class BackgroundLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("Visibility");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Get initial
- assertEquals(layer.getVisibility().getValue(), VISIBLE);
-
- // Set
- layer.setProperties(visibility(NONE));
- assertEquals(layer.getVisibility().getValue(), NONE);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
+
+ // Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
});
}
@@ -84,16 +72,13 @@ public class BackgroundLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("background-colorTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setBackgroundColorTransition(options);
- assertEquals(layer.getBackgroundColorTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setBackgroundColorTransition(options);
+ assertEquals(layer.getBackgroundColorTransition(), options);
});
}
@@ -102,15 +87,12 @@ public class BackgroundLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("background-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(backgroundColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getBackgroundColor().getValue(), (String) "rgba(0, 0, 0, 1)");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(backgroundColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getBackgroundColor().getValue(), (String) "rgba(0, 0, 0, 1)");
});
}
@@ -119,30 +101,27 @@ public class BackgroundLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("background-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- backgroundColor(
- zoom(
- exponential(
- stop(2, backgroundColor("rgba(0, 0, 0, 1)"))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ backgroundColor(
+ zoom(
+ exponential(
+ stop(2, backgroundColor("rgba(0, 0, 0, 1)"))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getBackgroundColor());
- assertNotNull(layer.getBackgroundColor().getFunction());
- assertEquals(CameraFunction.class, layer.getBackgroundColor().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getBackgroundColor().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getBackgroundColor().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getBackgroundColor().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getBackgroundColor());
+ assertNotNull(layer.getBackgroundColor().getFunction());
+ assertEquals(CameraFunction.class, layer.getBackgroundColor().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getBackgroundColor().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getBackgroundColor().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getBackgroundColor().getFunction().getStops()).size());
});
}
@@ -151,15 +130,12 @@ public class BackgroundLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("background-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(backgroundColor(Color.RED));
- assertEquals(layer.getBackgroundColorAsInt(), Color.RED);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(backgroundColor(Color.RED));
+ assertEquals(layer.getBackgroundColorAsInt(), Color.RED);
});
}
@@ -168,16 +144,13 @@ public class BackgroundLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("background-patternTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setBackgroundPatternTransition(options);
- assertEquals(layer.getBackgroundPatternTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setBackgroundPatternTransition(options);
+ assertEquals(layer.getBackgroundPatternTransition(), options);
});
}
@@ -186,15 +159,12 @@ public class BackgroundLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("background-pattern");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(backgroundPattern("pedestrian-polygon"));
- assertEquals((String) layer.getBackgroundPattern().getValue(), (String) "pedestrian-polygon");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(backgroundPattern("pedestrian-polygon"));
+ assertEquals((String) layer.getBackgroundPattern().getValue(), (String) "pedestrian-polygon");
});
}
@@ -203,29 +173,26 @@ public class BackgroundLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("background-pattern");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- backgroundPattern(
- zoom(
- interval(
- stop(2, backgroundPattern("pedestrian-polygon"))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ backgroundPattern(
+ zoom(
+ interval(
+ stop(2, backgroundPattern("pedestrian-polygon"))
)
)
- );
-
- // Verify
- assertNotNull(layer.getBackgroundPattern());
- assertNotNull(layer.getBackgroundPattern().getFunction());
- assertEquals(CameraFunction.class, layer.getBackgroundPattern().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getBackgroundPattern().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getBackgroundPattern().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getBackgroundPattern());
+ assertNotNull(layer.getBackgroundPattern().getFunction());
+ assertEquals(CameraFunction.class, layer.getBackgroundPattern().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getBackgroundPattern().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getBackgroundPattern().getFunction().getStops()).size());
});
}
@@ -234,16 +201,13 @@ public class BackgroundLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("background-opacityTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setBackgroundOpacityTransition(options);
- assertEquals(layer.getBackgroundOpacityTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setBackgroundOpacityTransition(options);
+ assertEquals(layer.getBackgroundOpacityTransition(), options);
});
}
@@ -252,15 +216,12 @@ public class BackgroundLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("background-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(backgroundOpacity(0.3f));
- assertEquals((Float) layer.getBackgroundOpacity().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(backgroundOpacity(0.3f));
+ assertEquals((Float) layer.getBackgroundOpacity().getValue(), (Float) 0.3f);
});
}
@@ -269,30 +230,27 @@ public class BackgroundLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("background-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- backgroundOpacity(
- zoom(
- exponential(
- stop(2, backgroundOpacity(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ backgroundOpacity(
+ zoom(
+ exponential(
+ stop(2, backgroundOpacity(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getBackgroundOpacity());
- assertNotNull(layer.getBackgroundOpacity().getFunction());
- assertEquals(CameraFunction.class, layer.getBackgroundOpacity().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getBackgroundOpacity().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getBackgroundOpacity().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getBackgroundOpacity().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getBackgroundOpacity());
+ assertNotNull(layer.getBackgroundOpacity().getFunction());
+ assertEquals(CameraFunction.class, layer.getBackgroundOpacity().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getBackgroundOpacity().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getBackgroundOpacity().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getBackgroundOpacity().getFunction().getStops()).size());
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerTest.java
index 559e446307..af6ed7f5b9 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerTest.java
@@ -3,14 +3,10 @@
package com.mapbox.mapboxsdk.testapp.style;
import android.graphics.Color;
-import android.support.test.espresso.UiController;
import android.support.test.runner.AndroidJUnit4;
-import timber.log.Timber;
-
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.style.functions.CompositeFunction;
import com.mapbox.mapboxsdk.style.functions.CameraFunction;
+import com.mapbox.mapboxsdk.style.functions.CompositeFunction;
import com.mapbox.mapboxsdk.style.functions.SourceFunction;
import com.mapbox.mapboxsdk.style.functions.stops.CategoricalStops;
import com.mapbox.mapboxsdk.style.functions.stops.ExponentialStops;
@@ -19,22 +15,42 @@ import com.mapbox.mapboxsdk.style.functions.stops.IntervalStops;
import com.mapbox.mapboxsdk.style.functions.stops.Stop;
import com.mapbox.mapboxsdk.style.functions.stops.Stops;
import com.mapbox.mapboxsdk.style.layers.CircleLayer;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
+import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static com.mapbox.mapboxsdk.style.functions.Function.*;
+import timber.log.Timber;
+
+import static com.mapbox.mapboxsdk.style.functions.Function.composite;
+import static com.mapbox.mapboxsdk.style.functions.Function.property;
+import static com.mapbox.mapboxsdk.style.functions.Function.zoom;
import static com.mapbox.mapboxsdk.style.functions.stops.Stop.stop;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stops.*;
+import static com.mapbox.mapboxsdk.style.functions.stops.Stops.categorical;
+import static com.mapbox.mapboxsdk.style.functions.stops.Stops.exponential;
+import static com.mapbox.mapboxsdk.style.functions.stops.Stops.interval;
+import static com.mapbox.mapboxsdk.style.layers.Property.CIRCLE_PITCH_ALIGNMENT_MAP;
+import static com.mapbox.mapboxsdk.style.layers.Property.CIRCLE_PITCH_SCALE_MAP;
+import static com.mapbox.mapboxsdk.style.layers.Property.CIRCLE_TRANSLATE_ANCHOR_MAP;
+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.circleBlur;
+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.circlePitchScale;
+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.circleStrokeOpacity;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleStrokeWidth;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleTranslate;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleTranslateAnchor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.visibility;
import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
-import static org.junit.Assert.*;
-import static com.mapbox.mapboxsdk.style.layers.Property.*;
-import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
-
-import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
-import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
/**
* Basic smoke tests for CircleLayer
@@ -51,17 +67,14 @@ public class CircleLayerTest extends BaseActivityTest {
private void setupLayer() {
Timber.i("Retrieving layer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Timber.i("Adding layer");
- layer = new CircleLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- // Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new CircleLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ // Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
});
}
@@ -71,18 +84,15 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("Visibility");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- // Get initial
- assertEquals(layer.getVisibility().getValue(), VISIBLE);
+ // Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
- // Set
- layer.setProperties(visibility(NONE));
- assertEquals(layer.getVisibility().getValue(), NONE);
- }
+ // Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
});
}
@@ -91,19 +101,16 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("SourceLayer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Get initial
- assertEquals(layer.getSourceLayer(), "composite");
-
- // Set
- final String sourceLayer = "test";
- layer.setSourceLayer(sourceLayer);
- assertEquals(layer.getSourceLayer(), sourceLayer);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getSourceLayer(), "composite");
+
+ // Set
+ final String sourceLayer = "test";
+ layer.setSourceLayer(sourceLayer);
+ assertEquals(layer.getSourceLayer(), sourceLayer);
});
}
@@ -112,16 +119,13 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-radiusTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setCircleRadiusTransition(options);
- assertEquals(layer.getCircleRadiusTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setCircleRadiusTransition(options);
+ assertEquals(layer.getCircleRadiusTransition(), options);
});
}
@@ -130,15 +134,12 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-radius");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(circleRadius(0.3f));
- assertEquals((Float) layer.getCircleRadius().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(circleRadius(0.3f));
+ assertEquals((Float) layer.getCircleRadius().getValue(), (Float) 0.3f);
});
}
@@ -147,30 +148,27 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-radius");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleRadius(
- zoom(
- exponential(
- stop(2, circleRadius(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleRadius(
+ zoom(
+ exponential(
+ stop(2, circleRadius(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getCircleRadius());
- assertNotNull(layer.getCircleRadius().getFunction());
- assertEquals(CameraFunction.class, layer.getCircleRadius().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getCircleRadius().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getCircleRadius().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getCircleRadius().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleRadius());
+ assertNotNull(layer.getCircleRadius().getFunction());
+ assertEquals(CameraFunction.class, layer.getCircleRadius().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getCircleRadius().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getCircleRadius().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getCircleRadius().getFunction().getStops()).size());
});
}
@@ -179,23 +177,20 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-radius");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleRadius(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getCircleRadius());
- assertNotNull(layer.getCircleRadius().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleRadius().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleRadius().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getCircleRadius().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleRadius(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleRadius());
+ assertNotNull(layer.getCircleRadius().getFunction());
+ assertEquals(SourceFunction.class, layer.getCircleRadius().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleRadius().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getCircleRadius().getFunction().getStops().getClass());
});
}
@@ -204,30 +199,27 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-radius");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleRadius(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, circleRadius(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleRadius(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, circleRadius(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getCircleRadius());
- assertNotNull(layer.getCircleRadius().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleRadius().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleRadius().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getCircleRadius().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleRadius());
+ assertNotNull(layer.getCircleRadius().getFunction());
+ assertEquals(SourceFunction.class, layer.getCircleRadius().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleRadius().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getCircleRadius().getFunction().getStops().getClass());
});
}
@@ -236,33 +228,30 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-radius");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleRadius(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, circleRadius(0.3f))
- )
- ).withDefaultValue(circleRadius(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleRadius());
- assertNotNull(layer.getCircleRadius().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleRadius().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleRadius().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getCircleRadius().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getCircleRadius().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getCircleRadius().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getCircleRadius().getFunction()).getDefaultValue().getValue());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleRadius(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, circleRadius(0.3f))
+ )
+ ).withDefaultValue(circleRadius(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleRadius());
+ assertNotNull(layer.getCircleRadius().getFunction());
+ assertEquals(SourceFunction.class, layer.getCircleRadius().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleRadius().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getCircleRadius().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getCircleRadius().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getCircleRadius().getFunction()).getDefaultValue().getValue());
+ assertEquals(0.3f, ((SourceFunction) layer.getCircleRadius().getFunction()).getDefaultValue().getValue());
});
}
@@ -272,38 +261,35 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-radius");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleRadius(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, circleRadius(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(circleRadius(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleRadius());
- assertNotNull(layer.getCircleRadius().getFunction());
- assertEquals(CompositeFunction.class, layer.getCircleRadius().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getCircleRadius().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getCircleRadius().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getCircleRadius().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getCircleRadius().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleRadius(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, circleRadius(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(circleRadius(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleRadius());
+ assertNotNull(layer.getCircleRadius().getFunction());
+ assertEquals(CompositeFunction.class, layer.getCircleRadius().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getCircleRadius().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getCircleRadius().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getCircleRadius().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getCircleRadius().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
});
}
@@ -312,16 +298,13 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-colorTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setCircleColorTransition(options);
- assertEquals(layer.getCircleColorTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setCircleColorTransition(options);
+ assertEquals(layer.getCircleColorTransition(), options);
});
}
@@ -330,15 +313,12 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(circleColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getCircleColor().getValue(), (String) "rgba(0, 0, 0, 1)");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(circleColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getCircleColor().getValue(), (String) "rgba(0, 0, 0, 1)");
});
}
@@ -347,30 +327,27 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleColor(
- zoom(
- exponential(
- stop(2, circleColor("rgba(0, 0, 0, 1)"))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleColor(
+ zoom(
+ exponential(
+ stop(2, circleColor("rgba(0, 0, 0, 1)"))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getCircleColor());
- assertNotNull(layer.getCircleColor().getFunction());
- assertEquals(CameraFunction.class, layer.getCircleColor().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getCircleColor().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getCircleColor().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getCircleColor().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleColor());
+ assertNotNull(layer.getCircleColor().getFunction());
+ assertEquals(CameraFunction.class, layer.getCircleColor().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getCircleColor().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getCircleColor().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getCircleColor().getFunction().getStops()).size());
});
}
@@ -379,23 +356,20 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleColor(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getCircleColor());
- assertNotNull(layer.getCircleColor().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleColor().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getCircleColor().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleColor(property("FeaturePropertyA", Stops.<String>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleColor());
+ assertNotNull(layer.getCircleColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getCircleColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleColor().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getCircleColor().getFunction().getStops().getClass());
});
}
@@ -404,30 +378,27 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleColor(
- property(
- "FeaturePropertyA",
- exponential(
- stop(Color.RED, circleColor(Color.RED))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleColor(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(Color.RED, circleColor(Color.RED))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getCircleColor());
- assertNotNull(layer.getCircleColor().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleColor().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getCircleColor().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleColor());
+ assertNotNull(layer.getCircleColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getCircleColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleColor().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getCircleColor().getFunction().getStops().getClass());
});
}
@@ -436,33 +407,30 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleColor(
- property(
- "FeaturePropertyA",
- categorical(
- stop("valueA", circleColor(Color.RED))
- )
- ).withDefaultValue(circleColor(Color.GREEN))
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleColor());
- assertNotNull(layer.getCircleColor().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleColor().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getCircleColor().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getCircleColor().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getCircleColor().getFunction()).getDefaultValue().getValue());
- assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getCircleColor().getFunction()).getDefaultValue().getColorInt());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleColor(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop("valueA", circleColor(Color.RED))
+ )
+ ).withDefaultValue(circleColor(Color.GREEN))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleColor());
+ assertNotNull(layer.getCircleColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getCircleColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleColor().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getCircleColor().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getCircleColor().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getCircleColor().getFunction()).getDefaultValue().getValue());
+ assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getCircleColor().getFunction()).getDefaultValue().getColorInt());
});
}
@@ -472,15 +440,12 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(circleColor(Color.RED));
- assertEquals(layer.getCircleColorAsInt(), Color.RED);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(circleColor(Color.RED));
+ assertEquals(layer.getCircleColorAsInt(), Color.RED);
});
}
@@ -489,16 +454,13 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-blurTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setCircleBlurTransition(options);
- assertEquals(layer.getCircleBlurTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setCircleBlurTransition(options);
+ assertEquals(layer.getCircleBlurTransition(), options);
});
}
@@ -507,15 +469,12 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(circleBlur(0.3f));
- assertEquals((Float) layer.getCircleBlur().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(circleBlur(0.3f));
+ assertEquals((Float) layer.getCircleBlur().getValue(), (Float) 0.3f);
});
}
@@ -524,30 +483,27 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleBlur(
- zoom(
- exponential(
- stop(2, circleBlur(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleBlur(
+ zoom(
+ exponential(
+ stop(2, circleBlur(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getCircleBlur());
- assertNotNull(layer.getCircleBlur().getFunction());
- assertEquals(CameraFunction.class, layer.getCircleBlur().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getCircleBlur().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getCircleBlur().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getCircleBlur().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleBlur());
+ assertNotNull(layer.getCircleBlur().getFunction());
+ assertEquals(CameraFunction.class, layer.getCircleBlur().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getCircleBlur().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getCircleBlur().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getCircleBlur().getFunction().getStops()).size());
});
}
@@ -556,23 +512,20 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleBlur(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getCircleBlur());
- assertNotNull(layer.getCircleBlur().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleBlur().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getCircleBlur().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleBlur(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleBlur());
+ assertNotNull(layer.getCircleBlur().getFunction());
+ assertEquals(SourceFunction.class, layer.getCircleBlur().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleBlur().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getCircleBlur().getFunction().getStops().getClass());
});
}
@@ -581,30 +534,27 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleBlur(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, circleBlur(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleBlur(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, circleBlur(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getCircleBlur());
- assertNotNull(layer.getCircleBlur().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleBlur().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getCircleBlur().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleBlur());
+ assertNotNull(layer.getCircleBlur().getFunction());
+ assertEquals(SourceFunction.class, layer.getCircleBlur().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleBlur().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getCircleBlur().getFunction().getStops().getClass());
});
}
@@ -613,33 +563,30 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleBlur(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, circleBlur(0.3f))
- )
- ).withDefaultValue(circleBlur(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleBlur());
- assertNotNull(layer.getCircleBlur().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleBlur().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getCircleBlur().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getCircleBlur().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getCircleBlur().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getCircleBlur().getFunction()).getDefaultValue().getValue());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleBlur(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, circleBlur(0.3f))
+ )
+ ).withDefaultValue(circleBlur(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleBlur());
+ assertNotNull(layer.getCircleBlur().getFunction());
+ assertEquals(SourceFunction.class, layer.getCircleBlur().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleBlur().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getCircleBlur().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getCircleBlur().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getCircleBlur().getFunction()).getDefaultValue().getValue());
+ assertEquals(0.3f, ((SourceFunction) layer.getCircleBlur().getFunction()).getDefaultValue().getValue());
});
}
@@ -649,38 +596,35 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleBlur(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, circleBlur(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(circleBlur(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleBlur());
- assertNotNull(layer.getCircleBlur().getFunction());
- assertEquals(CompositeFunction.class, layer.getCircleBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getCircleBlur().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getCircleBlur().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getCircleBlur().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getCircleBlur().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleBlur(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, circleBlur(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(circleBlur(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleBlur());
+ assertNotNull(layer.getCircleBlur().getFunction());
+ assertEquals(CompositeFunction.class, layer.getCircleBlur().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getCircleBlur().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getCircleBlur().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getCircleBlur().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getCircleBlur().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
});
}
@@ -689,16 +633,13 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-opacityTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setCircleOpacityTransition(options);
- assertEquals(layer.getCircleOpacityTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setCircleOpacityTransition(options);
+ assertEquals(layer.getCircleOpacityTransition(), options);
});
}
@@ -707,15 +648,12 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(circleOpacity(0.3f));
- assertEquals((Float) layer.getCircleOpacity().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(circleOpacity(0.3f));
+ assertEquals((Float) layer.getCircleOpacity().getValue(), (Float) 0.3f);
});
}
@@ -724,30 +662,27 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleOpacity(
- zoom(
- exponential(
- stop(2, circleOpacity(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleOpacity(
+ zoom(
+ exponential(
+ stop(2, circleOpacity(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getCircleOpacity());
- assertNotNull(layer.getCircleOpacity().getFunction());
- assertEquals(CameraFunction.class, layer.getCircleOpacity().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getCircleOpacity().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getCircleOpacity().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getCircleOpacity().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleOpacity());
+ assertNotNull(layer.getCircleOpacity().getFunction());
+ assertEquals(CameraFunction.class, layer.getCircleOpacity().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getCircleOpacity().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getCircleOpacity().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getCircleOpacity().getFunction().getStops()).size());
});
}
@@ -756,23 +691,20 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleOpacity(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getCircleOpacity());
- assertNotNull(layer.getCircleOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleOpacity().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getCircleOpacity().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleOpacity(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleOpacity());
+ assertNotNull(layer.getCircleOpacity().getFunction());
+ assertEquals(SourceFunction.class, layer.getCircleOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleOpacity().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getCircleOpacity().getFunction().getStops().getClass());
});
}
@@ -781,30 +713,27 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleOpacity(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, circleOpacity(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleOpacity(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, circleOpacity(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getCircleOpacity());
- assertNotNull(layer.getCircleOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleOpacity().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getCircleOpacity().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleOpacity());
+ assertNotNull(layer.getCircleOpacity().getFunction());
+ assertEquals(SourceFunction.class, layer.getCircleOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleOpacity().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getCircleOpacity().getFunction().getStops().getClass());
});
}
@@ -813,33 +742,30 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleOpacity(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, circleOpacity(0.3f))
- )
- ).withDefaultValue(circleOpacity(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleOpacity());
- assertNotNull(layer.getCircleOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleOpacity().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getCircleOpacity().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getCircleOpacity().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getCircleOpacity().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getCircleOpacity().getFunction()).getDefaultValue().getValue());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleOpacity(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, circleOpacity(0.3f))
+ )
+ ).withDefaultValue(circleOpacity(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleOpacity());
+ assertNotNull(layer.getCircleOpacity().getFunction());
+ assertEquals(SourceFunction.class, layer.getCircleOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleOpacity().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getCircleOpacity().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getCircleOpacity().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getCircleOpacity().getFunction()).getDefaultValue().getValue());
+ assertEquals(0.3f, ((SourceFunction) layer.getCircleOpacity().getFunction()).getDefaultValue().getValue());
});
}
@@ -849,38 +775,35 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleOpacity(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, circleOpacity(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(circleOpacity(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleOpacity());
- assertNotNull(layer.getCircleOpacity().getFunction());
- assertEquals(CompositeFunction.class, layer.getCircleOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getCircleOpacity().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getCircleOpacity().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getCircleOpacity().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getCircleOpacity().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleOpacity(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, circleOpacity(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(circleOpacity(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleOpacity());
+ assertNotNull(layer.getCircleOpacity().getFunction());
+ assertEquals(CompositeFunction.class, layer.getCircleOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getCircleOpacity().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getCircleOpacity().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getCircleOpacity().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getCircleOpacity().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
});
}
@@ -889,16 +812,13 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-translateTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setCircleTranslateTransition(options);
- assertEquals(layer.getCircleTranslateTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setCircleTranslateTransition(options);
+ assertEquals(layer.getCircleTranslateTransition(), options);
});
}
@@ -907,15 +827,12 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-translate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(circleTranslate(new Float[] {0f, 0f}));
- assertEquals((Float[]) layer.getCircleTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(circleTranslate(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getCircleTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
});
}
@@ -924,30 +841,27 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-translate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleTranslate(
- zoom(
- exponential(
- stop(2, circleTranslate(new Float[] {0f, 0f}))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleTranslate(
+ zoom(
+ exponential(
+ stop(2, circleTranslate(new Float[] {0f, 0f}))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getCircleTranslate());
- assertNotNull(layer.getCircleTranslate().getFunction());
- assertEquals(CameraFunction.class, layer.getCircleTranslate().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getCircleTranslate().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getCircleTranslate().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getCircleTranslate().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleTranslate());
+ assertNotNull(layer.getCircleTranslate().getFunction());
+ assertEquals(CameraFunction.class, layer.getCircleTranslate().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getCircleTranslate().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getCircleTranslate().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getCircleTranslate().getFunction().getStops()).size());
});
}
@@ -956,15 +870,12 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-translate-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(circleTranslateAnchor(CIRCLE_TRANSLATE_ANCHOR_MAP));
- assertEquals((String) layer.getCircleTranslateAnchor().getValue(), (String) CIRCLE_TRANSLATE_ANCHOR_MAP);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(circleTranslateAnchor(CIRCLE_TRANSLATE_ANCHOR_MAP));
+ assertEquals((String) layer.getCircleTranslateAnchor().getValue(), (String) CIRCLE_TRANSLATE_ANCHOR_MAP);
});
}
@@ -973,29 +884,26 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-translate-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleTranslateAnchor(
- zoom(
- interval(
- stop(2, circleTranslateAnchor(CIRCLE_TRANSLATE_ANCHOR_MAP))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleTranslateAnchor(
+ zoom(
+ interval(
+ stop(2, circleTranslateAnchor(CIRCLE_TRANSLATE_ANCHOR_MAP))
)
)
- );
-
- // Verify
- assertNotNull(layer.getCircleTranslateAnchor());
- assertNotNull(layer.getCircleTranslateAnchor().getFunction());
- assertEquals(CameraFunction.class, layer.getCircleTranslateAnchor().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getCircleTranslateAnchor().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getCircleTranslateAnchor().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleTranslateAnchor());
+ assertNotNull(layer.getCircleTranslateAnchor().getFunction());
+ assertEquals(CameraFunction.class, layer.getCircleTranslateAnchor().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getCircleTranslateAnchor().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getCircleTranslateAnchor().getFunction().getStops()).size());
});
}
@@ -1004,15 +912,12 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-pitch-scale");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(circlePitchScale(CIRCLE_PITCH_SCALE_MAP));
- assertEquals((String) layer.getCirclePitchScale().getValue(), (String) CIRCLE_PITCH_SCALE_MAP);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(circlePitchScale(CIRCLE_PITCH_SCALE_MAP));
+ assertEquals((String) layer.getCirclePitchScale().getValue(), (String) CIRCLE_PITCH_SCALE_MAP);
});
}
@@ -1021,29 +926,26 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-pitch-scale");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circlePitchScale(
- zoom(
- interval(
- stop(2, circlePitchScale(CIRCLE_PITCH_SCALE_MAP))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circlePitchScale(
+ zoom(
+ interval(
+ stop(2, circlePitchScale(CIRCLE_PITCH_SCALE_MAP))
)
)
- );
-
- // Verify
- assertNotNull(layer.getCirclePitchScale());
- assertNotNull(layer.getCirclePitchScale().getFunction());
- assertEquals(CameraFunction.class, layer.getCirclePitchScale().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getCirclePitchScale().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getCirclePitchScale().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCirclePitchScale());
+ assertNotNull(layer.getCirclePitchScale().getFunction());
+ assertEquals(CameraFunction.class, layer.getCirclePitchScale().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getCirclePitchScale().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getCirclePitchScale().getFunction().getStops()).size());
});
}
@@ -1052,15 +954,12 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-pitch-alignment");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(circlePitchAlignment(CIRCLE_PITCH_ALIGNMENT_MAP));
- assertEquals((String) layer.getCirclePitchAlignment().getValue(), (String) CIRCLE_PITCH_ALIGNMENT_MAP);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(circlePitchAlignment(CIRCLE_PITCH_ALIGNMENT_MAP));
+ assertEquals((String) layer.getCirclePitchAlignment().getValue(), (String) CIRCLE_PITCH_ALIGNMENT_MAP);
});
}
@@ -1069,29 +968,26 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-pitch-alignment");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circlePitchAlignment(
- zoom(
- interval(
- stop(2, circlePitchAlignment(CIRCLE_PITCH_ALIGNMENT_MAP))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circlePitchAlignment(
+ zoom(
+ interval(
+ stop(2, circlePitchAlignment(CIRCLE_PITCH_ALIGNMENT_MAP))
)
)
- );
-
- // Verify
- assertNotNull(layer.getCirclePitchAlignment());
- assertNotNull(layer.getCirclePitchAlignment().getFunction());
- assertEquals(CameraFunction.class, layer.getCirclePitchAlignment().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getCirclePitchAlignment().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getCirclePitchAlignment().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCirclePitchAlignment());
+ assertNotNull(layer.getCirclePitchAlignment().getFunction());
+ assertEquals(CameraFunction.class, layer.getCirclePitchAlignment().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getCirclePitchAlignment().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getCirclePitchAlignment().getFunction().getStops()).size());
});
}
@@ -1100,16 +996,13 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-stroke-widthTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setCircleStrokeWidthTransition(options);
- assertEquals(layer.getCircleStrokeWidthTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setCircleStrokeWidthTransition(options);
+ assertEquals(layer.getCircleStrokeWidthTransition(), options);
});
}
@@ -1118,15 +1011,12 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-stroke-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(circleStrokeWidth(0.3f));
- assertEquals((Float) layer.getCircleStrokeWidth().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(circleStrokeWidth(0.3f));
+ assertEquals((Float) layer.getCircleStrokeWidth().getValue(), (Float) 0.3f);
});
}
@@ -1135,30 +1025,27 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-stroke-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleStrokeWidth(
- zoom(
- exponential(
- stop(2, circleStrokeWidth(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleStrokeWidth(
+ zoom(
+ exponential(
+ stop(2, circleStrokeWidth(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getCircleStrokeWidth());
- assertNotNull(layer.getCircleStrokeWidth().getFunction());
- assertEquals(CameraFunction.class, layer.getCircleStrokeWidth().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getCircleStrokeWidth().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getCircleStrokeWidth().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getCircleStrokeWidth().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleStrokeWidth());
+ assertNotNull(layer.getCircleStrokeWidth().getFunction());
+ assertEquals(CameraFunction.class, layer.getCircleStrokeWidth().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getCircleStrokeWidth().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getCircleStrokeWidth().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getCircleStrokeWidth().getFunction().getStops()).size());
});
}
@@ -1167,23 +1054,20 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-stroke-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleStrokeWidth(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getCircleStrokeWidth());
- assertNotNull(layer.getCircleStrokeWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleStrokeWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeWidth().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getCircleStrokeWidth().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleStrokeWidth(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleStrokeWidth());
+ assertNotNull(layer.getCircleStrokeWidth().getFunction());
+ assertEquals(SourceFunction.class, layer.getCircleStrokeWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeWidth().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getCircleStrokeWidth().getFunction().getStops().getClass());
});
}
@@ -1192,30 +1076,27 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-stroke-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleStrokeWidth(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, circleStrokeWidth(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleStrokeWidth(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, circleStrokeWidth(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getCircleStrokeWidth());
- assertNotNull(layer.getCircleStrokeWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleStrokeWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeWidth().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getCircleStrokeWidth().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleStrokeWidth());
+ assertNotNull(layer.getCircleStrokeWidth().getFunction());
+ assertEquals(SourceFunction.class, layer.getCircleStrokeWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeWidth().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getCircleStrokeWidth().getFunction().getStops().getClass());
});
}
@@ -1224,33 +1105,30 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-stroke-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleStrokeWidth(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, circleStrokeWidth(0.3f))
- )
- ).withDefaultValue(circleStrokeWidth(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleStrokeWidth());
- assertNotNull(layer.getCircleStrokeWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleStrokeWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeWidth().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getCircleStrokeWidth().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getCircleStrokeWidth().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getCircleStrokeWidth().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getCircleStrokeWidth().getFunction()).getDefaultValue().getValue());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleStrokeWidth(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, circleStrokeWidth(0.3f))
+ )
+ ).withDefaultValue(circleStrokeWidth(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleStrokeWidth());
+ assertNotNull(layer.getCircleStrokeWidth().getFunction());
+ assertEquals(SourceFunction.class, layer.getCircleStrokeWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeWidth().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getCircleStrokeWidth().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getCircleStrokeWidth().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getCircleStrokeWidth().getFunction()).getDefaultValue().getValue());
+ assertEquals(0.3f, ((SourceFunction) layer.getCircleStrokeWidth().getFunction()).getDefaultValue().getValue());
});
}
@@ -1260,38 +1138,35 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-stroke-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleStrokeWidth(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, circleStrokeWidth(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(circleStrokeWidth(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleStrokeWidth());
- assertNotNull(layer.getCircleStrokeWidth().getFunction());
- assertEquals(CompositeFunction.class, layer.getCircleStrokeWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getCircleStrokeWidth().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getCircleStrokeWidth().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getCircleStrokeWidth().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getCircleStrokeWidth().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleStrokeWidth(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, circleStrokeWidth(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(circleStrokeWidth(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleStrokeWidth());
+ assertNotNull(layer.getCircleStrokeWidth().getFunction());
+ assertEquals(CompositeFunction.class, layer.getCircleStrokeWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getCircleStrokeWidth().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getCircleStrokeWidth().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getCircleStrokeWidth().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getCircleStrokeWidth().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
});
}
@@ -1300,16 +1175,13 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-stroke-colorTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setCircleStrokeColorTransition(options);
- assertEquals(layer.getCircleStrokeColorTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setCircleStrokeColorTransition(options);
+ assertEquals(layer.getCircleStrokeColorTransition(), options);
});
}
@@ -1318,15 +1190,12 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-stroke-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(circleStrokeColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getCircleStrokeColor().getValue(), (String) "rgba(0, 0, 0, 1)");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(circleStrokeColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getCircleStrokeColor().getValue(), (String) "rgba(0, 0, 0, 1)");
});
}
@@ -1335,30 +1204,27 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-stroke-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleStrokeColor(
- zoom(
- exponential(
- stop(2, circleStrokeColor("rgba(0, 0, 0, 1)"))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleStrokeColor(
+ zoom(
+ exponential(
+ stop(2, circleStrokeColor("rgba(0, 0, 0, 1)"))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getCircleStrokeColor());
- assertNotNull(layer.getCircleStrokeColor().getFunction());
- assertEquals(CameraFunction.class, layer.getCircleStrokeColor().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getCircleStrokeColor().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getCircleStrokeColor().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getCircleStrokeColor().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleStrokeColor());
+ assertNotNull(layer.getCircleStrokeColor().getFunction());
+ assertEquals(CameraFunction.class, layer.getCircleStrokeColor().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getCircleStrokeColor().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getCircleStrokeColor().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getCircleStrokeColor().getFunction().getStops()).size());
});
}
@@ -1367,23 +1233,20 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-stroke-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleStrokeColor(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getCircleStrokeColor());
- assertNotNull(layer.getCircleStrokeColor().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleStrokeColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeColor().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getCircleStrokeColor().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleStrokeColor(property("FeaturePropertyA", Stops.<String>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleStrokeColor());
+ assertNotNull(layer.getCircleStrokeColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getCircleStrokeColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeColor().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getCircleStrokeColor().getFunction().getStops().getClass());
});
}
@@ -1392,30 +1255,27 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-stroke-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleStrokeColor(
- property(
- "FeaturePropertyA",
- exponential(
- stop(Color.RED, circleStrokeColor(Color.RED))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleStrokeColor(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(Color.RED, circleStrokeColor(Color.RED))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getCircleStrokeColor());
- assertNotNull(layer.getCircleStrokeColor().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleStrokeColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeColor().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getCircleStrokeColor().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleStrokeColor());
+ assertNotNull(layer.getCircleStrokeColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getCircleStrokeColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeColor().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getCircleStrokeColor().getFunction().getStops().getClass());
});
}
@@ -1424,33 +1284,30 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-stroke-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleStrokeColor(
- property(
- "FeaturePropertyA",
- categorical(
- stop("valueA", circleStrokeColor(Color.RED))
- )
- ).withDefaultValue(circleStrokeColor(Color.GREEN))
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleStrokeColor());
- assertNotNull(layer.getCircleStrokeColor().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleStrokeColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeColor().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getCircleStrokeColor().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getCircleStrokeColor().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getCircleStrokeColor().getFunction()).getDefaultValue().getValue());
- assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getCircleStrokeColor().getFunction()).getDefaultValue().getColorInt());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleStrokeColor(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop("valueA", circleStrokeColor(Color.RED))
+ )
+ ).withDefaultValue(circleStrokeColor(Color.GREEN))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleStrokeColor());
+ assertNotNull(layer.getCircleStrokeColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getCircleStrokeColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeColor().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getCircleStrokeColor().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getCircleStrokeColor().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getCircleStrokeColor().getFunction()).getDefaultValue().getValue());
+ assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getCircleStrokeColor().getFunction()).getDefaultValue().getColorInt());
});
}
@@ -1460,15 +1317,12 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-stroke-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(circleStrokeColor(Color.RED));
- assertEquals(layer.getCircleStrokeColorAsInt(), Color.RED);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(circleStrokeColor(Color.RED));
+ assertEquals(layer.getCircleStrokeColorAsInt(), Color.RED);
});
}
@@ -1477,16 +1331,13 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-stroke-opacityTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setCircleStrokeOpacityTransition(options);
- assertEquals(layer.getCircleStrokeOpacityTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setCircleStrokeOpacityTransition(options);
+ assertEquals(layer.getCircleStrokeOpacityTransition(), options);
});
}
@@ -1495,15 +1346,12 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-stroke-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(circleStrokeOpacity(0.3f));
- assertEquals((Float) layer.getCircleStrokeOpacity().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(circleStrokeOpacity(0.3f));
+ assertEquals((Float) layer.getCircleStrokeOpacity().getValue(), (Float) 0.3f);
});
}
@@ -1512,30 +1360,27 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-stroke-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleStrokeOpacity(
- zoom(
- exponential(
- stop(2, circleStrokeOpacity(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleStrokeOpacity(
+ zoom(
+ exponential(
+ stop(2, circleStrokeOpacity(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getCircleStrokeOpacity());
- assertNotNull(layer.getCircleStrokeOpacity().getFunction());
- assertEquals(CameraFunction.class, layer.getCircleStrokeOpacity().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getCircleStrokeOpacity().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getCircleStrokeOpacity().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getCircleStrokeOpacity().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleStrokeOpacity());
+ assertNotNull(layer.getCircleStrokeOpacity().getFunction());
+ assertEquals(CameraFunction.class, layer.getCircleStrokeOpacity().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getCircleStrokeOpacity().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getCircleStrokeOpacity().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getCircleStrokeOpacity().getFunction().getStops()).size());
});
}
@@ -1544,23 +1389,20 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-stroke-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleStrokeOpacity(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getCircleStrokeOpacity());
- assertNotNull(layer.getCircleStrokeOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleStrokeOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeOpacity().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getCircleStrokeOpacity().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleStrokeOpacity(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleStrokeOpacity());
+ assertNotNull(layer.getCircleStrokeOpacity().getFunction());
+ assertEquals(SourceFunction.class, layer.getCircleStrokeOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeOpacity().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getCircleStrokeOpacity().getFunction().getStops().getClass());
});
}
@@ -1569,30 +1411,27 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-stroke-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleStrokeOpacity(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, circleStrokeOpacity(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleStrokeOpacity(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, circleStrokeOpacity(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getCircleStrokeOpacity());
- assertNotNull(layer.getCircleStrokeOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleStrokeOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeOpacity().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getCircleStrokeOpacity().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleStrokeOpacity());
+ assertNotNull(layer.getCircleStrokeOpacity().getFunction());
+ assertEquals(SourceFunction.class, layer.getCircleStrokeOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeOpacity().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getCircleStrokeOpacity().getFunction().getStops().getClass());
});
}
@@ -1601,33 +1440,30 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-stroke-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleStrokeOpacity(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, circleStrokeOpacity(0.3f))
- )
- ).withDefaultValue(circleStrokeOpacity(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleStrokeOpacity());
- assertNotNull(layer.getCircleStrokeOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleStrokeOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeOpacity().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getCircleStrokeOpacity().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getCircleStrokeOpacity().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getCircleStrokeOpacity().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getCircleStrokeOpacity().getFunction()).getDefaultValue().getValue());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleStrokeOpacity(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, circleStrokeOpacity(0.3f))
+ )
+ ).withDefaultValue(circleStrokeOpacity(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleStrokeOpacity());
+ assertNotNull(layer.getCircleStrokeOpacity().getFunction());
+ assertEquals(SourceFunction.class, layer.getCircleStrokeOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeOpacity().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getCircleStrokeOpacity().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getCircleStrokeOpacity().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getCircleStrokeOpacity().getFunction()).getDefaultValue().getValue());
+ assertEquals(0.3f, ((SourceFunction) layer.getCircleStrokeOpacity().getFunction()).getDefaultValue().getValue());
});
}
@@ -1637,38 +1473,35 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-stroke-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleStrokeOpacity(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, circleStrokeOpacity(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(circleStrokeOpacity(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleStrokeOpacity());
- assertNotNull(layer.getCircleStrokeOpacity().getFunction());
- assertEquals(CompositeFunction.class, layer.getCircleStrokeOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getCircleStrokeOpacity().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getCircleStrokeOpacity().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getCircleStrokeOpacity().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getCircleStrokeOpacity().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circleStrokeOpacity(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, circleStrokeOpacity(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(circleStrokeOpacity(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCircleStrokeOpacity());
+ assertNotNull(layer.getCircleStrokeOpacity().getFunction());
+ assertEquals(CompositeFunction.class, layer.getCircleStrokeOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getCircleStrokeOpacity().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getCircleStrokeOpacity().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getCircleStrokeOpacity().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getCircleStrokeOpacity().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillExtrusionLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillExtrusionLayerTest.java
index 66c6093537..3a1cba5cf2 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillExtrusionLayerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillExtrusionLayerTest.java
@@ -3,14 +3,10 @@
package com.mapbox.mapboxsdk.testapp.style;
import android.graphics.Color;
-import android.support.test.espresso.UiController;
import android.support.test.runner.AndroidJUnit4;
-import timber.log.Timber;
-
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.style.functions.CompositeFunction;
import com.mapbox.mapboxsdk.style.functions.CameraFunction;
+import com.mapbox.mapboxsdk.style.functions.CompositeFunction;
import com.mapbox.mapboxsdk.style.functions.SourceFunction;
import com.mapbox.mapboxsdk.style.functions.stops.CategoricalStops;
import com.mapbox.mapboxsdk.style.functions.stops.ExponentialStops;
@@ -19,22 +15,36 @@ import com.mapbox.mapboxsdk.style.functions.stops.IntervalStops;
import com.mapbox.mapboxsdk.style.functions.stops.Stop;
import com.mapbox.mapboxsdk.style.functions.stops.Stops;
import com.mapbox.mapboxsdk.style.layers.FillExtrusionLayer;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
+import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static com.mapbox.mapboxsdk.style.functions.Function.*;
+import timber.log.Timber;
+
+import static com.mapbox.mapboxsdk.style.functions.Function.composite;
+import static com.mapbox.mapboxsdk.style.functions.Function.property;
+import static com.mapbox.mapboxsdk.style.functions.Function.zoom;
import static com.mapbox.mapboxsdk.style.functions.stops.Stop.stop;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stops.*;
+import static com.mapbox.mapboxsdk.style.functions.stops.Stops.categorical;
+import static com.mapbox.mapboxsdk.style.functions.stops.Stops.exponential;
+import static com.mapbox.mapboxsdk.style.functions.stops.Stops.interval;
+import static com.mapbox.mapboxsdk.style.layers.Property.FILL_EXTRUSION_TRANSLATE_ANCHOR_MAP;
+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.fillExtrusionBase;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionHeight;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionOpacity;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionPattern;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionTranslate;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionTranslateAnchor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.visibility;
import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
-import static org.junit.Assert.*;
-import static com.mapbox.mapboxsdk.style.layers.Property.*;
-import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
-
-import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
-import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
/**
* Basic smoke tests for FillExtrusionLayer
@@ -51,17 +61,14 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
private void setupLayer() {
Timber.i("Retrieving layer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Timber.i("Adding layer");
- layer = new FillExtrusionLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- // Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new FillExtrusionLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ // Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
});
}
@@ -71,18 +78,15 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("Visibility");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- // Get initial
- assertEquals(layer.getVisibility().getValue(), VISIBLE);
+ // Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
- // Set
- layer.setProperties(visibility(NONE));
- assertEquals(layer.getVisibility().getValue(), NONE);
- }
+ // Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
});
}
@@ -91,19 +95,16 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("SourceLayer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Get initial
- assertEquals(layer.getSourceLayer(), "composite");
-
- // Set
- final String sourceLayer = "test";
- layer.setSourceLayer(sourceLayer);
- assertEquals(layer.getSourceLayer(), sourceLayer);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getSourceLayer(), "composite");
+
+ // Set
+ final String sourceLayer = "test";
+ layer.setSourceLayer(sourceLayer);
+ assertEquals(layer.getSourceLayer(), sourceLayer);
});
}
@@ -112,16 +113,13 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-opacityTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setFillExtrusionOpacityTransition(options);
- assertEquals(layer.getFillExtrusionOpacityTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillExtrusionOpacityTransition(options);
+ assertEquals(layer.getFillExtrusionOpacityTransition(), options);
});
}
@@ -130,15 +128,12 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillExtrusionOpacity(0.3f));
- assertEquals((Float) layer.getFillExtrusionOpacity().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(fillExtrusionOpacity(0.3f));
+ assertEquals((Float) layer.getFillExtrusionOpacity().getValue(), (Float) 0.3f);
});
}
@@ -147,30 +142,27 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionOpacity(
- zoom(
- exponential(
- stop(2, fillExtrusionOpacity(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillExtrusionOpacity(
+ zoom(
+ exponential(
+ stop(2, fillExtrusionOpacity(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionOpacity());
- assertNotNull(layer.getFillExtrusionOpacity().getFunction());
- assertEquals(CameraFunction.class, layer.getFillExtrusionOpacity().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getFillExtrusionOpacity().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getFillExtrusionOpacity().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getFillExtrusionOpacity().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getFillExtrusionOpacity());
+ assertNotNull(layer.getFillExtrusionOpacity().getFunction());
+ assertEquals(CameraFunction.class, layer.getFillExtrusionOpacity().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getFillExtrusionOpacity().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getFillExtrusionOpacity().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getFillExtrusionOpacity().getFunction().getStops()).size());
});
}
@@ -179,16 +171,13 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-colorTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setFillExtrusionColorTransition(options);
- assertEquals(layer.getFillExtrusionColorTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillExtrusionColorTransition(options);
+ assertEquals(layer.getFillExtrusionColorTransition(), options);
});
}
@@ -197,15 +186,12 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillExtrusionColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getFillExtrusionColor().getValue(), (String) "rgba(0, 0, 0, 1)");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(fillExtrusionColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getFillExtrusionColor().getValue(), (String) "rgba(0, 0, 0, 1)");
});
}
@@ -214,30 +200,27 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionColor(
- zoom(
- exponential(
- stop(2, fillExtrusionColor("rgba(0, 0, 0, 1)"))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillExtrusionColor(
+ zoom(
+ exponential(
+ stop(2, fillExtrusionColor("rgba(0, 0, 0, 1)"))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionColor());
- assertNotNull(layer.getFillExtrusionColor().getFunction());
- assertEquals(CameraFunction.class, layer.getFillExtrusionColor().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getFillExtrusionColor().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getFillExtrusionColor().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getFillExtrusionColor().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getFillExtrusionColor());
+ assertNotNull(layer.getFillExtrusionColor().getFunction());
+ assertEquals(CameraFunction.class, layer.getFillExtrusionColor().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getFillExtrusionColor().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getFillExtrusionColor().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getFillExtrusionColor().getFunction().getStops()).size());
});
}
@@ -246,23 +229,20 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionColor(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionColor());
- assertNotNull(layer.getFillExtrusionColor().getFunction());
- assertEquals(SourceFunction.class, layer.getFillExtrusionColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillExtrusionColor().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getFillExtrusionColor().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillExtrusionColor(property("FeaturePropertyA", Stops.<String>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getFillExtrusionColor());
+ assertNotNull(layer.getFillExtrusionColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getFillExtrusionColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillExtrusionColor().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getFillExtrusionColor().getFunction().getStops().getClass());
});
}
@@ -271,30 +251,27 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionColor(
- property(
- "FeaturePropertyA",
- exponential(
- stop(Color.RED, fillExtrusionColor(Color.RED))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillExtrusionColor(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(Color.RED, fillExtrusionColor(Color.RED))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionColor());
- assertNotNull(layer.getFillExtrusionColor().getFunction());
- assertEquals(SourceFunction.class, layer.getFillExtrusionColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillExtrusionColor().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getFillExtrusionColor().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getFillExtrusionColor());
+ assertNotNull(layer.getFillExtrusionColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getFillExtrusionColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillExtrusionColor().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getFillExtrusionColor().getFunction().getStops().getClass());
});
}
@@ -303,33 +280,30 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionColor(
- property(
- "FeaturePropertyA",
- categorical(
- stop("valueA", fillExtrusionColor(Color.RED))
- )
- ).withDefaultValue(fillExtrusionColor(Color.GREEN))
- )
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionColor());
- assertNotNull(layer.getFillExtrusionColor().getFunction());
- assertEquals(SourceFunction.class, layer.getFillExtrusionColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillExtrusionColor().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getFillExtrusionColor().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getFillExtrusionColor().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getFillExtrusionColor().getFunction()).getDefaultValue().getValue());
- assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getFillExtrusionColor().getFunction()).getDefaultValue().getColorInt());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillExtrusionColor(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop("valueA", fillExtrusionColor(Color.RED))
+ )
+ ).withDefaultValue(fillExtrusionColor(Color.GREEN))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getFillExtrusionColor());
+ assertNotNull(layer.getFillExtrusionColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getFillExtrusionColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillExtrusionColor().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getFillExtrusionColor().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getFillExtrusionColor().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getFillExtrusionColor().getFunction()).getDefaultValue().getValue());
+ assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getFillExtrusionColor().getFunction()).getDefaultValue().getColorInt());
});
}
@@ -339,15 +313,12 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillExtrusionColor(Color.RED));
- assertEquals(layer.getFillExtrusionColorAsInt(), Color.RED);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(fillExtrusionColor(Color.RED));
+ assertEquals(layer.getFillExtrusionColorAsInt(), Color.RED);
});
}
@@ -356,16 +327,13 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-translateTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setFillExtrusionTranslateTransition(options);
- assertEquals(layer.getFillExtrusionTranslateTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillExtrusionTranslateTransition(options);
+ assertEquals(layer.getFillExtrusionTranslateTransition(), options);
});
}
@@ -374,15 +342,12 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-translate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillExtrusionTranslate(new Float[] {0f, 0f}));
- assertEquals((Float[]) layer.getFillExtrusionTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(fillExtrusionTranslate(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getFillExtrusionTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
});
}
@@ -391,30 +356,27 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-translate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionTranslate(
- zoom(
- exponential(
- stop(2, fillExtrusionTranslate(new Float[] {0f, 0f}))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillExtrusionTranslate(
+ zoom(
+ exponential(
+ stop(2, fillExtrusionTranslate(new Float[] {0f, 0f}))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionTranslate());
- assertNotNull(layer.getFillExtrusionTranslate().getFunction());
- assertEquals(CameraFunction.class, layer.getFillExtrusionTranslate().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getFillExtrusionTranslate().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getFillExtrusionTranslate().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getFillExtrusionTranslate().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getFillExtrusionTranslate());
+ assertNotNull(layer.getFillExtrusionTranslate().getFunction());
+ assertEquals(CameraFunction.class, layer.getFillExtrusionTranslate().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getFillExtrusionTranslate().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getFillExtrusionTranslate().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getFillExtrusionTranslate().getFunction().getStops()).size());
});
}
@@ -423,15 +385,12 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-translate-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillExtrusionTranslateAnchor(FILL_EXTRUSION_TRANSLATE_ANCHOR_MAP));
- assertEquals((String) layer.getFillExtrusionTranslateAnchor().getValue(), (String) FILL_EXTRUSION_TRANSLATE_ANCHOR_MAP);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(fillExtrusionTranslateAnchor(FILL_EXTRUSION_TRANSLATE_ANCHOR_MAP));
+ assertEquals((String) layer.getFillExtrusionTranslateAnchor().getValue(), (String) FILL_EXTRUSION_TRANSLATE_ANCHOR_MAP);
});
}
@@ -440,29 +399,26 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-translate-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionTranslateAnchor(
- zoom(
- interval(
- stop(2, fillExtrusionTranslateAnchor(FILL_EXTRUSION_TRANSLATE_ANCHOR_MAP))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillExtrusionTranslateAnchor(
+ zoom(
+ interval(
+ stop(2, fillExtrusionTranslateAnchor(FILL_EXTRUSION_TRANSLATE_ANCHOR_MAP))
)
)
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionTranslateAnchor());
- assertNotNull(layer.getFillExtrusionTranslateAnchor().getFunction());
- assertEquals(CameraFunction.class, layer.getFillExtrusionTranslateAnchor().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getFillExtrusionTranslateAnchor().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getFillExtrusionTranslateAnchor().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getFillExtrusionTranslateAnchor());
+ assertNotNull(layer.getFillExtrusionTranslateAnchor().getFunction());
+ assertEquals(CameraFunction.class, layer.getFillExtrusionTranslateAnchor().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getFillExtrusionTranslateAnchor().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getFillExtrusionTranslateAnchor().getFunction().getStops()).size());
});
}
@@ -471,16 +427,13 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-patternTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setFillExtrusionPatternTransition(options);
- assertEquals(layer.getFillExtrusionPatternTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillExtrusionPatternTransition(options);
+ assertEquals(layer.getFillExtrusionPatternTransition(), options);
});
}
@@ -489,15 +442,12 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-pattern");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillExtrusionPattern("pedestrian-polygon"));
- assertEquals((String) layer.getFillExtrusionPattern().getValue(), (String) "pedestrian-polygon");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(fillExtrusionPattern("pedestrian-polygon"));
+ assertEquals((String) layer.getFillExtrusionPattern().getValue(), (String) "pedestrian-polygon");
});
}
@@ -506,29 +456,26 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-pattern");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionPattern(
- zoom(
- interval(
- stop(2, fillExtrusionPattern("pedestrian-polygon"))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillExtrusionPattern(
+ zoom(
+ interval(
+ stop(2, fillExtrusionPattern("pedestrian-polygon"))
)
)
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionPattern());
- assertNotNull(layer.getFillExtrusionPattern().getFunction());
- assertEquals(CameraFunction.class, layer.getFillExtrusionPattern().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getFillExtrusionPattern().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getFillExtrusionPattern().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getFillExtrusionPattern());
+ assertNotNull(layer.getFillExtrusionPattern().getFunction());
+ assertEquals(CameraFunction.class, layer.getFillExtrusionPattern().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getFillExtrusionPattern().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getFillExtrusionPattern().getFunction().getStops()).size());
});
}
@@ -537,16 +484,13 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-heightTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setFillExtrusionHeightTransition(options);
- assertEquals(layer.getFillExtrusionHeightTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillExtrusionHeightTransition(options);
+ assertEquals(layer.getFillExtrusionHeightTransition(), options);
});
}
@@ -555,15 +499,12 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-height");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillExtrusionHeight(0.3f));
- assertEquals((Float) layer.getFillExtrusionHeight().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(fillExtrusionHeight(0.3f));
+ assertEquals((Float) layer.getFillExtrusionHeight().getValue(), (Float) 0.3f);
});
}
@@ -572,30 +513,27 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-height");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionHeight(
- zoom(
- exponential(
- stop(2, fillExtrusionHeight(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillExtrusionHeight(
+ zoom(
+ exponential(
+ stop(2, fillExtrusionHeight(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionHeight());
- assertNotNull(layer.getFillExtrusionHeight().getFunction());
- assertEquals(CameraFunction.class, layer.getFillExtrusionHeight().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getFillExtrusionHeight().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getFillExtrusionHeight().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getFillExtrusionHeight().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getFillExtrusionHeight());
+ assertNotNull(layer.getFillExtrusionHeight().getFunction());
+ assertEquals(CameraFunction.class, layer.getFillExtrusionHeight().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getFillExtrusionHeight().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getFillExtrusionHeight().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getFillExtrusionHeight().getFunction().getStops()).size());
});
}
@@ -604,23 +542,20 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-height");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionHeight(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionHeight());
- assertNotNull(layer.getFillExtrusionHeight().getFunction());
- assertEquals(SourceFunction.class, layer.getFillExtrusionHeight().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillExtrusionHeight().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getFillExtrusionHeight().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillExtrusionHeight(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getFillExtrusionHeight());
+ assertNotNull(layer.getFillExtrusionHeight().getFunction());
+ assertEquals(SourceFunction.class, layer.getFillExtrusionHeight().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillExtrusionHeight().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getFillExtrusionHeight().getFunction().getStops().getClass());
});
}
@@ -629,30 +564,27 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-height");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionHeight(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, fillExtrusionHeight(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillExtrusionHeight(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, fillExtrusionHeight(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionHeight());
- assertNotNull(layer.getFillExtrusionHeight().getFunction());
- assertEquals(SourceFunction.class, layer.getFillExtrusionHeight().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillExtrusionHeight().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getFillExtrusionHeight().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getFillExtrusionHeight());
+ assertNotNull(layer.getFillExtrusionHeight().getFunction());
+ assertEquals(SourceFunction.class, layer.getFillExtrusionHeight().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillExtrusionHeight().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getFillExtrusionHeight().getFunction().getStops().getClass());
});
}
@@ -661,33 +593,30 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-height");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionHeight(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, fillExtrusionHeight(0.3f))
- )
- ).withDefaultValue(fillExtrusionHeight(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionHeight());
- assertNotNull(layer.getFillExtrusionHeight().getFunction());
- assertEquals(SourceFunction.class, layer.getFillExtrusionHeight().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillExtrusionHeight().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getFillExtrusionHeight().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getFillExtrusionHeight().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getFillExtrusionHeight().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getFillExtrusionHeight().getFunction()).getDefaultValue().getValue());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillExtrusionHeight(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, fillExtrusionHeight(0.3f))
+ )
+ ).withDefaultValue(fillExtrusionHeight(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getFillExtrusionHeight());
+ assertNotNull(layer.getFillExtrusionHeight().getFunction());
+ assertEquals(SourceFunction.class, layer.getFillExtrusionHeight().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillExtrusionHeight().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getFillExtrusionHeight().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getFillExtrusionHeight().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getFillExtrusionHeight().getFunction()).getDefaultValue().getValue());
+ assertEquals(0.3f, ((SourceFunction) layer.getFillExtrusionHeight().getFunction()).getDefaultValue().getValue());
});
}
@@ -697,38 +626,35 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-height");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionHeight(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, fillExtrusionHeight(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(fillExtrusionHeight(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionHeight());
- assertNotNull(layer.getFillExtrusionHeight().getFunction());
- assertEquals(CompositeFunction.class, layer.getFillExtrusionHeight().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getFillExtrusionHeight().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getFillExtrusionHeight().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getFillExtrusionHeight().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getFillExtrusionHeight().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillExtrusionHeight(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, fillExtrusionHeight(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(fillExtrusionHeight(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getFillExtrusionHeight());
+ assertNotNull(layer.getFillExtrusionHeight().getFunction());
+ assertEquals(CompositeFunction.class, layer.getFillExtrusionHeight().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getFillExtrusionHeight().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getFillExtrusionHeight().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getFillExtrusionHeight().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getFillExtrusionHeight().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
});
}
@@ -737,16 +663,13 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-baseTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setFillExtrusionBaseTransition(options);
- assertEquals(layer.getFillExtrusionBaseTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillExtrusionBaseTransition(options);
+ assertEquals(layer.getFillExtrusionBaseTransition(), options);
});
}
@@ -755,15 +678,12 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-base");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillExtrusionBase(0.3f));
- assertEquals((Float) layer.getFillExtrusionBase().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(fillExtrusionBase(0.3f));
+ assertEquals((Float) layer.getFillExtrusionBase().getValue(), (Float) 0.3f);
});
}
@@ -772,30 +692,27 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-base");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionBase(
- zoom(
- exponential(
- stop(2, fillExtrusionBase(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillExtrusionBase(
+ zoom(
+ exponential(
+ stop(2, fillExtrusionBase(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionBase());
- assertNotNull(layer.getFillExtrusionBase().getFunction());
- assertEquals(CameraFunction.class, layer.getFillExtrusionBase().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getFillExtrusionBase().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getFillExtrusionBase().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getFillExtrusionBase().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getFillExtrusionBase());
+ assertNotNull(layer.getFillExtrusionBase().getFunction());
+ assertEquals(CameraFunction.class, layer.getFillExtrusionBase().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getFillExtrusionBase().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getFillExtrusionBase().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getFillExtrusionBase().getFunction().getStops()).size());
});
}
@@ -804,23 +721,20 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-base");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionBase(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionBase());
- assertNotNull(layer.getFillExtrusionBase().getFunction());
- assertEquals(SourceFunction.class, layer.getFillExtrusionBase().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillExtrusionBase().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getFillExtrusionBase().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillExtrusionBase(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getFillExtrusionBase());
+ assertNotNull(layer.getFillExtrusionBase().getFunction());
+ assertEquals(SourceFunction.class, layer.getFillExtrusionBase().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillExtrusionBase().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getFillExtrusionBase().getFunction().getStops().getClass());
});
}
@@ -829,30 +743,27 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-base");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionBase(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, fillExtrusionBase(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillExtrusionBase(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, fillExtrusionBase(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionBase());
- assertNotNull(layer.getFillExtrusionBase().getFunction());
- assertEquals(SourceFunction.class, layer.getFillExtrusionBase().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillExtrusionBase().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getFillExtrusionBase().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getFillExtrusionBase());
+ assertNotNull(layer.getFillExtrusionBase().getFunction());
+ assertEquals(SourceFunction.class, layer.getFillExtrusionBase().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillExtrusionBase().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getFillExtrusionBase().getFunction().getStops().getClass());
});
}
@@ -861,33 +772,30 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-base");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionBase(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, fillExtrusionBase(0.3f))
- )
- ).withDefaultValue(fillExtrusionBase(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionBase());
- assertNotNull(layer.getFillExtrusionBase().getFunction());
- assertEquals(SourceFunction.class, layer.getFillExtrusionBase().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillExtrusionBase().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getFillExtrusionBase().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getFillExtrusionBase().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getFillExtrusionBase().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getFillExtrusionBase().getFunction()).getDefaultValue().getValue());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillExtrusionBase(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, fillExtrusionBase(0.3f))
+ )
+ ).withDefaultValue(fillExtrusionBase(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getFillExtrusionBase());
+ assertNotNull(layer.getFillExtrusionBase().getFunction());
+ assertEquals(SourceFunction.class, layer.getFillExtrusionBase().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillExtrusionBase().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getFillExtrusionBase().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getFillExtrusionBase().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getFillExtrusionBase().getFunction()).getDefaultValue().getValue());
+ assertEquals(0.3f, ((SourceFunction) layer.getFillExtrusionBase().getFunction()).getDefaultValue().getValue());
});
}
@@ -897,38 +805,35 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-base");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionBase(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, fillExtrusionBase(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(fillExtrusionBase(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionBase());
- assertNotNull(layer.getFillExtrusionBase().getFunction());
- assertEquals(CompositeFunction.class, layer.getFillExtrusionBase().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getFillExtrusionBase().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getFillExtrusionBase().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getFillExtrusionBase().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getFillExtrusionBase().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillExtrusionBase(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, fillExtrusionBase(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(fillExtrusionBase(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getFillExtrusionBase());
+ assertNotNull(layer.getFillExtrusionBase().getFunction());
+ assertEquals(CompositeFunction.class, layer.getFillExtrusionBase().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getFillExtrusionBase().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getFillExtrusionBase().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getFillExtrusionBase().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getFillExtrusionBase().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerTest.java
index 939bcb6892..a5e7ea5fc9 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerTest.java
@@ -3,14 +3,10 @@
package com.mapbox.mapboxsdk.testapp.style;
import android.graphics.Color;
-import android.support.test.espresso.UiController;
import android.support.test.runner.AndroidJUnit4;
-import timber.log.Timber;
-
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.style.functions.CompositeFunction;
import com.mapbox.mapboxsdk.style.functions.CameraFunction;
+import com.mapbox.mapboxsdk.style.functions.CompositeFunction;
import com.mapbox.mapboxsdk.style.functions.SourceFunction;
import com.mapbox.mapboxsdk.style.functions.stops.CategoricalStops;
import com.mapbox.mapboxsdk.style.functions.stops.ExponentialStops;
@@ -19,22 +15,36 @@ import com.mapbox.mapboxsdk.style.functions.stops.IntervalStops;
import com.mapbox.mapboxsdk.style.functions.stops.Stop;
import com.mapbox.mapboxsdk.style.functions.stops.Stops;
import com.mapbox.mapboxsdk.style.layers.FillLayer;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
+import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static com.mapbox.mapboxsdk.style.functions.Function.*;
+import timber.log.Timber;
+
+import static com.mapbox.mapboxsdk.style.functions.Function.composite;
+import static com.mapbox.mapboxsdk.style.functions.Function.property;
+import static com.mapbox.mapboxsdk.style.functions.Function.zoom;
import static com.mapbox.mapboxsdk.style.functions.stops.Stop.stop;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stops.*;
+import static com.mapbox.mapboxsdk.style.functions.stops.Stops.categorical;
+import static com.mapbox.mapboxsdk.style.functions.stops.Stops.exponential;
+import static com.mapbox.mapboxsdk.style.functions.stops.Stops.interval;
+import static com.mapbox.mapboxsdk.style.layers.Property.FILL_TRANSLATE_ANCHOR_MAP;
+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.fillAntialias;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillOpacity;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillOutlineColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillPattern;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillTranslate;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillTranslateAnchor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.visibility;
import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
-import static org.junit.Assert.*;
-import static com.mapbox.mapboxsdk.style.layers.Property.*;
-import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
-
-import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
-import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
/**
* Basic smoke tests for FillLayer
@@ -51,17 +61,14 @@ public class FillLayerTest extends BaseActivityTest {
private void setupLayer() {
Timber.i("Retrieving layer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Timber.i("Adding layer");
- layer = new FillLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- // Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new FillLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ // Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
});
}
@@ -71,18 +78,15 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("Visibility");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- // Get initial
- assertEquals(layer.getVisibility().getValue(), VISIBLE);
+ // Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
- // Set
- layer.setProperties(visibility(NONE));
- assertEquals(layer.getVisibility().getValue(), NONE);
- }
+ // Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
});
}
@@ -91,19 +95,16 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("SourceLayer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Get initial
- assertEquals(layer.getSourceLayer(), "composite");
-
- // Set
- final String sourceLayer = "test";
- layer.setSourceLayer(sourceLayer);
- assertEquals(layer.getSourceLayer(), sourceLayer);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getSourceLayer(), "composite");
+
+ // Set
+ final String sourceLayer = "test";
+ layer.setSourceLayer(sourceLayer);
+ assertEquals(layer.getSourceLayer(), sourceLayer);
});
}
@@ -112,15 +113,12 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-antialias");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillAntialias(true));
- assertEquals((Boolean) layer.getFillAntialias().getValue(), (Boolean) true);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(fillAntialias(true));
+ assertEquals((Boolean) layer.getFillAntialias().getValue(), (Boolean) true);
});
}
@@ -129,29 +127,26 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-antialias");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillAntialias(
- zoom(
- interval(
- stop(2, fillAntialias(true))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillAntialias(
+ zoom(
+ interval(
+ stop(2, fillAntialias(true))
)
)
- );
-
- // Verify
- assertNotNull(layer.getFillAntialias());
- assertNotNull(layer.getFillAntialias().getFunction());
- assertEquals(CameraFunction.class, layer.getFillAntialias().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getFillAntialias().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getFillAntialias().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getFillAntialias());
+ assertNotNull(layer.getFillAntialias().getFunction());
+ assertEquals(CameraFunction.class, layer.getFillAntialias().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getFillAntialias().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getFillAntialias().getFunction().getStops()).size());
});
}
@@ -160,16 +155,13 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-opacityTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setFillOpacityTransition(options);
- assertEquals(layer.getFillOpacityTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillOpacityTransition(options);
+ assertEquals(layer.getFillOpacityTransition(), options);
});
}
@@ -178,15 +170,12 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillOpacity(0.3f));
- assertEquals((Float) layer.getFillOpacity().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(fillOpacity(0.3f));
+ assertEquals((Float) layer.getFillOpacity().getValue(), (Float) 0.3f);
});
}
@@ -195,30 +184,27 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillOpacity(
- zoom(
- exponential(
- stop(2, fillOpacity(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillOpacity(
+ zoom(
+ exponential(
+ stop(2, fillOpacity(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getFillOpacity());
- assertNotNull(layer.getFillOpacity().getFunction());
- assertEquals(CameraFunction.class, layer.getFillOpacity().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getFillOpacity().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getFillOpacity().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getFillOpacity().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getFillOpacity());
+ assertNotNull(layer.getFillOpacity().getFunction());
+ assertEquals(CameraFunction.class, layer.getFillOpacity().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getFillOpacity().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getFillOpacity().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getFillOpacity().getFunction().getStops()).size());
});
}
@@ -227,23 +213,20 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillOpacity(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getFillOpacity());
- assertNotNull(layer.getFillOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getFillOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillOpacity().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getFillOpacity().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillOpacity(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getFillOpacity());
+ assertNotNull(layer.getFillOpacity().getFunction());
+ assertEquals(SourceFunction.class, layer.getFillOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillOpacity().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getFillOpacity().getFunction().getStops().getClass());
});
}
@@ -252,30 +235,27 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillOpacity(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, fillOpacity(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillOpacity(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, fillOpacity(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getFillOpacity());
- assertNotNull(layer.getFillOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getFillOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillOpacity().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getFillOpacity().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getFillOpacity());
+ assertNotNull(layer.getFillOpacity().getFunction());
+ assertEquals(SourceFunction.class, layer.getFillOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillOpacity().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getFillOpacity().getFunction().getStops().getClass());
});
}
@@ -284,33 +264,30 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillOpacity(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, fillOpacity(0.3f))
- )
- ).withDefaultValue(fillOpacity(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getFillOpacity());
- assertNotNull(layer.getFillOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getFillOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillOpacity().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getFillOpacity().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getFillOpacity().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getFillOpacity().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getFillOpacity().getFunction()).getDefaultValue().getValue());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillOpacity(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, fillOpacity(0.3f))
+ )
+ ).withDefaultValue(fillOpacity(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getFillOpacity());
+ assertNotNull(layer.getFillOpacity().getFunction());
+ assertEquals(SourceFunction.class, layer.getFillOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillOpacity().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getFillOpacity().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getFillOpacity().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getFillOpacity().getFunction()).getDefaultValue().getValue());
+ assertEquals(0.3f, ((SourceFunction) layer.getFillOpacity().getFunction()).getDefaultValue().getValue());
});
}
@@ -320,38 +297,35 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillOpacity(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, fillOpacity(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(fillOpacity(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getFillOpacity());
- assertNotNull(layer.getFillOpacity().getFunction());
- assertEquals(CompositeFunction.class, layer.getFillOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getFillOpacity().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getFillOpacity().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getFillOpacity().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getFillOpacity().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillOpacity(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, fillOpacity(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(fillOpacity(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getFillOpacity());
+ assertNotNull(layer.getFillOpacity().getFunction());
+ assertEquals(CompositeFunction.class, layer.getFillOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getFillOpacity().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getFillOpacity().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getFillOpacity().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getFillOpacity().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
});
}
@@ -360,16 +334,13 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-colorTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setFillColorTransition(options);
- assertEquals(layer.getFillColorTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillColorTransition(options);
+ assertEquals(layer.getFillColorTransition(), options);
});
}
@@ -378,15 +349,12 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getFillColor().getValue(), (String) "rgba(0, 0, 0, 1)");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(fillColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getFillColor().getValue(), (String) "rgba(0, 0, 0, 1)");
});
}
@@ -395,30 +363,27 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillColor(
- zoom(
- exponential(
- stop(2, fillColor("rgba(0, 0, 0, 1)"))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillColor(
+ zoom(
+ exponential(
+ stop(2, fillColor("rgba(0, 0, 0, 1)"))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getFillColor());
- assertNotNull(layer.getFillColor().getFunction());
- assertEquals(CameraFunction.class, layer.getFillColor().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getFillColor().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getFillColor().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getFillColor().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getFillColor());
+ assertNotNull(layer.getFillColor().getFunction());
+ assertEquals(CameraFunction.class, layer.getFillColor().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getFillColor().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getFillColor().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getFillColor().getFunction().getStops()).size());
});
}
@@ -427,23 +392,20 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillColor(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getFillColor());
- assertNotNull(layer.getFillColor().getFunction());
- assertEquals(SourceFunction.class, layer.getFillColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillColor().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getFillColor().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillColor(property("FeaturePropertyA", Stops.<String>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getFillColor());
+ assertNotNull(layer.getFillColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getFillColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillColor().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getFillColor().getFunction().getStops().getClass());
});
}
@@ -452,30 +414,27 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillColor(
- property(
- "FeaturePropertyA",
- exponential(
- stop(Color.RED, fillColor(Color.RED))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillColor(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(Color.RED, fillColor(Color.RED))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getFillColor());
- assertNotNull(layer.getFillColor().getFunction());
- assertEquals(SourceFunction.class, layer.getFillColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillColor().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getFillColor().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getFillColor());
+ assertNotNull(layer.getFillColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getFillColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillColor().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getFillColor().getFunction().getStops().getClass());
});
}
@@ -484,33 +443,30 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillColor(
- property(
- "FeaturePropertyA",
- categorical(
- stop("valueA", fillColor(Color.RED))
- )
- ).withDefaultValue(fillColor(Color.GREEN))
- )
- );
-
- // Verify
- assertNotNull(layer.getFillColor());
- assertNotNull(layer.getFillColor().getFunction());
- assertEquals(SourceFunction.class, layer.getFillColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillColor().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getFillColor().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getFillColor().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getFillColor().getFunction()).getDefaultValue().getValue());
- assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getFillColor().getFunction()).getDefaultValue().getColorInt());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillColor(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop("valueA", fillColor(Color.RED))
+ )
+ ).withDefaultValue(fillColor(Color.GREEN))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getFillColor());
+ assertNotNull(layer.getFillColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getFillColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillColor().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getFillColor().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getFillColor().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getFillColor().getFunction()).getDefaultValue().getValue());
+ assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getFillColor().getFunction()).getDefaultValue().getColorInt());
});
}
@@ -520,15 +476,12 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillColor(Color.RED));
- assertEquals(layer.getFillColorAsInt(), Color.RED);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(fillColor(Color.RED));
+ assertEquals(layer.getFillColorAsInt(), Color.RED);
});
}
@@ -537,16 +490,13 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-outline-colorTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setFillOutlineColorTransition(options);
- assertEquals(layer.getFillOutlineColorTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillOutlineColorTransition(options);
+ assertEquals(layer.getFillOutlineColorTransition(), options);
});
}
@@ -555,15 +505,12 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-outline-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillOutlineColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getFillOutlineColor().getValue(), (String) "rgba(0, 0, 0, 1)");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(fillOutlineColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getFillOutlineColor().getValue(), (String) "rgba(0, 0, 0, 1)");
});
}
@@ -572,30 +519,27 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-outline-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillOutlineColor(
- zoom(
- exponential(
- stop(2, fillOutlineColor("rgba(0, 0, 0, 1)"))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillOutlineColor(
+ zoom(
+ exponential(
+ stop(2, fillOutlineColor("rgba(0, 0, 0, 1)"))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getFillOutlineColor());
- assertNotNull(layer.getFillOutlineColor().getFunction());
- assertEquals(CameraFunction.class, layer.getFillOutlineColor().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getFillOutlineColor().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getFillOutlineColor().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getFillOutlineColor().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getFillOutlineColor());
+ assertNotNull(layer.getFillOutlineColor().getFunction());
+ assertEquals(CameraFunction.class, layer.getFillOutlineColor().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getFillOutlineColor().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getFillOutlineColor().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getFillOutlineColor().getFunction().getStops()).size());
});
}
@@ -604,23 +548,20 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-outline-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillOutlineColor(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getFillOutlineColor());
- assertNotNull(layer.getFillOutlineColor().getFunction());
- assertEquals(SourceFunction.class, layer.getFillOutlineColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillOutlineColor().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getFillOutlineColor().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillOutlineColor(property("FeaturePropertyA", Stops.<String>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getFillOutlineColor());
+ assertNotNull(layer.getFillOutlineColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getFillOutlineColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillOutlineColor().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getFillOutlineColor().getFunction().getStops().getClass());
});
}
@@ -629,30 +570,27 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-outline-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillOutlineColor(
- property(
- "FeaturePropertyA",
- exponential(
- stop(Color.RED, fillOutlineColor(Color.RED))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillOutlineColor(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(Color.RED, fillOutlineColor(Color.RED))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getFillOutlineColor());
- assertNotNull(layer.getFillOutlineColor().getFunction());
- assertEquals(SourceFunction.class, layer.getFillOutlineColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillOutlineColor().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getFillOutlineColor().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getFillOutlineColor());
+ assertNotNull(layer.getFillOutlineColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getFillOutlineColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillOutlineColor().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getFillOutlineColor().getFunction().getStops().getClass());
});
}
@@ -661,33 +599,30 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-outline-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillOutlineColor(
- property(
- "FeaturePropertyA",
- categorical(
- stop("valueA", fillOutlineColor(Color.RED))
- )
- ).withDefaultValue(fillOutlineColor(Color.GREEN))
- )
- );
-
- // Verify
- assertNotNull(layer.getFillOutlineColor());
- assertNotNull(layer.getFillOutlineColor().getFunction());
- assertEquals(SourceFunction.class, layer.getFillOutlineColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillOutlineColor().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getFillOutlineColor().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getFillOutlineColor().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getFillOutlineColor().getFunction()).getDefaultValue().getValue());
- assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getFillOutlineColor().getFunction()).getDefaultValue().getColorInt());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillOutlineColor(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop("valueA", fillOutlineColor(Color.RED))
+ )
+ ).withDefaultValue(fillOutlineColor(Color.GREEN))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getFillOutlineColor());
+ assertNotNull(layer.getFillOutlineColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getFillOutlineColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillOutlineColor().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getFillOutlineColor().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getFillOutlineColor().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getFillOutlineColor().getFunction()).getDefaultValue().getValue());
+ assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getFillOutlineColor().getFunction()).getDefaultValue().getColorInt());
});
}
@@ -697,15 +632,12 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-outline-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillOutlineColor(Color.RED));
- assertEquals(layer.getFillOutlineColorAsInt(), Color.RED);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(fillOutlineColor(Color.RED));
+ assertEquals(layer.getFillOutlineColorAsInt(), Color.RED);
});
}
@@ -714,16 +646,13 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-translateTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setFillTranslateTransition(options);
- assertEquals(layer.getFillTranslateTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillTranslateTransition(options);
+ assertEquals(layer.getFillTranslateTransition(), options);
});
}
@@ -732,15 +661,12 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-translate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillTranslate(new Float[] {0f, 0f}));
- assertEquals((Float[]) layer.getFillTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(fillTranslate(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getFillTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
});
}
@@ -749,30 +675,27 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-translate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillTranslate(
- zoom(
- exponential(
- stop(2, fillTranslate(new Float[] {0f, 0f}))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillTranslate(
+ zoom(
+ exponential(
+ stop(2, fillTranslate(new Float[] {0f, 0f}))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getFillTranslate());
- assertNotNull(layer.getFillTranslate().getFunction());
- assertEquals(CameraFunction.class, layer.getFillTranslate().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getFillTranslate().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getFillTranslate().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getFillTranslate().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getFillTranslate());
+ assertNotNull(layer.getFillTranslate().getFunction());
+ assertEquals(CameraFunction.class, layer.getFillTranslate().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getFillTranslate().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getFillTranslate().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getFillTranslate().getFunction().getStops()).size());
});
}
@@ -781,15 +704,12 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-translate-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillTranslateAnchor(FILL_TRANSLATE_ANCHOR_MAP));
- assertEquals((String) layer.getFillTranslateAnchor().getValue(), (String) FILL_TRANSLATE_ANCHOR_MAP);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(fillTranslateAnchor(FILL_TRANSLATE_ANCHOR_MAP));
+ assertEquals((String) layer.getFillTranslateAnchor().getValue(), (String) FILL_TRANSLATE_ANCHOR_MAP);
});
}
@@ -798,29 +718,26 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-translate-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillTranslateAnchor(
- zoom(
- interval(
- stop(2, fillTranslateAnchor(FILL_TRANSLATE_ANCHOR_MAP))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillTranslateAnchor(
+ zoom(
+ interval(
+ stop(2, fillTranslateAnchor(FILL_TRANSLATE_ANCHOR_MAP))
)
)
- );
-
- // Verify
- assertNotNull(layer.getFillTranslateAnchor());
- assertNotNull(layer.getFillTranslateAnchor().getFunction());
- assertEquals(CameraFunction.class, layer.getFillTranslateAnchor().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getFillTranslateAnchor().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getFillTranslateAnchor().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getFillTranslateAnchor());
+ assertNotNull(layer.getFillTranslateAnchor().getFunction());
+ assertEquals(CameraFunction.class, layer.getFillTranslateAnchor().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getFillTranslateAnchor().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getFillTranslateAnchor().getFunction().getStops()).size());
});
}
@@ -829,16 +746,13 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-patternTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setFillPatternTransition(options);
- assertEquals(layer.getFillPatternTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillPatternTransition(options);
+ assertEquals(layer.getFillPatternTransition(), options);
});
}
@@ -847,15 +761,12 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-pattern");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillPattern("pedestrian-polygon"));
- assertEquals((String) layer.getFillPattern().getValue(), (String) "pedestrian-polygon");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(fillPattern("pedestrian-polygon"));
+ assertEquals((String) layer.getFillPattern().getValue(), (String) "pedestrian-polygon");
});
}
@@ -864,29 +775,26 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-pattern");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillPattern(
- zoom(
- interval(
- stop(2, fillPattern("pedestrian-polygon"))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ fillPattern(
+ zoom(
+ interval(
+ stop(2, fillPattern("pedestrian-polygon"))
)
)
- );
-
- // Verify
- assertNotNull(layer.getFillPattern());
- assertNotNull(layer.getFillPattern().getFunction());
- assertEquals(CameraFunction.class, layer.getFillPattern().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getFillPattern().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getFillPattern().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getFillPattern());
+ assertNotNull(layer.getFillPattern().getFunction());
+ assertEquals(CameraFunction.class, layer.getFillPattern().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getFillPattern().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getFillPattern().getFunction().getStops()).size());
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ImageTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ImageTest.java
index 60cf4ced3d..c049fabb52 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ImageTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ImageTest.java
@@ -3,10 +3,8 @@ package com.mapbox.mapboxsdk.testapp.style;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
-import android.support.test.espresso.UiController;
import android.support.test.runner.AndroidJUnit4;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
@@ -34,21 +32,18 @@ public class ImageTest extends BaseActivityTest {
@Test
public void testAddGetImage() {
validateTestSetup();
- MapboxMapAction.invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- Drawable drawable = rule.getActivity().getResources().getDrawable(R.drawable.ic_launcher_round);
- assertTrue(drawable instanceof BitmapDrawable);
+ MapboxMapAction.invoke(mapboxMap, (uiController, mapboxMap) -> {
+ Drawable drawable = rule.getActivity().getResources().getDrawable(R.drawable.ic_launcher_round);
+ assertTrue(drawable instanceof BitmapDrawable);
- Bitmap bitmapSet = ((BitmapDrawable) drawable).getBitmap();
- mapboxMap.addImage(IMAGE_ID, bitmapSet);
+ Bitmap bitmapSet = ((BitmapDrawable) drawable).getBitmap();
+ mapboxMap.addImage(IMAGE_ID, bitmapSet);
- Bitmap bitmapGet = mapboxMap.getImage(IMAGE_ID);
- assertTrue(bitmapGet.sameAs(bitmapSet));
+ Bitmap bitmapGet = mapboxMap.getImage(IMAGE_ID);
+ assertTrue(bitmapGet.sameAs(bitmapSet));
- mapboxMap.removeImage(IMAGE_ID);
- assertNull(mapboxMap.getImage(IMAGE_ID));
- }
+ mapboxMap.removeImage(IMAGE_ID);
+ assertNull(mapboxMap.getImage(IMAGE_ID));
});
}
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LightTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LightTest.java
index 88da6e45be..21026527c5 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LightTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LightTest.java
@@ -6,24 +6,22 @@ import android.support.test.espresso.ViewAction;
import android.support.test.runner.AndroidJUnit4;
import android.view.View;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.style.light.Light;
import com.mapbox.mapboxsdk.style.functions.Function;
import com.mapbox.mapboxsdk.style.functions.stops.IdentityStops;
import com.mapbox.mapboxsdk.style.layers.FillExtrusionLayer;
import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
+import com.mapbox.mapboxsdk.style.light.Light;
import com.mapbox.mapboxsdk.style.light.Position;
import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
import com.mapbox.mapboxsdk.testapp.activity.style.FillExtrusionStyleTestActivity;
-import timber.log.Timber;
-
import org.hamcrest.Matcher;
import org.junit.Test;
import org.junit.runner.RunWith;
+import timber.log.Timber;
+
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
@@ -33,7 +31,6 @@ import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionBas
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionColor;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionHeight;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionOpacity;
-
import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
@@ -48,14 +45,11 @@ public class LightTest extends BaseActivityTest {
validateTestSetup();
setupLight();
Timber.i("anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(light);
- // Set and Get
- light.setAnchor(ANCHOR_MAP);
- assertEquals("Anchor should match", ANCHOR_MAP, light.getAnchor());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(light);
+ // Set and Get
+ light.setAnchor(ANCHOR_MAP);
+ assertEquals("Anchor should match", ANCHOR_MAP, light.getAnchor());
});
}
@@ -64,15 +58,12 @@ public class LightTest extends BaseActivityTest {
validateTestSetup();
setupLight();
Timber.i("positionTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(light);
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- light.setPositionTransition(options);
- assertEquals("Transition options should match", options, light.getPositionTransition());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(light);
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ light.setPositionTransition(options);
+ assertEquals("Transition options should match", options, light.getPositionTransition());
});
}
@@ -81,15 +72,12 @@ public class LightTest extends BaseActivityTest {
validateTestSetup();
setupLight();
Timber.i("position");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(light);
- // Set and Get
- Position position = new Position(1, 2, 3);
- light.setPosition(position);
- assertEquals("Position should match", position, light.getPosition());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(light);
+ // Set and Get
+ Position position = new Position(1, 2, 3);
+ light.setPosition(position);
+ assertEquals("Position should match", position, light.getPosition());
});
}
@@ -98,15 +86,12 @@ public class LightTest extends BaseActivityTest {
validateTestSetup();
setupLight();
Timber.i("colorTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(light);
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- light.setColorTransition(options);
- assertEquals("Transition options should match", options, light.getColorTransition());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(light);
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ light.setColorTransition(options);
+ assertEquals("Transition options should match", options, light.getColorTransition());
});
}
@@ -115,14 +100,11 @@ public class LightTest extends BaseActivityTest {
validateTestSetup();
setupLight();
Timber.i("color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(light);
- // Set and Get
- light.setColor("rgba(0, 0, 0, 1)");
- assertEquals("Color should match", "rgba(0, 0, 0, 1)".replaceAll("\\s+", ""), light.getColor());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(light);
+ // Set and Get
+ light.setColor("rgba(0, 0, 0, 1)");
+ assertEquals("Color should match", "rgba(0, 0, 0, 1)".replaceAll("\\s+", ""), light.getColor());
});
}
@@ -131,15 +113,12 @@ public class LightTest extends BaseActivityTest {
validateTestSetup();
setupLight();
Timber.i("intensityTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(light);
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- light.setIntensityTransition(options);
- assertEquals("Transition options should match", options, light.getIntensityTransition());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(light);
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ light.setIntensityTransition(options);
+ assertEquals("Transition options should match", options, light.getIntensityTransition());
});
}
@@ -148,14 +127,11 @@ public class LightTest extends BaseActivityTest {
validateTestSetup();
setupLight();
Timber.i("intensity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(light);
- // Set and Get
- light.setIntensity(0.3f);
- assertEquals("Intensity should match", 0.3f, light.getIntensity());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(light);
+ // Set and Get
+ light.setIntensity(0.3f);
+ assertEquals("Intensity should match", 0.3f, light.getIntensity());
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java
index 8123d24be8..544c5505ed 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java
@@ -3,14 +3,10 @@
package com.mapbox.mapboxsdk.testapp.style;
import android.graphics.Color;
-import android.support.test.espresso.UiController;
import android.support.test.runner.AndroidJUnit4;
-import timber.log.Timber;
-
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.style.functions.CompositeFunction;
import com.mapbox.mapboxsdk.style.functions.CameraFunction;
+import com.mapbox.mapboxsdk.style.functions.CompositeFunction;
import com.mapbox.mapboxsdk.style.functions.SourceFunction;
import com.mapbox.mapboxsdk.style.functions.stops.CategoricalStops;
import com.mapbox.mapboxsdk.style.functions.stops.ExponentialStops;
@@ -19,22 +15,45 @@ import com.mapbox.mapboxsdk.style.functions.stops.IntervalStops;
import com.mapbox.mapboxsdk.style.functions.stops.Stop;
import com.mapbox.mapboxsdk.style.functions.stops.Stops;
import com.mapbox.mapboxsdk.style.layers.LineLayer;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
+import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static com.mapbox.mapboxsdk.style.functions.Function.*;
+import timber.log.Timber;
+
+import static com.mapbox.mapboxsdk.style.functions.Function.composite;
+import static com.mapbox.mapboxsdk.style.functions.Function.property;
+import static com.mapbox.mapboxsdk.style.functions.Function.zoom;
import static com.mapbox.mapboxsdk.style.functions.stops.Stop.stop;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stops.*;
+import static com.mapbox.mapboxsdk.style.functions.stops.Stops.categorical;
+import static com.mapbox.mapboxsdk.style.functions.stops.Stops.exponential;
+import static com.mapbox.mapboxsdk.style.functions.stops.Stops.interval;
+import static com.mapbox.mapboxsdk.style.layers.Property.LINE_CAP_BUTT;
+import static com.mapbox.mapboxsdk.style.layers.Property.LINE_JOIN_BEVEL;
+import static com.mapbox.mapboxsdk.style.layers.Property.LINE_TRANSLATE_ANCHOR_MAP;
+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.lineBlur;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineCap;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineDasharray;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineGapWidth;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineJoin;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineMiterLimit;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineOffset;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineOpacity;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.linePattern;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineRoundLimit;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineTranslate;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineTranslateAnchor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineWidth;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.visibility;
import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
-import static org.junit.Assert.*;
-import static com.mapbox.mapboxsdk.style.layers.Property.*;
-import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
-
-import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
-import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
/**
* Basic smoke tests for LineLayer
@@ -51,17 +70,14 @@ public class LineLayerTest extends BaseActivityTest {
private void setupLayer() {
Timber.i("Retrieving layer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Timber.i("Adding layer");
- layer = new LineLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- // Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ // Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
});
}
@@ -71,18 +87,15 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("Visibility");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- // Get initial
- assertEquals(layer.getVisibility().getValue(), VISIBLE);
+ // Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
- // Set
- layer.setProperties(visibility(NONE));
- assertEquals(layer.getVisibility().getValue(), NONE);
- }
+ // Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
});
}
@@ -91,19 +104,16 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("SourceLayer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Get initial
- assertEquals(layer.getSourceLayer(), "composite");
-
- // Set
- final String sourceLayer = "test";
- layer.setSourceLayer(sourceLayer);
- assertEquals(layer.getSourceLayer(), sourceLayer);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getSourceLayer(), "composite");
+
+ // Set
+ final String sourceLayer = "test";
+ layer.setSourceLayer(sourceLayer);
+ assertEquals(layer.getSourceLayer(), sourceLayer);
});
}
@@ -112,15 +122,12 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-cap");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(lineCap(LINE_CAP_BUTT));
- assertEquals((String) layer.getLineCap().getValue(), (String) LINE_CAP_BUTT);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(lineCap(LINE_CAP_BUTT));
+ assertEquals((String) layer.getLineCap().getValue(), (String) LINE_CAP_BUTT);
});
}
@@ -129,29 +136,26 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-cap");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineCap(
- zoom(
- interval(
- stop(2, lineCap(LINE_CAP_BUTT))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineCap(
+ zoom(
+ interval(
+ stop(2, lineCap(LINE_CAP_BUTT))
)
)
- );
-
- // Verify
- assertNotNull(layer.getLineCap());
- assertNotNull(layer.getLineCap().getFunction());
- assertEquals(CameraFunction.class, layer.getLineCap().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getLineCap().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getLineCap().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineCap());
+ assertNotNull(layer.getLineCap().getFunction());
+ assertEquals(CameraFunction.class, layer.getLineCap().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getLineCap().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getLineCap().getFunction().getStops()).size());
});
}
@@ -160,15 +164,12 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-join");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(lineJoin(LINE_JOIN_BEVEL));
- assertEquals((String) layer.getLineJoin().getValue(), (String) LINE_JOIN_BEVEL);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(lineJoin(LINE_JOIN_BEVEL));
+ assertEquals((String) layer.getLineJoin().getValue(), (String) LINE_JOIN_BEVEL);
});
}
@@ -177,29 +178,26 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-join");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineJoin(
- zoom(
- interval(
- stop(2, lineJoin(LINE_JOIN_BEVEL))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineJoin(
+ zoom(
+ interval(
+ stop(2, lineJoin(LINE_JOIN_BEVEL))
)
)
- );
-
- // Verify
- assertNotNull(layer.getLineJoin());
- assertNotNull(layer.getLineJoin().getFunction());
- assertEquals(CameraFunction.class, layer.getLineJoin().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getLineJoin().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getLineJoin().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineJoin());
+ assertNotNull(layer.getLineJoin().getFunction());
+ assertEquals(CameraFunction.class, layer.getLineJoin().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getLineJoin().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getLineJoin().getFunction().getStops()).size());
});
}
@@ -208,23 +206,20 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-join");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineJoin(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getLineJoin());
- assertNotNull(layer.getLineJoin().getFunction());
- assertEquals(SourceFunction.class, layer.getLineJoin().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineJoin().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getLineJoin().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineJoin(property("FeaturePropertyA", Stops.<String>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getLineJoin());
+ assertNotNull(layer.getLineJoin().getFunction());
+ assertEquals(SourceFunction.class, layer.getLineJoin().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineJoin().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getLineJoin().getFunction().getStops().getClass());
});
}
@@ -233,30 +228,27 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-join");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineJoin(
- property(
- "FeaturePropertyA",
- interval(
- stop(1, lineJoin(LINE_JOIN_BEVEL))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineJoin(
+ property(
+ "FeaturePropertyA",
+ interval(
+ stop(1, lineJoin(LINE_JOIN_BEVEL))
)
)
- );
-
- // Verify
- assertNotNull(layer.getLineJoin());
- assertNotNull(layer.getLineJoin().getFunction());
- assertEquals(SourceFunction.class, layer.getLineJoin().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineJoin().getFunction()).getProperty());
- assertEquals(IntervalStops.class, layer.getLineJoin().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineJoin());
+ assertNotNull(layer.getLineJoin().getFunction());
+ assertEquals(SourceFunction.class, layer.getLineJoin().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineJoin().getFunction()).getProperty());
+ assertEquals(IntervalStops.class, layer.getLineJoin().getFunction().getStops().getClass());
});
}
@@ -265,15 +257,12 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-miter-limit");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(lineMiterLimit(0.3f));
- assertEquals((Float) layer.getLineMiterLimit().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(lineMiterLimit(0.3f));
+ assertEquals((Float) layer.getLineMiterLimit().getValue(), (Float) 0.3f);
});
}
@@ -282,30 +271,27 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-miter-limit");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineMiterLimit(
- zoom(
- exponential(
- stop(2, lineMiterLimit(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineMiterLimit(
+ zoom(
+ exponential(
+ stop(2, lineMiterLimit(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getLineMiterLimit());
- assertNotNull(layer.getLineMiterLimit().getFunction());
- assertEquals(CameraFunction.class, layer.getLineMiterLimit().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineMiterLimit().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getLineMiterLimit().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getLineMiterLimit().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineMiterLimit());
+ assertNotNull(layer.getLineMiterLimit().getFunction());
+ assertEquals(CameraFunction.class, layer.getLineMiterLimit().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getLineMiterLimit().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getLineMiterLimit().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getLineMiterLimit().getFunction().getStops()).size());
});
}
@@ -314,15 +300,12 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-round-limit");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(lineRoundLimit(0.3f));
- assertEquals((Float) layer.getLineRoundLimit().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(lineRoundLimit(0.3f));
+ assertEquals((Float) layer.getLineRoundLimit().getValue(), (Float) 0.3f);
});
}
@@ -331,30 +314,27 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-round-limit");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineRoundLimit(
- zoom(
- exponential(
- stop(2, lineRoundLimit(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineRoundLimit(
+ zoom(
+ exponential(
+ stop(2, lineRoundLimit(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getLineRoundLimit());
- assertNotNull(layer.getLineRoundLimit().getFunction());
- assertEquals(CameraFunction.class, layer.getLineRoundLimit().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineRoundLimit().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getLineRoundLimit().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getLineRoundLimit().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineRoundLimit());
+ assertNotNull(layer.getLineRoundLimit().getFunction());
+ assertEquals(CameraFunction.class, layer.getLineRoundLimit().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getLineRoundLimit().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getLineRoundLimit().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getLineRoundLimit().getFunction().getStops()).size());
});
}
@@ -363,16 +343,13 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-opacityTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setLineOpacityTransition(options);
- assertEquals(layer.getLineOpacityTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setLineOpacityTransition(options);
+ assertEquals(layer.getLineOpacityTransition(), options);
});
}
@@ -381,15 +358,12 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(lineOpacity(0.3f));
- assertEquals((Float) layer.getLineOpacity().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(lineOpacity(0.3f));
+ assertEquals((Float) layer.getLineOpacity().getValue(), (Float) 0.3f);
});
}
@@ -398,30 +372,27 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineOpacity(
- zoom(
- exponential(
- stop(2, lineOpacity(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineOpacity(
+ zoom(
+ exponential(
+ stop(2, lineOpacity(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getLineOpacity());
- assertNotNull(layer.getLineOpacity().getFunction());
- assertEquals(CameraFunction.class, layer.getLineOpacity().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineOpacity().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getLineOpacity().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getLineOpacity().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineOpacity());
+ assertNotNull(layer.getLineOpacity().getFunction());
+ assertEquals(CameraFunction.class, layer.getLineOpacity().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getLineOpacity().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getLineOpacity().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getLineOpacity().getFunction().getStops()).size());
});
}
@@ -430,23 +401,20 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineOpacity(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getLineOpacity());
- assertNotNull(layer.getLineOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getLineOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineOpacity().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getLineOpacity().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineOpacity(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getLineOpacity());
+ assertNotNull(layer.getLineOpacity().getFunction());
+ assertEquals(SourceFunction.class, layer.getLineOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineOpacity().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getLineOpacity().getFunction().getStops().getClass());
});
}
@@ -455,30 +423,27 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineOpacity(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, lineOpacity(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineOpacity(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, lineOpacity(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getLineOpacity());
- assertNotNull(layer.getLineOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getLineOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineOpacity().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getLineOpacity().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineOpacity());
+ assertNotNull(layer.getLineOpacity().getFunction());
+ assertEquals(SourceFunction.class, layer.getLineOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineOpacity().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getLineOpacity().getFunction().getStops().getClass());
});
}
@@ -487,33 +452,30 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineOpacity(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, lineOpacity(0.3f))
- )
- ).withDefaultValue(lineOpacity(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getLineOpacity());
- assertNotNull(layer.getLineOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getLineOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineOpacity().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getLineOpacity().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getLineOpacity().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getLineOpacity().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getLineOpacity().getFunction()).getDefaultValue().getValue());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineOpacity(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, lineOpacity(0.3f))
+ )
+ ).withDefaultValue(lineOpacity(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineOpacity());
+ assertNotNull(layer.getLineOpacity().getFunction());
+ assertEquals(SourceFunction.class, layer.getLineOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineOpacity().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getLineOpacity().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getLineOpacity().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getLineOpacity().getFunction()).getDefaultValue().getValue());
+ assertEquals(0.3f, ((SourceFunction) layer.getLineOpacity().getFunction()).getDefaultValue().getValue());
});
}
@@ -523,38 +485,35 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineOpacity(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, lineOpacity(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(lineOpacity(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getLineOpacity());
- assertNotNull(layer.getLineOpacity().getFunction());
- assertEquals(CompositeFunction.class, layer.getLineOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getLineOpacity().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getLineOpacity().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getLineOpacity().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getLineOpacity().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineOpacity(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, lineOpacity(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(lineOpacity(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineOpacity());
+ assertNotNull(layer.getLineOpacity().getFunction());
+ assertEquals(CompositeFunction.class, layer.getLineOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getLineOpacity().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getLineOpacity().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getLineOpacity().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getLineOpacity().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
});
}
@@ -563,16 +522,13 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-colorTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setLineColorTransition(options);
- assertEquals(layer.getLineColorTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setLineColorTransition(options);
+ assertEquals(layer.getLineColorTransition(), options);
});
}
@@ -581,15 +537,12 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(lineColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getLineColor().getValue(), (String) "rgba(0, 0, 0, 1)");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(lineColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getLineColor().getValue(), (String) "rgba(0, 0, 0, 1)");
});
}
@@ -598,30 +551,27 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineColor(
- zoom(
- exponential(
- stop(2, lineColor("rgba(0, 0, 0, 1)"))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineColor(
+ zoom(
+ exponential(
+ stop(2, lineColor("rgba(0, 0, 0, 1)"))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getLineColor());
- assertNotNull(layer.getLineColor().getFunction());
- assertEquals(CameraFunction.class, layer.getLineColor().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineColor().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getLineColor().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getLineColor().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineColor());
+ assertNotNull(layer.getLineColor().getFunction());
+ assertEquals(CameraFunction.class, layer.getLineColor().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getLineColor().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getLineColor().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getLineColor().getFunction().getStops()).size());
});
}
@@ -630,23 +580,20 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineColor(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getLineColor());
- assertNotNull(layer.getLineColor().getFunction());
- assertEquals(SourceFunction.class, layer.getLineColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineColor().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getLineColor().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineColor(property("FeaturePropertyA", Stops.<String>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getLineColor());
+ assertNotNull(layer.getLineColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getLineColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineColor().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getLineColor().getFunction().getStops().getClass());
});
}
@@ -655,30 +602,27 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineColor(
- property(
- "FeaturePropertyA",
- exponential(
- stop(Color.RED, lineColor(Color.RED))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineColor(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(Color.RED, lineColor(Color.RED))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getLineColor());
- assertNotNull(layer.getLineColor().getFunction());
- assertEquals(SourceFunction.class, layer.getLineColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineColor().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getLineColor().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineColor());
+ assertNotNull(layer.getLineColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getLineColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineColor().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getLineColor().getFunction().getStops().getClass());
});
}
@@ -687,33 +631,30 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineColor(
- property(
- "FeaturePropertyA",
- categorical(
- stop("valueA", lineColor(Color.RED))
- )
- ).withDefaultValue(lineColor(Color.GREEN))
- )
- );
-
- // Verify
- assertNotNull(layer.getLineColor());
- assertNotNull(layer.getLineColor().getFunction());
- assertEquals(SourceFunction.class, layer.getLineColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineColor().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getLineColor().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getLineColor().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getLineColor().getFunction()).getDefaultValue().getValue());
- assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getLineColor().getFunction()).getDefaultValue().getColorInt());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineColor(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop("valueA", lineColor(Color.RED))
+ )
+ ).withDefaultValue(lineColor(Color.GREEN))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineColor());
+ assertNotNull(layer.getLineColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getLineColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineColor().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getLineColor().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getLineColor().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getLineColor().getFunction()).getDefaultValue().getValue());
+ assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getLineColor().getFunction()).getDefaultValue().getColorInt());
});
}
@@ -723,15 +664,12 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(lineColor(Color.RED));
- assertEquals(layer.getLineColorAsInt(), Color.RED);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(lineColor(Color.RED));
+ assertEquals(layer.getLineColorAsInt(), Color.RED);
});
}
@@ -740,16 +678,13 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-translateTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setLineTranslateTransition(options);
- assertEquals(layer.getLineTranslateTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setLineTranslateTransition(options);
+ assertEquals(layer.getLineTranslateTransition(), options);
});
}
@@ -758,15 +693,12 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-translate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(lineTranslate(new Float[] {0f, 0f}));
- assertEquals((Float[]) layer.getLineTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(lineTranslate(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getLineTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
});
}
@@ -775,30 +707,27 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-translate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineTranslate(
- zoom(
- exponential(
- stop(2, lineTranslate(new Float[] {0f, 0f}))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineTranslate(
+ zoom(
+ exponential(
+ stop(2, lineTranslate(new Float[] {0f, 0f}))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getLineTranslate());
- assertNotNull(layer.getLineTranslate().getFunction());
- assertEquals(CameraFunction.class, layer.getLineTranslate().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineTranslate().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getLineTranslate().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getLineTranslate().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineTranslate());
+ assertNotNull(layer.getLineTranslate().getFunction());
+ assertEquals(CameraFunction.class, layer.getLineTranslate().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getLineTranslate().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getLineTranslate().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getLineTranslate().getFunction().getStops()).size());
});
}
@@ -807,15 +736,12 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-translate-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(lineTranslateAnchor(LINE_TRANSLATE_ANCHOR_MAP));
- assertEquals((String) layer.getLineTranslateAnchor().getValue(), (String) LINE_TRANSLATE_ANCHOR_MAP);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(lineTranslateAnchor(LINE_TRANSLATE_ANCHOR_MAP));
+ assertEquals((String) layer.getLineTranslateAnchor().getValue(), (String) LINE_TRANSLATE_ANCHOR_MAP);
});
}
@@ -824,29 +750,26 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-translate-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineTranslateAnchor(
- zoom(
- interval(
- stop(2, lineTranslateAnchor(LINE_TRANSLATE_ANCHOR_MAP))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineTranslateAnchor(
+ zoom(
+ interval(
+ stop(2, lineTranslateAnchor(LINE_TRANSLATE_ANCHOR_MAP))
)
)
- );
-
- // Verify
- assertNotNull(layer.getLineTranslateAnchor());
- assertNotNull(layer.getLineTranslateAnchor().getFunction());
- assertEquals(CameraFunction.class, layer.getLineTranslateAnchor().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getLineTranslateAnchor().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getLineTranslateAnchor().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineTranslateAnchor());
+ assertNotNull(layer.getLineTranslateAnchor().getFunction());
+ assertEquals(CameraFunction.class, layer.getLineTranslateAnchor().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getLineTranslateAnchor().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getLineTranslateAnchor().getFunction().getStops()).size());
});
}
@@ -855,16 +778,13 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-widthTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setLineWidthTransition(options);
- assertEquals(layer.getLineWidthTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setLineWidthTransition(options);
+ assertEquals(layer.getLineWidthTransition(), options);
});
}
@@ -873,15 +793,12 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(lineWidth(0.3f));
- assertEquals((Float) layer.getLineWidth().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(lineWidth(0.3f));
+ assertEquals((Float) layer.getLineWidth().getValue(), (Float) 0.3f);
});
}
@@ -890,30 +807,27 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineWidth(
- zoom(
- exponential(
- stop(2, lineWidth(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineWidth(
+ zoom(
+ exponential(
+ stop(2, lineWidth(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getLineWidth());
- assertNotNull(layer.getLineWidth().getFunction());
- assertEquals(CameraFunction.class, layer.getLineWidth().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineWidth().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineWidth());
+ assertNotNull(layer.getLineWidth().getFunction());
+ assertEquals(CameraFunction.class, layer.getLineWidth().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getLineWidth().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).size());
});
}
@@ -922,23 +836,20 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineWidth(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getLineWidth());
- assertNotNull(layer.getLineWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getLineWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineWidth().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getLineWidth().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineWidth(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getLineWidth());
+ assertNotNull(layer.getLineWidth().getFunction());
+ assertEquals(SourceFunction.class, layer.getLineWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineWidth().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getLineWidth().getFunction().getStops().getClass());
});
}
@@ -947,30 +858,27 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineWidth(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, lineWidth(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineWidth(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, lineWidth(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getLineWidth());
- assertNotNull(layer.getLineWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getLineWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineWidth().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getLineWidth().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineWidth());
+ assertNotNull(layer.getLineWidth().getFunction());
+ assertEquals(SourceFunction.class, layer.getLineWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineWidth().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getLineWidth().getFunction().getStops().getClass());
});
}
@@ -979,33 +887,30 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineWidth(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, lineWidth(0.3f))
- )
- ).withDefaultValue(lineWidth(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getLineWidth());
- assertNotNull(layer.getLineWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getLineWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineWidth().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getLineWidth().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getLineWidth().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getLineWidth().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getLineWidth().getFunction()).getDefaultValue().getValue());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineWidth(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, lineWidth(0.3f))
+ )
+ ).withDefaultValue(lineWidth(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineWidth());
+ assertNotNull(layer.getLineWidth().getFunction());
+ assertEquals(SourceFunction.class, layer.getLineWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineWidth().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getLineWidth().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getLineWidth().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getLineWidth().getFunction()).getDefaultValue().getValue());
+ assertEquals(0.3f, ((SourceFunction) layer.getLineWidth().getFunction()).getDefaultValue().getValue());
});
}
@@ -1015,38 +920,35 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineWidth(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, lineWidth(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(lineWidth(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getLineWidth());
- assertNotNull(layer.getLineWidth().getFunction());
- assertEquals(CompositeFunction.class, layer.getLineWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getLineWidth().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getLineWidth().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getLineWidth().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineWidth(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, lineWidth(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(lineWidth(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineWidth());
+ assertNotNull(layer.getLineWidth().getFunction());
+ assertEquals(CompositeFunction.class, layer.getLineWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getLineWidth().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getLineWidth().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getLineWidth().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
});
}
@@ -1055,16 +957,13 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-gap-widthTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setLineGapWidthTransition(options);
- assertEquals(layer.getLineGapWidthTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setLineGapWidthTransition(options);
+ assertEquals(layer.getLineGapWidthTransition(), options);
});
}
@@ -1073,15 +972,12 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-gap-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(lineGapWidth(0.3f));
- assertEquals((Float) layer.getLineGapWidth().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(lineGapWidth(0.3f));
+ assertEquals((Float) layer.getLineGapWidth().getValue(), (Float) 0.3f);
});
}
@@ -1090,30 +986,27 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-gap-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineGapWidth(
- zoom(
- exponential(
- stop(2, lineGapWidth(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineGapWidth(
+ zoom(
+ exponential(
+ stop(2, lineGapWidth(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getLineGapWidth());
- assertNotNull(layer.getLineGapWidth().getFunction());
- assertEquals(CameraFunction.class, layer.getLineGapWidth().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineGapWidth().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getLineGapWidth().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getLineGapWidth().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineGapWidth());
+ assertNotNull(layer.getLineGapWidth().getFunction());
+ assertEquals(CameraFunction.class, layer.getLineGapWidth().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getLineGapWidth().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getLineGapWidth().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getLineGapWidth().getFunction().getStops()).size());
});
}
@@ -1122,23 +1015,20 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-gap-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineGapWidth(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getLineGapWidth());
- assertNotNull(layer.getLineGapWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getLineGapWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineGapWidth().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getLineGapWidth().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineGapWidth(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getLineGapWidth());
+ assertNotNull(layer.getLineGapWidth().getFunction());
+ assertEquals(SourceFunction.class, layer.getLineGapWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineGapWidth().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getLineGapWidth().getFunction().getStops().getClass());
});
}
@@ -1147,30 +1037,27 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-gap-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineGapWidth(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, lineGapWidth(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineGapWidth(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, lineGapWidth(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getLineGapWidth());
- assertNotNull(layer.getLineGapWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getLineGapWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineGapWidth().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getLineGapWidth().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineGapWidth());
+ assertNotNull(layer.getLineGapWidth().getFunction());
+ assertEquals(SourceFunction.class, layer.getLineGapWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineGapWidth().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getLineGapWidth().getFunction().getStops().getClass());
});
}
@@ -1179,33 +1066,30 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-gap-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineGapWidth(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, lineGapWidth(0.3f))
- )
- ).withDefaultValue(lineGapWidth(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getLineGapWidth());
- assertNotNull(layer.getLineGapWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getLineGapWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineGapWidth().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getLineGapWidth().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getLineGapWidth().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getLineGapWidth().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getLineGapWidth().getFunction()).getDefaultValue().getValue());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineGapWidth(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, lineGapWidth(0.3f))
+ )
+ ).withDefaultValue(lineGapWidth(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineGapWidth());
+ assertNotNull(layer.getLineGapWidth().getFunction());
+ assertEquals(SourceFunction.class, layer.getLineGapWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineGapWidth().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getLineGapWidth().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getLineGapWidth().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getLineGapWidth().getFunction()).getDefaultValue().getValue());
+ assertEquals(0.3f, ((SourceFunction) layer.getLineGapWidth().getFunction()).getDefaultValue().getValue());
});
}
@@ -1215,38 +1099,35 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-gap-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineGapWidth(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, lineGapWidth(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(lineGapWidth(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getLineGapWidth());
- assertNotNull(layer.getLineGapWidth().getFunction());
- assertEquals(CompositeFunction.class, layer.getLineGapWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getLineGapWidth().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getLineGapWidth().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getLineGapWidth().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getLineGapWidth().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineGapWidth(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, lineGapWidth(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(lineGapWidth(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineGapWidth());
+ assertNotNull(layer.getLineGapWidth().getFunction());
+ assertEquals(CompositeFunction.class, layer.getLineGapWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getLineGapWidth().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getLineGapWidth().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getLineGapWidth().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getLineGapWidth().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
});
}
@@ -1255,16 +1136,13 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-offsetTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setLineOffsetTransition(options);
- assertEquals(layer.getLineOffsetTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setLineOffsetTransition(options);
+ assertEquals(layer.getLineOffsetTransition(), options);
});
}
@@ -1273,15 +1151,12 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-offset");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(lineOffset(0.3f));
- assertEquals((Float) layer.getLineOffset().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(lineOffset(0.3f));
+ assertEquals((Float) layer.getLineOffset().getValue(), (Float) 0.3f);
});
}
@@ -1290,30 +1165,27 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-offset");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineOffset(
- zoom(
- exponential(
- stop(2, lineOffset(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineOffset(
+ zoom(
+ exponential(
+ stop(2, lineOffset(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getLineOffset());
- assertNotNull(layer.getLineOffset().getFunction());
- assertEquals(CameraFunction.class, layer.getLineOffset().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineOffset().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getLineOffset().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getLineOffset().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineOffset());
+ assertNotNull(layer.getLineOffset().getFunction());
+ assertEquals(CameraFunction.class, layer.getLineOffset().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getLineOffset().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getLineOffset().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getLineOffset().getFunction().getStops()).size());
});
}
@@ -1322,23 +1194,20 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-offset");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineOffset(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getLineOffset());
- assertNotNull(layer.getLineOffset().getFunction());
- assertEquals(SourceFunction.class, layer.getLineOffset().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineOffset().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getLineOffset().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineOffset(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getLineOffset());
+ assertNotNull(layer.getLineOffset().getFunction());
+ assertEquals(SourceFunction.class, layer.getLineOffset().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineOffset().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getLineOffset().getFunction().getStops().getClass());
});
}
@@ -1347,30 +1216,27 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-offset");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineOffset(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, lineOffset(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineOffset(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, lineOffset(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getLineOffset());
- assertNotNull(layer.getLineOffset().getFunction());
- assertEquals(SourceFunction.class, layer.getLineOffset().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineOffset().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getLineOffset().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineOffset());
+ assertNotNull(layer.getLineOffset().getFunction());
+ assertEquals(SourceFunction.class, layer.getLineOffset().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineOffset().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getLineOffset().getFunction().getStops().getClass());
});
}
@@ -1379,33 +1245,30 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-offset");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineOffset(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, lineOffset(0.3f))
- )
- ).withDefaultValue(lineOffset(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getLineOffset());
- assertNotNull(layer.getLineOffset().getFunction());
- assertEquals(SourceFunction.class, layer.getLineOffset().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineOffset().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getLineOffset().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getLineOffset().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getLineOffset().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getLineOffset().getFunction()).getDefaultValue().getValue());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineOffset(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, lineOffset(0.3f))
+ )
+ ).withDefaultValue(lineOffset(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineOffset());
+ assertNotNull(layer.getLineOffset().getFunction());
+ assertEquals(SourceFunction.class, layer.getLineOffset().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineOffset().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getLineOffset().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getLineOffset().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getLineOffset().getFunction()).getDefaultValue().getValue());
+ assertEquals(0.3f, ((SourceFunction) layer.getLineOffset().getFunction()).getDefaultValue().getValue());
});
}
@@ -1415,38 +1278,35 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-offset");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineOffset(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, lineOffset(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(lineOffset(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getLineOffset());
- assertNotNull(layer.getLineOffset().getFunction());
- assertEquals(CompositeFunction.class, layer.getLineOffset().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getLineOffset().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getLineOffset().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getLineOffset().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getLineOffset().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineOffset(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, lineOffset(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(lineOffset(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineOffset());
+ assertNotNull(layer.getLineOffset().getFunction());
+ assertEquals(CompositeFunction.class, layer.getLineOffset().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getLineOffset().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getLineOffset().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getLineOffset().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getLineOffset().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
});
}
@@ -1455,16 +1315,13 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-blurTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setLineBlurTransition(options);
- assertEquals(layer.getLineBlurTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setLineBlurTransition(options);
+ assertEquals(layer.getLineBlurTransition(), options);
});
}
@@ -1473,15 +1330,12 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(lineBlur(0.3f));
- assertEquals((Float) layer.getLineBlur().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(lineBlur(0.3f));
+ assertEquals((Float) layer.getLineBlur().getValue(), (Float) 0.3f);
});
}
@@ -1490,30 +1344,27 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineBlur(
- zoom(
- exponential(
- stop(2, lineBlur(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineBlur(
+ zoom(
+ exponential(
+ stop(2, lineBlur(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getLineBlur());
- assertNotNull(layer.getLineBlur().getFunction());
- assertEquals(CameraFunction.class, layer.getLineBlur().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineBlur().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getLineBlur().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getLineBlur().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineBlur());
+ assertNotNull(layer.getLineBlur().getFunction());
+ assertEquals(CameraFunction.class, layer.getLineBlur().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getLineBlur().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getLineBlur().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getLineBlur().getFunction().getStops()).size());
});
}
@@ -1522,23 +1373,20 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineBlur(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getLineBlur());
- assertNotNull(layer.getLineBlur().getFunction());
- assertEquals(SourceFunction.class, layer.getLineBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineBlur().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getLineBlur().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineBlur(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getLineBlur());
+ assertNotNull(layer.getLineBlur().getFunction());
+ assertEquals(SourceFunction.class, layer.getLineBlur().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineBlur().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getLineBlur().getFunction().getStops().getClass());
});
}
@@ -1547,30 +1395,27 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineBlur(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, lineBlur(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineBlur(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, lineBlur(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getLineBlur());
- assertNotNull(layer.getLineBlur().getFunction());
- assertEquals(SourceFunction.class, layer.getLineBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineBlur().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getLineBlur().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineBlur());
+ assertNotNull(layer.getLineBlur().getFunction());
+ assertEquals(SourceFunction.class, layer.getLineBlur().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineBlur().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getLineBlur().getFunction().getStops().getClass());
});
}
@@ -1579,33 +1424,30 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineBlur(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, lineBlur(0.3f))
- )
- ).withDefaultValue(lineBlur(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getLineBlur());
- assertNotNull(layer.getLineBlur().getFunction());
- assertEquals(SourceFunction.class, layer.getLineBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineBlur().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getLineBlur().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getLineBlur().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getLineBlur().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getLineBlur().getFunction()).getDefaultValue().getValue());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineBlur(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, lineBlur(0.3f))
+ )
+ ).withDefaultValue(lineBlur(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineBlur());
+ assertNotNull(layer.getLineBlur().getFunction());
+ assertEquals(SourceFunction.class, layer.getLineBlur().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineBlur().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getLineBlur().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getLineBlur().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getLineBlur().getFunction()).getDefaultValue().getValue());
+ assertEquals(0.3f, ((SourceFunction) layer.getLineBlur().getFunction()).getDefaultValue().getValue());
});
}
@@ -1615,38 +1457,35 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineBlur(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, lineBlur(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(lineBlur(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getLineBlur());
- assertNotNull(layer.getLineBlur().getFunction());
- assertEquals(CompositeFunction.class, layer.getLineBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getLineBlur().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getLineBlur().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getLineBlur().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getLineBlur().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineBlur(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, lineBlur(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(lineBlur(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineBlur());
+ assertNotNull(layer.getLineBlur().getFunction());
+ assertEquals(CompositeFunction.class, layer.getLineBlur().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getLineBlur().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getLineBlur().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getLineBlur().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getLineBlur().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
});
}
@@ -1655,16 +1494,13 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-dasharrayTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setLineDasharrayTransition(options);
- assertEquals(layer.getLineDasharrayTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setLineDasharrayTransition(options);
+ assertEquals(layer.getLineDasharrayTransition(), options);
});
}
@@ -1673,15 +1509,12 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-dasharray");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(lineDasharray(new Float[] {}));
- assertEquals((Float[]) layer.getLineDasharray().getValue(), (Float[]) new Float[] {});
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(lineDasharray(new Float[] {}));
+ assertEquals((Float[]) layer.getLineDasharray().getValue(), (Float[]) new Float[] {});
});
}
@@ -1690,29 +1523,26 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-dasharray");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineDasharray(
- zoom(
- interval(
- stop(2, lineDasharray(new Float[] {}))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ lineDasharray(
+ zoom(
+ interval(
+ stop(2, lineDasharray(new Float[] {}))
)
)
- );
-
- // Verify
- assertNotNull(layer.getLineDasharray());
- assertNotNull(layer.getLineDasharray().getFunction());
- assertEquals(CameraFunction.class, layer.getLineDasharray().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getLineDasharray().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getLineDasharray().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLineDasharray());
+ assertNotNull(layer.getLineDasharray().getFunction());
+ assertEquals(CameraFunction.class, layer.getLineDasharray().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getLineDasharray().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getLineDasharray().getFunction().getStops()).size());
});
}
@@ -1721,16 +1551,13 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-patternTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setLinePatternTransition(options);
- assertEquals(layer.getLinePatternTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setLinePatternTransition(options);
+ assertEquals(layer.getLinePatternTransition(), options);
});
}
@@ -1739,15 +1566,12 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-pattern");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(linePattern("pedestrian-polygon"));
- assertEquals((String) layer.getLinePattern().getValue(), (String) "pedestrian-polygon");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(linePattern("pedestrian-polygon"));
+ assertEquals((String) layer.getLinePattern().getValue(), (String) "pedestrian-polygon");
});
}
@@ -1756,29 +1580,26 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-pattern");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- linePattern(
- zoom(
- interval(
- stop(2, linePattern("pedestrian-polygon"))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ linePattern(
+ zoom(
+ interval(
+ stop(2, linePattern("pedestrian-polygon"))
)
)
- );
-
- // Verify
- assertNotNull(layer.getLinePattern());
- assertNotNull(layer.getLinePattern().getFunction());
- assertEquals(CameraFunction.class, layer.getLinePattern().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getLinePattern().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getLinePattern().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getLinePattern());
+ assertNotNull(layer.getLinePattern().getFunction());
+ assertEquals(CameraFunction.class, layer.getLinePattern().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getLinePattern().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getLinePattern().getFunction().getStops()).size());
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerTest.java
index 020effe331..11368767fe 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerTest.java
@@ -2,39 +2,36 @@
package com.mapbox.mapboxsdk.testapp.style;
-import android.graphics.Color;
-import android.support.test.espresso.UiController;
import android.support.test.runner.AndroidJUnit4;
-import timber.log.Timber;
-
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.style.functions.CompositeFunction;
import com.mapbox.mapboxsdk.style.functions.CameraFunction;
-import com.mapbox.mapboxsdk.style.functions.SourceFunction;
-import com.mapbox.mapboxsdk.style.functions.stops.CategoricalStops;
import com.mapbox.mapboxsdk.style.functions.stops.ExponentialStops;
-import com.mapbox.mapboxsdk.style.functions.stops.IdentityStops;
-import com.mapbox.mapboxsdk.style.functions.stops.IntervalStops;
-import com.mapbox.mapboxsdk.style.functions.stops.Stop;
-import com.mapbox.mapboxsdk.style.functions.stops.Stops;
import com.mapbox.mapboxsdk.style.layers.RasterLayer;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
+import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static com.mapbox.mapboxsdk.style.functions.Function.*;
+import timber.log.Timber;
+
+import static com.mapbox.mapboxsdk.style.functions.Function.zoom;
import static com.mapbox.mapboxsdk.style.functions.stops.Stop.stop;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stops.*;
+import static com.mapbox.mapboxsdk.style.functions.stops.Stops.exponential;
+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.rasterBrightnessMax;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.rasterBrightnessMin;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.rasterContrast;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.rasterFadeDuration;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.rasterHueRotate;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.rasterOpacity;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.rasterSaturation;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.visibility;
import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
-import static org.junit.Assert.*;
-import static com.mapbox.mapboxsdk.style.layers.Property.*;
-import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
-
-import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
-import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
/**
* Basic smoke tests for RasterLayer
@@ -51,17 +48,14 @@ public class RasterLayerTest extends BaseActivityTest {
private void setupLayer() {
Timber.i("Retrieving layer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Timber.i("Adding layer");
- layer = new RasterLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- // Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new RasterLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ // Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
});
}
@@ -71,18 +65,15 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("Visibility");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- // Get initial
- assertEquals(layer.getVisibility().getValue(), VISIBLE);
+ // Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
- // Set
- layer.setProperties(visibility(NONE));
- assertEquals(layer.getVisibility().getValue(), NONE);
- }
+ // Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
});
}
@@ -91,16 +82,13 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-opacityTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setRasterOpacityTransition(options);
- assertEquals(layer.getRasterOpacityTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setRasterOpacityTransition(options);
+ assertEquals(layer.getRasterOpacityTransition(), options);
});
}
@@ -109,15 +97,12 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(rasterOpacity(0.3f));
- assertEquals((Float) layer.getRasterOpacity().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(rasterOpacity(0.3f));
+ assertEquals((Float) layer.getRasterOpacity().getValue(), (Float) 0.3f);
});
}
@@ -126,30 +111,27 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- rasterOpacity(
- zoom(
- exponential(
- stop(2, rasterOpacity(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ rasterOpacity(
+ zoom(
+ exponential(
+ stop(2, rasterOpacity(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getRasterOpacity());
- assertNotNull(layer.getRasterOpacity().getFunction());
- assertEquals(CameraFunction.class, layer.getRasterOpacity().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getRasterOpacity().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getRasterOpacity().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getRasterOpacity().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getRasterOpacity());
+ assertNotNull(layer.getRasterOpacity().getFunction());
+ assertEquals(CameraFunction.class, layer.getRasterOpacity().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getRasterOpacity().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getRasterOpacity().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getRasterOpacity().getFunction().getStops()).size());
});
}
@@ -158,16 +140,13 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-hue-rotateTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setRasterHueRotateTransition(options);
- assertEquals(layer.getRasterHueRotateTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setRasterHueRotateTransition(options);
+ assertEquals(layer.getRasterHueRotateTransition(), options);
});
}
@@ -176,15 +155,12 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-hue-rotate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(rasterHueRotate(0.3f));
- assertEquals((Float) layer.getRasterHueRotate().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(rasterHueRotate(0.3f));
+ assertEquals((Float) layer.getRasterHueRotate().getValue(), (Float) 0.3f);
});
}
@@ -193,30 +169,27 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-hue-rotate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- rasterHueRotate(
- zoom(
- exponential(
- stop(2, rasterHueRotate(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ rasterHueRotate(
+ zoom(
+ exponential(
+ stop(2, rasterHueRotate(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getRasterHueRotate());
- assertNotNull(layer.getRasterHueRotate().getFunction());
- assertEquals(CameraFunction.class, layer.getRasterHueRotate().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getRasterHueRotate().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getRasterHueRotate().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getRasterHueRotate().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getRasterHueRotate());
+ assertNotNull(layer.getRasterHueRotate().getFunction());
+ assertEquals(CameraFunction.class, layer.getRasterHueRotate().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getRasterHueRotate().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getRasterHueRotate().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getRasterHueRotate().getFunction().getStops()).size());
});
}
@@ -225,16 +198,13 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-brightness-minTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setRasterBrightnessMinTransition(options);
- assertEquals(layer.getRasterBrightnessMinTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setRasterBrightnessMinTransition(options);
+ assertEquals(layer.getRasterBrightnessMinTransition(), options);
});
}
@@ -243,15 +213,12 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-brightness-min");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(rasterBrightnessMin(0.3f));
- assertEquals((Float) layer.getRasterBrightnessMin().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(rasterBrightnessMin(0.3f));
+ assertEquals((Float) layer.getRasterBrightnessMin().getValue(), (Float) 0.3f);
});
}
@@ -260,30 +227,27 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-brightness-min");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- rasterBrightnessMin(
- zoom(
- exponential(
- stop(2, rasterBrightnessMin(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ rasterBrightnessMin(
+ zoom(
+ exponential(
+ stop(2, rasterBrightnessMin(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getRasterBrightnessMin());
- assertNotNull(layer.getRasterBrightnessMin().getFunction());
- assertEquals(CameraFunction.class, layer.getRasterBrightnessMin().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getRasterBrightnessMin().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getRasterBrightnessMin().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getRasterBrightnessMin().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getRasterBrightnessMin());
+ assertNotNull(layer.getRasterBrightnessMin().getFunction());
+ assertEquals(CameraFunction.class, layer.getRasterBrightnessMin().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getRasterBrightnessMin().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getRasterBrightnessMin().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getRasterBrightnessMin().getFunction().getStops()).size());
});
}
@@ -292,16 +256,13 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-brightness-maxTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setRasterBrightnessMaxTransition(options);
- assertEquals(layer.getRasterBrightnessMaxTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setRasterBrightnessMaxTransition(options);
+ assertEquals(layer.getRasterBrightnessMaxTransition(), options);
});
}
@@ -310,15 +271,12 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-brightness-max");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(rasterBrightnessMax(0.3f));
- assertEquals((Float) layer.getRasterBrightnessMax().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(rasterBrightnessMax(0.3f));
+ assertEquals((Float) layer.getRasterBrightnessMax().getValue(), (Float) 0.3f);
});
}
@@ -327,30 +285,27 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-brightness-max");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- rasterBrightnessMax(
- zoom(
- exponential(
- stop(2, rasterBrightnessMax(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ rasterBrightnessMax(
+ zoom(
+ exponential(
+ stop(2, rasterBrightnessMax(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getRasterBrightnessMax());
- assertNotNull(layer.getRasterBrightnessMax().getFunction());
- assertEquals(CameraFunction.class, layer.getRasterBrightnessMax().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getRasterBrightnessMax().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getRasterBrightnessMax().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getRasterBrightnessMax().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getRasterBrightnessMax());
+ assertNotNull(layer.getRasterBrightnessMax().getFunction());
+ assertEquals(CameraFunction.class, layer.getRasterBrightnessMax().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getRasterBrightnessMax().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getRasterBrightnessMax().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getRasterBrightnessMax().getFunction().getStops()).size());
});
}
@@ -359,16 +314,13 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-saturationTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setRasterSaturationTransition(options);
- assertEquals(layer.getRasterSaturationTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setRasterSaturationTransition(options);
+ assertEquals(layer.getRasterSaturationTransition(), options);
});
}
@@ -377,15 +329,12 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-saturation");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(rasterSaturation(0.3f));
- assertEquals((Float) layer.getRasterSaturation().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(rasterSaturation(0.3f));
+ assertEquals((Float) layer.getRasterSaturation().getValue(), (Float) 0.3f);
});
}
@@ -394,30 +343,27 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-saturation");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- rasterSaturation(
- zoom(
- exponential(
- stop(2, rasterSaturation(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ rasterSaturation(
+ zoom(
+ exponential(
+ stop(2, rasterSaturation(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getRasterSaturation());
- assertNotNull(layer.getRasterSaturation().getFunction());
- assertEquals(CameraFunction.class, layer.getRasterSaturation().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getRasterSaturation().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getRasterSaturation().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getRasterSaturation().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getRasterSaturation());
+ assertNotNull(layer.getRasterSaturation().getFunction());
+ assertEquals(CameraFunction.class, layer.getRasterSaturation().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getRasterSaturation().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getRasterSaturation().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getRasterSaturation().getFunction().getStops()).size());
});
}
@@ -426,16 +372,13 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-contrastTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setRasterContrastTransition(options);
- assertEquals(layer.getRasterContrastTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setRasterContrastTransition(options);
+ assertEquals(layer.getRasterContrastTransition(), options);
});
}
@@ -444,15 +387,12 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-contrast");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(rasterContrast(0.3f));
- assertEquals((Float) layer.getRasterContrast().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(rasterContrast(0.3f));
+ assertEquals((Float) layer.getRasterContrast().getValue(), (Float) 0.3f);
});
}
@@ -461,30 +401,27 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-contrast");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- rasterContrast(
- zoom(
- exponential(
- stop(2, rasterContrast(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ rasterContrast(
+ zoom(
+ exponential(
+ stop(2, rasterContrast(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getRasterContrast());
- assertNotNull(layer.getRasterContrast().getFunction());
- assertEquals(CameraFunction.class, layer.getRasterContrast().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getRasterContrast().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getRasterContrast().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getRasterContrast().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getRasterContrast());
+ assertNotNull(layer.getRasterContrast().getFunction());
+ assertEquals(CameraFunction.class, layer.getRasterContrast().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getRasterContrast().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getRasterContrast().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getRasterContrast().getFunction().getStops()).size());
});
}
@@ -493,16 +430,13 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-fade-durationTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setRasterFadeDurationTransition(options);
- assertEquals(layer.getRasterFadeDurationTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setRasterFadeDurationTransition(options);
+ assertEquals(layer.getRasterFadeDurationTransition(), options);
});
}
@@ -511,15 +445,12 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-fade-duration");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(rasterFadeDuration(0.3f));
- assertEquals((Float) layer.getRasterFadeDuration().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(rasterFadeDuration(0.3f));
+ assertEquals((Float) layer.getRasterFadeDuration().getValue(), (Float) 0.3f);
});
}
@@ -528,30 +459,27 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-fade-duration");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- rasterFadeDuration(
- zoom(
- exponential(
- stop(2, rasterFadeDuration(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ rasterFadeDuration(
+ zoom(
+ exponential(
+ stop(2, rasterFadeDuration(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getRasterFadeDuration());
- assertNotNull(layer.getRasterFadeDuration().getFunction());
- assertEquals(CameraFunction.class, layer.getRasterFadeDuration().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getRasterFadeDuration().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getRasterFadeDuration().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getRasterFadeDuration().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getRasterFadeDuration());
+ assertNotNull(layer.getRasterFadeDuration().getFunction());
+ assertEquals(CameraFunction.class, layer.getRasterFadeDuration().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getRasterFadeDuration().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getRasterFadeDuration().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getRasterFadeDuration().getFunction().getStops()).size());
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTests.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTests.java
index bf8bcb9f66..fc526176d4 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTests.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTests.java
@@ -8,7 +8,6 @@ import android.support.test.espresso.ViewAction;
import android.support.test.runner.AndroidJUnit4;
import android.view.View;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.style.layers.CannotAddLayerException;
import com.mapbox.mapboxsdk.style.layers.CircleLayer;
import com.mapbox.mapboxsdk.style.layers.FillLayer;
@@ -22,7 +21,6 @@ import com.mapbox.mapboxsdk.style.sources.RasterSource;
import com.mapbox.mapboxsdk.style.sources.Source;
import com.mapbox.mapboxsdk.style.sources.VectorSource;
import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
import com.mapbox.mapboxsdk.testapp.activity.style.RuntimeStyleTestActivity;
@@ -192,41 +190,38 @@ public class RuntimeStyleTests extends BaseActivityTest {
@Test
public void testAddRemoveSource() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- mapboxMap.addSource(new VectorSource("my-source", "mapbox://mapbox.mapbox-terrain-v2"));
- mapboxMap.removeSource("my-source");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ mapboxMap.addSource(new VectorSource("my-source", "mapbox://mapbox.mapbox-terrain-v2"));
+ mapboxMap.removeSource("my-source");
- // Add initial source
- mapboxMap.addSource(new VectorSource("my-source", "mapbox://mapbox.mapbox-terrain-v2"));
+ // Add initial source
+ mapboxMap.addSource(new VectorSource("my-source", "mapbox://mapbox.mapbox-terrain-v2"));
- // Remove
- Source mySource = mapboxMap.removeSource("my-source");
- assertNotNull(mySource);
- assertNull(mapboxMap.getLayer("my-source"));
+ // Remove
+ Source mySource = mapboxMap.removeSource("my-source");
+ assertNotNull(mySource);
+ assertNull(mapboxMap.getLayer("my-source"));
- // Add
- Source source = new VectorSource("my-source", "mapbox://mapbox.mapbox-terrain-v2");
- mapboxMap.addSource(source);
+ // Add
+ Source source = new VectorSource("my-source", "mapbox://mapbox.mapbox-terrain-v2");
+ mapboxMap.addSource(source);
- // Remove, preserving the reference
- mapboxMap.removeSource(source);
+ // Remove, preserving the reference
+ mapboxMap.removeSource(source);
- // Re-add the reference...
- mapboxMap.addSource(source);
+ // Re-add the reference...
+ mapboxMap.addSource(source);
- // Ensure it's there
- Assert.assertNotNull(mapboxMap.getSource(source.getId()));
+ // Ensure it's there
+ Assert.assertNotNull(mapboxMap.getSource(source.getId()));
- // Test adding a duplicate source
- try {
- Source source2 = new VectorSource("my-source", "mapbox://mapbox.mapbox-terrain-v2");
- mapboxMap.addSource(source2);
- fail("Should not have been allowed to add a source with a duplicate id");
- } catch (CannotAddSourceException cannotAddSourceException) {
- // OK
- }
+ // Test adding a duplicate source
+ try {
+ Source source2 = new VectorSource("my-source", "mapbox://mapbox.mapbox-terrain-v2");
+ mapboxMap.addSource(source2);
+ fail("Should not have been allowed to add a source with a duplicate id");
+ } catch (CannotAddSourceException cannotAddSourceException) {
+ // OK
}
});
@@ -235,45 +230,36 @@ public class RuntimeStyleTests extends BaseActivityTest {
@Test
public void testVectorSourceUrlGetter() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- VectorSource source = new VectorSource("my-source", "mapbox://mapbox.mapbox-terrain-v2");
- mapboxMap.addSource(source);
- assertEquals("mapbox://mapbox.mapbox-terrain-v2", source.getUrl());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ VectorSource source = new VectorSource("my-source", "mapbox://mapbox.mapbox-terrain-v2");
+ mapboxMap.addSource(source);
+ assertEquals("mapbox://mapbox.mapbox-terrain-v2", source.getUrl());
});
}
@Test
public void testRasterSourceUrlGetter() {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- RasterSource source = new RasterSource("my-source", "mapbox://mapbox.mapbox-terrain-v2");
- mapboxMap.addSource(source);
- assertEquals("mapbox://mapbox.mapbox-terrain-v2", source.getUrl());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ RasterSource source = new RasterSource("my-source", "mapbox://mapbox.mapbox-terrain-v2");
+ mapboxMap.addSource(source);
+ assertEquals("mapbox://mapbox.mapbox-terrain-v2", source.getUrl());
});
}
@Test
public void testGeoJsonSourceUrlGetter() throws MalformedURLException {
validateTestSetup();
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- GeoJsonSource source = new GeoJsonSource("my-source");
- mapboxMap.addSource(source);
- assertNull(source.getUrl());
- try {
- source.setUrl(new URL("http://mapbox.com/my-file.json"));
- } catch (MalformedURLException exception) {
- fail();
- }
- assertEquals("http://mapbox.com/my-file.json", source.getUrl());
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ GeoJsonSource source = new GeoJsonSource("my-source");
+ mapboxMap.addSource(source);
+ assertNull(source.getUrl());
+ try {
+ source.setUrl(new URL("http://mapbox.com/my-file.json"));
+ } catch (MalformedURLException exception) {
+ fail();
}
+ assertEquals("http://mapbox.com/my-file.json", source.getUrl());
});
}
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 f8248ae4a7..cb79700430 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
@@ -3,14 +3,10 @@
package com.mapbox.mapboxsdk.testapp.style;
import android.graphics.Color;
-import android.support.test.espresso.UiController;
import android.support.test.runner.AndroidJUnit4;
-import timber.log.Timber;
-
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.style.functions.CompositeFunction;
import com.mapbox.mapboxsdk.style.functions.CameraFunction;
+import com.mapbox.mapboxsdk.style.functions.CompositeFunction;
import com.mapbox.mapboxsdk.style.functions.SourceFunction;
import com.mapbox.mapboxsdk.style.functions.stops.CategoricalStops;
import com.mapbox.mapboxsdk.style.functions.stops.ExponentialStops;
@@ -19,22 +15,90 @@ import com.mapbox.mapboxsdk.style.functions.stops.IntervalStops;
import com.mapbox.mapboxsdk.style.functions.stops.Stop;
import com.mapbox.mapboxsdk.style.functions.stops.Stops;
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
+import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static com.mapbox.mapboxsdk.style.functions.Function.*;
+import timber.log.Timber;
+
+import static com.mapbox.mapboxsdk.style.functions.Function.composite;
+import static com.mapbox.mapboxsdk.style.functions.Function.property;
+import static com.mapbox.mapboxsdk.style.functions.Function.zoom;
import static com.mapbox.mapboxsdk.style.functions.stops.Stop.stop;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stops.*;
+import static com.mapbox.mapboxsdk.style.functions.stops.Stops.categorical;
+import static com.mapbox.mapboxsdk.style.functions.stops.Stops.exponential;
+import static com.mapbox.mapboxsdk.style.functions.stops.Stops.interval;
+import static com.mapbox.mapboxsdk.style.layers.Property.ICON_ANCHOR_CENTER;
+import static com.mapbox.mapboxsdk.style.layers.Property.ICON_PITCH_ALIGNMENT_MAP;
+import static com.mapbox.mapboxsdk.style.layers.Property.ICON_ROTATION_ALIGNMENT_MAP;
+import static com.mapbox.mapboxsdk.style.layers.Property.ICON_TEXT_FIT_NONE;
+import static com.mapbox.mapboxsdk.style.layers.Property.ICON_TRANSLATE_ANCHOR_MAP;
+import static com.mapbox.mapboxsdk.style.layers.Property.NONE;
+import static com.mapbox.mapboxsdk.style.layers.Property.SYMBOL_PLACEMENT_POINT;
+import static com.mapbox.mapboxsdk.style.layers.Property.TEXT_ANCHOR_CENTER;
+import static com.mapbox.mapboxsdk.style.layers.Property.TEXT_JUSTIFY_LEFT;
+import static com.mapbox.mapboxsdk.style.layers.Property.TEXT_PITCH_ALIGNMENT_MAP;
+import static com.mapbox.mapboxsdk.style.layers.Property.TEXT_ROTATION_ALIGNMENT_MAP;
+import static com.mapbox.mapboxsdk.style.layers.Property.TEXT_TRANSFORM_NONE;
+import static com.mapbox.mapboxsdk.style.layers.Property.TEXT_TRANSLATE_ANCHOR_MAP;
+import static com.mapbox.mapboxsdk.style.layers.Property.VISIBLE;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAllowOverlap;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAnchor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconHaloBlur;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconHaloColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconHaloWidth;
+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.iconKeepUpright;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconOffset;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconOpacity;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconOptional;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconPadding;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconPitchAlignment;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconRotate;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconRotationAlignment;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconSize;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconTextFit;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconTextFitPadding;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconTranslate;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconTranslateAnchor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.symbolAvoidEdges;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.symbolPlacement;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.symbolSpacing;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textAllowOverlap;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textAnchor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textField;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textFont;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textHaloBlur;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textHaloColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textHaloWidth;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textIgnorePlacement;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textJustify;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textKeepUpright;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textLetterSpacing;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textLineHeight;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textMaxAngle;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textMaxWidth;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textOffset;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textOpacity;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textOptional;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textPadding;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textPitchAlignment;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textRotate;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textRotationAlignment;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textSize;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textTransform;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textTranslate;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textTranslateAnchor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.visibility;
import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
-import static org.junit.Assert.*;
-import static com.mapbox.mapboxsdk.style.layers.Property.*;
-import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
-
-import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
-import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
/**
* Basic smoke tests for SymbolLayer
@@ -51,17 +115,14 @@ public class SymbolLayerTest extends BaseActivityTest {
private void setupLayer() {
Timber.i("Retrieving layer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Timber.i("Adding layer");
- layer = new SymbolLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- // Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ // Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
});
}
@@ -71,18 +132,15 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("Visibility");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- // Get initial
- assertEquals(layer.getVisibility().getValue(), VISIBLE);
+ // Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
- // Set
- layer.setProperties(visibility(NONE));
- assertEquals(layer.getVisibility().getValue(), NONE);
- }
+ // Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
});
}
@@ -91,19 +149,16 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("SourceLayer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Get initial
- assertEquals(layer.getSourceLayer(), "composite");
-
- // Set
- final String sourceLayer = "test";
- layer.setSourceLayer(sourceLayer);
- assertEquals(layer.getSourceLayer(), sourceLayer);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getSourceLayer(), "composite");
+
+ // Set
+ final String sourceLayer = "test";
+ layer.setSourceLayer(sourceLayer);
+ assertEquals(layer.getSourceLayer(), sourceLayer);
});
}
@@ -112,15 +167,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("symbol-placement");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(symbolPlacement(SYMBOL_PLACEMENT_POINT));
- assertEquals((String) layer.getSymbolPlacement().getValue(), (String) SYMBOL_PLACEMENT_POINT);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(symbolPlacement(SYMBOL_PLACEMENT_POINT));
+ assertEquals((String) layer.getSymbolPlacement().getValue(), (String) SYMBOL_PLACEMENT_POINT);
});
}
@@ -129,29 +181,26 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("symbol-placement");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- symbolPlacement(
- zoom(
- interval(
- stop(2, symbolPlacement(SYMBOL_PLACEMENT_POINT))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ symbolPlacement(
+ zoom(
+ interval(
+ stop(2, symbolPlacement(SYMBOL_PLACEMENT_POINT))
)
)
- );
-
- // Verify
- assertNotNull(layer.getSymbolPlacement());
- assertNotNull(layer.getSymbolPlacement().getFunction());
- assertEquals(CameraFunction.class, layer.getSymbolPlacement().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getSymbolPlacement().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getSymbolPlacement().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getSymbolPlacement());
+ assertNotNull(layer.getSymbolPlacement().getFunction());
+ assertEquals(CameraFunction.class, layer.getSymbolPlacement().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getSymbolPlacement().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getSymbolPlacement().getFunction().getStops()).size());
});
}
@@ -160,15 +209,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("symbol-spacing");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(symbolSpacing(0.3f));
- assertEquals((Float) layer.getSymbolSpacing().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(symbolSpacing(0.3f));
+ assertEquals((Float) layer.getSymbolSpacing().getValue(), (Float) 0.3f);
});
}
@@ -177,30 +223,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("symbol-spacing");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- symbolSpacing(
- zoom(
- exponential(
- stop(2, symbolSpacing(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ symbolSpacing(
+ zoom(
+ exponential(
+ stop(2, symbolSpacing(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getSymbolSpacing());
- assertNotNull(layer.getSymbolSpacing().getFunction());
- assertEquals(CameraFunction.class, layer.getSymbolSpacing().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getSymbolSpacing().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getSymbolSpacing().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getSymbolSpacing().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getSymbolSpacing());
+ assertNotNull(layer.getSymbolSpacing().getFunction());
+ assertEquals(CameraFunction.class, layer.getSymbolSpacing().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getSymbolSpacing().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getSymbolSpacing().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getSymbolSpacing().getFunction().getStops()).size());
});
}
@@ -209,15 +252,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("symbol-avoid-edges");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(symbolAvoidEdges(true));
- assertEquals((Boolean) layer.getSymbolAvoidEdges().getValue(), (Boolean) true);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(symbolAvoidEdges(true));
+ assertEquals((Boolean) layer.getSymbolAvoidEdges().getValue(), (Boolean) true);
});
}
@@ -226,29 +266,26 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("symbol-avoid-edges");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- symbolAvoidEdges(
- zoom(
- interval(
- stop(2, symbolAvoidEdges(true))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ symbolAvoidEdges(
+ zoom(
+ interval(
+ stop(2, symbolAvoidEdges(true))
)
)
- );
-
- // Verify
- assertNotNull(layer.getSymbolAvoidEdges());
- assertNotNull(layer.getSymbolAvoidEdges().getFunction());
- assertEquals(CameraFunction.class, layer.getSymbolAvoidEdges().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getSymbolAvoidEdges().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getSymbolAvoidEdges().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getSymbolAvoidEdges());
+ assertNotNull(layer.getSymbolAvoidEdges().getFunction());
+ assertEquals(CameraFunction.class, layer.getSymbolAvoidEdges().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getSymbolAvoidEdges().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getSymbolAvoidEdges().getFunction().getStops()).size());
});
}
@@ -257,15 +294,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-allow-overlap");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconAllowOverlap(true));
- assertEquals((Boolean) layer.getIconAllowOverlap().getValue(), (Boolean) true);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(iconAllowOverlap(true));
+ assertEquals((Boolean) layer.getIconAllowOverlap().getValue(), (Boolean) true);
});
}
@@ -274,29 +308,26 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-allow-overlap");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconAllowOverlap(
- zoom(
- interval(
- stop(2, iconAllowOverlap(true))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconAllowOverlap(
+ zoom(
+ interval(
+ stop(2, iconAllowOverlap(true))
)
)
- );
-
- // Verify
- assertNotNull(layer.getIconAllowOverlap());
- assertNotNull(layer.getIconAllowOverlap().getFunction());
- assertEquals(CameraFunction.class, layer.getIconAllowOverlap().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getIconAllowOverlap().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getIconAllowOverlap().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconAllowOverlap());
+ assertNotNull(layer.getIconAllowOverlap().getFunction());
+ assertEquals(CameraFunction.class, layer.getIconAllowOverlap().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getIconAllowOverlap().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getIconAllowOverlap().getFunction().getStops()).size());
});
}
@@ -305,15 +336,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-ignore-placement");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconIgnorePlacement(true));
- assertEquals((Boolean) layer.getIconIgnorePlacement().getValue(), (Boolean) true);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(iconIgnorePlacement(true));
+ assertEquals((Boolean) layer.getIconIgnorePlacement().getValue(), (Boolean) true);
});
}
@@ -322,29 +350,26 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-ignore-placement");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconIgnorePlacement(
- zoom(
- interval(
- stop(2, iconIgnorePlacement(true))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconIgnorePlacement(
+ zoom(
+ interval(
+ stop(2, iconIgnorePlacement(true))
)
)
- );
-
- // Verify
- assertNotNull(layer.getIconIgnorePlacement());
- assertNotNull(layer.getIconIgnorePlacement().getFunction());
- assertEquals(CameraFunction.class, layer.getIconIgnorePlacement().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getIconIgnorePlacement().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getIconIgnorePlacement().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconIgnorePlacement());
+ assertNotNull(layer.getIconIgnorePlacement().getFunction());
+ assertEquals(CameraFunction.class, layer.getIconIgnorePlacement().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getIconIgnorePlacement().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getIconIgnorePlacement().getFunction().getStops()).size());
});
}
@@ -353,15 +378,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-optional");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconOptional(true));
- assertEquals((Boolean) layer.getIconOptional().getValue(), (Boolean) true);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(iconOptional(true));
+ assertEquals((Boolean) layer.getIconOptional().getValue(), (Boolean) true);
});
}
@@ -370,29 +392,26 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-optional");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconOptional(
- zoom(
- interval(
- stop(2, iconOptional(true))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconOptional(
+ zoom(
+ interval(
+ stop(2, iconOptional(true))
)
)
- );
-
- // Verify
- assertNotNull(layer.getIconOptional());
- assertNotNull(layer.getIconOptional().getFunction());
- assertEquals(CameraFunction.class, layer.getIconOptional().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getIconOptional().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getIconOptional().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconOptional());
+ assertNotNull(layer.getIconOptional().getFunction());
+ assertEquals(CameraFunction.class, layer.getIconOptional().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getIconOptional().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getIconOptional().getFunction().getStops()).size());
});
}
@@ -401,15 +420,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-rotation-alignment");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconRotationAlignment(ICON_ROTATION_ALIGNMENT_MAP));
- assertEquals((String) layer.getIconRotationAlignment().getValue(), (String) ICON_ROTATION_ALIGNMENT_MAP);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(iconRotationAlignment(ICON_ROTATION_ALIGNMENT_MAP));
+ assertEquals((String) layer.getIconRotationAlignment().getValue(), (String) ICON_ROTATION_ALIGNMENT_MAP);
});
}
@@ -418,29 +434,26 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-rotation-alignment");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconRotationAlignment(
- zoom(
- interval(
- stop(2, iconRotationAlignment(ICON_ROTATION_ALIGNMENT_MAP))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconRotationAlignment(
+ zoom(
+ interval(
+ stop(2, iconRotationAlignment(ICON_ROTATION_ALIGNMENT_MAP))
)
)
- );
-
- // Verify
- assertNotNull(layer.getIconRotationAlignment());
- assertNotNull(layer.getIconRotationAlignment().getFunction());
- assertEquals(CameraFunction.class, layer.getIconRotationAlignment().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getIconRotationAlignment().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getIconRotationAlignment().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconRotationAlignment());
+ assertNotNull(layer.getIconRotationAlignment().getFunction());
+ assertEquals(CameraFunction.class, layer.getIconRotationAlignment().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getIconRotationAlignment().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getIconRotationAlignment().getFunction().getStops()).size());
});
}
@@ -449,15 +462,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-size");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconSize(0.3f));
- assertEquals((Float) layer.getIconSize().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(iconSize(0.3f));
+ assertEquals((Float) layer.getIconSize().getValue(), (Float) 0.3f);
});
}
@@ -466,30 +476,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-size");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconSize(
- zoom(
- exponential(
- stop(2, iconSize(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconSize(
+ zoom(
+ exponential(
+ stop(2, iconSize(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getIconSize());
- assertNotNull(layer.getIconSize().getFunction());
- assertEquals(CameraFunction.class, layer.getIconSize().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getIconSize().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getIconSize().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getIconSize().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconSize());
+ assertNotNull(layer.getIconSize().getFunction());
+ assertEquals(CameraFunction.class, layer.getIconSize().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getIconSize().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getIconSize().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getIconSize().getFunction().getStops()).size());
});
}
@@ -498,23 +505,20 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-size");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconSize(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getIconSize());
- assertNotNull(layer.getIconSize().getFunction());
- assertEquals(SourceFunction.class, layer.getIconSize().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconSize().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getIconSize().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconSize(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getIconSize());
+ assertNotNull(layer.getIconSize().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconSize().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconSize().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getIconSize().getFunction().getStops().getClass());
});
}
@@ -523,30 +527,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-size");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconSize(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, iconSize(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconSize(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, iconSize(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getIconSize());
- assertNotNull(layer.getIconSize().getFunction());
- assertEquals(SourceFunction.class, layer.getIconSize().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconSize().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getIconSize().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconSize());
+ assertNotNull(layer.getIconSize().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconSize().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconSize().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getIconSize().getFunction().getStops().getClass());
});
}
@@ -555,33 +556,30 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-size");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconSize(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, iconSize(0.3f))
- )
- ).withDefaultValue(iconSize(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getIconSize());
- assertNotNull(layer.getIconSize().getFunction());
- assertEquals(SourceFunction.class, layer.getIconSize().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconSize().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getIconSize().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getIconSize().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getIconSize().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getIconSize().getFunction()).getDefaultValue().getValue());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconSize(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, iconSize(0.3f))
+ )
+ ).withDefaultValue(iconSize(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconSize());
+ assertNotNull(layer.getIconSize().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconSize().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconSize().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getIconSize().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getIconSize().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getIconSize().getFunction()).getDefaultValue().getValue());
+ assertEquals(0.3f, ((SourceFunction) layer.getIconSize().getFunction()).getDefaultValue().getValue());
});
}
@@ -591,38 +589,35 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-size");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconSize(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, iconSize(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(iconSize(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getIconSize());
- assertNotNull(layer.getIconSize().getFunction());
- assertEquals(CompositeFunction.class, layer.getIconSize().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getIconSize().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getIconSize().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getIconSize().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getIconSize().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconSize(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, iconSize(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(iconSize(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconSize());
+ assertNotNull(layer.getIconSize().getFunction());
+ assertEquals(CompositeFunction.class, layer.getIconSize().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getIconSize().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getIconSize().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getIconSize().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getIconSize().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
});
}
@@ -631,15 +626,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-text-fit");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconTextFit(ICON_TEXT_FIT_NONE));
- assertEquals((String) layer.getIconTextFit().getValue(), (String) ICON_TEXT_FIT_NONE);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(iconTextFit(ICON_TEXT_FIT_NONE));
+ assertEquals((String) layer.getIconTextFit().getValue(), (String) ICON_TEXT_FIT_NONE);
});
}
@@ -648,29 +640,26 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-text-fit");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconTextFit(
- zoom(
- interval(
- stop(2, iconTextFit(ICON_TEXT_FIT_NONE))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconTextFit(
+ zoom(
+ interval(
+ stop(2, iconTextFit(ICON_TEXT_FIT_NONE))
)
)
- );
-
- // Verify
- assertNotNull(layer.getIconTextFit());
- assertNotNull(layer.getIconTextFit().getFunction());
- assertEquals(CameraFunction.class, layer.getIconTextFit().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getIconTextFit().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getIconTextFit().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconTextFit());
+ assertNotNull(layer.getIconTextFit().getFunction());
+ assertEquals(CameraFunction.class, layer.getIconTextFit().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getIconTextFit().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getIconTextFit().getFunction().getStops()).size());
});
}
@@ -679,15 +668,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-text-fit-padding");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconTextFitPadding(new Float[] {0f, 0f, 0f, 0f}));
- assertEquals((Float[]) layer.getIconTextFitPadding().getValue(), (Float[]) new Float[] {0f, 0f, 0f, 0f});
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(iconTextFitPadding(new Float[] {0f, 0f, 0f, 0f}));
+ assertEquals((Float[]) layer.getIconTextFitPadding().getValue(), (Float[]) new Float[] {0f, 0f, 0f, 0f});
});
}
@@ -696,30 +682,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-text-fit-padding");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconTextFitPadding(
- zoom(
- exponential(
- stop(2, iconTextFitPadding(new Float[] {0f, 0f, 0f, 0f}))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconTextFitPadding(
+ zoom(
+ exponential(
+ stop(2, iconTextFitPadding(new Float[] {0f, 0f, 0f, 0f}))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getIconTextFitPadding());
- assertNotNull(layer.getIconTextFitPadding().getFunction());
- assertEquals(CameraFunction.class, layer.getIconTextFitPadding().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getIconTextFitPadding().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getIconTextFitPadding().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getIconTextFitPadding().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconTextFitPadding());
+ assertNotNull(layer.getIconTextFitPadding().getFunction());
+ assertEquals(CameraFunction.class, layer.getIconTextFitPadding().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getIconTextFitPadding().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getIconTextFitPadding().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getIconTextFitPadding().getFunction().getStops()).size());
});
}
@@ -728,15 +711,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-image");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconImage("undefined"));
- assertEquals((String) layer.getIconImage().getValue(), (String) "undefined");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(iconImage("undefined"));
+ assertEquals((String) layer.getIconImage().getValue(), (String) "undefined");
});
}
@@ -745,29 +725,26 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-image");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconImage(
- zoom(
- interval(
- stop(2, iconImage("undefined"))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconImage(
+ zoom(
+ interval(
+ stop(2, iconImage("undefined"))
)
)
- );
-
- // Verify
- assertNotNull(layer.getIconImage());
- assertNotNull(layer.getIconImage().getFunction());
- assertEquals(CameraFunction.class, layer.getIconImage().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getIconImage().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getIconImage().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconImage());
+ assertNotNull(layer.getIconImage().getFunction());
+ assertEquals(CameraFunction.class, layer.getIconImage().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getIconImage().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getIconImage().getFunction().getStops()).size());
});
}
@@ -776,23 +753,20 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-image");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconImage(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getIconImage());
- assertNotNull(layer.getIconImage().getFunction());
- assertEquals(SourceFunction.class, layer.getIconImage().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconImage().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getIconImage().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconImage(property("FeaturePropertyA", Stops.<String>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getIconImage());
+ assertNotNull(layer.getIconImage().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconImage().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconImage().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getIconImage().getFunction().getStops().getClass());
});
}
@@ -801,30 +775,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-image");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconImage(
- property(
- "FeaturePropertyA",
- interval(
- stop(1, iconImage("undefined"))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconImage(
+ property(
+ "FeaturePropertyA",
+ interval(
+ stop(1, iconImage("undefined"))
)
)
- );
-
- // Verify
- assertNotNull(layer.getIconImage());
- assertNotNull(layer.getIconImage().getFunction());
- assertEquals(SourceFunction.class, layer.getIconImage().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconImage().getFunction()).getProperty());
- assertEquals(IntervalStops.class, layer.getIconImage().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconImage());
+ assertNotNull(layer.getIconImage().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconImage().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconImage().getFunction()).getProperty());
+ assertEquals(IntervalStops.class, layer.getIconImage().getFunction().getStops().getClass());
});
}
@@ -833,15 +804,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-rotate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconRotate(0.3f));
- assertEquals((Float) layer.getIconRotate().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(iconRotate(0.3f));
+ assertEquals((Float) layer.getIconRotate().getValue(), (Float) 0.3f);
});
}
@@ -850,30 +818,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-rotate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconRotate(
- zoom(
- exponential(
- stop(2, iconRotate(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconRotate(
+ zoom(
+ exponential(
+ stop(2, iconRotate(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getIconRotate());
- assertNotNull(layer.getIconRotate().getFunction());
- assertEquals(CameraFunction.class, layer.getIconRotate().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getIconRotate().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getIconRotate().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getIconRotate().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconRotate());
+ assertNotNull(layer.getIconRotate().getFunction());
+ assertEquals(CameraFunction.class, layer.getIconRotate().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getIconRotate().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getIconRotate().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getIconRotate().getFunction().getStops()).size());
});
}
@@ -882,23 +847,20 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-rotate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconRotate(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getIconRotate());
- assertNotNull(layer.getIconRotate().getFunction());
- assertEquals(SourceFunction.class, layer.getIconRotate().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconRotate().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getIconRotate().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconRotate(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getIconRotate());
+ assertNotNull(layer.getIconRotate().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconRotate().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconRotate().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getIconRotate().getFunction().getStops().getClass());
});
}
@@ -907,30 +869,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-rotate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconRotate(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, iconRotate(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconRotate(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, iconRotate(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getIconRotate());
- assertNotNull(layer.getIconRotate().getFunction());
- assertEquals(SourceFunction.class, layer.getIconRotate().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconRotate().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getIconRotate().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconRotate());
+ assertNotNull(layer.getIconRotate().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconRotate().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconRotate().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getIconRotate().getFunction().getStops().getClass());
});
}
@@ -939,33 +898,30 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-rotate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconRotate(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, iconRotate(0.3f))
- )
- ).withDefaultValue(iconRotate(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getIconRotate());
- assertNotNull(layer.getIconRotate().getFunction());
- assertEquals(SourceFunction.class, layer.getIconRotate().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconRotate().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getIconRotate().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getIconRotate().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getIconRotate().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getIconRotate().getFunction()).getDefaultValue().getValue());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconRotate(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, iconRotate(0.3f))
+ )
+ ).withDefaultValue(iconRotate(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconRotate());
+ assertNotNull(layer.getIconRotate().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconRotate().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconRotate().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getIconRotate().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getIconRotate().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getIconRotate().getFunction()).getDefaultValue().getValue());
+ assertEquals(0.3f, ((SourceFunction) layer.getIconRotate().getFunction()).getDefaultValue().getValue());
});
}
@@ -975,38 +931,35 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-rotate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconRotate(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, iconRotate(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(iconRotate(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getIconRotate());
- assertNotNull(layer.getIconRotate().getFunction());
- assertEquals(CompositeFunction.class, layer.getIconRotate().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getIconRotate().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getIconRotate().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getIconRotate().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getIconRotate().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconRotate(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, iconRotate(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(iconRotate(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconRotate());
+ assertNotNull(layer.getIconRotate().getFunction());
+ assertEquals(CompositeFunction.class, layer.getIconRotate().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getIconRotate().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getIconRotate().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getIconRotate().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getIconRotate().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
});
}
@@ -1015,15 +968,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-padding");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconPadding(0.3f));
- assertEquals((Float) layer.getIconPadding().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(iconPadding(0.3f));
+ assertEquals((Float) layer.getIconPadding().getValue(), (Float) 0.3f);
});
}
@@ -1032,30 +982,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-padding");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconPadding(
- zoom(
- exponential(
- stop(2, iconPadding(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconPadding(
+ zoom(
+ exponential(
+ stop(2, iconPadding(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getIconPadding());
- assertNotNull(layer.getIconPadding().getFunction());
- assertEquals(CameraFunction.class, layer.getIconPadding().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getIconPadding().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getIconPadding().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getIconPadding().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconPadding());
+ assertNotNull(layer.getIconPadding().getFunction());
+ assertEquals(CameraFunction.class, layer.getIconPadding().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getIconPadding().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getIconPadding().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getIconPadding().getFunction().getStops()).size());
});
}
@@ -1064,15 +1011,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-keep-upright");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconKeepUpright(true));
- assertEquals((Boolean) layer.getIconKeepUpright().getValue(), (Boolean) true);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(iconKeepUpright(true));
+ assertEquals((Boolean) layer.getIconKeepUpright().getValue(), (Boolean) true);
});
}
@@ -1081,29 +1025,26 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-keep-upright");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconKeepUpright(
- zoom(
- interval(
- stop(2, iconKeepUpright(true))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconKeepUpright(
+ zoom(
+ interval(
+ stop(2, iconKeepUpright(true))
)
)
- );
-
- // Verify
- assertNotNull(layer.getIconKeepUpright());
- assertNotNull(layer.getIconKeepUpright().getFunction());
- assertEquals(CameraFunction.class, layer.getIconKeepUpright().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getIconKeepUpright().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getIconKeepUpright().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconKeepUpright());
+ assertNotNull(layer.getIconKeepUpright().getFunction());
+ assertEquals(CameraFunction.class, layer.getIconKeepUpright().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getIconKeepUpright().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getIconKeepUpright().getFunction().getStops()).size());
});
}
@@ -1112,15 +1053,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-offset");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconOffset(new Float[] {0f, 0f}));
- assertEquals((Float[]) layer.getIconOffset().getValue(), (Float[]) new Float[] {0f, 0f});
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(iconOffset(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getIconOffset().getValue(), (Float[]) new Float[] {0f, 0f});
});
}
@@ -1129,30 +1067,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-offset");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconOffset(
- zoom(
- exponential(
- stop(2, iconOffset(new Float[] {0f, 0f}))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconOffset(
+ zoom(
+ exponential(
+ stop(2, iconOffset(new Float[] {0f, 0f}))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getIconOffset());
- assertNotNull(layer.getIconOffset().getFunction());
- assertEquals(CameraFunction.class, layer.getIconOffset().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getIconOffset().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getIconOffset().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getIconOffset().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconOffset());
+ assertNotNull(layer.getIconOffset().getFunction());
+ assertEquals(CameraFunction.class, layer.getIconOffset().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getIconOffset().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getIconOffset().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getIconOffset().getFunction().getStops()).size());
});
}
@@ -1161,23 +1096,20 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-offset");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconOffset(property("FeaturePropertyA", Stops.<Float[]>identity()))
- );
-
- // Verify
- assertNotNull(layer.getIconOffset());
- assertNotNull(layer.getIconOffset().getFunction());
- assertEquals(SourceFunction.class, layer.getIconOffset().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconOffset().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getIconOffset().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconOffset(property("FeaturePropertyA", Stops.<Float[]>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getIconOffset());
+ assertNotNull(layer.getIconOffset().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconOffset().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconOffset().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getIconOffset().getFunction().getStops().getClass());
});
}
@@ -1186,30 +1118,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-offset");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconOffset(
- property(
- "FeaturePropertyA",
- interval(
- stop(1, iconOffset(new Float[] {0f, 0f}))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconOffset(
+ property(
+ "FeaturePropertyA",
+ interval(
+ stop(1, iconOffset(new Float[] {0f, 0f}))
)
)
- );
-
- // Verify
- assertNotNull(layer.getIconOffset());
- assertNotNull(layer.getIconOffset().getFunction());
- assertEquals(SourceFunction.class, layer.getIconOffset().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconOffset().getFunction()).getProperty());
- assertEquals(IntervalStops.class, layer.getIconOffset().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconOffset());
+ assertNotNull(layer.getIconOffset().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconOffset().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconOffset().getFunction()).getProperty());
+ assertEquals(IntervalStops.class, layer.getIconOffset().getFunction().getStops().getClass());
});
}
@@ -1218,15 +1147,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconAnchor(ICON_ANCHOR_CENTER));
- assertEquals((String) layer.getIconAnchor().getValue(), (String) ICON_ANCHOR_CENTER);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(iconAnchor(ICON_ANCHOR_CENTER));
+ assertEquals((String) layer.getIconAnchor().getValue(), (String) ICON_ANCHOR_CENTER);
});
}
@@ -1235,29 +1161,26 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconAnchor(
- zoom(
- interval(
- stop(2, iconAnchor(ICON_ANCHOR_CENTER))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconAnchor(
+ zoom(
+ interval(
+ stop(2, iconAnchor(ICON_ANCHOR_CENTER))
)
)
- );
-
- // Verify
- assertNotNull(layer.getIconAnchor());
- assertNotNull(layer.getIconAnchor().getFunction());
- assertEquals(CameraFunction.class, layer.getIconAnchor().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getIconAnchor().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getIconAnchor().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconAnchor());
+ assertNotNull(layer.getIconAnchor().getFunction());
+ assertEquals(CameraFunction.class, layer.getIconAnchor().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getIconAnchor().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getIconAnchor().getFunction().getStops()).size());
});
}
@@ -1266,23 +1189,20 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconAnchor(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getIconAnchor());
- assertNotNull(layer.getIconAnchor().getFunction());
- assertEquals(SourceFunction.class, layer.getIconAnchor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconAnchor().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getIconAnchor().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconAnchor(property("FeaturePropertyA", Stops.<String>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getIconAnchor());
+ assertNotNull(layer.getIconAnchor().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconAnchor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconAnchor().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getIconAnchor().getFunction().getStops().getClass());
});
}
@@ -1291,30 +1211,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconAnchor(
- property(
- "FeaturePropertyA",
- interval(
- stop(1, iconAnchor(ICON_ANCHOR_CENTER))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconAnchor(
+ property(
+ "FeaturePropertyA",
+ interval(
+ stop(1, iconAnchor(ICON_ANCHOR_CENTER))
)
)
- );
-
- // Verify
- assertNotNull(layer.getIconAnchor());
- assertNotNull(layer.getIconAnchor().getFunction());
- assertEquals(SourceFunction.class, layer.getIconAnchor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconAnchor().getFunction()).getProperty());
- assertEquals(IntervalStops.class, layer.getIconAnchor().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconAnchor());
+ assertNotNull(layer.getIconAnchor().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconAnchor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconAnchor().getFunction()).getProperty());
+ assertEquals(IntervalStops.class, layer.getIconAnchor().getFunction().getStops().getClass());
});
}
@@ -1323,15 +1240,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-pitch-alignment");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconPitchAlignment(ICON_PITCH_ALIGNMENT_MAP));
- assertEquals((String) layer.getIconPitchAlignment().getValue(), (String) ICON_PITCH_ALIGNMENT_MAP);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(iconPitchAlignment(ICON_PITCH_ALIGNMENT_MAP));
+ assertEquals((String) layer.getIconPitchAlignment().getValue(), (String) ICON_PITCH_ALIGNMENT_MAP);
});
}
@@ -1340,29 +1254,26 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-pitch-alignment");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconPitchAlignment(
- zoom(
- interval(
- stop(2, iconPitchAlignment(ICON_PITCH_ALIGNMENT_MAP))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconPitchAlignment(
+ zoom(
+ interval(
+ stop(2, iconPitchAlignment(ICON_PITCH_ALIGNMENT_MAP))
)
)
- );
-
- // Verify
- assertNotNull(layer.getIconPitchAlignment());
- assertNotNull(layer.getIconPitchAlignment().getFunction());
- assertEquals(CameraFunction.class, layer.getIconPitchAlignment().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getIconPitchAlignment().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getIconPitchAlignment().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconPitchAlignment());
+ assertNotNull(layer.getIconPitchAlignment().getFunction());
+ assertEquals(CameraFunction.class, layer.getIconPitchAlignment().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getIconPitchAlignment().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getIconPitchAlignment().getFunction().getStops()).size());
});
}
@@ -1371,15 +1282,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-pitch-alignment");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textPitchAlignment(TEXT_PITCH_ALIGNMENT_MAP));
- assertEquals((String) layer.getTextPitchAlignment().getValue(), (String) TEXT_PITCH_ALIGNMENT_MAP);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textPitchAlignment(TEXT_PITCH_ALIGNMENT_MAP));
+ assertEquals((String) layer.getTextPitchAlignment().getValue(), (String) TEXT_PITCH_ALIGNMENT_MAP);
});
}
@@ -1388,29 +1296,26 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-pitch-alignment");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textPitchAlignment(
- zoom(
- interval(
- stop(2, textPitchAlignment(TEXT_PITCH_ALIGNMENT_MAP))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textPitchAlignment(
+ zoom(
+ interval(
+ stop(2, textPitchAlignment(TEXT_PITCH_ALIGNMENT_MAP))
)
)
- );
-
- // Verify
- assertNotNull(layer.getTextPitchAlignment());
- assertNotNull(layer.getTextPitchAlignment().getFunction());
- assertEquals(CameraFunction.class, layer.getTextPitchAlignment().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getTextPitchAlignment().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getTextPitchAlignment().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextPitchAlignment());
+ assertNotNull(layer.getTextPitchAlignment().getFunction());
+ assertEquals(CameraFunction.class, layer.getTextPitchAlignment().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getTextPitchAlignment().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getTextPitchAlignment().getFunction().getStops()).size());
});
}
@@ -1419,15 +1324,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-rotation-alignment");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textRotationAlignment(TEXT_ROTATION_ALIGNMENT_MAP));
- assertEquals((String) layer.getTextRotationAlignment().getValue(), (String) TEXT_ROTATION_ALIGNMENT_MAP);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textRotationAlignment(TEXT_ROTATION_ALIGNMENT_MAP));
+ assertEquals((String) layer.getTextRotationAlignment().getValue(), (String) TEXT_ROTATION_ALIGNMENT_MAP);
});
}
@@ -1436,29 +1338,26 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-rotation-alignment");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textRotationAlignment(
- zoom(
- interval(
- stop(2, textRotationAlignment(TEXT_ROTATION_ALIGNMENT_MAP))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textRotationAlignment(
+ zoom(
+ interval(
+ stop(2, textRotationAlignment(TEXT_ROTATION_ALIGNMENT_MAP))
)
)
- );
-
- // Verify
- assertNotNull(layer.getTextRotationAlignment());
- assertNotNull(layer.getTextRotationAlignment().getFunction());
- assertEquals(CameraFunction.class, layer.getTextRotationAlignment().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getTextRotationAlignment().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getTextRotationAlignment().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextRotationAlignment());
+ assertNotNull(layer.getTextRotationAlignment().getFunction());
+ assertEquals(CameraFunction.class, layer.getTextRotationAlignment().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getTextRotationAlignment().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getTextRotationAlignment().getFunction().getStops()).size());
});
}
@@ -1467,15 +1366,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-field");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textField(""));
- assertEquals((String) layer.getTextField().getValue(), (String) "");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textField(""));
+ assertEquals((String) layer.getTextField().getValue(), (String) "");
});
}
@@ -1484,29 +1380,26 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-field");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textField(
- zoom(
- interval(
- stop(2, textField(""))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textField(
+ zoom(
+ interval(
+ stop(2, textField(""))
)
)
- );
-
- // Verify
- assertNotNull(layer.getTextField());
- assertNotNull(layer.getTextField().getFunction());
- assertEquals(CameraFunction.class, layer.getTextField().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getTextField().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getTextField().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextField());
+ assertNotNull(layer.getTextField().getFunction());
+ assertEquals(CameraFunction.class, layer.getTextField().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getTextField().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getTextField().getFunction().getStops()).size());
});
}
@@ -1515,23 +1408,20 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-field");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textField(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getTextField());
- assertNotNull(layer.getTextField().getFunction());
- assertEquals(SourceFunction.class, layer.getTextField().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextField().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getTextField().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textField(property("FeaturePropertyA", Stops.<String>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getTextField());
+ assertNotNull(layer.getTextField().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextField().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextField().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getTextField().getFunction().getStops().getClass());
});
}
@@ -1540,30 +1430,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-field");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textField(
- property(
- "FeaturePropertyA",
- interval(
- stop(1, textField(""))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textField(
+ property(
+ "FeaturePropertyA",
+ interval(
+ stop(1, textField(""))
)
)
- );
-
- // Verify
- assertNotNull(layer.getTextField());
- assertNotNull(layer.getTextField().getFunction());
- assertEquals(SourceFunction.class, layer.getTextField().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextField().getFunction()).getProperty());
- assertEquals(IntervalStops.class, layer.getTextField().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextField());
+ assertNotNull(layer.getTextField().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextField().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextField().getFunction()).getProperty());
+ assertEquals(IntervalStops.class, layer.getTextField().getFunction().getStops().getClass());
});
}
@@ -1572,15 +1459,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-font");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textFont(new String[]{"Open Sans Regular", "Arial Unicode MS Regular"}));
- assertEquals((String[]) layer.getTextFont().getValue(), (String[]) new String[]{"Open Sans Regular", "Arial Unicode MS Regular"});
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textFont(new String[]{"Open Sans Regular", "Arial Unicode MS Regular"}));
+ assertEquals((String[]) layer.getTextFont().getValue(), (String[]) new String[]{"Open Sans Regular", "Arial Unicode MS Regular"});
});
}
@@ -1589,29 +1473,26 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-font");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textFont(
- zoom(
- interval(
- stop(2, textFont(new String[]{"Open Sans Regular", "Arial Unicode MS Regular"}))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textFont(
+ zoom(
+ interval(
+ stop(2, textFont(new String[]{"Open Sans Regular", "Arial Unicode MS Regular"}))
)
)
- );
-
- // Verify
- assertNotNull(layer.getTextFont());
- assertNotNull(layer.getTextFont().getFunction());
- assertEquals(CameraFunction.class, layer.getTextFont().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getTextFont().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getTextFont().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextFont());
+ assertNotNull(layer.getTextFont().getFunction());
+ assertEquals(CameraFunction.class, layer.getTextFont().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getTextFont().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getTextFont().getFunction().getStops()).size());
});
}
@@ -1620,15 +1501,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-size");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textSize(0.3f));
- assertEquals((Float) layer.getTextSize().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textSize(0.3f));
+ assertEquals((Float) layer.getTextSize().getValue(), (Float) 0.3f);
});
}
@@ -1637,30 +1515,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-size");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textSize(
- zoom(
- exponential(
- stop(2, textSize(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textSize(
+ zoom(
+ exponential(
+ stop(2, textSize(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getTextSize());
- assertNotNull(layer.getTextSize().getFunction());
- assertEquals(CameraFunction.class, layer.getTextSize().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getTextSize().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getTextSize().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getTextSize().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextSize());
+ assertNotNull(layer.getTextSize().getFunction());
+ assertEquals(CameraFunction.class, layer.getTextSize().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getTextSize().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getTextSize().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getTextSize().getFunction().getStops()).size());
});
}
@@ -1669,23 +1544,20 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-size");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textSize(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getTextSize());
- assertNotNull(layer.getTextSize().getFunction());
- assertEquals(SourceFunction.class, layer.getTextSize().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextSize().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getTextSize().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textSize(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getTextSize());
+ assertNotNull(layer.getTextSize().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextSize().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextSize().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getTextSize().getFunction().getStops().getClass());
});
}
@@ -1694,30 +1566,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-size");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textSize(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, textSize(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textSize(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, textSize(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getTextSize());
- assertNotNull(layer.getTextSize().getFunction());
- assertEquals(SourceFunction.class, layer.getTextSize().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextSize().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextSize().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextSize());
+ assertNotNull(layer.getTextSize().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextSize().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextSize().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getTextSize().getFunction().getStops().getClass());
});
}
@@ -1726,33 +1595,30 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-size");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textSize(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, textSize(0.3f))
- )
- ).withDefaultValue(textSize(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextSize());
- assertNotNull(layer.getTextSize().getFunction());
- assertEquals(SourceFunction.class, layer.getTextSize().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextSize().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getTextSize().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getTextSize().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getTextSize().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getTextSize().getFunction()).getDefaultValue().getValue());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textSize(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, textSize(0.3f))
+ )
+ ).withDefaultValue(textSize(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextSize());
+ assertNotNull(layer.getTextSize().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextSize().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextSize().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getTextSize().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getTextSize().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getTextSize().getFunction()).getDefaultValue().getValue());
+ assertEquals(0.3f, ((SourceFunction) layer.getTextSize().getFunction()).getDefaultValue().getValue());
});
}
@@ -1762,38 +1628,35 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-size");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textSize(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, textSize(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(textSize(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextSize());
- assertNotNull(layer.getTextSize().getFunction());
- assertEquals(CompositeFunction.class, layer.getTextSize().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getTextSize().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextSize().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getTextSize().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getTextSize().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textSize(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, textSize(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(textSize(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextSize());
+ assertNotNull(layer.getTextSize().getFunction());
+ assertEquals(CompositeFunction.class, layer.getTextSize().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getTextSize().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getTextSize().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getTextSize().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getTextSize().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
});
}
@@ -1802,15 +1665,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-max-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textMaxWidth(0.3f));
- assertEquals((Float) layer.getTextMaxWidth().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textMaxWidth(0.3f));
+ assertEquals((Float) layer.getTextMaxWidth().getValue(), (Float) 0.3f);
});
}
@@ -1819,30 +1679,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-max-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textMaxWidth(
- zoom(
- exponential(
- stop(2, textMaxWidth(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textMaxWidth(
+ zoom(
+ exponential(
+ stop(2, textMaxWidth(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getTextMaxWidth());
- assertNotNull(layer.getTextMaxWidth().getFunction());
- assertEquals(CameraFunction.class, layer.getTextMaxWidth().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getTextMaxWidth().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getTextMaxWidth().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getTextMaxWidth().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextMaxWidth());
+ assertNotNull(layer.getTextMaxWidth().getFunction());
+ assertEquals(CameraFunction.class, layer.getTextMaxWidth().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getTextMaxWidth().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getTextMaxWidth().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getTextMaxWidth().getFunction().getStops()).size());
});
}
@@ -1851,23 +1708,20 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-max-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textMaxWidth(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getTextMaxWidth());
- assertNotNull(layer.getTextMaxWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getTextMaxWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextMaxWidth().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getTextMaxWidth().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textMaxWidth(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getTextMaxWidth());
+ assertNotNull(layer.getTextMaxWidth().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextMaxWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextMaxWidth().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getTextMaxWidth().getFunction().getStops().getClass());
});
}
@@ -1876,30 +1730,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-max-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textMaxWidth(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, textMaxWidth(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textMaxWidth(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, textMaxWidth(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getTextMaxWidth());
- assertNotNull(layer.getTextMaxWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getTextMaxWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextMaxWidth().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextMaxWidth().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextMaxWidth());
+ assertNotNull(layer.getTextMaxWidth().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextMaxWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextMaxWidth().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getTextMaxWidth().getFunction().getStops().getClass());
});
}
@@ -1908,33 +1759,30 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-max-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textMaxWidth(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, textMaxWidth(0.3f))
- )
- ).withDefaultValue(textMaxWidth(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextMaxWidth());
- assertNotNull(layer.getTextMaxWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getTextMaxWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextMaxWidth().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getTextMaxWidth().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getTextMaxWidth().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getTextMaxWidth().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getTextMaxWidth().getFunction()).getDefaultValue().getValue());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textMaxWidth(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, textMaxWidth(0.3f))
+ )
+ ).withDefaultValue(textMaxWidth(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextMaxWidth());
+ assertNotNull(layer.getTextMaxWidth().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextMaxWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextMaxWidth().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getTextMaxWidth().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getTextMaxWidth().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getTextMaxWidth().getFunction()).getDefaultValue().getValue());
+ assertEquals(0.3f, ((SourceFunction) layer.getTextMaxWidth().getFunction()).getDefaultValue().getValue());
});
}
@@ -1944,38 +1792,35 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-max-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textMaxWidth(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, textMaxWidth(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(textMaxWidth(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextMaxWidth());
- assertNotNull(layer.getTextMaxWidth().getFunction());
- assertEquals(CompositeFunction.class, layer.getTextMaxWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getTextMaxWidth().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextMaxWidth().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getTextMaxWidth().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getTextMaxWidth().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textMaxWidth(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, textMaxWidth(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(textMaxWidth(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextMaxWidth());
+ assertNotNull(layer.getTextMaxWidth().getFunction());
+ assertEquals(CompositeFunction.class, layer.getTextMaxWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getTextMaxWidth().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getTextMaxWidth().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getTextMaxWidth().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getTextMaxWidth().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
});
}
@@ -1984,15 +1829,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-line-height");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textLineHeight(0.3f));
- assertEquals((Float) layer.getTextLineHeight().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textLineHeight(0.3f));
+ assertEquals((Float) layer.getTextLineHeight().getValue(), (Float) 0.3f);
});
}
@@ -2001,30 +1843,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-line-height");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textLineHeight(
- zoom(
- exponential(
- stop(2, textLineHeight(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textLineHeight(
+ zoom(
+ exponential(
+ stop(2, textLineHeight(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getTextLineHeight());
- assertNotNull(layer.getTextLineHeight().getFunction());
- assertEquals(CameraFunction.class, layer.getTextLineHeight().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getTextLineHeight().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getTextLineHeight().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getTextLineHeight().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextLineHeight());
+ assertNotNull(layer.getTextLineHeight().getFunction());
+ assertEquals(CameraFunction.class, layer.getTextLineHeight().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getTextLineHeight().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getTextLineHeight().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getTextLineHeight().getFunction().getStops()).size());
});
}
@@ -2033,15 +1872,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-letter-spacing");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textLetterSpacing(0.3f));
- assertEquals((Float) layer.getTextLetterSpacing().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textLetterSpacing(0.3f));
+ assertEquals((Float) layer.getTextLetterSpacing().getValue(), (Float) 0.3f);
});
}
@@ -2050,30 +1886,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-letter-spacing");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textLetterSpacing(
- zoom(
- exponential(
- stop(2, textLetterSpacing(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textLetterSpacing(
+ zoom(
+ exponential(
+ stop(2, textLetterSpacing(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getTextLetterSpacing());
- assertNotNull(layer.getTextLetterSpacing().getFunction());
- assertEquals(CameraFunction.class, layer.getTextLetterSpacing().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getTextLetterSpacing().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getTextLetterSpacing().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getTextLetterSpacing().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextLetterSpacing());
+ assertNotNull(layer.getTextLetterSpacing().getFunction());
+ assertEquals(CameraFunction.class, layer.getTextLetterSpacing().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getTextLetterSpacing().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getTextLetterSpacing().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getTextLetterSpacing().getFunction().getStops()).size());
});
}
@@ -2082,23 +1915,20 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-letter-spacing");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textLetterSpacing(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getTextLetterSpacing());
- assertNotNull(layer.getTextLetterSpacing().getFunction());
- assertEquals(SourceFunction.class, layer.getTextLetterSpacing().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextLetterSpacing().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getTextLetterSpacing().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textLetterSpacing(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getTextLetterSpacing());
+ assertNotNull(layer.getTextLetterSpacing().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextLetterSpacing().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextLetterSpacing().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getTextLetterSpacing().getFunction().getStops().getClass());
});
}
@@ -2107,30 +1937,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-letter-spacing");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textLetterSpacing(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, textLetterSpacing(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textLetterSpacing(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, textLetterSpacing(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getTextLetterSpacing());
- assertNotNull(layer.getTextLetterSpacing().getFunction());
- assertEquals(SourceFunction.class, layer.getTextLetterSpacing().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextLetterSpacing().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextLetterSpacing().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextLetterSpacing());
+ assertNotNull(layer.getTextLetterSpacing().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextLetterSpacing().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextLetterSpacing().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getTextLetterSpacing().getFunction().getStops().getClass());
});
}
@@ -2139,33 +1966,30 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-letter-spacing");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textLetterSpacing(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, textLetterSpacing(0.3f))
- )
- ).withDefaultValue(textLetterSpacing(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextLetterSpacing());
- assertNotNull(layer.getTextLetterSpacing().getFunction());
- assertEquals(SourceFunction.class, layer.getTextLetterSpacing().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextLetterSpacing().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getTextLetterSpacing().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getTextLetterSpacing().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getTextLetterSpacing().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getTextLetterSpacing().getFunction()).getDefaultValue().getValue());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textLetterSpacing(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, textLetterSpacing(0.3f))
+ )
+ ).withDefaultValue(textLetterSpacing(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextLetterSpacing());
+ assertNotNull(layer.getTextLetterSpacing().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextLetterSpacing().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextLetterSpacing().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getTextLetterSpacing().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getTextLetterSpacing().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getTextLetterSpacing().getFunction()).getDefaultValue().getValue());
+ assertEquals(0.3f, ((SourceFunction) layer.getTextLetterSpacing().getFunction()).getDefaultValue().getValue());
});
}
@@ -2175,38 +1999,35 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-letter-spacing");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textLetterSpacing(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, textLetterSpacing(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(textLetterSpacing(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextLetterSpacing());
- assertNotNull(layer.getTextLetterSpacing().getFunction());
- assertEquals(CompositeFunction.class, layer.getTextLetterSpacing().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getTextLetterSpacing().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextLetterSpacing().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getTextLetterSpacing().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getTextLetterSpacing().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textLetterSpacing(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, textLetterSpacing(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(textLetterSpacing(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextLetterSpacing());
+ assertNotNull(layer.getTextLetterSpacing().getFunction());
+ assertEquals(CompositeFunction.class, layer.getTextLetterSpacing().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getTextLetterSpacing().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getTextLetterSpacing().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getTextLetterSpacing().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getTextLetterSpacing().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
});
}
@@ -2215,15 +2036,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-justify");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textJustify(TEXT_JUSTIFY_LEFT));
- assertEquals((String) layer.getTextJustify().getValue(), (String) TEXT_JUSTIFY_LEFT);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textJustify(TEXT_JUSTIFY_LEFT));
+ assertEquals((String) layer.getTextJustify().getValue(), (String) TEXT_JUSTIFY_LEFT);
});
}
@@ -2232,29 +2050,26 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-justify");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textJustify(
- zoom(
- interval(
- stop(2, textJustify(TEXT_JUSTIFY_LEFT))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textJustify(
+ zoom(
+ interval(
+ stop(2, textJustify(TEXT_JUSTIFY_LEFT))
)
)
- );
-
- // Verify
- assertNotNull(layer.getTextJustify());
- assertNotNull(layer.getTextJustify().getFunction());
- assertEquals(CameraFunction.class, layer.getTextJustify().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getTextJustify().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getTextJustify().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextJustify());
+ assertNotNull(layer.getTextJustify().getFunction());
+ assertEquals(CameraFunction.class, layer.getTextJustify().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getTextJustify().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getTextJustify().getFunction().getStops()).size());
});
}
@@ -2263,23 +2078,20 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-justify");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textJustify(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getTextJustify());
- assertNotNull(layer.getTextJustify().getFunction());
- assertEquals(SourceFunction.class, layer.getTextJustify().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextJustify().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getTextJustify().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textJustify(property("FeaturePropertyA", Stops.<String>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getTextJustify());
+ assertNotNull(layer.getTextJustify().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextJustify().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextJustify().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getTextJustify().getFunction().getStops().getClass());
});
}
@@ -2288,30 +2100,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-justify");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textJustify(
- property(
- "FeaturePropertyA",
- interval(
- stop(1, textJustify(TEXT_JUSTIFY_LEFT))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textJustify(
+ property(
+ "FeaturePropertyA",
+ interval(
+ stop(1, textJustify(TEXT_JUSTIFY_LEFT))
)
)
- );
-
- // Verify
- assertNotNull(layer.getTextJustify());
- assertNotNull(layer.getTextJustify().getFunction());
- assertEquals(SourceFunction.class, layer.getTextJustify().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextJustify().getFunction()).getProperty());
- assertEquals(IntervalStops.class, layer.getTextJustify().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextJustify());
+ assertNotNull(layer.getTextJustify().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextJustify().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextJustify().getFunction()).getProperty());
+ assertEquals(IntervalStops.class, layer.getTextJustify().getFunction().getStops().getClass());
});
}
@@ -2320,15 +2129,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textAnchor(TEXT_ANCHOR_CENTER));
- assertEquals((String) layer.getTextAnchor().getValue(), (String) TEXT_ANCHOR_CENTER);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textAnchor(TEXT_ANCHOR_CENTER));
+ assertEquals((String) layer.getTextAnchor().getValue(), (String) TEXT_ANCHOR_CENTER);
});
}
@@ -2337,29 +2143,26 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textAnchor(
- zoom(
- interval(
- stop(2, textAnchor(TEXT_ANCHOR_CENTER))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textAnchor(
+ zoom(
+ interval(
+ stop(2, textAnchor(TEXT_ANCHOR_CENTER))
)
)
- );
-
- // Verify
- assertNotNull(layer.getTextAnchor());
- assertNotNull(layer.getTextAnchor().getFunction());
- assertEquals(CameraFunction.class, layer.getTextAnchor().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getTextAnchor().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getTextAnchor().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextAnchor());
+ assertNotNull(layer.getTextAnchor().getFunction());
+ assertEquals(CameraFunction.class, layer.getTextAnchor().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getTextAnchor().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getTextAnchor().getFunction().getStops()).size());
});
}
@@ -2368,23 +2171,20 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textAnchor(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getTextAnchor());
- assertNotNull(layer.getTextAnchor().getFunction());
- assertEquals(SourceFunction.class, layer.getTextAnchor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextAnchor().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getTextAnchor().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textAnchor(property("FeaturePropertyA", Stops.<String>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getTextAnchor());
+ assertNotNull(layer.getTextAnchor().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextAnchor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextAnchor().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getTextAnchor().getFunction().getStops().getClass());
});
}
@@ -2393,30 +2193,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textAnchor(
- property(
- "FeaturePropertyA",
- interval(
- stop(1, textAnchor(TEXT_ANCHOR_CENTER))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textAnchor(
+ property(
+ "FeaturePropertyA",
+ interval(
+ stop(1, textAnchor(TEXT_ANCHOR_CENTER))
)
)
- );
-
- // Verify
- assertNotNull(layer.getTextAnchor());
- assertNotNull(layer.getTextAnchor().getFunction());
- assertEquals(SourceFunction.class, layer.getTextAnchor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextAnchor().getFunction()).getProperty());
- assertEquals(IntervalStops.class, layer.getTextAnchor().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextAnchor());
+ assertNotNull(layer.getTextAnchor().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextAnchor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextAnchor().getFunction()).getProperty());
+ assertEquals(IntervalStops.class, layer.getTextAnchor().getFunction().getStops().getClass());
});
}
@@ -2425,15 +2222,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-max-angle");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textMaxAngle(0.3f));
- assertEquals((Float) layer.getTextMaxAngle().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textMaxAngle(0.3f));
+ assertEquals((Float) layer.getTextMaxAngle().getValue(), (Float) 0.3f);
});
}
@@ -2442,30 +2236,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-max-angle");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textMaxAngle(
- zoom(
- exponential(
- stop(2, textMaxAngle(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textMaxAngle(
+ zoom(
+ exponential(
+ stop(2, textMaxAngle(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getTextMaxAngle());
- assertNotNull(layer.getTextMaxAngle().getFunction());
- assertEquals(CameraFunction.class, layer.getTextMaxAngle().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getTextMaxAngle().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getTextMaxAngle().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getTextMaxAngle().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextMaxAngle());
+ assertNotNull(layer.getTextMaxAngle().getFunction());
+ assertEquals(CameraFunction.class, layer.getTextMaxAngle().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getTextMaxAngle().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getTextMaxAngle().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getTextMaxAngle().getFunction().getStops()).size());
});
}
@@ -2474,15 +2265,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-rotate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textRotate(0.3f));
- assertEquals((Float) layer.getTextRotate().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textRotate(0.3f));
+ assertEquals((Float) layer.getTextRotate().getValue(), (Float) 0.3f);
});
}
@@ -2491,30 +2279,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-rotate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textRotate(
- zoom(
- exponential(
- stop(2, textRotate(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textRotate(
+ zoom(
+ exponential(
+ stop(2, textRotate(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getTextRotate());
- assertNotNull(layer.getTextRotate().getFunction());
- assertEquals(CameraFunction.class, layer.getTextRotate().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getTextRotate().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getTextRotate().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getTextRotate().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextRotate());
+ assertNotNull(layer.getTextRotate().getFunction());
+ assertEquals(CameraFunction.class, layer.getTextRotate().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getTextRotate().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getTextRotate().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getTextRotate().getFunction().getStops()).size());
});
}
@@ -2523,23 +2308,20 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-rotate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textRotate(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getTextRotate());
- assertNotNull(layer.getTextRotate().getFunction());
- assertEquals(SourceFunction.class, layer.getTextRotate().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextRotate().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getTextRotate().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textRotate(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getTextRotate());
+ assertNotNull(layer.getTextRotate().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextRotate().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextRotate().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getTextRotate().getFunction().getStops().getClass());
});
}
@@ -2548,30 +2330,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-rotate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textRotate(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, textRotate(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textRotate(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, textRotate(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getTextRotate());
- assertNotNull(layer.getTextRotate().getFunction());
- assertEquals(SourceFunction.class, layer.getTextRotate().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextRotate().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextRotate().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextRotate());
+ assertNotNull(layer.getTextRotate().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextRotate().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextRotate().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getTextRotate().getFunction().getStops().getClass());
});
}
@@ -2580,33 +2359,30 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-rotate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textRotate(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, textRotate(0.3f))
- )
- ).withDefaultValue(textRotate(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextRotate());
- assertNotNull(layer.getTextRotate().getFunction());
- assertEquals(SourceFunction.class, layer.getTextRotate().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextRotate().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getTextRotate().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getTextRotate().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getTextRotate().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getTextRotate().getFunction()).getDefaultValue().getValue());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textRotate(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, textRotate(0.3f))
+ )
+ ).withDefaultValue(textRotate(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextRotate());
+ assertNotNull(layer.getTextRotate().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextRotate().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextRotate().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getTextRotate().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getTextRotate().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getTextRotate().getFunction()).getDefaultValue().getValue());
+ assertEquals(0.3f, ((SourceFunction) layer.getTextRotate().getFunction()).getDefaultValue().getValue());
});
}
@@ -2616,38 +2392,35 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-rotate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textRotate(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, textRotate(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(textRotate(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextRotate());
- assertNotNull(layer.getTextRotate().getFunction());
- assertEquals(CompositeFunction.class, layer.getTextRotate().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getTextRotate().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextRotate().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getTextRotate().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getTextRotate().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textRotate(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, textRotate(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(textRotate(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextRotate());
+ assertNotNull(layer.getTextRotate().getFunction());
+ assertEquals(CompositeFunction.class, layer.getTextRotate().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getTextRotate().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getTextRotate().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getTextRotate().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getTextRotate().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
});
}
@@ -2656,15 +2429,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-padding");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textPadding(0.3f));
- assertEquals((Float) layer.getTextPadding().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textPadding(0.3f));
+ assertEquals((Float) layer.getTextPadding().getValue(), (Float) 0.3f);
});
}
@@ -2673,30 +2443,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-padding");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textPadding(
- zoom(
- exponential(
- stop(2, textPadding(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textPadding(
+ zoom(
+ exponential(
+ stop(2, textPadding(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getTextPadding());
- assertNotNull(layer.getTextPadding().getFunction());
- assertEquals(CameraFunction.class, layer.getTextPadding().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getTextPadding().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getTextPadding().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getTextPadding().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextPadding());
+ assertNotNull(layer.getTextPadding().getFunction());
+ assertEquals(CameraFunction.class, layer.getTextPadding().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getTextPadding().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getTextPadding().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getTextPadding().getFunction().getStops()).size());
});
}
@@ -2705,15 +2472,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-keep-upright");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textKeepUpright(true));
- assertEquals((Boolean) layer.getTextKeepUpright().getValue(), (Boolean) true);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textKeepUpright(true));
+ assertEquals((Boolean) layer.getTextKeepUpright().getValue(), (Boolean) true);
});
}
@@ -2722,29 +2486,26 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-keep-upright");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textKeepUpright(
- zoom(
- interval(
- stop(2, textKeepUpright(true))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textKeepUpright(
+ zoom(
+ interval(
+ stop(2, textKeepUpright(true))
)
)
- );
-
- // Verify
- assertNotNull(layer.getTextKeepUpright());
- assertNotNull(layer.getTextKeepUpright().getFunction());
- assertEquals(CameraFunction.class, layer.getTextKeepUpright().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getTextKeepUpright().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getTextKeepUpright().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextKeepUpright());
+ assertNotNull(layer.getTextKeepUpright().getFunction());
+ assertEquals(CameraFunction.class, layer.getTextKeepUpright().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getTextKeepUpright().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getTextKeepUpright().getFunction().getStops()).size());
});
}
@@ -2753,15 +2514,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-transform");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textTransform(TEXT_TRANSFORM_NONE));
- assertEquals((String) layer.getTextTransform().getValue(), (String) TEXT_TRANSFORM_NONE);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textTransform(TEXT_TRANSFORM_NONE));
+ assertEquals((String) layer.getTextTransform().getValue(), (String) TEXT_TRANSFORM_NONE);
});
}
@@ -2770,29 +2528,26 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-transform");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textTransform(
- zoom(
- interval(
- stop(2, textTransform(TEXT_TRANSFORM_NONE))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textTransform(
+ zoom(
+ interval(
+ stop(2, textTransform(TEXT_TRANSFORM_NONE))
)
)
- );
-
- // Verify
- assertNotNull(layer.getTextTransform());
- assertNotNull(layer.getTextTransform().getFunction());
- assertEquals(CameraFunction.class, layer.getTextTransform().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getTextTransform().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getTextTransform().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextTransform());
+ assertNotNull(layer.getTextTransform().getFunction());
+ assertEquals(CameraFunction.class, layer.getTextTransform().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getTextTransform().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getTextTransform().getFunction().getStops()).size());
});
}
@@ -2801,23 +2556,20 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-transform");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textTransform(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getTextTransform());
- assertNotNull(layer.getTextTransform().getFunction());
- assertEquals(SourceFunction.class, layer.getTextTransform().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextTransform().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getTextTransform().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textTransform(property("FeaturePropertyA", Stops.<String>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getTextTransform());
+ assertNotNull(layer.getTextTransform().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextTransform().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextTransform().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getTextTransform().getFunction().getStops().getClass());
});
}
@@ -2826,30 +2578,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-transform");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textTransform(
- property(
- "FeaturePropertyA",
- interval(
- stop(1, textTransform(TEXT_TRANSFORM_NONE))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textTransform(
+ property(
+ "FeaturePropertyA",
+ interval(
+ stop(1, textTransform(TEXT_TRANSFORM_NONE))
)
)
- );
-
- // Verify
- assertNotNull(layer.getTextTransform());
- assertNotNull(layer.getTextTransform().getFunction());
- assertEquals(SourceFunction.class, layer.getTextTransform().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextTransform().getFunction()).getProperty());
- assertEquals(IntervalStops.class, layer.getTextTransform().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextTransform());
+ assertNotNull(layer.getTextTransform().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextTransform().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextTransform().getFunction()).getProperty());
+ assertEquals(IntervalStops.class, layer.getTextTransform().getFunction().getStops().getClass());
});
}
@@ -2858,15 +2607,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-offset");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textOffset(new Float[] {0f, 0f}));
- assertEquals((Float[]) layer.getTextOffset().getValue(), (Float[]) new Float[] {0f, 0f});
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textOffset(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getTextOffset().getValue(), (Float[]) new Float[] {0f, 0f});
});
}
@@ -2875,30 +2621,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-offset");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textOffset(
- zoom(
- exponential(
- stop(2, textOffset(new Float[] {0f, 0f}))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textOffset(
+ zoom(
+ exponential(
+ stop(2, textOffset(new Float[] {0f, 0f}))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getTextOffset());
- assertNotNull(layer.getTextOffset().getFunction());
- assertEquals(CameraFunction.class, layer.getTextOffset().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getTextOffset().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getTextOffset().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getTextOffset().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextOffset());
+ assertNotNull(layer.getTextOffset().getFunction());
+ assertEquals(CameraFunction.class, layer.getTextOffset().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getTextOffset().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getTextOffset().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getTextOffset().getFunction().getStops()).size());
});
}
@@ -2907,23 +2650,20 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-offset");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textOffset(property("FeaturePropertyA", Stops.<Float[]>identity()))
- );
-
- // Verify
- assertNotNull(layer.getTextOffset());
- assertNotNull(layer.getTextOffset().getFunction());
- assertEquals(SourceFunction.class, layer.getTextOffset().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextOffset().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getTextOffset().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textOffset(property("FeaturePropertyA", Stops.<Float[]>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getTextOffset());
+ assertNotNull(layer.getTextOffset().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextOffset().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextOffset().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getTextOffset().getFunction().getStops().getClass());
});
}
@@ -2932,30 +2672,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-offset");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textOffset(
- property(
- "FeaturePropertyA",
- interval(
- stop(1, textOffset(new Float[] {0f, 0f}))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textOffset(
+ property(
+ "FeaturePropertyA",
+ interval(
+ stop(1, textOffset(new Float[] {0f, 0f}))
)
)
- );
-
- // Verify
- assertNotNull(layer.getTextOffset());
- assertNotNull(layer.getTextOffset().getFunction());
- assertEquals(SourceFunction.class, layer.getTextOffset().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextOffset().getFunction()).getProperty());
- assertEquals(IntervalStops.class, layer.getTextOffset().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextOffset());
+ assertNotNull(layer.getTextOffset().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextOffset().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextOffset().getFunction()).getProperty());
+ assertEquals(IntervalStops.class, layer.getTextOffset().getFunction().getStops().getClass());
});
}
@@ -2964,15 +2701,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-allow-overlap");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textAllowOverlap(true));
- assertEquals((Boolean) layer.getTextAllowOverlap().getValue(), (Boolean) true);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textAllowOverlap(true));
+ assertEquals((Boolean) layer.getTextAllowOverlap().getValue(), (Boolean) true);
});
}
@@ -2981,29 +2715,26 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-allow-overlap");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textAllowOverlap(
- zoom(
- interval(
- stop(2, textAllowOverlap(true))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textAllowOverlap(
+ zoom(
+ interval(
+ stop(2, textAllowOverlap(true))
)
)
- );
-
- // Verify
- assertNotNull(layer.getTextAllowOverlap());
- assertNotNull(layer.getTextAllowOverlap().getFunction());
- assertEquals(CameraFunction.class, layer.getTextAllowOverlap().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getTextAllowOverlap().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getTextAllowOverlap().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextAllowOverlap());
+ assertNotNull(layer.getTextAllowOverlap().getFunction());
+ assertEquals(CameraFunction.class, layer.getTextAllowOverlap().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getTextAllowOverlap().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getTextAllowOverlap().getFunction().getStops()).size());
});
}
@@ -3012,15 +2743,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-ignore-placement");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textIgnorePlacement(true));
- assertEquals((Boolean) layer.getTextIgnorePlacement().getValue(), (Boolean) true);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textIgnorePlacement(true));
+ assertEquals((Boolean) layer.getTextIgnorePlacement().getValue(), (Boolean) true);
});
}
@@ -3029,29 +2757,26 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-ignore-placement");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textIgnorePlacement(
- zoom(
- interval(
- stop(2, textIgnorePlacement(true))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textIgnorePlacement(
+ zoom(
+ interval(
+ stop(2, textIgnorePlacement(true))
)
)
- );
-
- // Verify
- assertNotNull(layer.getTextIgnorePlacement());
- assertNotNull(layer.getTextIgnorePlacement().getFunction());
- assertEquals(CameraFunction.class, layer.getTextIgnorePlacement().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getTextIgnorePlacement().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getTextIgnorePlacement().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextIgnorePlacement());
+ assertNotNull(layer.getTextIgnorePlacement().getFunction());
+ assertEquals(CameraFunction.class, layer.getTextIgnorePlacement().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getTextIgnorePlacement().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getTextIgnorePlacement().getFunction().getStops()).size());
});
}
@@ -3060,15 +2785,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-optional");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textOptional(true));
- assertEquals((Boolean) layer.getTextOptional().getValue(), (Boolean) true);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textOptional(true));
+ assertEquals((Boolean) layer.getTextOptional().getValue(), (Boolean) true);
});
}
@@ -3077,29 +2799,26 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-optional");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textOptional(
- zoom(
- interval(
- stop(2, textOptional(true))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textOptional(
+ zoom(
+ interval(
+ stop(2, textOptional(true))
)
)
- );
-
- // Verify
- assertNotNull(layer.getTextOptional());
- assertNotNull(layer.getTextOptional().getFunction());
- assertEquals(CameraFunction.class, layer.getTextOptional().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getTextOptional().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getTextOptional().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextOptional());
+ assertNotNull(layer.getTextOptional().getFunction());
+ assertEquals(CameraFunction.class, layer.getTextOptional().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getTextOptional().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getTextOptional().getFunction().getStops()).size());
});
}
@@ -3108,16 +2827,13 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-opacityTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setIconOpacityTransition(options);
- assertEquals(layer.getIconOpacityTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setIconOpacityTransition(options);
+ assertEquals(layer.getIconOpacityTransition(), options);
});
}
@@ -3126,15 +2842,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconOpacity(0.3f));
- assertEquals((Float) layer.getIconOpacity().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(iconOpacity(0.3f));
+ assertEquals((Float) layer.getIconOpacity().getValue(), (Float) 0.3f);
});
}
@@ -3143,30 +2856,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconOpacity(
- zoom(
- exponential(
- stop(2, iconOpacity(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconOpacity(
+ zoom(
+ exponential(
+ stop(2, iconOpacity(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getIconOpacity());
- assertNotNull(layer.getIconOpacity().getFunction());
- assertEquals(CameraFunction.class, layer.getIconOpacity().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getIconOpacity().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getIconOpacity().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getIconOpacity().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconOpacity());
+ assertNotNull(layer.getIconOpacity().getFunction());
+ assertEquals(CameraFunction.class, layer.getIconOpacity().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getIconOpacity().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getIconOpacity().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getIconOpacity().getFunction().getStops()).size());
});
}
@@ -3175,23 +2885,20 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconOpacity(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getIconOpacity());
- assertNotNull(layer.getIconOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getIconOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconOpacity().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getIconOpacity().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconOpacity(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getIconOpacity());
+ assertNotNull(layer.getIconOpacity().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconOpacity().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getIconOpacity().getFunction().getStops().getClass());
});
}
@@ -3200,30 +2907,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconOpacity(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, iconOpacity(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconOpacity(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, iconOpacity(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getIconOpacity());
- assertNotNull(layer.getIconOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getIconOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconOpacity().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getIconOpacity().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconOpacity());
+ assertNotNull(layer.getIconOpacity().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconOpacity().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getIconOpacity().getFunction().getStops().getClass());
});
}
@@ -3232,33 +2936,30 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconOpacity(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, iconOpacity(0.3f))
- )
- ).withDefaultValue(iconOpacity(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getIconOpacity());
- assertNotNull(layer.getIconOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getIconOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconOpacity().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getIconOpacity().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getIconOpacity().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getIconOpacity().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getIconOpacity().getFunction()).getDefaultValue().getValue());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconOpacity(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, iconOpacity(0.3f))
+ )
+ ).withDefaultValue(iconOpacity(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconOpacity());
+ assertNotNull(layer.getIconOpacity().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconOpacity().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getIconOpacity().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getIconOpacity().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getIconOpacity().getFunction()).getDefaultValue().getValue());
+ assertEquals(0.3f, ((SourceFunction) layer.getIconOpacity().getFunction()).getDefaultValue().getValue());
});
}
@@ -3268,38 +2969,35 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconOpacity(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, iconOpacity(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(iconOpacity(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getIconOpacity());
- assertNotNull(layer.getIconOpacity().getFunction());
- assertEquals(CompositeFunction.class, layer.getIconOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getIconOpacity().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getIconOpacity().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getIconOpacity().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getIconOpacity().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconOpacity(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, iconOpacity(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(iconOpacity(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconOpacity());
+ assertNotNull(layer.getIconOpacity().getFunction());
+ assertEquals(CompositeFunction.class, layer.getIconOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getIconOpacity().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getIconOpacity().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getIconOpacity().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getIconOpacity().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
});
}
@@ -3308,16 +3006,13 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-colorTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setIconColorTransition(options);
- assertEquals(layer.getIconColorTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setIconColorTransition(options);
+ assertEquals(layer.getIconColorTransition(), options);
});
}
@@ -3326,15 +3021,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getIconColor().getValue(), (String) "rgba(0, 0, 0, 1)");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(iconColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getIconColor().getValue(), (String) "rgba(0, 0, 0, 1)");
});
}
@@ -3343,30 +3035,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconColor(
- zoom(
- exponential(
- stop(2, iconColor("rgba(0, 0, 0, 1)"))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconColor(
+ zoom(
+ exponential(
+ stop(2, iconColor("rgba(0, 0, 0, 1)"))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getIconColor());
- assertNotNull(layer.getIconColor().getFunction());
- assertEquals(CameraFunction.class, layer.getIconColor().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getIconColor().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getIconColor().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getIconColor().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconColor());
+ assertNotNull(layer.getIconColor().getFunction());
+ assertEquals(CameraFunction.class, layer.getIconColor().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getIconColor().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getIconColor().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getIconColor().getFunction().getStops()).size());
});
}
@@ -3375,23 +3064,20 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconColor(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getIconColor());
- assertNotNull(layer.getIconColor().getFunction());
- assertEquals(SourceFunction.class, layer.getIconColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconColor().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getIconColor().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconColor(property("FeaturePropertyA", Stops.<String>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getIconColor());
+ assertNotNull(layer.getIconColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconColor().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getIconColor().getFunction().getStops().getClass());
});
}
@@ -3400,30 +3086,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconColor(
- property(
- "FeaturePropertyA",
- exponential(
- stop(Color.RED, iconColor(Color.RED))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconColor(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(Color.RED, iconColor(Color.RED))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getIconColor());
- assertNotNull(layer.getIconColor().getFunction());
- assertEquals(SourceFunction.class, layer.getIconColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconColor().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getIconColor().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconColor());
+ assertNotNull(layer.getIconColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconColor().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getIconColor().getFunction().getStops().getClass());
});
}
@@ -3432,33 +3115,30 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconColor(
- property(
- "FeaturePropertyA",
- categorical(
- stop("valueA", iconColor(Color.RED))
- )
- ).withDefaultValue(iconColor(Color.GREEN))
- )
- );
-
- // Verify
- assertNotNull(layer.getIconColor());
- assertNotNull(layer.getIconColor().getFunction());
- assertEquals(SourceFunction.class, layer.getIconColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconColor().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getIconColor().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getIconColor().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getIconColor().getFunction()).getDefaultValue().getValue());
- assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getIconColor().getFunction()).getDefaultValue().getColorInt());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconColor(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop("valueA", iconColor(Color.RED))
+ )
+ ).withDefaultValue(iconColor(Color.GREEN))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconColor());
+ assertNotNull(layer.getIconColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconColor().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getIconColor().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getIconColor().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getIconColor().getFunction()).getDefaultValue().getValue());
+ assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getIconColor().getFunction()).getDefaultValue().getColorInt());
});
}
@@ -3468,15 +3148,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconColor(Color.RED));
- assertEquals(layer.getIconColorAsInt(), Color.RED);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(iconColor(Color.RED));
+ assertEquals(layer.getIconColorAsInt(), Color.RED);
});
}
@@ -3485,16 +3162,13 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-halo-colorTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setIconHaloColorTransition(options);
- assertEquals(layer.getIconHaloColorTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setIconHaloColorTransition(options);
+ assertEquals(layer.getIconHaloColorTransition(), options);
});
}
@@ -3503,15 +3177,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-halo-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconHaloColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getIconHaloColor().getValue(), (String) "rgba(0, 0, 0, 1)");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(iconHaloColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getIconHaloColor().getValue(), (String) "rgba(0, 0, 0, 1)");
});
}
@@ -3520,30 +3191,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-halo-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconHaloColor(
- zoom(
- exponential(
- stop(2, iconHaloColor("rgba(0, 0, 0, 1)"))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconHaloColor(
+ zoom(
+ exponential(
+ stop(2, iconHaloColor("rgba(0, 0, 0, 1)"))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getIconHaloColor());
- assertNotNull(layer.getIconHaloColor().getFunction());
- assertEquals(CameraFunction.class, layer.getIconHaloColor().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getIconHaloColor().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getIconHaloColor().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getIconHaloColor().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconHaloColor());
+ assertNotNull(layer.getIconHaloColor().getFunction());
+ assertEquals(CameraFunction.class, layer.getIconHaloColor().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getIconHaloColor().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getIconHaloColor().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getIconHaloColor().getFunction().getStops()).size());
});
}
@@ -3552,23 +3220,20 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-halo-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconHaloColor(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getIconHaloColor());
- assertNotNull(layer.getIconHaloColor().getFunction());
- assertEquals(SourceFunction.class, layer.getIconHaloColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloColor().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getIconHaloColor().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconHaloColor(property("FeaturePropertyA", Stops.<String>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getIconHaloColor());
+ assertNotNull(layer.getIconHaloColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconHaloColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloColor().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getIconHaloColor().getFunction().getStops().getClass());
});
}
@@ -3577,30 +3242,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-halo-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconHaloColor(
- property(
- "FeaturePropertyA",
- exponential(
- stop(Color.RED, iconHaloColor(Color.RED))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconHaloColor(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(Color.RED, iconHaloColor(Color.RED))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getIconHaloColor());
- assertNotNull(layer.getIconHaloColor().getFunction());
- assertEquals(SourceFunction.class, layer.getIconHaloColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloColor().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getIconHaloColor().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconHaloColor());
+ assertNotNull(layer.getIconHaloColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconHaloColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloColor().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getIconHaloColor().getFunction().getStops().getClass());
});
}
@@ -3609,33 +3271,30 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-halo-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconHaloColor(
- property(
- "FeaturePropertyA",
- categorical(
- stop("valueA", iconHaloColor(Color.RED))
- )
- ).withDefaultValue(iconHaloColor(Color.GREEN))
- )
- );
-
- // Verify
- assertNotNull(layer.getIconHaloColor());
- assertNotNull(layer.getIconHaloColor().getFunction());
- assertEquals(SourceFunction.class, layer.getIconHaloColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloColor().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getIconHaloColor().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getIconHaloColor().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getIconHaloColor().getFunction()).getDefaultValue().getValue());
- assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getIconHaloColor().getFunction()).getDefaultValue().getColorInt());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconHaloColor(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop("valueA", iconHaloColor(Color.RED))
+ )
+ ).withDefaultValue(iconHaloColor(Color.GREEN))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconHaloColor());
+ assertNotNull(layer.getIconHaloColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconHaloColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloColor().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getIconHaloColor().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getIconHaloColor().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getIconHaloColor().getFunction()).getDefaultValue().getValue());
+ assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getIconHaloColor().getFunction()).getDefaultValue().getColorInt());
});
}
@@ -3645,15 +3304,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-halo-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconHaloColor(Color.RED));
- assertEquals(layer.getIconHaloColorAsInt(), Color.RED);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(iconHaloColor(Color.RED));
+ assertEquals(layer.getIconHaloColorAsInt(), Color.RED);
});
}
@@ -3662,16 +3318,13 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-halo-widthTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setIconHaloWidthTransition(options);
- assertEquals(layer.getIconHaloWidthTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setIconHaloWidthTransition(options);
+ assertEquals(layer.getIconHaloWidthTransition(), options);
});
}
@@ -3680,15 +3333,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-halo-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconHaloWidth(0.3f));
- assertEquals((Float) layer.getIconHaloWidth().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(iconHaloWidth(0.3f));
+ assertEquals((Float) layer.getIconHaloWidth().getValue(), (Float) 0.3f);
});
}
@@ -3697,30 +3347,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-halo-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconHaloWidth(
- zoom(
- exponential(
- stop(2, iconHaloWidth(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconHaloWidth(
+ zoom(
+ exponential(
+ stop(2, iconHaloWidth(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getIconHaloWidth());
- assertNotNull(layer.getIconHaloWidth().getFunction());
- assertEquals(CameraFunction.class, layer.getIconHaloWidth().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getIconHaloWidth().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getIconHaloWidth().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getIconHaloWidth().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconHaloWidth());
+ assertNotNull(layer.getIconHaloWidth().getFunction());
+ assertEquals(CameraFunction.class, layer.getIconHaloWidth().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getIconHaloWidth().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getIconHaloWidth().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getIconHaloWidth().getFunction().getStops()).size());
});
}
@@ -3729,23 +3376,20 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-halo-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconHaloWidth(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getIconHaloWidth());
- assertNotNull(layer.getIconHaloWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getIconHaloWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloWidth().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getIconHaloWidth().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconHaloWidth(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getIconHaloWidth());
+ assertNotNull(layer.getIconHaloWidth().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconHaloWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloWidth().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getIconHaloWidth().getFunction().getStops().getClass());
});
}
@@ -3754,30 +3398,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-halo-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconHaloWidth(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, iconHaloWidth(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconHaloWidth(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, iconHaloWidth(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getIconHaloWidth());
- assertNotNull(layer.getIconHaloWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getIconHaloWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloWidth().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getIconHaloWidth().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconHaloWidth());
+ assertNotNull(layer.getIconHaloWidth().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconHaloWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloWidth().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getIconHaloWidth().getFunction().getStops().getClass());
});
}
@@ -3786,33 +3427,30 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-halo-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconHaloWidth(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, iconHaloWidth(0.3f))
- )
- ).withDefaultValue(iconHaloWidth(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getIconHaloWidth());
- assertNotNull(layer.getIconHaloWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getIconHaloWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloWidth().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getIconHaloWidth().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getIconHaloWidth().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getIconHaloWidth().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getIconHaloWidth().getFunction()).getDefaultValue().getValue());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconHaloWidth(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, iconHaloWidth(0.3f))
+ )
+ ).withDefaultValue(iconHaloWidth(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconHaloWidth());
+ assertNotNull(layer.getIconHaloWidth().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconHaloWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloWidth().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getIconHaloWidth().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getIconHaloWidth().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getIconHaloWidth().getFunction()).getDefaultValue().getValue());
+ assertEquals(0.3f, ((SourceFunction) layer.getIconHaloWidth().getFunction()).getDefaultValue().getValue());
});
}
@@ -3822,38 +3460,35 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-halo-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconHaloWidth(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, iconHaloWidth(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(iconHaloWidth(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getIconHaloWidth());
- assertNotNull(layer.getIconHaloWidth().getFunction());
- assertEquals(CompositeFunction.class, layer.getIconHaloWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getIconHaloWidth().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getIconHaloWidth().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getIconHaloWidth().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getIconHaloWidth().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconHaloWidth(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, iconHaloWidth(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(iconHaloWidth(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconHaloWidth());
+ assertNotNull(layer.getIconHaloWidth().getFunction());
+ assertEquals(CompositeFunction.class, layer.getIconHaloWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getIconHaloWidth().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getIconHaloWidth().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getIconHaloWidth().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getIconHaloWidth().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
});
}
@@ -3862,16 +3497,13 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-halo-blurTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setIconHaloBlurTransition(options);
- assertEquals(layer.getIconHaloBlurTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setIconHaloBlurTransition(options);
+ assertEquals(layer.getIconHaloBlurTransition(), options);
});
}
@@ -3880,15 +3512,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-halo-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconHaloBlur(0.3f));
- assertEquals((Float) layer.getIconHaloBlur().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(iconHaloBlur(0.3f));
+ assertEquals((Float) layer.getIconHaloBlur().getValue(), (Float) 0.3f);
});
}
@@ -3897,30 +3526,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-halo-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconHaloBlur(
- zoom(
- exponential(
- stop(2, iconHaloBlur(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconHaloBlur(
+ zoom(
+ exponential(
+ stop(2, iconHaloBlur(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getIconHaloBlur());
- assertNotNull(layer.getIconHaloBlur().getFunction());
- assertEquals(CameraFunction.class, layer.getIconHaloBlur().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getIconHaloBlur().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getIconHaloBlur().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getIconHaloBlur().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconHaloBlur());
+ assertNotNull(layer.getIconHaloBlur().getFunction());
+ assertEquals(CameraFunction.class, layer.getIconHaloBlur().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getIconHaloBlur().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getIconHaloBlur().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getIconHaloBlur().getFunction().getStops()).size());
});
}
@@ -3929,23 +3555,20 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-halo-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconHaloBlur(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getIconHaloBlur());
- assertNotNull(layer.getIconHaloBlur().getFunction());
- assertEquals(SourceFunction.class, layer.getIconHaloBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloBlur().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getIconHaloBlur().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconHaloBlur(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getIconHaloBlur());
+ assertNotNull(layer.getIconHaloBlur().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconHaloBlur().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloBlur().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getIconHaloBlur().getFunction().getStops().getClass());
});
}
@@ -3954,30 +3577,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-halo-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconHaloBlur(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, iconHaloBlur(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconHaloBlur(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, iconHaloBlur(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getIconHaloBlur());
- assertNotNull(layer.getIconHaloBlur().getFunction());
- assertEquals(SourceFunction.class, layer.getIconHaloBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloBlur().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getIconHaloBlur().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconHaloBlur());
+ assertNotNull(layer.getIconHaloBlur().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconHaloBlur().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloBlur().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getIconHaloBlur().getFunction().getStops().getClass());
});
}
@@ -3986,33 +3606,30 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-halo-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconHaloBlur(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, iconHaloBlur(0.3f))
- )
- ).withDefaultValue(iconHaloBlur(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getIconHaloBlur());
- assertNotNull(layer.getIconHaloBlur().getFunction());
- assertEquals(SourceFunction.class, layer.getIconHaloBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloBlur().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getIconHaloBlur().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getIconHaloBlur().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getIconHaloBlur().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getIconHaloBlur().getFunction()).getDefaultValue().getValue());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconHaloBlur(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, iconHaloBlur(0.3f))
+ )
+ ).withDefaultValue(iconHaloBlur(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconHaloBlur());
+ assertNotNull(layer.getIconHaloBlur().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconHaloBlur().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloBlur().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getIconHaloBlur().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getIconHaloBlur().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getIconHaloBlur().getFunction()).getDefaultValue().getValue());
+ assertEquals(0.3f, ((SourceFunction) layer.getIconHaloBlur().getFunction()).getDefaultValue().getValue());
});
}
@@ -4022,38 +3639,35 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-halo-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconHaloBlur(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, iconHaloBlur(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(iconHaloBlur(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getIconHaloBlur());
- assertNotNull(layer.getIconHaloBlur().getFunction());
- assertEquals(CompositeFunction.class, layer.getIconHaloBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getIconHaloBlur().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getIconHaloBlur().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getIconHaloBlur().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getIconHaloBlur().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconHaloBlur(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, iconHaloBlur(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(iconHaloBlur(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconHaloBlur());
+ assertNotNull(layer.getIconHaloBlur().getFunction());
+ assertEquals(CompositeFunction.class, layer.getIconHaloBlur().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getIconHaloBlur().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getIconHaloBlur().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getIconHaloBlur().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getIconHaloBlur().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
});
}
@@ -4062,16 +3676,13 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-translateTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setIconTranslateTransition(options);
- assertEquals(layer.getIconTranslateTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setIconTranslateTransition(options);
+ assertEquals(layer.getIconTranslateTransition(), options);
});
}
@@ -4080,15 +3691,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-translate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconTranslate(new Float[] {0f, 0f}));
- assertEquals((Float[]) layer.getIconTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(iconTranslate(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getIconTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
});
}
@@ -4097,30 +3705,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-translate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconTranslate(
- zoom(
- exponential(
- stop(2, iconTranslate(new Float[] {0f, 0f}))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconTranslate(
+ zoom(
+ exponential(
+ stop(2, iconTranslate(new Float[] {0f, 0f}))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getIconTranslate());
- assertNotNull(layer.getIconTranslate().getFunction());
- assertEquals(CameraFunction.class, layer.getIconTranslate().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getIconTranslate().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getIconTranslate().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getIconTranslate().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconTranslate());
+ assertNotNull(layer.getIconTranslate().getFunction());
+ assertEquals(CameraFunction.class, layer.getIconTranslate().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getIconTranslate().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getIconTranslate().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getIconTranslate().getFunction().getStops()).size());
});
}
@@ -4129,15 +3734,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-translate-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconTranslateAnchor(ICON_TRANSLATE_ANCHOR_MAP));
- assertEquals((String) layer.getIconTranslateAnchor().getValue(), (String) ICON_TRANSLATE_ANCHOR_MAP);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(iconTranslateAnchor(ICON_TRANSLATE_ANCHOR_MAP));
+ assertEquals((String) layer.getIconTranslateAnchor().getValue(), (String) ICON_TRANSLATE_ANCHOR_MAP);
});
}
@@ -4146,29 +3748,26 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-translate-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconTranslateAnchor(
- zoom(
- interval(
- stop(2, iconTranslateAnchor(ICON_TRANSLATE_ANCHOR_MAP))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconTranslateAnchor(
+ zoom(
+ interval(
+ stop(2, iconTranslateAnchor(ICON_TRANSLATE_ANCHOR_MAP))
)
)
- );
-
- // Verify
- assertNotNull(layer.getIconTranslateAnchor());
- assertNotNull(layer.getIconTranslateAnchor().getFunction());
- assertEquals(CameraFunction.class, layer.getIconTranslateAnchor().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getIconTranslateAnchor().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getIconTranslateAnchor().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconTranslateAnchor());
+ assertNotNull(layer.getIconTranslateAnchor().getFunction());
+ assertEquals(CameraFunction.class, layer.getIconTranslateAnchor().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getIconTranslateAnchor().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getIconTranslateAnchor().getFunction().getStops()).size());
});
}
@@ -4177,16 +3776,13 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-opacityTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setTextOpacityTransition(options);
- assertEquals(layer.getTextOpacityTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setTextOpacityTransition(options);
+ assertEquals(layer.getTextOpacityTransition(), options);
});
}
@@ -4195,15 +3791,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textOpacity(0.3f));
- assertEquals((Float) layer.getTextOpacity().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textOpacity(0.3f));
+ assertEquals((Float) layer.getTextOpacity().getValue(), (Float) 0.3f);
});
}
@@ -4212,30 +3805,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textOpacity(
- zoom(
- exponential(
- stop(2, textOpacity(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textOpacity(
+ zoom(
+ exponential(
+ stop(2, textOpacity(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getTextOpacity());
- assertNotNull(layer.getTextOpacity().getFunction());
- assertEquals(CameraFunction.class, layer.getTextOpacity().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getTextOpacity().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getTextOpacity().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getTextOpacity().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextOpacity());
+ assertNotNull(layer.getTextOpacity().getFunction());
+ assertEquals(CameraFunction.class, layer.getTextOpacity().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getTextOpacity().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getTextOpacity().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getTextOpacity().getFunction().getStops()).size());
});
}
@@ -4244,23 +3834,20 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textOpacity(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getTextOpacity());
- assertNotNull(layer.getTextOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getTextOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextOpacity().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getTextOpacity().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textOpacity(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getTextOpacity());
+ assertNotNull(layer.getTextOpacity().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextOpacity().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getTextOpacity().getFunction().getStops().getClass());
});
}
@@ -4269,30 +3856,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textOpacity(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, textOpacity(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textOpacity(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, textOpacity(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getTextOpacity());
- assertNotNull(layer.getTextOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getTextOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextOpacity().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextOpacity().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextOpacity());
+ assertNotNull(layer.getTextOpacity().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextOpacity().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getTextOpacity().getFunction().getStops().getClass());
});
}
@@ -4301,33 +3885,30 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textOpacity(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, textOpacity(0.3f))
- )
- ).withDefaultValue(textOpacity(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextOpacity());
- assertNotNull(layer.getTextOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getTextOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextOpacity().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getTextOpacity().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getTextOpacity().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getTextOpacity().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getTextOpacity().getFunction()).getDefaultValue().getValue());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textOpacity(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, textOpacity(0.3f))
+ )
+ ).withDefaultValue(textOpacity(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextOpacity());
+ assertNotNull(layer.getTextOpacity().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextOpacity().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getTextOpacity().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getTextOpacity().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getTextOpacity().getFunction()).getDefaultValue().getValue());
+ assertEquals(0.3f, ((SourceFunction) layer.getTextOpacity().getFunction()).getDefaultValue().getValue());
});
}
@@ -4337,38 +3918,35 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textOpacity(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, textOpacity(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(textOpacity(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextOpacity());
- assertNotNull(layer.getTextOpacity().getFunction());
- assertEquals(CompositeFunction.class, layer.getTextOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getTextOpacity().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextOpacity().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getTextOpacity().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getTextOpacity().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textOpacity(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, textOpacity(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(textOpacity(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextOpacity());
+ assertNotNull(layer.getTextOpacity().getFunction());
+ assertEquals(CompositeFunction.class, layer.getTextOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getTextOpacity().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getTextOpacity().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getTextOpacity().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getTextOpacity().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
});
}
@@ -4377,16 +3955,13 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-colorTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setTextColorTransition(options);
- assertEquals(layer.getTextColorTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setTextColorTransition(options);
+ assertEquals(layer.getTextColorTransition(), options);
});
}
@@ -4395,15 +3970,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getTextColor().getValue(), (String) "rgba(0, 0, 0, 1)");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getTextColor().getValue(), (String) "rgba(0, 0, 0, 1)");
});
}
@@ -4412,30 +3984,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textColor(
- zoom(
- exponential(
- stop(2, textColor("rgba(0, 0, 0, 1)"))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textColor(
+ zoom(
+ exponential(
+ stop(2, textColor("rgba(0, 0, 0, 1)"))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getTextColor());
- assertNotNull(layer.getTextColor().getFunction());
- assertEquals(CameraFunction.class, layer.getTextColor().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getTextColor().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getTextColor().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getTextColor().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextColor());
+ assertNotNull(layer.getTextColor().getFunction());
+ assertEquals(CameraFunction.class, layer.getTextColor().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getTextColor().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getTextColor().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getTextColor().getFunction().getStops()).size());
});
}
@@ -4444,23 +4013,20 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textColor(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getTextColor());
- assertNotNull(layer.getTextColor().getFunction());
- assertEquals(SourceFunction.class, layer.getTextColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextColor().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getTextColor().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textColor(property("FeaturePropertyA", Stops.<String>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getTextColor());
+ assertNotNull(layer.getTextColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextColor().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getTextColor().getFunction().getStops().getClass());
});
}
@@ -4469,30 +4035,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textColor(
- property(
- "FeaturePropertyA",
- exponential(
- stop(Color.RED, textColor(Color.RED))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textColor(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(Color.RED, textColor(Color.RED))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getTextColor());
- assertNotNull(layer.getTextColor().getFunction());
- assertEquals(SourceFunction.class, layer.getTextColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextColor().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextColor().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextColor());
+ assertNotNull(layer.getTextColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextColor().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getTextColor().getFunction().getStops().getClass());
});
}
@@ -4501,33 +4064,30 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textColor(
- property(
- "FeaturePropertyA",
- categorical(
- stop("valueA", textColor(Color.RED))
- )
- ).withDefaultValue(textColor(Color.GREEN))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextColor());
- assertNotNull(layer.getTextColor().getFunction());
- assertEquals(SourceFunction.class, layer.getTextColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextColor().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getTextColor().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getTextColor().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getTextColor().getFunction()).getDefaultValue().getValue());
- assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getTextColor().getFunction()).getDefaultValue().getColorInt());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textColor(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop("valueA", textColor(Color.RED))
+ )
+ ).withDefaultValue(textColor(Color.GREEN))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextColor());
+ assertNotNull(layer.getTextColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextColor().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getTextColor().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getTextColor().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getTextColor().getFunction()).getDefaultValue().getValue());
+ assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getTextColor().getFunction()).getDefaultValue().getColorInt());
});
}
@@ -4537,15 +4097,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textColor(Color.RED));
- assertEquals(layer.getTextColorAsInt(), Color.RED);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textColor(Color.RED));
+ assertEquals(layer.getTextColorAsInt(), Color.RED);
});
}
@@ -4554,16 +4111,13 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-halo-colorTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setTextHaloColorTransition(options);
- assertEquals(layer.getTextHaloColorTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setTextHaloColorTransition(options);
+ assertEquals(layer.getTextHaloColorTransition(), options);
});
}
@@ -4572,15 +4126,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-halo-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textHaloColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getTextHaloColor().getValue(), (String) "rgba(0, 0, 0, 1)");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textHaloColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getTextHaloColor().getValue(), (String) "rgba(0, 0, 0, 1)");
});
}
@@ -4589,30 +4140,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-halo-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textHaloColor(
- zoom(
- exponential(
- stop(2, textHaloColor("rgba(0, 0, 0, 1)"))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textHaloColor(
+ zoom(
+ exponential(
+ stop(2, textHaloColor("rgba(0, 0, 0, 1)"))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getTextHaloColor());
- assertNotNull(layer.getTextHaloColor().getFunction());
- assertEquals(CameraFunction.class, layer.getTextHaloColor().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getTextHaloColor().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getTextHaloColor().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getTextHaloColor().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextHaloColor());
+ assertNotNull(layer.getTextHaloColor().getFunction());
+ assertEquals(CameraFunction.class, layer.getTextHaloColor().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getTextHaloColor().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getTextHaloColor().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getTextHaloColor().getFunction().getStops()).size());
});
}
@@ -4621,23 +4169,20 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-halo-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textHaloColor(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getTextHaloColor());
- assertNotNull(layer.getTextHaloColor().getFunction());
- assertEquals(SourceFunction.class, layer.getTextHaloColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloColor().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getTextHaloColor().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textHaloColor(property("FeaturePropertyA", Stops.<String>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getTextHaloColor());
+ assertNotNull(layer.getTextHaloColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextHaloColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloColor().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getTextHaloColor().getFunction().getStops().getClass());
});
}
@@ -4646,30 +4191,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-halo-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textHaloColor(
- property(
- "FeaturePropertyA",
- exponential(
- stop(Color.RED, textHaloColor(Color.RED))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textHaloColor(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(Color.RED, textHaloColor(Color.RED))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getTextHaloColor());
- assertNotNull(layer.getTextHaloColor().getFunction());
- assertEquals(SourceFunction.class, layer.getTextHaloColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloColor().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextHaloColor().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextHaloColor());
+ assertNotNull(layer.getTextHaloColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextHaloColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloColor().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getTextHaloColor().getFunction().getStops().getClass());
});
}
@@ -4678,33 +4220,30 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-halo-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textHaloColor(
- property(
- "FeaturePropertyA",
- categorical(
- stop("valueA", textHaloColor(Color.RED))
- )
- ).withDefaultValue(textHaloColor(Color.GREEN))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextHaloColor());
- assertNotNull(layer.getTextHaloColor().getFunction());
- assertEquals(SourceFunction.class, layer.getTextHaloColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloColor().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getTextHaloColor().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getTextHaloColor().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getTextHaloColor().getFunction()).getDefaultValue().getValue());
- assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getTextHaloColor().getFunction()).getDefaultValue().getColorInt());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textHaloColor(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop("valueA", textHaloColor(Color.RED))
+ )
+ ).withDefaultValue(textHaloColor(Color.GREEN))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextHaloColor());
+ assertNotNull(layer.getTextHaloColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextHaloColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloColor().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getTextHaloColor().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getTextHaloColor().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getTextHaloColor().getFunction()).getDefaultValue().getValue());
+ assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getTextHaloColor().getFunction()).getDefaultValue().getColorInt());
});
}
@@ -4714,15 +4253,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-halo-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textHaloColor(Color.RED));
- assertEquals(layer.getTextHaloColorAsInt(), Color.RED);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textHaloColor(Color.RED));
+ assertEquals(layer.getTextHaloColorAsInt(), Color.RED);
});
}
@@ -4731,16 +4267,13 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-halo-widthTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setTextHaloWidthTransition(options);
- assertEquals(layer.getTextHaloWidthTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setTextHaloWidthTransition(options);
+ assertEquals(layer.getTextHaloWidthTransition(), options);
});
}
@@ -4749,15 +4282,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-halo-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textHaloWidth(0.3f));
- assertEquals((Float) layer.getTextHaloWidth().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textHaloWidth(0.3f));
+ assertEquals((Float) layer.getTextHaloWidth().getValue(), (Float) 0.3f);
});
}
@@ -4766,30 +4296,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-halo-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textHaloWidth(
- zoom(
- exponential(
- stop(2, textHaloWidth(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textHaloWidth(
+ zoom(
+ exponential(
+ stop(2, textHaloWidth(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getTextHaloWidth());
- assertNotNull(layer.getTextHaloWidth().getFunction());
- assertEquals(CameraFunction.class, layer.getTextHaloWidth().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getTextHaloWidth().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getTextHaloWidth().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getTextHaloWidth().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextHaloWidth());
+ assertNotNull(layer.getTextHaloWidth().getFunction());
+ assertEquals(CameraFunction.class, layer.getTextHaloWidth().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getTextHaloWidth().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getTextHaloWidth().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getTextHaloWidth().getFunction().getStops()).size());
});
}
@@ -4798,23 +4325,20 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-halo-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textHaloWidth(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getTextHaloWidth());
- assertNotNull(layer.getTextHaloWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getTextHaloWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloWidth().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getTextHaloWidth().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textHaloWidth(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getTextHaloWidth());
+ assertNotNull(layer.getTextHaloWidth().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextHaloWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloWidth().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getTextHaloWidth().getFunction().getStops().getClass());
});
}
@@ -4823,30 +4347,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-halo-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textHaloWidth(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, textHaloWidth(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textHaloWidth(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, textHaloWidth(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getTextHaloWidth());
- assertNotNull(layer.getTextHaloWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getTextHaloWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloWidth().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextHaloWidth().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextHaloWidth());
+ assertNotNull(layer.getTextHaloWidth().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextHaloWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloWidth().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getTextHaloWidth().getFunction().getStops().getClass());
});
}
@@ -4855,33 +4376,30 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-halo-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textHaloWidth(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, textHaloWidth(0.3f))
- )
- ).withDefaultValue(textHaloWidth(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextHaloWidth());
- assertNotNull(layer.getTextHaloWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getTextHaloWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloWidth().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getTextHaloWidth().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getTextHaloWidth().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getTextHaloWidth().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getTextHaloWidth().getFunction()).getDefaultValue().getValue());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textHaloWidth(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, textHaloWidth(0.3f))
+ )
+ ).withDefaultValue(textHaloWidth(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextHaloWidth());
+ assertNotNull(layer.getTextHaloWidth().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextHaloWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloWidth().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getTextHaloWidth().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getTextHaloWidth().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getTextHaloWidth().getFunction()).getDefaultValue().getValue());
+ assertEquals(0.3f, ((SourceFunction) layer.getTextHaloWidth().getFunction()).getDefaultValue().getValue());
});
}
@@ -4891,38 +4409,35 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-halo-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textHaloWidth(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, textHaloWidth(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(textHaloWidth(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextHaloWidth());
- assertNotNull(layer.getTextHaloWidth().getFunction());
- assertEquals(CompositeFunction.class, layer.getTextHaloWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getTextHaloWidth().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextHaloWidth().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getTextHaloWidth().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getTextHaloWidth().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textHaloWidth(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, textHaloWidth(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(textHaloWidth(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextHaloWidth());
+ assertNotNull(layer.getTextHaloWidth().getFunction());
+ assertEquals(CompositeFunction.class, layer.getTextHaloWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getTextHaloWidth().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getTextHaloWidth().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getTextHaloWidth().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getTextHaloWidth().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
});
}
@@ -4931,16 +4446,13 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-halo-blurTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setTextHaloBlurTransition(options);
- assertEquals(layer.getTextHaloBlurTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setTextHaloBlurTransition(options);
+ assertEquals(layer.getTextHaloBlurTransition(), options);
});
}
@@ -4949,15 +4461,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-halo-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textHaloBlur(0.3f));
- assertEquals((Float) layer.getTextHaloBlur().getValue(), (Float) 0.3f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textHaloBlur(0.3f));
+ assertEquals((Float) layer.getTextHaloBlur().getValue(), (Float) 0.3f);
});
}
@@ -4966,30 +4475,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-halo-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textHaloBlur(
- zoom(
- exponential(
- stop(2, textHaloBlur(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textHaloBlur(
+ zoom(
+ exponential(
+ stop(2, textHaloBlur(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getTextHaloBlur());
- assertNotNull(layer.getTextHaloBlur().getFunction());
- assertEquals(CameraFunction.class, layer.getTextHaloBlur().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getTextHaloBlur().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getTextHaloBlur().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getTextHaloBlur().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextHaloBlur());
+ assertNotNull(layer.getTextHaloBlur().getFunction());
+ assertEquals(CameraFunction.class, layer.getTextHaloBlur().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getTextHaloBlur().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getTextHaloBlur().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getTextHaloBlur().getFunction().getStops()).size());
});
}
@@ -4998,23 +4504,20 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-halo-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textHaloBlur(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getTextHaloBlur());
- assertNotNull(layer.getTextHaloBlur().getFunction());
- assertEquals(SourceFunction.class, layer.getTextHaloBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloBlur().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getTextHaloBlur().getFunction().getStops().getClass());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textHaloBlur(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getTextHaloBlur());
+ assertNotNull(layer.getTextHaloBlur().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextHaloBlur().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloBlur().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getTextHaloBlur().getFunction().getStops().getClass());
});
}
@@ -5023,30 +4526,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-halo-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textHaloBlur(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, textHaloBlur(0.3f))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textHaloBlur(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, textHaloBlur(0.3f))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getTextHaloBlur());
- assertNotNull(layer.getTextHaloBlur().getFunction());
- assertEquals(SourceFunction.class, layer.getTextHaloBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloBlur().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextHaloBlur().getFunction().getStops().getClass());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextHaloBlur());
+ assertNotNull(layer.getTextHaloBlur().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextHaloBlur().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloBlur().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getTextHaloBlur().getFunction().getStops().getClass());
});
}
@@ -5055,33 +4555,30 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-halo-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textHaloBlur(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, textHaloBlur(0.3f))
- )
- ).withDefaultValue(textHaloBlur(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextHaloBlur());
- assertNotNull(layer.getTextHaloBlur().getFunction());
- assertEquals(SourceFunction.class, layer.getTextHaloBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloBlur().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getTextHaloBlur().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getTextHaloBlur().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getTextHaloBlur().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getTextHaloBlur().getFunction()).getDefaultValue().getValue());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textHaloBlur(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, textHaloBlur(0.3f))
+ )
+ ).withDefaultValue(textHaloBlur(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextHaloBlur());
+ assertNotNull(layer.getTextHaloBlur().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextHaloBlur().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloBlur().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getTextHaloBlur().getFunction().getStops().getClass());
+ assertNotNull(((SourceFunction) layer.getTextHaloBlur().getFunction()).getDefaultValue());
+ assertNotNull(((SourceFunction) layer.getTextHaloBlur().getFunction()).getDefaultValue().getValue());
+ assertEquals(0.3f, ((SourceFunction) layer.getTextHaloBlur().getFunction()).getDefaultValue().getValue());
});
}
@@ -5091,38 +4588,35 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-halo-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textHaloBlur(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, textHaloBlur(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(textHaloBlur(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextHaloBlur());
- assertNotNull(layer.getTextHaloBlur().getFunction());
- assertEquals(CompositeFunction.class, layer.getTextHaloBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getTextHaloBlur().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextHaloBlur().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getTextHaloBlur().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getTextHaloBlur().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textHaloBlur(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, textHaloBlur(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(textHaloBlur(0.3f))
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextHaloBlur());
+ assertNotNull(layer.getTextHaloBlur().getFunction());
+ assertEquals(CompositeFunction.class, layer.getTextHaloBlur().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getTextHaloBlur().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getTextHaloBlur().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getTextHaloBlur().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getTextHaloBlur().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
});
}
@@ -5131,16 +4625,13 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-translateTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setTextTranslateTransition(options);
- assertEquals(layer.getTextTranslateTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setTextTranslateTransition(options);
+ assertEquals(layer.getTextTranslateTransition(), options);
});
}
@@ -5149,15 +4640,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-translate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textTranslate(new Float[] {0f, 0f}));
- assertEquals((Float[]) layer.getTextTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textTranslate(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getTextTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
});
}
@@ -5166,30 +4654,27 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-translate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textTranslate(
- zoom(
- exponential(
- stop(2, textTranslate(new Float[] {0f, 0f}))
- ).withBase(0.5f)
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textTranslate(
+ zoom(
+ exponential(
+ stop(2, textTranslate(new Float[] {0f, 0f}))
+ ).withBase(0.5f)
)
- );
-
- // Verify
- assertNotNull(layer.getTextTranslate());
- assertNotNull(layer.getTextTranslate().getFunction());
- assertEquals(CameraFunction.class, layer.getTextTranslate().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getTextTranslate().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getTextTranslate().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getTextTranslate().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextTranslate());
+ assertNotNull(layer.getTextTranslate().getFunction());
+ assertEquals(CameraFunction.class, layer.getTextTranslate().getFunction().getClass());
+ assertEquals(ExponentialStops.class, layer.getTextTranslate().getFunction().getStops().getClass());
+ assertEquals(0.5f, ((ExponentialStops) layer.getTextTranslate().getFunction().getStops()).getBase(), 0.001);
+ assertEquals(1, ((ExponentialStops) layer.getTextTranslate().getFunction().getStops()).size());
});
}
@@ -5198,15 +4683,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-translate-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textTranslateAnchor(TEXT_TRANSLATE_ANCHOR_MAP));
- assertEquals((String) layer.getTextTranslateAnchor().getValue(), (String) TEXT_TRANSLATE_ANCHOR_MAP);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textTranslateAnchor(TEXT_TRANSLATE_ANCHOR_MAP));
+ assertEquals((String) layer.getTextTranslateAnchor().getValue(), (String) TEXT_TRANSLATE_ANCHOR_MAP);
});
}
@@ -5215,29 +4697,26 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-translate-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textTranslateAnchor(
- zoom(
- interval(
- stop(2, textTranslateAnchor(TEXT_TRANSLATE_ANCHOR_MAP))
- )
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textTranslateAnchor(
+ zoom(
+ interval(
+ stop(2, textTranslateAnchor(TEXT_TRANSLATE_ANCHOR_MAP))
)
)
- );
-
- // Verify
- assertNotNull(layer.getTextTranslateAnchor());
- assertNotNull(layer.getTextTranslateAnchor().getFunction());
- assertEquals(CameraFunction.class, layer.getTextTranslateAnchor().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getTextTranslateAnchor().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getTextTranslateAnchor().getFunction().getStops()).size());
- }
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextTranslateAnchor());
+ assertNotNull(layer.getTextTranslateAnchor().getFunction());
+ assertEquals(CameraFunction.class, layer.getTextTranslateAnchor().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getTextTranslateAnchor().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getTextTranslateAnchor().getFunction().getStops()).size());
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
index 6f311788ba..003fc1df6c 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
@@ -598,7 +598,17 @@
android:name="android.support.PARENT_ACTIVITY"
android:value=".activity.FeatureOverviewActivity"/>
</activity>
-
+ <activity
+ android:name=".activity.style.GridSourceActivity"
+ android:description="@string/description_grid_source"
+ android:label="@string/activity_grid_source">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_style"/>
+ <meta-data
+ android:name="android.support.PARENT_ACTIVITY"
+ android:value=".activity.FeatureOverviewActivity"/>
+ </activity>
<!-- Features -->
<activity
android:name=".activity.feature.QueryRenderedFeaturesPropertiesActivity"
@@ -796,4 +806,4 @@
<!-- android:value="true" /> -->
</application>
-</manifest> \ No newline at end of file
+</manifest>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/FeatureOverviewActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/FeatureOverviewActivity.java
index 3f20f19f5d..95cc9687f2 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/FeatureOverviewActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/FeatureOverviewActivity.java
@@ -16,7 +16,6 @@ import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
-import android.view.View;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.adapter.FeatureAdapter;
@@ -62,19 +61,16 @@ public class FeatureOverviewActivity extends AppCompatActivity implements Permis
recyclerView.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener());
recyclerView.setHasFixedSize(true);
- ItemClickSupport.addTo(recyclerView).setOnItemClickListener(new ItemClickSupport.OnItemClickListener() {
- @Override
- public void onItemClicked(RecyclerView recyclerView, int position, View view) {
- if (!sectionAdapter.isSectionHeaderPosition(position)) {
- int itemPosition = sectionAdapter.getConvertedPosition(position);
- Feature feature = features.get(itemPosition);
- if (feature.isRequiresLocationPermission()) {
- if (requestLocationPermission(itemPosition)) {
- return;
- }
+ ItemClickSupport.addTo(recyclerView).setOnItemClickListener((recyclerView, position, view) -> {
+ if (!sectionAdapter.isSectionHeaderPosition(position)) {
+ int itemPosition = sectionAdapter.getConvertedPosition(position);
+ Feature feature = features.get(itemPosition);
+ if (feature.isRequiresLocationPermission()) {
+ if (requestLocationPermission(itemPosition)) {
+ return;
}
- startFeature(feature);
}
+ startFeature(feature);
}
});
@@ -188,15 +184,12 @@ public class FeatureOverviewActivity extends AppCompatActivity implements Permis
}
if (!features.isEmpty()) {
- Comparator<Feature> comparator = new Comparator<Feature>() {
- @Override
- public int compare(Feature lhs, Feature rhs) {
- int result = lhs.getCategory().compareToIgnoreCase(rhs.getCategory());
- if (result == 0) {
- result = lhs.getLabel().compareToIgnoreCase(rhs.getLabel());
- }
- return result;
+ Comparator<Feature> comparator = (lhs, rhs) -> {
+ int result = lhs.getCategory().compareToIgnoreCase(rhs.getCategory());
+ if (result == 0) {
+ result = lhs.getLabel().compareToIgnoreCase(rhs.getLabel());
}
+ return result;
};
Collections.sort(features, comparator);
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AnimatedMarkerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AnimatedMarkerActivity.java
index d8752bbea2..a557bb4ed4 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AnimatedMarkerActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AnimatedMarkerActivity.java
@@ -7,7 +7,6 @@ import android.animation.TypeEvaluator;
import android.animation.ValueAnimator;
import android.os.Bundle;
import android.support.annotation.DrawableRes;
-import android.support.annotation.NonNull;
import android.support.v4.content.res.ResourcesCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
@@ -24,7 +23,6 @@ import com.mapbox.mapboxsdk.geometry.LatLng;
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.testapp.R;
import com.mapbox.mapboxsdk.testapp.utils.IconUtils;
import com.mapbox.services.api.utils.turf.TurfMeasurement;
@@ -59,25 +57,18 @@ public class AnimatedMarkerActivity extends AppCompatActivity {
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
+ mapView.getMapAsync(mapboxMap -> {
+ AnimatedMarkerActivity.this.mapboxMap = mapboxMap;
+ setupMap();
- @Override
- public void onMapReady(@NonNull final MapboxMap mapboxMap) {
- AnimatedMarkerActivity.this.mapboxMap = mapboxMap;
- setupMap();
-
- animationRunnable = new Runnable() {
- @Override
- public void run() {
- for (int i = 0; i < 10; i++) {
- addRandomCar();
- }
- addPassenger();
- addMainCar();
- }
- };
- mapView.post(animationRunnable);
- }
+ animationRunnable = () -> {
+ for (int i = 0; i < 10; i++) {
+ addRandomCar();
+ }
+ addPassenger();
+ addMainCar();
+ };
+ mapView.post(animationRunnable);
});
}
@@ -116,13 +107,10 @@ public class AnimatedMarkerActivity extends AppCompatActivity {
if (carMarker == null) {
carMarker = createCarMarker(randomLatLng, R.drawable.ic_taxi_top,
- new MarkerViewManager.OnMarkerViewAddedListener() {
- @Override
- public void onViewAdded(@NonNull MarkerView markerView) {
- // Make sure the car marker is selected so that it's always brought to the front (#5285)
- mapboxMap.selectMarker(carMarker);
- animateMoveToPassenger(carMarker);
- }
+ markerView -> {
+ // Make sure the car marker is selected so that it's always brought to the front (#5285)
+ mapboxMap.selectMarker(carMarker);
+ animateMoveToPassenger(carMarker);
});
markerViews.add(carMarker);
} else {
@@ -147,12 +135,7 @@ public class AnimatedMarkerActivity extends AppCompatActivity {
protected void addRandomCar() {
markerViews.add(createCarMarker(getLatLngInBounds(), R.drawable.ic_car_top,
- new MarkerViewManager.OnMarkerViewAddedListener() {
- @Override
- public void onViewAdded(@NonNull MarkerView markerView) {
- randomlyMoveMarker(markerView);
- }
- }));
+ markerView -> randomlyMoveMarker(markerView)));
}
private void randomlyMoveMarker(final MarkerView marker) {
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.java
index 666fd2eee6..afeb3b8979 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.java
@@ -5,7 +5,6 @@ import android.animation.AnimatorListenerAdapter;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
-import android.support.annotation.NonNull;
import android.support.v4.content.res.ResourcesCompat;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.AppCompatActivity;
@@ -17,30 +16,25 @@ import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
-
import com.mapbox.mapboxsdk.annotations.Icon;
-import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
import com.mapbox.mapboxsdk.annotations.MarkerViewOptions;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.utils.GeoParseUtil;
import com.mapbox.mapboxsdk.testapp.utils.IconUtils;
-
-import org.json.JSONException;
+import timber.log.Timber;
import java.io.IOException;
+import java.lang.ref.WeakReference;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Random;
-import timber.log.Timber;
-
/**
* Test activity showcasing adding a large amount of Markers or MarkerViews.
*/
@@ -50,6 +44,7 @@ public class BulkMarkerActivity extends AppCompatActivity implements AdapterView
private MapView mapView;
private boolean customMarkerView;
private List<LatLng> locations;
+ private ProgressDialog progressDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -58,12 +53,7 @@ public class BulkMarkerActivity extends AppCompatActivity implements AdapterView
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull MapboxMap mapboxMap) {
- BulkMarkerActivity.this.mapboxMap = mapboxMap;
- }
- });
+ mapView.getMapAsync(mapboxMap -> BulkMarkerActivity.this.mapboxMap = mapboxMap);
final View fab = findViewById(R.id.fab);
if (fab != null) {
@@ -88,6 +78,7 @@ public class BulkMarkerActivity extends AppCompatActivity implements AdapterView
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
int amount = Integer.valueOf(getResources().getStringArray(R.array.bulk_marker_list)[position]);
if (locations == null) {
+ progressDialog = ProgressDialog.show(this, "Loading", "Fetching markers", false);
new LoadLocationTask(this, amount).execute();
} else {
showMarkers(amount);
@@ -95,6 +86,7 @@ public class BulkMarkerActivity extends AppCompatActivity implements AdapterView
}
private void onLatLngListLoaded(List<LatLng> latLngs, int amount) {
+ progressDialog.hide();
locations = latLngs;
showMarkers(amount);
}
@@ -232,29 +224,22 @@ public class BulkMarkerActivity extends AppCompatActivity implements AdapterView
viewCountView = (TextView) findViewById(R.id.countView);
- mapView.addOnMapChangedListener(new MapView.OnMapChangedListener() {
- @Override
- public void onMapChanged(@MapView.MapChange int change) {
- if (change == MapView.REGION_IS_CHANGING || change == MapView.REGION_DID_CHANGE) {
- if (!mapboxMap.getMarkerViewManager().getMarkerViewAdapters().isEmpty()) {
- viewCountView.setText(String.format(Locale.getDefault(), "ViewCache size %d",
- mapboxMap.getMarkerViewManager().getMarkerViewContainer().getChildCount()));
- }
+ mapView.addOnMapChangedListener(change -> {
+ if (change == MapView.REGION_IS_CHANGING || change == MapView.REGION_DID_CHANGE) {
+ if (!mapboxMap.getMarkerViewManager().getMarkerViewAdapters().isEmpty()) {
+ viewCountView.setText(String.format(Locale.getDefault(), "ViewCache size %d",
+ mapboxMap.getMarkerViewManager().getMarkerViewContainer().getChildCount()));
}
}
});
mapboxMap.getMarkerViewManager().setOnMarkerViewClickListener(
- new MapboxMap.OnMarkerViewClickListener() {
- @Override
- public boolean onMarkerClick(
- @NonNull Marker marker, @NonNull View view, @NonNull MapboxMap.MarkerViewAdapter adapter) {
- Toast.makeText(
- BulkMarkerActivity.this,
- "Hello " + marker.getId(),
- Toast.LENGTH_SHORT).show();
- return false;
- }
+ (marker, view1, adapter) -> {
+ Toast.makeText(
+ BulkMarkerActivity.this,
+ "Hello " + marker.getId(),
+ Toast.LENGTH_SHORT).show();
+ return false;
});
}
}
@@ -262,32 +247,39 @@ public class BulkMarkerActivity extends AppCompatActivity implements AdapterView
private static class LoadLocationTask extends AsyncTask<Void, Integer, List<LatLng>> {
- private BulkMarkerActivity activity;
- private ProgressDialog progressDialog;
+ private WeakReference<BulkMarkerActivity> activity;
private int amount;
private LoadLocationTask(BulkMarkerActivity activity, int amount) {
this.amount = amount;
- this.activity = activity;
- progressDialog = ProgressDialog.show(activity, "Loading", "Fetching markers", false);
+ this.activity = new WeakReference<>(activity);
}
@Override
protected List<LatLng> doInBackground(Void... params) {
- try {
- String json = GeoParseUtil.loadStringFromAssets(activity.getApplicationContext(), "points.geojson");
- return GeoParseUtil.parseGeoJsonCoordinates(json);
- } catch (IOException | JSONException exception) {
- Timber.e(exception, "Could not add markers");
- return null;
+ BulkMarkerActivity activity = this.activity.get();
+ if (activity != null) {
+ String json = null;
+ try {
+ json = GeoParseUtil.loadStringFromAssets(activity.getApplicationContext(), "points.geojson");
+ } catch (IOException exception) {
+ Timber.e(exception, "Could not add markers");
+ }
+
+ if (json != null) {
+ return GeoParseUtil.parseGeoJsonCoordinates(json);
+ }
}
+ return null;
}
@Override
protected void onPostExecute(List<LatLng> locations) {
super.onPostExecute(locations);
- activity.onLatLngListLoaded(locations, amount);
- progressDialog.hide();
+ BulkMarkerActivity activity = this.activity.get();
+ if (activity != null) {
+ activity.onLatLngListLoaded(locations, amount);
+ }
}
}
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/DynamicMarkerChangeActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/DynamicMarkerChangeActivity.java
index f7ffc61a7d..1fe0340a55 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/DynamicMarkerChangeActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/DynamicMarkerChangeActivity.java
@@ -1,19 +1,16 @@
package com.mapbox.mapboxsdk.testapp.activity.annotation;
import android.os.Bundle;
-import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.res.ResourcesCompat;
import android.support.v7.app.AppCompatActivity;
-import android.view.View;
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.utils.IconUtils;
@@ -37,29 +34,23 @@ public class DynamicMarkerChangeActivity extends AppCompatActivity {
mapView = (MapView) findViewById(R.id.mapView);
mapView.setTag(false);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull MapboxMap mapboxMap) {
- DynamicMarkerChangeActivity.this.mapboxMap = mapboxMap;
- // Create marker
- MarkerOptions markerOptions = new MarkerOptions()
- .position(LAT_LNG_CHELSEA)
- .icon(IconUtils.drawableToIcon(DynamicMarkerChangeActivity.this, R.drawable.ic_stars,
- ResourcesCompat.getColor(getResources(), R.color.blueAccent, getTheme())))
- .title(getString(R.string.dynamic_marker_chelsea_title))
- .snippet(getString(R.string.dynamic_marker_chelsea_snippet));
- marker = mapboxMap.addMarker(markerOptions);
- }
+ mapView.getMapAsync(mapboxMap -> {
+ DynamicMarkerChangeActivity.this.mapboxMap = mapboxMap;
+ // Create marker
+ MarkerOptions markerOptions = new MarkerOptions()
+ .position(LAT_LNG_CHELSEA)
+ .icon(IconUtils.drawableToIcon(DynamicMarkerChangeActivity.this, R.drawable.ic_stars,
+ ResourcesCompat.getColor(getResources(), R.color.blueAccent, getTheme())))
+ .title(getString(R.string.dynamic_marker_chelsea_title))
+ .snippet(getString(R.string.dynamic_marker_chelsea_snippet));
+ marker = mapboxMap.addMarker(markerOptions);
});
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setColorFilter(ContextCompat.getColor(this, R.color.primary));
- fab.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (mapboxMap != null) {
- updateMarker();
- }
+ fab.setOnClickListener(view -> {
+ if (mapboxMap != null) {
+ updateMarker();
}
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewActivity.java
index 61ece0a94f..8c0dd69a0c 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewActivity.java
@@ -29,7 +29,6 @@ import com.mapbox.mapboxsdk.annotations.MarkerViewOptions;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.model.annotations.CountryMarkerView;
import com.mapbox.mapboxsdk.testapp.model.annotations.CountryMarkerViewOptions;
@@ -81,127 +80,117 @@ public class MarkerViewActivity extends AppCompatActivity {
final TextView viewCountView = (TextView) findViewById(R.id.countView);
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull MapboxMap mapboxMap) {
- MarkerViewActivity.this.mapboxMap = mapboxMap;
-
- final MarkerViewManager markerViewManager = mapboxMap.getMarkerViewManager();
-
- Icon usFlag = IconFactory.getInstance(MarkerViewActivity.this)
- .fromResource(R.drawable.ic_us);
-
- // add default ViewMarker markers
- for (int i = 0; i < LAT_LNGS.length; i++) {
- MarkerViewActivity.this.mapboxMap.addMarker(new MarkerViewOptions()
- .position(LAT_LNGS[i])
- .title(String.valueOf(i))
- .alpha(0.5f)
- .icon(usFlag)
- );
- }
-
- // add custom ViewMarker
- CountryMarkerViewOptions options = new CountryMarkerViewOptions();
- options.flagRes(R.drawable.icon_burned);
- options.abbrevName("Mapbox");
- options.title("Hello");
- options.position(new LatLng(38.899774, -77.023237));
- options.flat(true);
- MarkerView markerView = mapboxMap.addMarker(options);
-
- // Use object animator to rotate MarkerView
- ValueAnimator markerAnimator = ObjectAnimator.ofObject(markerView, "rotation", new FloatEvaluator(), -90, 90);
- markerAnimator.setDuration(5000);
- markerAnimator.start();
-
- MarkerViewActivity.this.mapboxMap.addMarker(new MarkerOptions()
- .title("United States")
- .position(new LatLng(38.902580, -77.050102))
- );
-
- rotateMarker = MarkerViewActivity.this.mapboxMap.addMarker(new TextMarkerViewOptions()
- .text("A")
- .rotation(rotation = 270)
- .position(new LatLng(38.889876, -77.008849))
- );
- loopMarkerRotate();
+ mapView.getMapAsync(mapboxMap -> {
+ MarkerViewActivity.this.mapboxMap = mapboxMap;
+ final MarkerViewManager markerViewManager = mapboxMap.getMarkerViewManager();
- MarkerViewActivity.this.mapboxMap.addMarker(new TextMarkerViewOptions()
- .text("B")
- .position(new LatLng(38.907327, -77.041293))
- );
+ Icon usFlag = IconFactory.getInstance(MarkerViewActivity.this)
+ .fromResource(R.drawable.ic_us);
- MarkerViewActivity.this.mapboxMap.addMarker(new TextMarkerViewOptions()
- .text("C")
- .position(new LatLng(38.897642, -77.041980))
- );
-
- // if you want to customise a ViewMarker you need to extend ViewMarker and provide an adapter implementation
- // set adapters for child classes of ViewMarker
- markerViewManager.addMarkerViewAdapter(new CountryAdapter(MarkerViewActivity.this, mapboxMap));
- markerViewManager.addMarkerViewAdapter(new TextAdapter(MarkerViewActivity.this, mapboxMap));
-
- final ViewGroup markerViewContainer = markerViewManager.getMarkerViewContainer();
-
- // add a change listener to validate the size of amount of child views
- mapView.addOnMapChangedListener(new MapView.OnMapChangedListener() {
- @Override
- public void onMapChanged(@MapView.MapChange int change) {
- if (change == MapView.REGION_IS_CHANGING || change == MapView.REGION_DID_CHANGE) {
- if (!markerViewManager.getMarkerViewAdapters().isEmpty() && viewCountView != null) {
- viewCountView.setText(String.format(
- Locale.getDefault(),
- getString(R.string.viewcache_size),
- markerViewContainer.getChildCount())
- );
- }
- }
- }
- });
-
- // add a OnMarkerView click listener
- MarkerViewActivity.this.mapboxMap.getMarkerViewManager().setOnMarkerViewClickListener(
- new MapboxMap.OnMarkerViewClickListener() {
- @Override
- public boolean onMarkerClick(@NonNull Marker marker, @NonNull View view,
- @NonNull MapboxMap.MarkerViewAdapter adapter) {
- Toast.makeText(MarkerViewActivity.this, "Hello " + marker.getId(), Toast.LENGTH_SHORT).show();
- return false;
- }
- });
-
- movingMarkerOne = MarkerViewActivity.this.mapboxMap.addMarker(new MarkerViewOptions()
- .position(CarLocation.CAR_0_LNGS[0])
- .icon(IconFactory.getInstance(mapView.getContext())
- .fromResource(R.drawable.ic_android))
+ // add default ViewMarker markers
+ for (int i = 0; i < LAT_LNGS.length; i++) {
+ MarkerViewActivity.this.mapboxMap.addMarker(new MarkerViewOptions()
+ .position(LAT_LNGS[i])
+ .title(String.valueOf(i))
+ .alpha(0.5f)
+ .icon(usFlag)
);
+ }
- movingMarkerTwo = mapboxMap.addMarker(new MarkerViewOptions()
- .position(CarLocation.CAR_1_LNGS[0])
- .icon(IconFactory.getInstance(mapView.getContext())
- .fromResource(R.drawable.ic_android_2))
- );
+ // add custom ViewMarker
+ CountryMarkerViewOptions options = new CountryMarkerViewOptions();
+ options.flagRes(R.drawable.icon_burned);
+ options.abbrevName("Mapbox");
+ options.title("Hello");
+ options.position(new LatLng(38.899774, -77.023237));
+ options.flat(true);
+ MarkerView markerView = mapboxMap.addMarker(options);
+
+ // Use object animator to rotate MarkerView
+ ValueAnimator markerAnimator = ObjectAnimator.ofObject(markerView, "rotation", new FloatEvaluator(), -90, 90);
+ markerAnimator.setDuration(5000);
+ markerAnimator.start();
+
+ MarkerViewActivity.this.mapboxMap.addMarker(new MarkerOptions()
+ .title("United States")
+ .position(new LatLng(38.902580, -77.050102))
+ );
+
+ rotateMarker = MarkerViewActivity.this.mapboxMap.addMarker(new TextMarkerViewOptions()
+ .text("A")
+ .rotation(rotation = 270)
+ .position(new LatLng(38.889876, -77.008849))
+ );
+ loopMarkerRotate();
- // allow more open infowindows at the same time
- mapboxMap.setAllowConcurrentMultipleOpenInfoWindows(true);
- // add offscreen markers
- Marker markerRightOffScreen = mapboxMap.addMarker(new MarkerOptions()
- .setPosition(new LatLng(38.892846, -76.909399))
- .title("InfoWindow")
- .snippet("Offscreen, to the right of the Map."));
+ MarkerViewActivity.this.mapboxMap.addMarker(new TextMarkerViewOptions()
+ .text("B")
+ .position(new LatLng(38.907327, -77.041293))
+ );
+
+ MarkerViewActivity.this.mapboxMap.addMarker(new TextMarkerViewOptions()
+ .text("C")
+ .position(new LatLng(38.897642, -77.041980))
+ );
+
+ // if you want to customise a ViewMarker you need to extend ViewMarker and provide an adapter implementation
+ // set adapters for child classes of ViewMarker
+ markerViewManager.addMarkerViewAdapter(new CountryAdapter(MarkerViewActivity.this, mapboxMap));
+ markerViewManager.addMarkerViewAdapter(new TextAdapter(MarkerViewActivity.this, mapboxMap));
+
+ final ViewGroup markerViewContainer = markerViewManager.getMarkerViewContainer();
+
+ // add a change listener to validate the size of amount of child views
+ mapView.addOnMapChangedListener(change -> {
+ if (change == MapView.REGION_IS_CHANGING || change == MapView.REGION_DID_CHANGE) {
+ if (!markerViewManager.getMarkerViewAdapters().isEmpty() && viewCountView != null) {
+ viewCountView.setText(String.format(
+ Locale.getDefault(),
+ getString(R.string.viewcache_size),
+ markerViewContainer.getChildCount())
+ );
+ }
+ }
+ });
- Marker markerRightBottomOffScreen = mapboxMap.addMarker(new MarkerOptions()
- .setPosition(new LatLng(38.791645, -77.039006))
- .title("InfoWindow")
- .snippet("Offscreen, to the bottom of the Map"));
+ // add a OnMarkerView click listener
+ MarkerViewActivity.this.mapboxMap.getMarkerViewManager().setOnMarkerViewClickListener(
+ (marker, view, adapter) -> {
+ Toast.makeText(MarkerViewActivity.this, "Hello " + marker.getId(), Toast.LENGTH_SHORT).show();
+ return false;
+ });
- // open infowindow offscreen markers
- mapboxMap.selectMarker(markerRightOffScreen);
- mapboxMap.selectMarker(markerRightBottomOffScreen);
- }
+ movingMarkerOne = MarkerViewActivity.this.mapboxMap.addMarker(new MarkerViewOptions()
+ .position(CarLocation.CAR_0_LNGS[0])
+ .icon(IconFactory.getInstance(mapView.getContext())
+ .fromResource(R.drawable.ic_android))
+ );
+
+ movingMarkerTwo = mapboxMap.addMarker(new MarkerViewOptions()
+ .position(CarLocation.CAR_1_LNGS[0])
+ .icon(IconFactory.getInstance(mapView.getContext())
+ .fromResource(R.drawable.ic_android_2))
+ );
+
+ // allow more open infowindows at the same time
+ mapboxMap.setAllowConcurrentMultipleOpenInfoWindows(true);
+
+ // add offscreen markers
+ Marker markerRightOffScreen = mapboxMap.addMarker(new MarkerOptions()
+ .setPosition(new LatLng(38.892846, -76.909399))
+ .title("InfoWindow")
+ .snippet("Offscreen, to the right of the Map."));
+
+ Marker markerRightBottomOffScreen = mapboxMap.addMarker(new MarkerOptions()
+ .setPosition(new LatLng(38.791645, -77.039006))
+ .title("InfoWindow")
+ .snippet("Offscreen, to the bottom of the Map"));
+
+ // open infowindow offscreen markers
+ mapboxMap.selectMarker(markerRightOffScreen);
+ mapboxMap.selectMarker(markerRightBottomOffScreen);
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolygonActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolygonActivity.java
index 49c9663672..93f2e9c98f 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolygonActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolygonActivity.java
@@ -2,7 +2,6 @@ package com.mapbox.mapboxsdk.testapp.activity.annotation;
import android.graphics.Color;
import android.os.Bundle;
-import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
@@ -78,16 +77,11 @@ public class PolygonActivity extends AppCompatActivity implements OnMapReadyCall
public void onMapReady(MapboxMap map) {
mapboxMap = map;
- map.setOnPolygonClickListener(new MapboxMap.OnPolygonClickListener() {
- @Override
- public void onPolygonClick(@NonNull Polygon polygon) {
- Toast.makeText(
- PolygonActivity.this,
- "You clicked on polygon with id = " + polygon.getId(),
- Toast.LENGTH_SHORT
- ).show();
- }
- });
+ map.setOnPolygonClickListener(polygon -> Toast.makeText(
+ PolygonActivity.this,
+ "You clicked on polygon with id = " + polygon.getId(),
+ Toast.LENGTH_SHORT
+ ).show());
polygon = mapboxMap.addPolygon(new PolygonOptions()
.addAll(STAR_SHAPE_POINTS)
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolylineActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolylineActivity.java
index b9dc39e5d4..fbf439448f 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolylineActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolylineActivity.java
@@ -2,7 +2,6 @@ package com.mapbox.mapboxsdk.testapp.activity.annotation;
import android.graphics.Color;
import android.os.Bundle;
-import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
@@ -14,7 +13,6 @@ import com.mapbox.mapboxsdk.annotations.PolylineOptions;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.testapp.R;
import java.util.ArrayList;
@@ -65,46 +63,35 @@ public class PolylineActivity extends AppCompatActivity {
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull final MapboxMap mapboxMap) {
- PolylineActivity.this.mapboxMap = mapboxMap;
-
- mapboxMap.setOnPolylineClickListener(new MapboxMap.OnPolylineClickListener() {
- @Override
- public void onPolylineClick(@NonNull Polyline polyline) {
- Toast.makeText(
- PolylineActivity.this,
- "You clicked on polygon with id = " + polyline.getId(),
- Toast.LENGTH_SHORT
- ).show();
- }
- });
+ mapView.getMapAsync(mapboxMap -> {
+ PolylineActivity.this.mapboxMap = mapboxMap;
- polylines = mapboxMap.addPolylines(polylineOptions);
- }
+ mapboxMap.setOnPolylineClickListener(polyline -> Toast.makeText(
+ PolylineActivity.this,
+ "You clicked on polygon with id = " + polyline.getId(),
+ Toast.LENGTH_SHORT
+ ).show());
+
+ polylines = mapboxMap.addPolylines(polylineOptions);
});
View fab = findViewById(R.id.fab);
if (fab != null) {
- fab.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (mapboxMap != null) {
- if (polylines != null && polylines.size() > 0) {
- if (polylines.size() == 1) {
- // test for removing annotation
- mapboxMap.removeAnnotation(polylines.get(0));
- } else {
- // test for removing annotations
- mapboxMap.removeAnnotations(polylines);
- }
+ fab.setOnClickListener(view -> {
+ if (mapboxMap != null) {
+ if (polylines != null && polylines.size() > 0) {
+ if (polylines.size() == 1) {
+ // test for removing annotation
+ mapboxMap.removeAnnotation(polylines.get(0));
+ } else {
+ // test for removing annotations
+ mapboxMap.removeAnnotations(polylines);
}
- polylineOptions.clear();
- polylineOptions.addAll(getRandomLine());
- polylines = mapboxMap.addPolylines(polylineOptions);
-
}
+ polylineOptions.clear();
+ polylineOptions.addAll(getRandomLine());
+ polylines = mapboxMap.addPolylines(polylineOptions);
+
}
});
}
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 7cfe35f160..29c0ae0fca 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
@@ -2,7 +2,6 @@ package com.mapbox.mapboxsdk.testapp.activity.annotation;
import android.graphics.PointF;
import android.os.Bundle;
-import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
@@ -12,7 +11,6 @@ import com.mapbox.mapboxsdk.annotations.MarkerOptions;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.testapp.R;
import java.text.DecimalFormat;
@@ -41,30 +39,17 @@ public class PressForMarkerActivity extends AppCompatActivity {
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(final MapboxMap map) {
- mapboxMap = map;
- resetMap();
+ mapView.getMapAsync(map -> {
+ mapboxMap = map;
+ resetMap();
+
+ mapboxMap.setOnMapLongClickListener(point -> addMarker(point));
+
+ mapboxMap.setOnMapClickListener(point -> addMarker(point));
- mapboxMap.setOnMapLongClickListener(new MapboxMap.OnMapLongClickListener() {
- @Override
- public void onMapLongClick(@NonNull LatLng point) {
- addMarker(point);
- }
- });
-
- mapboxMap.setOnMapClickListener(new MapboxMap.OnMapClickListener() {
- @Override
- public void onMapClick(@NonNull LatLng point) {
- addMarker(point);
- }
- });
-
- if (savedInstanceState != null) {
- markerList = savedInstanceState.getParcelableArrayList(STATE_MARKER_LIST);
- mapboxMap.addMarkers(markerList);
- }
+ if (savedInstanceState != null) {
+ markerList = savedInstanceState.getParcelableArrayList(STATE_MARKER_LIST);
+ mapboxMap.addMarkers(markerList);
}
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimationTypeActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimationTypeActivity.java
index 030785565e..14997b768b 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimationTypeActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimationTypeActivity.java
@@ -47,102 +47,88 @@ public class CameraAnimationTypeActivity extends AppCompatActivity implements On
mapboxMap = map;
mapboxMap.getUiSettings().setAttributionEnabled(false);
mapboxMap.getUiSettings().setLogoEnabled(false);
- mapboxMap.setOnCameraChangeListener(new MapboxMap.OnCameraChangeListener() {
- @Override
- public void onCameraChange(CameraPosition position) {
- Timber.w(position.toString());
- }
- });
+ mapboxMap.setOnCameraChangeListener(position -> Timber.w(position.toString()));
// handle move button clicks
View moveButton = findViewById(R.id.cameraMoveButton);
if (moveButton != null) {
- moveButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- CameraPosition cameraPosition = new CameraPosition.Builder()
- .target(getNextLatLng())
- .zoom(14)
- .tilt(30)
- .tilt(0)
- .build();
- mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
- }
+ moveButton.setOnClickListener(view -> {
+ CameraPosition cameraPosition = new CameraPosition.Builder()
+ .target(getNextLatLng())
+ .zoom(14)
+ .tilt(30)
+ .tilt(0)
+ .build();
+ mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
});
}
// handle ease button clicks
View easeButton = findViewById(R.id.cameraEaseButton);
if (easeButton != null) {
- easeButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- CameraPosition cameraPosition = new CameraPosition.Builder()
- .target(getNextLatLng())
- .zoom(15)
- .bearing(180)
- .tilt(30)
- .build();
-
- MapboxMap.CancelableCallback callback = new MapboxMap.CancelableCallback() {
- @Override
- public void onCancel() {
- Timber.i("Duration onCancel Callback called.");
- Toast.makeText(
- CameraAnimationTypeActivity.this,
- "Ease onCancel Callback called.",
- Toast.LENGTH_LONG).show();
- }
-
- @Override
- public void onFinish() {
- Timber.i("Duration onFinish Callback called.");
- Toast.makeText(
- CameraAnimationTypeActivity.this,
- "Ease onFinish Callback called.",
- Toast.LENGTH_LONG).show();
- }
- };
-
- mapboxMap.easeCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), 7500, callback);
- }
+ easeButton.setOnClickListener(view -> {
+ CameraPosition cameraPosition = new CameraPosition.Builder()
+ .target(getNextLatLng())
+ .zoom(15)
+ .bearing(180)
+ .tilt(30)
+ .build();
+
+ MapboxMap.CancelableCallback callback = new MapboxMap.CancelableCallback() {
+ @Override
+ public void onCancel() {
+ Timber.i("Duration onCancel Callback called.");
+ Toast.makeText(
+ CameraAnimationTypeActivity.this,
+ "Ease onCancel Callback called.",
+ Toast.LENGTH_LONG).show();
+ }
+
+ @Override
+ public void onFinish() {
+ Timber.i("Duration onFinish Callback called.");
+ Toast.makeText(
+ CameraAnimationTypeActivity.this,
+ "Ease onFinish Callback called.",
+ Toast.LENGTH_LONG).show();
+ }
+ };
+
+ mapboxMap.easeCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), 7500, callback);
});
}
// handle animate button clicks
View animateButton = findViewById(R.id.cameraAnimateButton);
if (animateButton != null) {
- animateButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- CameraPosition cameraPosition = new CameraPosition.Builder()
- .target(getNextLatLng())
- .bearing(270)
- .tilt(20)
- .build();
-
- MapboxMap.CancelableCallback callback = new MapboxMap.CancelableCallback() {
- @Override
- public void onCancel() {
- Timber.i("Duration onCancel Callback called.");
- Toast.makeText(
- CameraAnimationTypeActivity.this,
- "Duration onCancel Callback called.",
- Toast.LENGTH_LONG).show();
- }
-
- @Override
- public void onFinish() {
- Timber.i("Duration onFinish Callback called.");
- Toast.makeText(
- CameraAnimationTypeActivity.this,
- "Duration onFinish Callback called.",
- Toast.LENGTH_LONG).show();
- }
- };
-
- mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), 7500, callback);
- }
+ animateButton.setOnClickListener(view -> {
+ CameraPosition cameraPosition = new CameraPosition.Builder()
+ .target(getNextLatLng())
+ .bearing(270)
+ .tilt(20)
+ .build();
+
+ MapboxMap.CancelableCallback callback = new MapboxMap.CancelableCallback() {
+ @Override
+ public void onCancel() {
+ Timber.i("Duration onCancel Callback called.");
+ Toast.makeText(
+ CameraAnimationTypeActivity.this,
+ "Duration onCancel Callback called.",
+ Toast.LENGTH_LONG).show();
+ }
+
+ @Override
+ public void onFinish() {
+ Timber.i("Duration onFinish Callback called.");
+ Toast.makeText(
+ CameraAnimationTypeActivity.this,
+ "Duration onFinish Callback called.",
+ Toast.LENGTH_LONG).show();
+ }
+ };
+
+ mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), 7500, callback);
});
}
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimatorActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimatorActivity.java
index c8c5c6bd37..f25fd6ab27 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimatorActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimatorActivity.java
@@ -35,44 +35,30 @@ public class CameraAnimatorActivity extends AppCompatActivity implements OnMapRe
private final LongSparseArray<AnimatorBuilder> animators = new LongSparseArray<AnimatorBuilder>() {
{
- put(R.id.menu_action_accelerate_decelerate_interpolator, new AnimatorBuilder() {
- @Override
- public Animator build() {
- AnimatorSet animatorSet = new AnimatorSet();
- animatorSet.playTogether(
- createLatLngAnimator(START_LAT_LNG, new LatLng(37.826715, -122.422795)),
- obtainExampleInterpolator(new FastOutSlowInInterpolator(), 2500)
- );
- return animatorSet;
- }
+ put(R.id.menu_action_accelerate_decelerate_interpolator, () -> {
+ AnimatorSet animatorSet = new AnimatorSet();
+ animatorSet.playTogether(
+ createLatLngAnimator(START_LAT_LNG, new LatLng(37.826715, -122.422795)),
+ obtainExampleInterpolator(new FastOutSlowInInterpolator(), 2500)
+ );
+ return animatorSet;
});
- put(R.id.menu_action_bounce_interpolator, new AnimatorBuilder() {
- @Override
- public Animator build() {
- AnimatorSet animatorSet = new AnimatorSet();
- animatorSet.playTogether(
- createLatLngAnimator(START_LAT_LNG, new LatLng(37.787947, -122.407432)),
- obtainExampleInterpolator(new BounceInterpolator(), 3750)
- );
- return animatorSet;
- }
+ put(R.id.menu_action_bounce_interpolator, () -> {
+ AnimatorSet animatorSet = new AnimatorSet();
+ animatorSet.playTogether(
+ createLatLngAnimator(START_LAT_LNG, new LatLng(37.787947, -122.407432)),
+ obtainExampleInterpolator(new BounceInterpolator(), 3750)
+ );
+ return animatorSet;
});
- put(R.id.menu_action_anticipate_overshoot_interpolator, new AnimatorBuilder() {
- @Override
- public Animator build() {
- return obtainExampleInterpolator(new AnticipateOvershootInterpolator(), 2500);
- }
- });
+ put(R.id.menu_action_anticipate_overshoot_interpolator, () ->
+ obtainExampleInterpolator(new AnticipateOvershootInterpolator(), 2500)
+ );
- put(R.id.menu_action_path_interpolator, new AnimatorBuilder() {
- @Override
- public Animator build() {
- return obtainExampleInterpolator(
- PathInterpolatorCompat.create(.22f, .68f, 0, 1.71f), 2500);
- }
- });
+ put(R.id.menu_action_path_interpolator, () -> obtainExampleInterpolator(
+ PathInterpolatorCompat.create(.22f, .68f, 0, 1.71f), 2500));
}
};
@@ -98,20 +84,17 @@ public class CameraAnimatorActivity extends AppCompatActivity implements OnMapRe
}
private void initFab() {
- findViewById(R.id.fab).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- view.setVisibility(View.GONE);
-
- CameraPosition animatedPosition = new CameraPosition.Builder()
- .target(new LatLng(37.789992, -122.402214))
- .tilt(60)
- .zoom(14.5f)
- .bearing(135)
- .build();
-
- createExampleAnimator(mapboxMap.getCameraPosition(), animatedPosition).start();
- }
+ findViewById(R.id.fab).setOnClickListener(view -> {
+ view.setVisibility(View.GONE);
+
+ CameraPosition animatedPosition = new CameraPosition.Builder()
+ .target(new LatLng(37.789992, -122.402214))
+ .tilt(60)
+ .zoom(14.5f)
+ .bearing(135)
+ .build();
+
+ createExampleAnimator(mapboxMap.getCameraPosition(), animatedPosition).start();
});
}
@@ -132,12 +115,7 @@ public class CameraAnimatorActivity extends AppCompatActivity implements OnMapRe
ValueAnimator latLngAnimator = ValueAnimator.ofObject(new LatLngEvaluator(), currentPosition, targetPosition);
latLngAnimator.setDuration((long) (1000 * ANIMATION_DELAY_FACTOR));
latLngAnimator.setInterpolator(new FastOutSlowInInterpolator());
- latLngAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- mapboxMap.setLatLng((LatLng) animation.getAnimatedValue());
- }
- });
+ latLngAnimator.addUpdateListener(animation -> mapboxMap.setLatLng((LatLng) animation.getAnimatedValue()));
return latLngAnimator;
}
@@ -146,12 +124,7 @@ public class CameraAnimatorActivity extends AppCompatActivity implements OnMapRe
zoomAnimator.setDuration((long) (2200 * ANIMATION_DELAY_FACTOR));
zoomAnimator.setStartDelay((long) (600 * ANIMATION_DELAY_FACTOR));
zoomAnimator.setInterpolator(new AnticipateOvershootInterpolator());
- zoomAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- mapboxMap.setZoom((Float) animation.getAnimatedValue());
- }
- });
+ zoomAnimator.addUpdateListener(animation -> mapboxMap.setZoom((Float) animation.getAnimatedValue()));
return zoomAnimator;
}
@@ -160,12 +133,7 @@ public class CameraAnimatorActivity extends AppCompatActivity implements OnMapRe
bearingAnimator.setDuration((long) (1000 * ANIMATION_DELAY_FACTOR));
bearingAnimator.setStartDelay((long) (1000 * ANIMATION_DELAY_FACTOR));
bearingAnimator.setInterpolator(new FastOutLinearInInterpolator());
- bearingAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- mapboxMap.setBearing((Float) animation.getAnimatedValue());
- }
- });
+ bearingAnimator.addUpdateListener(animation -> mapboxMap.setBearing((Float) animation.getAnimatedValue()));
return bearingAnimator;
}
@@ -173,12 +141,7 @@ public class CameraAnimatorActivity extends AppCompatActivity implements OnMapRe
ValueAnimator tiltAnimator = ValueAnimator.ofFloat((float) currentTilt, (float) targetTilt);
tiltAnimator.setDuration((long) (1000 * ANIMATION_DELAY_FACTOR));
tiltAnimator.setStartDelay((long) (1500 * ANIMATION_DELAY_FACTOR));
- tiltAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- mapboxMap.setTilt((Float) animation.getAnimatedValue());
- }
- });
+ tiltAnimator.addUpdateListener(animation -> mapboxMap.setTilt((Float) animation.getAnimatedValue()));
return tiltAnimator;
}
@@ -229,12 +192,7 @@ public class CameraAnimatorActivity extends AppCompatActivity implements OnMapRe
ValueAnimator zoomAnimator = ValueAnimator.ofFloat(11.0f, 16.0f);
zoomAnimator.setDuration((long) (duration * ANIMATION_DELAY_FACTOR));
zoomAnimator.setInterpolator(interpolator);
- zoomAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- mapboxMap.setZoom((Float) animation.getAnimatedValue());
- }
- });
+ zoomAnimator.addUpdateListener(animation -> mapboxMap.setZoom((Float) animation.getAnimatedValue()));
return zoomAnimator;
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraPositionActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraPositionActivity.java
index e5c6a3f584..42711a4379 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraPositionActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraPositionActivity.java
@@ -162,13 +162,7 @@ public class CameraPositionActivity extends AppCompatActivity implements OnMapRe
}
};
- private MapboxMap.OnCameraMoveCanceledListener moveCanceledListener = new MapboxMap.OnCameraMoveCanceledListener() {
- @Override
- public void onCameraMoveCanceled() {
- Timber.e("OnCameraMoveCanceled");
-
- }
- };
+ private MapboxMap.OnCameraMoveCanceledListener moveCanceledListener = () -> Timber.e("OnCameraMoveCanceled");
private MapboxMap.OnCameraMoveStartedListener moveStartedListener = new MapboxMap.OnCameraMoveStartedListener() {
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 e3a9551b8e..686f564c5c 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
@@ -12,7 +12,6 @@ import com.mapbox.mapboxsdk.geometry.LatLng;
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.testapp.R;
import com.mapbox.mapboxsdk.testapp.view.LockableBottomSheetBehavior;
@@ -55,12 +54,9 @@ public class LatLngBoundsActivity extends AppCompatActivity implements View.OnCl
setContentView(R.layout.activity_latlngbounds);
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(final MapboxMap map) {
- mapboxMap = map;
- initMap();
- }
+ mapView.getMapAsync(map -> {
+ mapboxMap = map;
+ initMap();
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/ManualZoomActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/ManualZoomActivity.java
index b999572436..716d0463a5 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/ManualZoomActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/ManualZoomActivity.java
@@ -2,7 +2,6 @@ package com.mapbox.mapboxsdk.testapp.activity.camera;
import android.graphics.Point;
import android.os.Bundle;
-import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
@@ -12,7 +11,6 @@ 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.maps.UiSettings;
import com.mapbox.mapboxsdk.testapp.R;
@@ -35,14 +33,11 @@ public class ManualZoomActivity extends AppCompatActivity {
mapView = (MapView) findViewById(R.id.mapView);
mapView.setStyleUrl(Style.SATELLITE);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull final MapboxMap mapboxMap) {
- ManualZoomActivity.this.mapboxMap = mapboxMap;
-
- UiSettings uiSettings = ManualZoomActivity.this.mapboxMap.getUiSettings();
- uiSettings.setAllGesturesEnabled(false);
- }
+ mapView.getMapAsync(mapboxMap -> {
+ ManualZoomActivity.this.mapboxMap = mapboxMap;
+
+ UiSettings uiSettings = ManualZoomActivity.this.mapboxMap.getUiSettings();
+ uiSettings.setAllGesturesEnabled(false);
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/MaxMinZoomActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/MaxMinZoomActivity.java
index 53a5800f26..277eadb1b5 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/MaxMinZoomActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/MaxMinZoomActivity.java
@@ -1,11 +1,9 @@
package com.mapbox.mapboxsdk.testapp.activity.camera;
import android.os.Bundle;
-import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
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.OnMapReadyCallback;
@@ -37,17 +35,7 @@ public class MaxMinZoomActivity extends AppCompatActivity implements OnMapReadyC
mapboxMap = map;
mapboxMap.setMinZoomPreference(3);
mapboxMap.setMaxZoomPreference(5);
- mapboxMap.setOnMapClickListener(new MapboxMap.OnMapClickListener() {
- @Override
- public void onMapClick(@NonNull LatLng point) {
- map.setStyle(Style.OUTDOORS, new MapboxMap.OnStyleLoadedListener() {
- @Override
- public void onStyleLoaded(String style) {
- Timber.d("Style Loaded %s", style);
- }
- });
- }
- });
+ mapboxMap.setOnMapClickListener(point -> map.setStyle(Style.OUTDOORS, style -> Timber.d("Style Loaded %s", style)));
}
@Override
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/ScrollByActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/ScrollByActivity.java
index 2e889f6e11..4906559935 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/ScrollByActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/ScrollByActivity.java
@@ -9,7 +9,6 @@ import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
-import android.view.View;
import android.widget.SeekBar;
import android.widget.TextView;
@@ -69,15 +68,10 @@ public class ScrollByActivity extends AppCompatActivity implements OnMapReadyCal
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setColorFilter(ContextCompat.getColor(ScrollByActivity.this, R.color.primary));
- fab.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- mapboxMap.easeCamera(CameraUpdateFactory.scrollBy(
- seekBarX.getProgress() * MULTIPLIER_PER_PIXEL,
- seekBarY.getProgress() * MULTIPLIER_PER_PIXEL)
- );
- }
- });
+ fab.setOnClickListener(view -> mapboxMap.easeCamera(CameraUpdateFactory.scrollBy(
+ seekBarX.getProgress() * MULTIPLIER_PER_PIXEL,
+ seekBarY.getProgress() * MULTIPLIER_PER_PIXEL)
+ ));
}
@Override
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/customlayer/CustomLayerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/customlayer/CustomLayerActivity.java
index 1b49e9e3d6..4cad7593ef 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/customlayer/CustomLayerActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/customlayer/CustomLayerActivity.java
@@ -6,13 +6,11 @@ import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
-import android.view.View;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.style.layers.CustomLayer;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.model.customlayer.ExampleCustomLayer;
@@ -38,23 +36,17 @@ public class CustomLayerActivity extends AppCompatActivity {
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(MapboxMap map) {
- mapboxMap = map;
- mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(39.91448, -243.60947), 10));
+ mapView.getMapAsync(map -> {
+ mapboxMap = map;
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(39.91448, -243.60947), 10));
- }
});
fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setColorFilter(ContextCompat.getColor(this, R.color.primary));
- fab.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (mapboxMap != null) {
- swapCustomLayer();
- }
+ fab.setOnClickListener(view -> {
+ if (mapboxMap != null) {
+ swapCustomLayer();
}
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxCountActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxCountActivity.java
index 20174daeaa..70d5b53428 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxCountActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxCountActivity.java
@@ -9,7 +9,6 @@ import android.widget.Toast;
import com.google.gson.JsonElement;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.services.commons.geojson.Feature;
@@ -36,32 +35,25 @@ public class QueryRenderedFeaturesBoxCountActivity extends AppCompatActivity {
// Initialize map as normal
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @SuppressWarnings("ConstantConditions")
- @Override
- public void onMapReady(final MapboxMap mapboxMap) {
- QueryRenderedFeaturesBoxCountActivity.this.mapboxMap = mapboxMap;
- selectionBox.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- // Query
- int top = selectionBox.getTop() - mapView.getTop();
- int left = selectionBox.getLeft() - mapView.getLeft();
- RectF box = new RectF(left, top, left + selectionBox.getWidth(), top + selectionBox.getHeight());
- Timber.i("Querying box %s", box);
- List<Feature> features = mapboxMap.queryRenderedFeatures(box);
-
- // Show count
- Toast.makeText(
- QueryRenderedFeaturesBoxCountActivity.this,
- String.format("%s features in box", features.size()),
- Toast.LENGTH_SHORT).show();
-
- // Debug output
- debugOutput(features);
- }
- });
- }
+ mapView.getMapAsync(mapboxMap -> {
+ QueryRenderedFeaturesBoxCountActivity.this.mapboxMap = mapboxMap;
+ selectionBox.setOnClickListener(view -> {
+ // Query
+ int top = selectionBox.getTop() - mapView.getTop();
+ int left = selectionBox.getLeft() - mapView.getLeft();
+ RectF box = new RectF(left, top, left + selectionBox.getWidth(), top + selectionBox.getHeight());
+ Timber.i("Querying box %s", box);
+ List<Feature> features = mapboxMap.queryRenderedFeatures(box);
+
+ // Show count
+ Toast.makeText(
+ QueryRenderedFeaturesBoxCountActivity.this,
+ String.format("%s features in box", features.size()),
+ Toast.LENGTH_SHORT).show();
+
+ // Debug output
+ debugOutput(features);
+ });
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxHighlightActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxHighlightActivity.java
index 480e48437a..8c9d056764 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxHighlightActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxHighlightActivity.java
@@ -9,7 +9,6 @@ import android.widget.Toast;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.style.layers.FillLayer;
import com.mapbox.mapboxsdk.style.layers.Filter;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
@@ -41,41 +40,34 @@ public class QueryRenderedFeaturesBoxHighlightActivity extends AppCompatActivity
// Initialize map as normal
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @SuppressWarnings("ConstantConditions")
- @Override
- public void onMapReady(final MapboxMap mapboxMap) {
- QueryRenderedFeaturesBoxHighlightActivity.this.mapboxMap = mapboxMap;
-
- // Add layer / source
- final GeoJsonSource source = new GeoJsonSource("highlighted-shapes-source");
- mapboxMap.addSource(source);
- mapboxMap.addLayer(
- new FillLayer("highlighted-shapes-layer", "highlighted-shapes-source")
- .withProperties(fillColor(Color.RED))
- );
-
- selectionBox.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- // Query
- int top = selectionBox.getTop() - mapView.getTop();
- int left = selectionBox.getLeft() - mapView.getLeft();
- RectF box = new RectF(left, top, left + selectionBox.getWidth(), top + selectionBox.getHeight());
- Timber.i("Querying box %s for buildings", box);
- List<Feature> features = mapboxMap.queryRenderedFeatures(box, Filter.lt("height", 10), "building");
-
- // Show count
- Toast.makeText(
- QueryRenderedFeaturesBoxHighlightActivity.this,
- String.format("%s features in box", features.size()),
- Toast.LENGTH_SHORT).show();
-
- // Update source data
- source.setGeoJson(FeatureCollection.fromFeatures(features));
- }
- });
- }
+ mapView.getMapAsync(mapboxMap -> {
+ QueryRenderedFeaturesBoxHighlightActivity.this.mapboxMap = mapboxMap;
+
+ // Add layer / source
+ final GeoJsonSource source = new GeoJsonSource("highlighted-shapes-source");
+ mapboxMap.addSource(source);
+ mapboxMap.addLayer(
+ new FillLayer("highlighted-shapes-layer", "highlighted-shapes-source")
+ .withProperties(fillColor(Color.RED))
+ );
+
+ selectionBox.setOnClickListener(view -> {
+ // Query
+ int top = selectionBox.getTop() - mapView.getTop();
+ int left = selectionBox.getLeft() - mapView.getLeft();
+ RectF box = new RectF(left, top, left + selectionBox.getWidth(), top + selectionBox.getHeight());
+ Timber.i("Querying box %s for buildings", box);
+ List<Feature> features = mapboxMap.queryRenderedFeatures(box, Filter.lt("height", 10), "building");
+
+ // Show count
+ Toast.makeText(
+ QueryRenderedFeaturesBoxHighlightActivity.this,
+ String.format("%s features in box", features.size()),
+ Toast.LENGTH_SHORT).show();
+
+ // Update source data
+ source.setGeoJson(FeatureCollection.fromFeatures(features));
+ });
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxSymbolCountActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxSymbolCountActivity.java
index 220137d07d..9bad5f3e62 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxSymbolCountActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxSymbolCountActivity.java
@@ -9,7 +9,6 @@ import android.widget.Toast;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
import com.mapbox.mapboxsdk.testapp.R;
@@ -43,49 +42,42 @@ public class QueryRenderedFeaturesBoxSymbolCountActivity extends AppCompatActivi
// Initialize map as normal
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @SuppressWarnings("ConstantConditions")
- @Override
- public void onMapReady(final MapboxMap mapboxMap) {
- QueryRenderedFeaturesBoxSymbolCountActivity.this.mapboxMap = mapboxMap;
-
- // Add a symbol layer (also works with annotations)
- try {
- mapboxMap.addSource(new GeoJsonSource("symbols-source", ResourceUtils.readRawResource(
- QueryRenderedFeaturesBoxSymbolCountActivity.this, R.raw.test_points_utrecht)));
- } catch (IOException ioException) {
- Timber.e(ioException, "Could not load geojson");
- return;
- }
- mapboxMap.addImage(
- "test-icon",
- BitmapFactory.decodeResource(getResources(),
- R.drawable.mapbox_marker_icon_default)
- );
- mapboxMap.addLayer(new SymbolLayer("symbols-layer", "symbols-source").withProperties(iconImage("test-icon")));
-
- selectionBox.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- // Query
- int top = selectionBox.getTop() - mapView.getTop();
- int left = selectionBox.getLeft() - mapView.getLeft();
- RectF box = new RectF(left, top, left + selectionBox.getWidth(), top + selectionBox.getHeight());
- Timber.i("Querying box %s", box);
- List<Feature> features = mapboxMap.queryRenderedFeatures(box, "symbols-layer");
-
- // Show count
- if (toast != null) {
- toast.cancel();
- }
- toast = Toast.makeText(
- QueryRenderedFeaturesBoxSymbolCountActivity.this,
- String.format("%s features in box", features.size()),
- Toast.LENGTH_SHORT);
- toast.show();
- }
- });
+ mapView.getMapAsync(mapboxMap -> {
+ QueryRenderedFeaturesBoxSymbolCountActivity.this.mapboxMap = mapboxMap;
+
+ // Add a symbol layer (also works with annotations)
+ try {
+ mapboxMap.addSource(new GeoJsonSource("symbols-source", ResourceUtils.readRawResource(
+ QueryRenderedFeaturesBoxSymbolCountActivity.this, R.raw.test_points_utrecht)));
+ } catch (IOException ioException) {
+ Timber.e(ioException, "Could not load geojson");
+ return;
}
+ mapboxMap.addImage(
+ "test-icon",
+ BitmapFactory.decodeResource(getResources(),
+ R.drawable.mapbox_marker_icon_default)
+ );
+ mapboxMap.addLayer(new SymbolLayer("symbols-layer", "symbols-source").withProperties(iconImage("test-icon")));
+
+ selectionBox.setOnClickListener(view -> {
+ // Query
+ int top = selectionBox.getTop() - mapView.getTop();
+ int left = selectionBox.getLeft() - mapView.getLeft();
+ RectF box = new RectF(left, top, left + selectionBox.getWidth(), top + selectionBox.getHeight());
+ Timber.i("Querying box %s", box);
+ List<Feature> features = mapboxMap.queryRenderedFeatures(box, "symbols-layer");
+
+ // Show count
+ if (toast != null) {
+ toast.cancel();
+ }
+ toast = Toast.makeText(
+ QueryRenderedFeaturesBoxSymbolCountActivity.this,
+ String.format("%s features in box", features.size()),
+ Toast.LENGTH_SHORT);
+ toast.show();
+ });
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesPropertiesActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesPropertiesActivity.java
index 1bd6a34b7c..150b081f7f 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesPropertiesActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesPropertiesActivity.java
@@ -14,10 +14,8 @@ import android.widget.TextView;
import com.google.gson.JsonElement;
import com.mapbox.mapboxsdk.annotations.BaseMarkerOptions;
import com.mapbox.mapboxsdk.annotations.Marker;
-import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.services.commons.geojson.Feature;
@@ -45,40 +43,34 @@ public class QueryRenderedFeaturesPropertiesActivity extends AppCompatActivity {
// Initialize map as normal
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(final MapboxMap mapboxMap) {
- QueryRenderedFeaturesPropertiesActivity.this.mapboxMap = mapboxMap;
-
- // Add custom window adapter
- addCustomInfoWindowAdapter(mapboxMap);
-
- // Add a click listener
- mapboxMap.setOnMapClickListener(new MapboxMap.OnMapClickListener() {
- @Override
- public void onMapClick(@NonNull LatLng point) {
- // Query
- final PointF pixel = mapboxMap.getProjection().toScreenLocation(point);
- Timber.i(
- "Requesting features for %sx%s (%sx%s adjusted for density)",
- pixel.x, pixel.y, pixel.x / density, pixel.y / density
- );
- List<Feature> features = mapboxMap.queryRenderedFeatures(pixel);
-
- // Debug output
- debugOutput(features);
-
- // Remove any previous markers
- if (marker != null) {
- mapboxMap.removeMarker(marker);
- }
-
- // Add a marker on the clicked point
- marker = mapboxMap.addMarker(new CustomMarkerOptions().position(point).features(features));
- mapboxMap.selectMarker(marker);
- }
- });
- }
+ mapView.getMapAsync(mapboxMap -> {
+ QueryRenderedFeaturesPropertiesActivity.this.mapboxMap = mapboxMap;
+
+ // Add custom window adapter
+ addCustomInfoWindowAdapter(mapboxMap);
+
+ // Add a click listener
+ mapboxMap.setOnMapClickListener(point -> {
+ // Query
+ final PointF pixel = mapboxMap.getProjection().toScreenLocation(point);
+ Timber.i(
+ "Requesting features for %sx%s (%sx%s adjusted for density)",
+ pixel.x, pixel.y, pixel.x / density, pixel.y / density
+ );
+ List<Feature> features = mapboxMap.queryRenderedFeatures(pixel);
+
+ // Debug output
+ debugOutput(features);
+
+ // Remove any previous markers
+ if (marker != null) {
+ mapboxMap.removeMarker(marker);
+ }
+
+ // Add a marker on the clicked point
+ marker = mapboxMap.addMarker(new CustomMarkerOptions().position(point).features(features));
+ mapboxMap.selectMarker(marker);
+ });
});
}
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 861f2fef34..c8bef26856 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,15 +1,12 @@
package com.mapbox.mapboxsdk.testapp.activity.feature;
import android.os.Bundle;
-import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;
import com.google.gson.JsonObject;
-import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.style.layers.CircleLayer;
import com.mapbox.mapboxsdk.style.layers.Filter;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
@@ -38,32 +35,26 @@ public class QuerySourceFeaturesActivity extends AppCompatActivity {
// Initialize map as normal
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(final MapboxMap 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.fromCoordinates(new double[] {0, 0}), properties)
- }));
- mapboxMap.addSource(source);
-
- mapboxMap.addLayer(new CircleLayer("test-layer", source.getId()).withFilter(Filter.neq("key1", "value1")));
-
- // Add a click listener
- mapboxMap.setOnMapClickListener(new MapboxMap.OnMapClickListener() {
- @Override
- public void onMapClick(@NonNull LatLng point) {
- // Query
- List<Feature> features = source.querySourceFeatures(Filter.eq("key1", "value1"));
- Toast.makeText(QuerySourceFeaturesActivity.this, String.format("Found %s features",
- features.size()), Toast.LENGTH_SHORT).show();
- }
- });
- }
+ 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.fromCoordinates(new double[] {0, 0}), properties)
+ }));
+ mapboxMap.addSource(source);
+
+ mapboxMap.addLayer(new CircleLayer("test-layer", source.getId()).withFilter(Filter.neq("key1", "value1")));
+
+ // Add a click listener
+ mapboxMap.setOnMapClickListener(point -> {
+ // Query
+ List<Feature> features = source.querySourceFeatures(Filter.eq("key1", "value1"));
+ Toast.makeText(QuerySourceFeaturesActivity.this, String.format("Found %s features",
+ features.size()), Toast.LENGTH_SHORT).show();
+ });
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/MultiMapActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/MultiMapActivity.java
index eec440afb0..2305fdf16c 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/MultiMapActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/MultiMapActivity.java
@@ -1,7 +1,7 @@
package com.mapbox.mapboxsdk.testapp.activity.fragment;
-import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
+import android.support.v7.app.AppCompatActivity;
import com.mapbox.mapboxsdk.testapp.R;
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/ViewPagerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/ViewPagerActivity.java
index bbdf450505..26cf777ba9 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/ViewPagerActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/ViewPagerActivity.java
@@ -48,6 +48,7 @@ public class ViewPagerActivity extends AppCompatActivity {
public Fragment getItem(int position) {
SupportMapFragment fragment = null;
MapboxMapOptions options = new MapboxMapOptions();
+ options.textureMode(true);
switch (position) {
case 0:
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/PrintActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/PrintActivity.java
index 18d80586c9..d0d4368d36 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/PrintActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/PrintActivity.java
@@ -2,14 +2,12 @@ package com.mapbox.mapboxsdk.testapp.activity.imagegenerator;
import android.graphics.Bitmap;
import android.os.Bundle;
-import android.support.annotation.NonNull;
import android.support.v4.print.PrintHelper;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.testapp.R;
/**
@@ -27,21 +25,13 @@ public class PrintActivity extends AppCompatActivity implements MapboxMap.Snapsh
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull MapboxMap mapboxMap) {
- PrintActivity.this.mapboxMap = mapboxMap;
- }
- });
+ mapView.getMapAsync(mapboxMap -> PrintActivity.this.mapboxMap = mapboxMap);
final View fab = findViewById(R.id.fab);
if (fab != null) {
- fab.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (mapboxMap != null) {
- mapboxMap.snapshot(PrintActivity.this);
- }
+ fab.setOnClickListener(view -> {
+ if (mapboxMap != null) {
+ mapboxMap.snapshot(PrintActivity.this);
}
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/SnapshotActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/SnapshotActivity.java
index 655012f799..62d3ad34df 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/SnapshotActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/SnapshotActivity.java
@@ -1,6 +1,5 @@
package com.mapbox.mapboxsdk.testapp.activity.imagegenerator;
-import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.content.ContextCompat;
@@ -49,18 +48,15 @@ public class SnapshotActivity extends AppCompatActivity implements OnMapReadyCal
@Override
public void onClick(View view) {
final long startTime = System.nanoTime();
- mapboxMap.snapshot(new MapboxMap.SnapshotReadyCallback() {
- @Override
- public void onSnapshotReady(Bitmap snapshot) {
- long endTime = System.nanoTime();
- long duration = (long) ((endTime - startTime) / 1e6);
- ImageView snapshotView = (ImageView) findViewById(R.id.imageView);
- snapshotView.setImageBitmap(snapshot);
- Toast.makeText(
- SnapshotActivity.this,
- String.format(Locale.getDefault(), "Snapshot taken in %d ms", duration),
- Toast.LENGTH_LONG).show();
- }
+ mapboxMap.snapshot(snapshot -> {
+ long endTime = System.nanoTime();
+ long duration = (long) ((endTime - startTime) / 1e6);
+ ImageView snapshotView = (ImageView) findViewById(R.id.imageView);
+ snapshotView.setImageBitmap(snapshot);
+ Toast.makeText(
+ SnapshotActivity.this,
+ String.format(Locale.getDefault(), "Snapshot taken in %d ms", duration),
+ Toast.LENGTH_LONG).show();
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/DynamicInfoWindowAdapterActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/DynamicInfoWindowAdapterActivity.java
index 7fa4792a38..9dea4f77de 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/DynamicInfoWindowAdapterActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/DynamicInfoWindowAdapterActivity.java
@@ -2,14 +2,11 @@ package com.mapbox.mapboxsdk.testapp.activity.infowindow;
import android.graphics.Color;
import android.os.Bundle;
-import android.support.annotation.NonNull;
import android.support.v4.content.res.ResourcesCompat;
import android.support.v7.app.AppCompatActivity;
-import android.view.View;
import android.widget.TextView;
import com.mapbox.mapboxsdk.annotations.InfoWindow;
-import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerView;
import com.mapbox.mapboxsdk.annotations.MarkerViewOptions;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
@@ -57,28 +54,22 @@ public class DynamicInfoWindowAdapterActivity extends AppCompatActivity implemen
mapboxMap.selectMarker(marker);
// On map click, change the info window contents
- mapboxMap.setOnMapClickListener(new MapboxMap.OnMapClickListener() {
- @Override
- public void onMapClick(@NonNull LatLng point) {
- // Distance from click to marker
- double distanceKm = marker.getPosition().distanceTo(point) / 1000;
-
- // Get the info window
- final InfoWindow infoWindow = marker.getInfoWindow();
-
- // Get the view from the info window
- if (infoWindow != null && infoWindow.getView() != null) {
- // Set the new text on the text view in the info window
- TextView textView = (TextView) infoWindow.getView();
- textView.setText(String.format(Locale.getDefault(), "%.2fkm", distanceKm));
- textView.post(new Runnable() {
- @Override
- public void run() {
- // Update the info window position (as the text length changes)
- infoWindow.update();
- }
- });
- }
+ mapboxMap.setOnMapClickListener(point -> {
+ // Distance from click to marker
+ double distanceKm = marker.getPosition().distanceTo(point) / 1000;
+
+ // Get the info window
+ final InfoWindow infoWindow = marker.getInfoWindow();
+
+ // Get the view from the info window
+ if (infoWindow != null && infoWindow.getView() != null) {
+ // Set the new text on the text view in the info window
+ TextView textView = (TextView) infoWindow.getView();
+ textView.setText(String.format(Locale.getDefault(), "%.2fkm", distanceKm));
+ textView.post(() -> {
+ // Update the info window position (as the text length changes)
+ infoWindow.update();
+ });
}
});
@@ -97,17 +88,13 @@ public class DynamicInfoWindowAdapterActivity extends AppCompatActivity implemen
private void addCustomInfoWindowAdapter(final MapboxMap mapboxMap) {
final int padding = (int) getResources().getDimension(R.dimen.attr_margin);
- mapboxMap.setInfoWindowAdapter(new MapboxMap.InfoWindowAdapter() {
-
- @Override
- public View getInfoWindow(@NonNull Marker marker) {
- TextView textView = new TextView(DynamicInfoWindowAdapterActivity.this);
- textView.setText(marker.getTitle());
- textView.setBackgroundColor(Color.WHITE);
- textView.setText(R.string.action_calculate_distance);
- textView.setPadding(padding, padding, padding, padding);
- return textView;
- }
+ mapboxMap.setInfoWindowAdapter(marker -> {
+ TextView textView = new TextView(DynamicInfoWindowAdapterActivity.this);
+ textView.setText(marker.getTitle());
+ textView.setBackgroundColor(Color.WHITE);
+ textView.setText(R.string.action_calculate_distance);
+ textView.setPadding(padding, padding, padding, padding);
+ return textView;
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/InfoWindowAdapterActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/InfoWindowAdapterActivity.java
index 22347f8a92..d8dea0e3b5 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/InfoWindowAdapterActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/InfoWindowAdapterActivity.java
@@ -12,7 +12,6 @@ import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.model.annotations.CityStateMarker;
import com.mapbox.mapboxsdk.testapp.model.annotations.CityStateMarkerOptions;
@@ -33,13 +32,10 @@ public class InfoWindowAdapterActivity extends AppCompatActivity {
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull MapboxMap map) {
- mapboxMap = map;
- addMarkers();
- addCustomInfoWindowAdapter();
- }
+ mapView.getMapAsync(map -> {
+ mapboxMap = map;
+ addMarkers();
+ addCustomInfoWindowAdapter();
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/BottomSheetActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/BottomSheetActivity.java
index 2c83f6d908..3b58843e13 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/BottomSheetActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/BottomSheetActivity.java
@@ -7,6 +7,7 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.BottomSheetBehavior;
import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
@@ -35,7 +36,6 @@ public class BottomSheetActivity extends AppCompatActivity {
private static final String TAG_BOTTOM_FRAGMENT = "com.mapbox.mapboxsdk.fragment.tag.bottom";
private boolean bottomSheetFragmentAdded;
- private int mapViewCounter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
@@ -45,22 +45,11 @@ public class BottomSheetActivity extends AppCompatActivity {
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayHomeAsUpEnabled(true);
}
- findViewById(R.id.fabFragment).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- addMapFragment();
- }
- });
+ findViewById(R.id.fabFragment).setOnClickListener(v -> addMapFragment());
- findViewById(R.id.fabBottomSheet).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- toggleBottomSheetMapFragment();
- }
- });
+ findViewById(R.id.fabBottomSheet).setOnClickListener(v -> toggleBottomSheetMapFragment());
BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(findViewById(R.id.bottom_sheet));
bottomSheetBehavior.setPeekHeight((int) (64 * getResources().getDisplayMetrics().density));
@@ -78,25 +67,29 @@ public class BottomSheetActivity extends AppCompatActivity {
@Override
public void onBackPressed() {
- super.onBackPressed();
- if (mapViewCounter > 0) {
- mapViewCounter--;
- Toast.makeText(this, "Amount of main map fragments: " + mapViewCounter, Toast.LENGTH_SHORT).show();
+ FragmentManager fragmentManager = getSupportFragmentManager();
+
+ if (fragmentManager.getBackStackEntryCount() > 0) {
+ fragmentManager.popBackStack();
+ } else {
+ super.onBackPressed();
}
}
private void addMapFragment() {
- FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
- MainMapFragment mainMapFragment = MainMapFragment.newInstance(mapViewCounter);
- if (mapViewCounter == 0) {
+ FragmentManager fragmentManager = getSupportFragmentManager();
+ int fragmentCount = fragmentManager.getBackStackEntryCount();
+
+ FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
+ MainMapFragment mainMapFragment = MainMapFragment.newInstance(fragmentCount);
+ if (fragmentCount == 0) {
fragmentTransaction.add(R.id.fragment_container, mainMapFragment, TAG_MAIN_FRAGMENT);
} else {
fragmentTransaction.replace(R.id.fragment_container, mainMapFragment, TAG_MAIN_FRAGMENT);
}
- fragmentTransaction.addToBackStack(null);
+ fragmentTransaction.addToBackStack(String.valueOf(mainMapFragment.hashCode()));
fragmentTransaction.commit();
- mapViewCounter++;
- Toast.makeText(this, "Amount of main map fragments: " + mapViewCounter, Toast.LENGTH_SHORT).show();
+ Toast.makeText(this, "Amount of main map fragments: " + (fragmentCount + 1), Toast.LENGTH_SHORT).show();
}
private void toggleBottomSheetMapFragment() {
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DebugModeActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DebugModeActivity.java
index 9220a30c36..43e89728cb 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DebugModeActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DebugModeActivity.java
@@ -11,12 +11,10 @@ import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
-import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.constants.Style;
import com.mapbox.mapboxsdk.http.HttpRequestUtil;
import com.mapbox.mapboxsdk.maps.MapView;
@@ -84,13 +82,10 @@ public class DebugModeActivity extends AppCompatActivity implements OnMapReadyCa
private void setupMapView(Bundle savedInstanceState) {
mapView = (MapView) findViewById(R.id.mapView);
- mapView.addOnMapChangedListener(new MapView.OnMapChangedListener() {
- @Override
- public void onMapChanged(int change) {
- if (change == MapView.DID_FINISH_LOADING_STYLE && mapboxMap != null) {
- Timber.v("New style loaded with JSON: %s", mapboxMap.getStyleJson());
- setupNavigationView(mapboxMap.getLayers());
- }
+ mapView.addOnMapChangedListener(change -> {
+ if (change == MapView.DID_FINISH_LOADING_STYLE && mapboxMap != null) {
+ Timber.v("New style loaded with JSON: %s", mapboxMap.getStyleJson());
+ setupNavigationView(mapboxMap.getLayers());
}
});
@@ -112,25 +107,19 @@ public class DebugModeActivity extends AppCompatActivity implements OnMapReadyCa
private void setFpsView() {
final TextView fpsView = (TextView) findViewById(R.id.fpsView);
- mapboxMap.setOnFpsChangedListener(new MapboxMap.OnFpsChangedListener() {
- @Override
- public void onFpsChanged(double fps) {
- fpsView.setText(String.format(Locale.US, "FPS: %4.2f", fps));
- }
- });
+ mapboxMap.setOnFpsChangedListener(fps ->
+ fpsView.setText(String.format(Locale.US, "FPS: %4.2f", fps))
+ );
}
private void setupNavigationView(List<Layer> layerList) {
final LayerListAdapter adapter = new LayerListAdapter(this, layerList);
ListView listView = (ListView) findViewById(R.id.listView);
listView.setAdapter(adapter);
- listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- Layer clickedLayer = adapter.getItem(position);
- toggleLayerVisibility(clickedLayer);
- closeNavigationView();
- }
+ listView.setOnItemClickListener((parent, view, position, id) -> {
+ Layer clickedLayer = adapter.getItem(position);
+ toggleLayerVisibility(clickedLayer);
+ closeNavigationView();
});
}
@@ -150,44 +139,30 @@ public class DebugModeActivity extends AppCompatActivity implements OnMapReadyCa
private void setupZoomView() {
final TextView textView = (TextView) findViewById(R.id.textZoom);
- mapboxMap.setOnCameraChangeListener(new MapboxMap.OnCameraChangeListener() {
- @Override
- public void onCameraChange(CameraPosition position) {
- textView.setText(String.format(getString(R.string.debug_zoom), position.zoom));
- }
- });
+ mapboxMap.setOnCameraChangeListener(position ->
+ textView.setText(String.format(getString(R.string.debug_zoom), position.zoom))
+ );
}
private void setupDebugChangeView() {
FloatingActionButton fabDebug = (FloatingActionButton) findViewById(R.id.fabDebug);
- fabDebug.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (mapboxMap != null) {
- Timber.d("Debug FAB: isDebug Active? %s", mapboxMap.isDebugActive());
- mapboxMap.cycleDebugOptions();
- }
+ fabDebug.setOnClickListener(view -> {
+ if (mapboxMap != null) {
+ Timber.d("Debug FAB: isDebug Active? %s", mapboxMap.isDebugActive());
+ mapboxMap.cycleDebugOptions();
}
});
}
private void setupStyleChangeView() {
FloatingActionButton fabStyles = (FloatingActionButton) findViewById(R.id.fabStyles);
- fabStyles.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (mapboxMap != null) {
- currentStyleIndex++;
- if (currentStyleIndex == STYLES.length) {
- currentStyleIndex = 0;
- }
- mapboxMap.setStyleUrl(STYLES[currentStyleIndex], new MapboxMap.OnStyleLoadedListener() {
- @Override
- public void onStyleLoaded(String style) {
- Timber.d("Style loaded %s", style);
- }
- });
+ fabStyles.setOnClickListener(view -> {
+ if (mapboxMap != null) {
+ currentStyleIndex++;
+ if (currentStyleIndex == STYLES.length) {
+ currentStyleIndex = 0;
}
+ mapboxMap.setStyleUrl(STYLES[currentStyleIndex], style -> Timber.d("Style loaded %s", style));
}
});
}
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 462c0c8025..75b2378ef7 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
@@ -3,7 +3,6 @@ package com.mapbox.mapboxsdk.testapp.activity.maplayout;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
-import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
@@ -14,10 +13,8 @@ import android.view.ViewGroup;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.constants.MyLocationTracking;
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.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.TrackingSettings;
import com.mapbox.mapboxsdk.maps.UiSettings;
import com.mapbox.mapboxsdk.testapp.R;
@@ -90,47 +87,38 @@ public class DoubleMapActivity extends AppCompatActivity {
// MapView large
mapView = (MapView) view.findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull MapboxMap mapboxMap) {
- if (activity != null) {
- activity.setMapboxMap(mapboxMap);
- }
+ mapView.getMapAsync(mapboxMap -> {
+ if (activity != null) {
+ activity.setMapboxMap(mapboxMap);
}
});
// MapView mini
mapViewMini = (MapView) view.findViewById(R.id.mini_map);
mapViewMini.onCreate(savedInstanceState);
- mapViewMini.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull MapboxMap mapboxMap) {
- mapboxMap.setStyleUrl(Style.LIGHT);
- mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(4));
-
- UiSettings uiSettings = mapboxMap.getUiSettings();
- uiSettings.setAllGesturesEnabled(false);
- uiSettings.setCompassEnabled(false);
- uiSettings.setAttributionEnabled(false);
- uiSettings.setLogoEnabled(false);
-
- try {
- mapboxMap.setMyLocationEnabled(true);
- TrackingSettings settings = mapboxMap.getTrackingSettings();
- settings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW);
- } catch (SecurityException securityException) {
- // permission is handled in MainActivity
- getActivity().finish();
- }
-
- mapboxMap.setOnMapClickListener(new MapboxMap.OnMapClickListener() {
- @Override
- public void onMapClick(@NonNull LatLng point) {
- // test if we can open 2 activities after each other
- startActivity(new Intent(mapViewMini.getContext(), DoubleMapActivity.class));
- }
- });
+ mapViewMini.getMapAsync(mapboxMap -> {
+ mapboxMap.setStyleUrl(Style.LIGHT);
+ mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(4));
+
+ UiSettings uiSettings = mapboxMap.getUiSettings();
+ uiSettings.setAllGesturesEnabled(false);
+ uiSettings.setCompassEnabled(false);
+ uiSettings.setAttributionEnabled(false);
+ uiSettings.setLogoEnabled(false);
+
+ try {
+ mapboxMap.setMyLocationEnabled(true);
+ TrackingSettings settings = mapboxMap.getTrackingSettings();
+ settings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW);
+ } catch (SecurityException securityException) {
+ // permission is handled in MainActivity
+ getActivity().finish();
}
+
+ mapboxMap.setOnMapClickListener(point -> {
+ // test if we can open 2 activities after each other
+ startActivity(new Intent(mapViewMini.getContext(), DoubleMapActivity.class));
+ });
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/LocalGlyphActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/LocalGlyphActivity.java
index bc07765bf7..18d675a289 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/LocalGlyphActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/LocalGlyphActivity.java
@@ -12,6 +12,10 @@ import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.testapp.R;
+/**
+ * Test activity that displays the city of Suzhou with a mixture of server-generated
+ * latin glyphs and CJK glyphs generated locally using "Droid Sans" as a font family.
+ */
public class LocalGlyphActivity extends AppCompatActivity {
private MapView mapView;
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapChangeActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapChangeActivity.java
index 32344248bc..160e69ed6e 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapChangeActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapChangeActivity.java
@@ -8,7 +8,6 @@ import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.testapp.R;
import timber.log.Timber;
@@ -28,21 +27,13 @@ public class MapChangeActivity extends AppCompatActivity {
final LongSparseArray<String> mapChangeMap = buildMapChangeStringValueSparseArray();
mapView = (MapView) findViewById(R.id.mapView);
- mapView.addOnMapChangedListener(new MapView.OnMapChangedListener() {
- @Override
- public void onMapChanged(int change) {
- Timber.e("OnMapChange: %s, %s", change, mapChangeMap.get(change));
- }
- });
+ mapView.addOnMapChangedListener(change -> Timber.e("OnMapChange: %s, %s", change, mapChangeMap.get(change)));
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(MapboxMap map) {
- mapboxMap = map;
- mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(
- new LatLng(55.754020, 37.620948), 12), 9000);
- }
+ mapView.getMapAsync(map -> {
+ mapboxMap = map;
+ mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(
+ new LatLng(55.754020, 37.620948), 12), 9000);
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapInDialogActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapInDialogActivity.java
index f0827c65cc..ce00c9d18f 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapInDialogActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapInDialogActivity.java
@@ -29,13 +29,10 @@ public class MapInDialogActivity extends AppCompatActivity {
setContentView(R.layout.activity_map_in_dialog);
Button button = (Button) findViewById(R.id.button_open_dialog);
- button.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- FragmentManager fm = getSupportFragmentManager();
- MapDialogFragment editNameDialogFragment = MapDialogFragment.newInstance("Map Dialog");
- editNameDialogFragment.show(fm, "fragment_dialog_map");
- }
+ button.setOnClickListener(view -> {
+ FragmentManager fm = getSupportFragmentManager();
+ MapDialogFragment editNameDialogFragment = MapDialogFragment.newInstance("Map Dialog");
+ editNameDialogFragment.show(fm, "fragment_dialog_map");
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapPaddingActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapPaddingActivity.java
index 0cf0191cea..9a6079b157 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapPaddingActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapPaddingActivity.java
@@ -1,7 +1,6 @@
package com.mapbox.mapboxsdk.testapp.activity.maplayout;
import android.os.Bundle;
-import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
@@ -13,7 +12,6 @@ import com.mapbox.mapboxsdk.constants.MyLocationTracking;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.TrackingSettings;
import com.mapbox.mapboxsdk.testapp.R;
@@ -37,19 +35,16 @@ public class MapPaddingActivity extends AppCompatActivity {
mapView.setTag(true);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull MapboxMap mapboxMap) {
- MapPaddingActivity.this.mapboxMap = mapboxMap;
+ mapView.getMapAsync(mapboxMap -> {
+ MapPaddingActivity.this.mapboxMap = mapboxMap;
- int paddingLeft = (int) getResources().getDimension(R.dimen.map_padding_left);
- int paddingBottom = (int) getResources().getDimension(R.dimen.map_padding_bottom);
- int paddingRight = (int) getResources().getDimension(R.dimen.map_padding_right);
- int paddingTop = (int) getResources().getDimension(R.dimen.map_padding_top);
- mapboxMap.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
+ int paddingLeft = (int) getResources().getDimension(R.dimen.map_padding_left);
+ int paddingBottom = (int) getResources().getDimension(R.dimen.map_padding_bottom);
+ int paddingRight = (int) getResources().getDimension(R.dimen.map_padding_right);
+ int paddingTop = (int) getResources().getDimension(R.dimen.map_padding_top);
+ mapboxMap.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
- moveToBangalore();
- }
+ moveToBangalore();
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/VisibilityChangeActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/VisibilityChangeActivity.java
index 393abb7cd4..c5d7dfbef7 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/VisibilityChangeActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/VisibilityChangeActivity.java
@@ -9,7 +9,6 @@ import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.testapp.R;
/**
@@ -29,13 +28,10 @@ public class VisibilityChangeActivity extends AppCompatActivity {
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(MapboxMap map) {
- mapboxMap = map;
- mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(
- new LatLng(55.754020, 37.620948), 12), 9000);
- }
+ mapView.getMapAsync(map -> {
+ mapboxMap = map;
+ mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(
+ new LatLng(55.754020, 37.620948), 12), 9000);
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/DeleteRegionActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/DeleteRegionActivity.java
index 220f46f4e8..037c51f723 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/DeleteRegionActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/DeleteRegionActivity.java
@@ -1,7 +1,6 @@
package com.mapbox.mapboxsdk.testapp.activity.offline;
import android.content.Context;
-import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
@@ -53,18 +52,8 @@ public class DeleteRegionActivity extends AppCompatActivity implements AdapterVi
input.setText(metadata);
builder.setView(input);
- builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- delete(region);
- }
- });
- builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.cancel();
- }
- });
+ builder.setPositiveButton("OK", (dialog, which) -> delete(region));
+ builder.setNegativeButton("Cancel", (dialog, which) -> dialog.cancel());
builder.show();
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.java
index 3a59e0628d..79e76168d5 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.java
@@ -1,7 +1,6 @@
package com.mapbox.mapboxsdk.testapp.activity.offline;
import android.os.Bundle;
-import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
@@ -17,7 +16,6 @@ import com.mapbox.mapboxsdk.geometry.LatLng;
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.offline.OfflineManager;
import com.mapbox.mapboxsdk.offline.OfflineRegion;
import com.mapbox.mapboxsdk.offline.OfflineRegionError;
@@ -80,21 +78,18 @@ public class OfflineActivity extends AppCompatActivity
mapView = (MapView) findViewById(R.id.mapView);
mapView.setStyleUrl(STYLE_URL);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull MapboxMap mapboxMap) {
- Timber.d("Map is ready");
- OfflineActivity.this.mapboxMap = mapboxMap;
-
- // Set initial position to UNHQ in NYC
- mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(
- new CameraPosition.Builder()
- .target(new LatLng(40.749851, -73.967966))
- .zoom(14)
- .bearing(0)
- .tilt(0)
- .build()));
- }
+ mapView.getMapAsync(mapboxMap -> {
+ Timber.d("Map is ready");
+ OfflineActivity.this.mapboxMap = mapboxMap;
+
+ // Set initial position to UNHQ in NYC
+ mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(
+ new CameraPosition.Builder()
+ .target(new LatLng(40.749851, -73.967966))
+ .zoom(14)
+ .bearing(0)
+ .tilt(0)
+ .build()));
});
// The progress bar
@@ -102,20 +97,10 @@ public class OfflineActivity extends AppCompatActivity
// Set up button listeners
downloadRegion = (Button) findViewById(R.id.button_download_region);
- downloadRegion.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- handleDownloadRegion();
- }
- });
+ downloadRegion.setOnClickListener(view -> handleDownloadRegion());
listRegions = (Button) findViewById(R.id.button_list_regions);
- listRegions.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- handleListRegions();
- }
- });
+ listRegions.setOnClickListener(view -> handleListRegions());
// Set up the OfflineManager
offlineManager = OfflineManager.getInstance(this);
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/UpdateMetadataActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/UpdateMetadataActivity.java
index 285e896766..c5ad467673 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/UpdateMetadataActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/UpdateMetadataActivity.java
@@ -1,7 +1,6 @@
package com.mapbox.mapboxsdk.testapp.activity.offline;
import android.content.Context;
-import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
@@ -57,18 +56,10 @@ public class UpdateMetadataActivity extends AppCompatActivity implements Adapter
input.setSelection(metadata.length());
builder.setView(input);
- builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- updateMetadata(region, OfflineUtils.convertRegionName(input.getText().toString()));
- }
- });
- builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.cancel();
- }
- });
+ builder.setPositiveButton("OK", (dialog, which) ->
+ updateMetadata(region, OfflineUtils.convertRegionName(input.getText().toString()))
+ );
+ builder.setNegativeButton("Cancel", (dialog, which) -> dialog.cancel());
builder.show();
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterActivity.java
index c4fe93d200..aadf021a89 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterActivity.java
@@ -10,7 +10,6 @@ import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.constants.Style;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
-import com.mapbox.mapboxsdk.snapshotter.MapSnapshot;
import com.mapbox.mapboxsdk.snapshotter.MapSnapshotter;
import com.mapbox.mapboxsdk.testapp.R;
@@ -95,17 +94,14 @@ public class MapSnapshotterActivity extends AppCompatActivity {
MapSnapshotter snapshotter = new MapSnapshotter(MapSnapshotterActivity.this, options);
- snapshotter.start(new MapSnapshotter.SnapshotReadyCallback() {
- @Override
- public void onSnapshotReady(MapSnapshot snapshot) {
- Timber.i("Got the snapshot");
- ImageView imageView = new ImageView(MapSnapshotterActivity.this);
- imageView.setImageBitmap(snapshot.getBitmap());
- grid.addView(
- imageView,
- new GridLayout.LayoutParams(GridLayout.spec(row), GridLayout.spec(column))
- );
- }
+ snapshotter.start(snapshot -> {
+ Timber.i("Got the snapshot");
+ ImageView imageView = new ImageView(MapSnapshotterActivity.this);
+ imageView.setImageBitmap(snapshot.getBitmap());
+ grid.addView(
+ imageView,
+ new GridLayout.LayoutParams(GridLayout.spec(row), GridLayout.spec(column))
+ );
});
snapshotters.add(snapshotter);
}
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 50f9be77fa..ef5913beb0 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
@@ -31,24 +31,21 @@ public class MapSnapshotterReuseActivity extends AppCompatActivity implements Ma
fab = findViewById(R.id.fab);
fab.setVisibility(View.INVISIBLE);
- fab.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- fab.setVisibility(View.INVISIBLE);
-
- mapSnapshotter.setStyleUrl(getRandomStyle());
- if (random.nextInt(2) == 0) {
- mapSnapshotter.setCameraPosition(getRandomCameraPosition());
- } else {
- mapSnapshotter.setRegion(getRandomBounds());
- }
- if (random.nextInt(2) == 0) {
- mapSnapshotter.setSize(512, 512);
- } else {
- mapSnapshotter.setSize(256, 256);
- }
- mapSnapshotter.start(MapSnapshotterReuseActivity.this);
+ fab.setOnClickListener(v -> {
+ fab.setVisibility(View.INVISIBLE);
+
+ mapSnapshotter.setStyleUrl(getRandomStyle());
+ if (random.nextInt(2) == 0) {
+ mapSnapshotter.setCameraPosition(getRandomCameraPosition());
+ } else {
+ mapSnapshotter.setRegion(getRandomBounds());
}
+ if (random.nextInt(2) == 0) {
+ mapSnapshotter.setSize(512, 512);
+ } else {
+ mapSnapshotter.setSize(256, 256);
+ }
+ mapSnapshotter.start(MapSnapshotterReuseActivity.this);
});
mapSnapshotter = new MapSnapshotter(
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/storage/UrlTransformActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/storage/UrlTransformActivity.java
index 74b43e0257..6a1fd8e4e0 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/storage/UrlTransformActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/storage/UrlTransformActivity.java
@@ -6,7 +6,6 @@ import android.support.v7.app.AppCompatActivity;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.storage.FileSource;
import com.mapbox.mapboxsdk.storage.Resource;
import com.mapbox.mapboxsdk.testapp.R;
@@ -47,12 +46,9 @@ public class UrlTransformActivity extends AppCompatActivity {
// Get a handle to the file source and set the resource transform
FileSource.getInstance(UrlTransformActivity.this).setResourceTransform(new Transform());
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(MapboxMap map) {
- Timber.i("Map loaded");
- mapboxMap = map;
- }
+ mapView.getMapAsync(map -> {
+ Timber.i("Map loaded");
+ mapboxMap = map;
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/AnimatedImageSourceActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/AnimatedImageSourceActivity.java
index 1beba632b0..1014af25db 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/AnimatedImageSourceActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/AnimatedImageSourceActivity.java
@@ -18,7 +18,6 @@ import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.style.layers.RasterLayer;
import com.mapbox.mapboxsdk.style.sources.ImageSource;
-
import com.mapbox.mapboxsdk.testapp.R;
/**
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/BuildingFillExtrusionActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/BuildingFillExtrusionActivity.java
index def7d1678a..609910892b 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/BuildingFillExtrusionActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/BuildingFillExtrusionActivity.java
@@ -2,15 +2,12 @@ package com.mapbox.mapboxsdk.testapp.activity.style;
import android.graphics.Color;
import android.os.Bundle;
-import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
-import android.view.View;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.style.functions.Function;
import com.mapbox.mapboxsdk.style.functions.stops.IdentityStops;
import com.mapbox.mapboxsdk.style.layers.FillExtrusionLayer;
@@ -46,13 +43,10 @@ public class BuildingFillExtrusionActivity extends AppCompatActivity {
setContentView(R.layout.activity_building_layer);
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull final MapboxMap map) {
- mapboxMap = map;
- setupBuildings();
- setupLight();
- }
+ mapView.getMapAsync(map -> {
+ mapboxMap = map;
+ setupBuildings();
+ setupLight();
});
}
@@ -73,24 +67,18 @@ public class BuildingFillExtrusionActivity extends AppCompatActivity {
private void setupLight() {
light = mapboxMap.getLight();
- findViewById(R.id.fabLightPosition).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- isInitPosition = !isInitPosition;
- if (isInitPosition) {
- light.setPosition(new Position(1.5f, 90, 80));
- } else {
- light.setPosition(new Position(1.15f, 210, 30));
- }
+ findViewById(R.id.fabLightPosition).setOnClickListener(v -> {
+ isInitPosition = !isInitPosition;
+ if (isInitPosition) {
+ light.setPosition(new Position(1.5f, 90, 80));
+ } else {
+ light.setPosition(new Position(1.15f, 210, 30));
}
});
- findViewById(R.id.fabLightColor).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- isRedColor = !isRedColor;
- light.setColor(PropertyFactory.colorToRgbaString(isRedColor ? Color.RED : Color.BLUE));
- }
+ findViewById(R.id.fabLightColor).setOnClickListener(v -> {
+ isRedColor = !isRedColor;
+ light.setColor(PropertyFactory.colorToRgbaString(isRedColor ? Color.RED : Color.BLUE));
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/CircleLayerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/CircleLayerActivity.java
index f99a1fdb96..6aa8777777 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/CircleLayerActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/CircleLayerActivity.java
@@ -2,7 +2,6 @@ package com.mapbox.mapboxsdk.testapp.activity.style;
import android.graphics.Color;
import android.os.Bundle;
-import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
@@ -14,7 +13,6 @@ 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.OnMapReadyCallback;
import com.mapbox.mapboxsdk.style.layers.CircleLayer;
import com.mapbox.mapboxsdk.style.layers.LineLayer;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
@@ -56,16 +54,12 @@ public class CircleLayerActivity extends AppCompatActivity implements View.OnCli
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull
- final MapboxMap map) {
- mapboxMap = map;
- addBusStopSource();
- addBusStopCircleLayer();
- initFloatingActionButtons();
- isLoadingStyle = false;
- }
+ mapView.getMapAsync(map -> {
+ mapboxMap = map;
+ addBusStopSource();
+ addBusStopCircleLayer();
+ initFloatingActionButtons();
+ isLoadingStyle = false;
});
}
@@ -161,12 +155,9 @@ public class CircleLayerActivity extends AppCompatActivity implements View.OnCli
}
private void loadNewStyle() {
- mapboxMap.setStyleUrl(getNextStyle(), new MapboxMap.OnStyleLoadedListener() {
- @Override
- public void onStyleLoaded(String style) {
- addBusStop();
- isLoadingStyle = false;
- }
+ mapboxMap.setStyleUrl(getNextStyle(), style -> {
+ addBusStop();
+ isLoadingStyle = false;
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/CustomSpriteActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/CustomSpriteActivity.java
index 3763b45e7a..8d35e659d3 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/CustomSpriteActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/CustomSpriteActivity.java
@@ -2,7 +2,6 @@ package com.mapbox.mapboxsdk.testapp.activity.style;
import android.graphics.BitmapFactory;
import android.os.Bundle;
-import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
@@ -12,7 +11,6 @@ import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.style.layers.Layer;
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
@@ -45,56 +43,53 @@ public class CustomSpriteActivity extends AppCompatActivity {
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull final MapboxMap map) {
- mapboxMap = map;
- final FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
- fab.setColorFilter(ContextCompat.getColor(CustomSpriteActivity.this, R.color.primary));
- fab.setOnClickListener(new View.OnClickListener() {
- private Point point;
-
- @Override
- public void onClick(View view) {
- if (point == null) {
- Timber.i("First click -> Car");
- // Add an icon to reference later
- mapboxMap.addImage(CUSTOM_ICON, BitmapFactory.decodeResource(getResources(), R.drawable.ic_car_top));
-
- // Add a source with a geojson point
- point = Point.fromCoordinates(Position.fromCoordinates(13.400972d, 52.519003d));
- source = new GeoJsonSource(
- "point",
- FeatureCollection.fromFeatures(new Feature[] {Feature.fromGeometry(point)})
- );
- mapboxMap.addSource(source);
-
- // Add a symbol layer that references that point source
- layer = new SymbolLayer("layer", "point");
- layer.setProperties(
- // Set the id of the sprite to use
- iconImage(CUSTOM_ICON)
- );
-
- // lets add a circle below labels!
- mapboxMap.addLayerBelow(layer, "waterway-label");
-
- fab.setImageResource(R.drawable.ic_directions_car_black);
- } else {
- // Update point
- point = Point.fromCoordinates(
- Position.fromCoordinates(point.getCoordinates().getLongitude() + 0.001,
- point.getCoordinates().getLatitude() + 0.001)
- );
- source.setGeoJson(FeatureCollection.fromFeatures(new Feature[] {Feature.fromGeometry(point)}));
-
- // Move the camera as well
- mapboxMap.moveCamera(CameraUpdateFactory.newLatLng(new LatLng(
- point.getCoordinates().getLatitude(), point.getCoordinates().getLongitude())));
- }
+ mapView.getMapAsync(map -> {
+ mapboxMap = map;
+ final FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
+ fab.setColorFilter(ContextCompat.getColor(CustomSpriteActivity.this, R.color.primary));
+ fab.setOnClickListener(new View.OnClickListener() {
+ private Point point;
+
+ @Override
+ public void onClick(View view) {
+ if (point == null) {
+ Timber.i("First click -> Car");
+ // Add an icon to reference later
+ mapboxMap.addImage(CUSTOM_ICON, BitmapFactory.decodeResource(getResources(), R.drawable.ic_car_top));
+
+ // Add a source with a geojson point
+ point = Point.fromCoordinates(Position.fromCoordinates(13.400972d, 52.519003d));
+ source = new GeoJsonSource(
+ "point",
+ FeatureCollection.fromFeatures(new Feature[] {Feature.fromGeometry(point)})
+ );
+ mapboxMap.addSource(source);
+
+ // Add a symbol layer that references that point source
+ layer = new SymbolLayer("layer", "point");
+ layer.setProperties(
+ // Set the id of the sprite to use
+ iconImage(CUSTOM_ICON)
+ );
+
+ // lets add a circle below labels!
+ mapboxMap.addLayerBelow(layer, "waterway-label");
+
+ fab.setImageResource(R.drawable.ic_directions_car_black);
+ } else {
+ // Update point
+ point = Point.fromCoordinates(
+ Position.fromCoordinates(point.getCoordinates().getLongitude() + 0.001,
+ point.getCoordinates().getLatitude() + 0.001)
+ );
+ source.setGeoJson(FeatureCollection.fromFeatures(new Feature[] {Feature.fromGeometry(point)}));
+
+ // Move the camera as well
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLng(new LatLng(
+ point.getCoordinates().getLatitude(), point.getCoordinates().getLongitude())));
}
- });
- }
+ }
+ });
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/DataDrivenStyleActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/DataDrivenStyleActivity.java
index 571b48daa6..cbac62bcc1 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/DataDrivenStyleActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/DataDrivenStyleActivity.java
@@ -5,14 +5,14 @@ import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
+import android.widget.TextView;
import android.widget.Toast;
+import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
-import com.mapbox.mapboxsdk.style.functions.stops.Stops;
import com.mapbox.mapboxsdk.style.layers.FillLayer;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
import com.mapbox.mapboxsdk.style.sources.Source;
@@ -23,13 +23,16 @@ import java.io.IOException;
import timber.log.Timber;
-import static com.mapbox.mapboxsdk.style.functions.Function.composite;
-import static com.mapbox.mapboxsdk.style.functions.Function.property;
-import static com.mapbox.mapboxsdk.style.functions.Function.zoom;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stop.stop;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stops.categorical;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stops.exponential;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stops.interval;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.color;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.exponential;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
+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.literal;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.match;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.step;
+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.PropertyFactory.fillAntialias;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillColor;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillOpacity;
@@ -53,22 +56,32 @@ public class DataDrivenStyleActivity extends AppCompatActivity {
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(map -> {
+ // Store for later
+ mapboxMap = map;
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(MapboxMap map) {
- // Store for later
- mapboxMap = map;
+ // Add a parks layer
+ addParksLayer();
+
+ // Add debug overlay
+ setupDebugZoomView();
- // Add a parks layer
- addParksLayer();
+ // Center and Zoom (Amsterdam, zoomed to streets)
+ mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(52.379189, 4.899431), 14));
+ });
+ }
- // Center and Zoom (Amsterdam, zoomed to streets)
- mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(52.379189, 4.899431), 14));
+ private void setupDebugZoomView() {
+ final TextView textView = (TextView) findViewById(R.id.textZoom);
+ mapboxMap.setOnCameraChangeListener(new MapboxMap.OnCameraChangeListener() {
+ @Override
+ public void onCameraChange(CameraPosition position) {
+ textView.setText(String.format(getString(R.string.debug_zoom), position.zoom));
}
});
}
+
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_data_driven_style, menu);
@@ -159,12 +172,11 @@ public class DataDrivenStyleActivity extends AppCompatActivity {
assert layer != null;
layer.setProperties(
fillColor(
- zoom(
- exponential(
- stop(1, fillColor(Color.RED)),
- stop(5, fillColor(Color.BLUE)),
- stop(10, fillColor(Color.GREEN))
- ).withBase(0.5f)
+ interpolate(
+ exponential(0.5f), zoom(),
+ stop(1, color(Color.RED)),
+ stop(5, color(Color.BLUE)),
+ stop(10, color(Color.GREEN))
)
)
);
@@ -178,12 +190,11 @@ public class DataDrivenStyleActivity extends AppCompatActivity {
assert layer != null;
layer.setProperties(
fillColor(
- zoom(
- interval(
- stop(1, fillColor(Color.RED)),
- stop(5, fillColor(Color.BLUE)),
- stop(10, fillColor(Color.GREEN))
- )
+ step(zoom(),
+ color(Color.CYAN),
+ stop(1, color(Color.RED)),
+ stop(5, color(Color.BLUE)),
+ stop(10, color(Color.GREEN))
)
)
);
@@ -197,13 +208,12 @@ public class DataDrivenStyleActivity extends AppCompatActivity {
assert layer != null;
layer.setProperties(
fillColor(
- property(
- "stroke-width",
- exponential(
- stop(1f, fillColor(Color.RED)),
- stop(5f, fillColor(Color.BLUE)),
- stop(10f, fillColor(Color.GREEN))
- ).withBase(0.5f)
+ interpolate(
+ exponential(0.5f),
+ get("stroke-width"),
+ stop(1f, color(Color.RED)),
+ stop(5f, color(Color.BLUE)),
+ stop(10f, color(Color.GREEN))
)
)
);
@@ -217,13 +227,13 @@ public class DataDrivenStyleActivity extends AppCompatActivity {
assert layer != null;
layer.setProperties(
fillColor(
- property(
- "name",
- categorical(
- stop("Westerpark", fillColor(Color.RED)),
- stop("Jordaan", fillColor(Color.BLUE)),
- stop("Prinseneiland", fillColor(Color.GREEN))
- ))
+ match(
+ get("name"),
+ literal("Westerpark"), color(Color.RED),
+ literal("Jordaan"), color(Color.BLUE),
+ literal("Prinseneiland"), color(Color.GREEN),
+ color(Color.CYAN)
+ )
)
);
@@ -236,9 +246,7 @@ public class DataDrivenStyleActivity extends AppCompatActivity {
assert layer != null;
layer.setProperties(
fillOpacity(
- property(
- "fill-opacity",
- Stops.<Float>identity())
+ get("fill-opacity")
)
);
@@ -251,13 +259,13 @@ public class DataDrivenStyleActivity extends AppCompatActivity {
assert layer != null;
layer.setProperties(
fillColor(
- property(
- "stroke-width",
- interval(
- stop(1f, fillColor(Color.RED)),
- stop(5f, fillColor(Color.BLUE)),
- stop(10f, fillColor(Color.GREEN))
- ))
+ step(
+ get("stroke-width"),
+ color(Color.CYAN),
+ stop(1f, color(Color.RED)),
+ stop(2f, color(Color.BLUE)),
+ stop(3f, color(Color.GREEN))
+ )
)
);
@@ -270,16 +278,30 @@ public class DataDrivenStyleActivity extends AppCompatActivity {
assert layer != null;
layer.setProperties(
fillColor(
- composite(
- "stroke-width",
- exponential(
- stop(1, 1, fillColor(Color.RED)),
- stop(10, 2, fillColor(Color.BLUE)),
- stop(22, 3, fillColor(Color.GREEN)),
- stop(1, 1, fillColor(Color.CYAN)),
- stop(10, 2, fillColor(Color.GRAY)),
- stop(22, 3, fillColor(Color.YELLOW))
- ).withBase(1f)
+ interpolate(
+ exponential(1f),
+ zoom(),
+ stop(12, step(
+ get("stroke-width"),
+ color(Color.BLACK),
+ stop(1f, color(Color.RED)),
+ stop(2f, color(Color.WHITE)),
+ stop(3f, color(Color.BLUE))
+ )),
+ stop(15, step(
+ get("stroke-width"),
+ color(Color.BLACK),
+ stop(1f, color(Color.YELLOW)),
+ stop(2f, color(Color.LTGRAY)),
+ stop(3f, color(Color.CYAN))
+ )),
+ stop(18, step(
+ get("stroke-width"),
+ color(Color.BLACK),
+ stop(1f, color(Color.WHITE)),
+ stop(2f, color(Color.GRAY)),
+ stop(3f, color(Color.GREEN)))
+ )
)
)
);
@@ -288,21 +310,36 @@ public class DataDrivenStyleActivity extends AppCompatActivity {
}
private void addCompositeIntervalFunction() {
- Timber.i("Add composite exponential function");
+ Timber.i("Add composite interval function");
FillLayer layer = mapboxMap.getLayerAs(AMSTERDAM_PARKS_LAYER);
assert layer != null;
layer.setProperties(
fillColor(
- composite(
- "stroke-width",
- interval(
- stop(1, 1, fillColor(Color.RED)),
- stop(10, 2, fillColor(Color.BLUE)),
- stop(22, 3, fillColor(Color.GREEN)),
- stop(1, 1, fillColor(Color.CYAN)),
- stop(10, 2, fillColor(Color.GRAY)),
- stop(22, 3, fillColor(Color.YELLOW))
+ interpolate(
+ linear(),
+ zoom(),
+ stop(12, step(
+ get("stroke-width"),
+ color(Color.BLACK),
+ stop(1f, color(Color.RED)),
+ stop(2f, color(Color.WHITE)),
+ stop(3f, color(Color.BLUE))
+ )),
+ stop(15, step(
+ get("stroke-width"),
+ color(Color.BLACK),
+ stop(1f, color(Color.YELLOW)),
+ stop(2f, color(Color.LTGRAY)),
+ stop(3f, color(Color.CYAN))
+ )),
+ stop(18, step(
+ get("stroke-width"),
+ color(Color.BLACK),
+ stop(1f, color(Color.WHITE)),
+ stop(2f, color(Color.GRAY)),
+ stop(3f, color(Color.GREEN))
))
+ )
)
);
@@ -315,30 +352,92 @@ public class DataDrivenStyleActivity extends AppCompatActivity {
assert layer != null;
layer.setProperties(
fillColor(
- composite(
- "name",
- categorical(
- stop(7f, "Westerpark", fillColor(Color.RED)),
- stop(8f, "Westerpark", fillColor(Color.BLUE)),
- stop(9f, "Westerpark", fillColor(Color.RED)),
- stop(10f, "Westerpark", fillColor(Color.BLUE)),
- stop(11f, "Westerpark", fillColor(Color.RED)),
- stop(12f, "Westerpark", fillColor(Color.BLUE)),
- stop(13f, "Westerpark", fillColor(Color.RED)),
- stop(14f, "Westerpark", fillColor(Color.BLUE)),
- stop(15f, "Westerpark", fillColor(Color.RED)),
- stop(16f, "Westerpark", fillColor(Color.BLUE)),
- stop(17f, "Westerpark", fillColor(Color.RED)),
- stop(18f, "Westerpark", fillColor(Color.BLUE)),
- stop(19f, "Westerpark", fillColor(Color.RED)),
- stop(20f, "Westerpark", fillColor(Color.BLUE)),
- stop(21f, "Westerpark", fillColor(Color.RED)),
- stop(22f, "Westerpark", fillColor(Color.BLUE)),
- stop(14f, "Jordaan", fillColor(Color.GREEN)),
- stop(18f, "Jordaan", fillColor(Color.CYAN)),
- stop(14f, "Prinseneiland", fillColor(Color.WHITE)),
- stop(18f, "Prinseneiland", fillColor(Color.BLACK))
+ step(zoom(),
+ color(Color.BLACK),
+ stop(7f, match(
+ get("name"),
+ literal("Westerpark"), color(Color.RED),
+ color(Color.BLACK)
+ )),
+ stop(8f, match(
+ get("name"),
+ literal("Westerpark"), color(Color.BLUE),
+ color(Color.BLACK)
+ )),
+ stop(9f, match(
+ get("name"),
+ literal("Westerpark"), color(Color.RED),
+ color(Color.BLACK)
+ )),
+ stop(10f, match(
+ get("name"),
+ literal("Westerpark"), color(Color.BLUE),
+ color(Color.BLACK)
+ )),
+ stop(11f, match(
+ get("name"),
+ literal("Westerpark"), color(Color.RED),
+ color(Color.BLACK)
+ )),
+ stop(12f, match(
+ get("name"),
+ literal("Westerpark"), color(Color.BLUE),
+ color(Color.BLACK)
+ )),
+ stop(13f, match(
+ get("name"),
+ literal("Westerpark"), color(Color.RED),
+ color(Color.BLACK)
+ )),
+ stop(14f, match(
+ get("name"),
+ literal("Westerpark"), color(Color.BLUE),
+ literal("Jordaan"), color(Color.GREEN),
+ literal("PrinsenEiland"), color(Color.WHITE),
+ color(Color.BLACK)
+ )),
+ stop(15f, match(
+ get("name"),
+ literal("Westerpark"), color(Color.RED),
+ color(Color.BLACK)
+ )),
+ stop(16f, match(
+ get("name"),
+ literal("Westerpark"), color(Color.BLUE),
+ color(Color.BLACK)
+ )),
+ stop(17f, match(
+ get("name"),
+ literal("Westerpark"), color(Color.RED),
+ color(Color.BLACK)
+ )),
+ stop(18f, match(
+ get("name"),
+ literal("Westerpark"), color(Color.BLUE),
+ literal("Jordaan"), color(Color.CYAN),
+ color(Color.BLACK)
+ )),
+ stop(19f, match(
+ get("name"),
+ literal("Westerpark"), color(Color.RED),
+ color(Color.BLACK)
+ )),
+ stop(20f, match(
+ get("name"),
+ literal("Westerpark"), color(Color.BLUE),
+ color(Color.BLACK)
+ )),
+ stop(21f, match(
+ get("name"),
+ literal("Westerpark"), color(Color.RED),
+ color(Color.BLACK)
+ )),
+ stop(22f, match(
+ get("name"),
+ literal("Westerpark"), color(Color.BLUE),
+ color(Color.BLACK)
))
+ )
)
);
@@ -359,7 +458,6 @@ public class DataDrivenStyleActivity extends AppCompatActivity {
return;
}
-
// Add a fill layer
mapboxMap.addLayer(new FillLayer(AMSTERDAM_PARKS_LAYER, source.getId())
.withProperties(
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/FillExtrusionActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/FillExtrusionActivity.java
index 52ba8d7c7b..a88a489cb1 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/FillExtrusionActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/FillExtrusionActivity.java
@@ -2,7 +2,6 @@ package com.mapbox.mapboxsdk.testapp.activity.style;
import android.graphics.Color;
import android.os.Bundle;
-import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import com.mapbox.mapboxsdk.camera.CameraPosition;
@@ -10,7 +9,6 @@ import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.style.layers.FillExtrusionLayer;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
import com.mapbox.mapboxsdk.testapp.R;
@@ -35,58 +33,55 @@ public class FillExtrusionActivity extends AppCompatActivity {
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull final MapboxMap map) {
- mapboxMap = map;
- Polygon domTower = Polygon.fromCoordinates(new double[][][] {
- new double[][] {
- new double[] {
- 5.12112557888031,
- 52.09071040847704
- },
- new double[] {
- 5.121227502822875,
- 52.09053901776669
- },
- new double[] {
- 5.121484994888306,
- 52.090601641371805
- },
- new double[] {
- 5.1213884353637695,
- 52.090766439912635
- },
- new double[] {
- 5.12112557888031,
- 52.09071040847704
- }
+ mapView.getMapAsync(map -> {
+ mapboxMap = map;
+ Polygon domTower = Polygon.fromCoordinates(new double[][][] {
+ new double[][] {
+ new double[] {
+ 5.12112557888031,
+ 52.09071040847704
+ },
+ new double[] {
+ 5.121227502822875,
+ 52.09053901776669
+ },
+ new double[] {
+ 5.121484994888306,
+ 52.090601641371805
+ },
+ new double[] {
+ 5.1213884353637695,
+ 52.090766439912635
+ },
+ new double[] {
+ 5.12112557888031,
+ 52.09071040847704
}
- });
-
- GeoJsonSource source = new GeoJsonSource("extrusion-source", domTower);
- map.addSource(source);
-
- mapboxMap.addLayer(
- new FillExtrusionLayer("extrusion-layer", source.getId())
- .withProperties(
- fillExtrusionHeight(40f),
- fillExtrusionOpacity(0.5f),
- fillExtrusionColor(Color.RED)
- )
- );
-
- mapboxMap.animateCamera(
- CameraUpdateFactory.newCameraPosition(
- new CameraPosition.Builder()
- .target(new LatLng(52.09071040847704, 5.12112557888031))
- .tilt(45.0)
- .zoom(18)
- .build()
- ),
- 10000
- );
- }
+ }
+ });
+
+ GeoJsonSource source = new GeoJsonSource("extrusion-source", domTower);
+ map.addSource(source);
+
+ mapboxMap.addLayer(
+ new FillExtrusionLayer("extrusion-layer", source.getId())
+ .withProperties(
+ fillExtrusionHeight(40f),
+ fillExtrusionOpacity(0.5f),
+ fillExtrusionColor(Color.RED)
+ )
+ );
+
+ mapboxMap.animateCamera(
+ CameraUpdateFactory.newCameraPosition(
+ new CameraPosition.Builder()
+ .target(new LatLng(52.09071040847704, 5.12112557888031))
+ .tilt(45.0)
+ .zoom(18)
+ .build()
+ ),
+ 10000
+ );
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/FillExtrusionStyleTestActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/FillExtrusionStyleTestActivity.java
index 24914fcbb2..b872d022e3 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/FillExtrusionStyleTestActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/FillExtrusionStyleTestActivity.java
@@ -5,7 +5,6 @@ import android.support.v7.app.AppCompatActivity;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.testapp.R;
/**
@@ -24,12 +23,7 @@ public class FillExtrusionStyleTestActivity extends AppCompatActivity {
// Initialize map as normal
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(MapboxMap mapboxMap) {
- FillExtrusionStyleTestActivity.this.mapboxMap = mapboxMap;
- }
- });
+ mapView.getMapAsync(mapboxMap -> FillExtrusionStyleTestActivity.this.mapboxMap = mapboxMap);
}
public MapboxMap getMapboxMap() {
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/GeoJsonClusteringActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/GeoJsonClusteringActivity.java
index a2111bc304..8664979292 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/GeoJsonClusteringActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/GeoJsonClusteringActivity.java
@@ -10,7 +10,6 @@ import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.style.layers.CircleLayer;
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
import com.mapbox.mapboxsdk.style.sources.GeoJsonOptions;
@@ -50,15 +49,12 @@ public class GeoJsonClusteringActivity extends AppCompatActivity {
// noinspection ConstantConditions
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(MapboxMap map) {
- mapboxMap = map;
- mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(37.7749, 122.4194), 0));
+ mapView.getMapAsync(map -> {
+ mapboxMap = map;
+ mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(37.7749, 122.4194), 0));
- // Add a clustered source with some layers
- addClusteredGeoJsonSource();
- }
+ // Add a clustered source with some layers
+ addClusteredGeoJsonSource();
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/GridSourceActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/GridSourceActivity.java
new file mode 100644
index 0000000000..9dda0f8fa2
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/GridSourceActivity.java
@@ -0,0 +1,151 @@
+package com.mapbox.mapboxsdk.testapp.activity.style;
+
+import android.graphics.Color;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v7.app.AppCompatActivity;
+
+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.style.layers.LineLayer;
+import com.mapbox.mapboxsdk.style.sources.CustomGeometrySource;
+import com.mapbox.mapboxsdk.style.sources.GeometryTileProvider;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.services.commons.geojson.Feature;
+import com.mapbox.services.commons.geojson.FeatureCollection;
+import com.mapbox.services.commons.geojson.MultiLineString;
+import com.mapbox.services.commons.models.Position;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineColor;
+
+/**
+ * Test activity showcasing using CustomGeometrySource to create a grid overlay on the map.
+ */
+public class GridSourceActivity extends AppCompatActivity implements OnMapReadyCallback {
+
+ private static final String ID_GRID_SOURCE = "grid_source";
+ private static final String ID_GRID_LAYER = "grid_layer";
+
+ private MapView mapView;
+ private MapboxMap mapboxMap;
+
+ /**
+ * Implementation of GeometryTileProvider that returns features representing a zoom-dependent
+ * grid.
+ */
+ static class GridProvider implements GeometryTileProvider {
+ public FeatureCollection getFeaturesForBounds(LatLngBounds bounds, int zoom) {
+ List<Feature> features = new ArrayList<>();
+ double gridSpacing;
+ if (zoom >= 13) {
+ gridSpacing = 0.01;
+ } else if (zoom >= 11) {
+ gridSpacing = 0.05;
+ } else if (zoom == 10) {
+ gridSpacing = .1;
+ } else if (zoom == 9) {
+ gridSpacing = 0.25;
+ } else if (zoom == 8) {
+ gridSpacing = 0.5;
+ } else if (zoom >= 6) {
+ gridSpacing = 1;
+ } else if (zoom == 5) {
+ gridSpacing = 2;
+ } else if (zoom >= 4) {
+ gridSpacing = 5;
+ } else if (zoom == 2) {
+ gridSpacing = 10;
+ } else {
+ gridSpacing = 20;
+ }
+
+ List gridLines = new ArrayList();
+ for (double y = Math.ceil(bounds.getLatNorth() / gridSpacing) * gridSpacing;
+ y >= Math.floor(bounds.getLatSouth() / gridSpacing) * gridSpacing; y -= gridSpacing) {
+ gridLines.add(Arrays.asList(Position.fromCoordinates(bounds.getLonWest(), y),
+ Position.fromCoordinates(bounds.getLonEast(), y)));
+ }
+ features.add(Feature.fromGeometry(MultiLineString.fromCoordinates(gridLines)));
+
+ gridLines = new ArrayList();
+ for (double x = Math.floor(bounds.getLonWest() / gridSpacing) * gridSpacing;
+ x <= Math.ceil(bounds.getLonEast() / gridSpacing) * gridSpacing; x += gridSpacing) {
+ gridLines.add(Arrays.asList(Position.fromCoordinates(x, bounds.getLatSouth()),
+ Position.fromCoordinates(x, bounds.getLatNorth())));
+ }
+ features.add(Feature.fromGeometry(MultiLineString.fromCoordinates(gridLines)));
+
+ return FeatureCollection.fromFeatures(features);
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_grid_source);
+
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(@NonNull final MapboxMap map) {
+ mapboxMap = map;
+
+ // add source
+ CustomGeometrySource source = new CustomGeometrySource(ID_GRID_SOURCE, new GridProvider());
+ mapboxMap.addSource(source);
+
+ // add layer
+ LineLayer layer = new LineLayer(ID_GRID_LAYER, ID_GRID_SOURCE);
+ layer.setProperties(
+ lineColor(Color.parseColor("#000000"))
+ );
+
+ mapboxMap.addLayer(layer);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @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/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleActivity.java
index adce889007..25d1040bf0 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleActivity.java
@@ -12,10 +12,6 @@ import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
-import com.mapbox.mapboxsdk.style.functions.Function;
-import com.mapbox.mapboxsdk.style.functions.stops.ExponentialStops;
-import com.mapbox.mapboxsdk.style.functions.stops.Stop;
import com.mapbox.mapboxsdk.style.layers.CircleLayer;
import com.mapbox.mapboxsdk.style.layers.FillLayer;
import com.mapbox.mapboxsdk.style.layers.Layer;
@@ -42,9 +38,11 @@ import java.util.List;
import timber.log.Timber;
-import static com.mapbox.mapboxsdk.style.functions.Function.zoom;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stop.stop;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stops.exponential;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.color;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.exponential;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.interpolate;
+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.Filter.all;
import static com.mapbox.mapboxsdk.style.layers.Filter.eq;
import static com.mapbox.mapboxsdk.style.layers.Filter.gte;
@@ -85,18 +83,15 @@ public class RuntimeStyleActivity extends AppCompatActivity {
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(MapboxMap map) {
- // Store for later
- mapboxMap = map;
+ mapView.getMapAsync(map -> {
+ // Store for later
+ mapboxMap = map;
- // Center and Zoom (Amsterdam, zoomed to streets)
- mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(52.379189, 4.899431), 14));
+ // Center and Zoom (Amsterdam, zoomed to streets)
+ mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(52.379189, 4.899431), 14));
- mapboxMap.setTransitionDuration(250);
- mapboxMap.setTransitionDelay(50);
- }
+ mapboxMap.setTransitionDuration(250);
+ mapboxMap.setTransitionDelay(50);
});
}
@@ -362,32 +357,29 @@ public class RuntimeStyleActivity extends AppCompatActivity {
private void animateParksSource(final FeatureCollection parks, final int counter) {
Handler handler = new Handler(getMainLooper());
- handler.postDelayed(new Runnable() {
- @Override
- public void run() {
- if (mapboxMap == null) {
- return;
- }
+ handler.postDelayed(() -> {
+ if (mapboxMap == null) {
+ return;
+ }
- Timber.d("Updating parks source");
- // change the source
- int park = counter < parks.getFeatures().size() - 1 ? counter : 0;
+ Timber.d("Updating parks source");
+ // change the source
+ int park = counter < parks.getFeatures().size() - 1 ? counter : 0;
- GeoJsonSource source = mapboxMap.getSourceAs("dynamic-park-source");
+ GeoJsonSource source = mapboxMap.getSourceAs("dynamic-park-source");
- if (source == null) {
- Timber.e("Source not found");
- Toast.makeText(RuntimeStyleActivity.this, "Source not found", Toast.LENGTH_SHORT).show();
- return;
- }
+ if (source == null) {
+ Timber.e("Source not found");
+ Toast.makeText(RuntimeStyleActivity.this, "Source not found", Toast.LENGTH_SHORT).show();
+ return;
+ }
- List<Feature> features = new ArrayList<>();
- features.add(parks.getFeatures().get(park));
- source.setGeoJson(FeatureCollection.fromFeatures(features));
+ List<Feature> features = new ArrayList<>();
+ features.add(parks.getFeatures().get(park));
+ source.setGeoJson(FeatureCollection.fromFeatures(features));
- // Re-post
- animateParksSource(parks, park + 1);
- }
+ // Re-post
+ animateParksSource(parks, park + 1);
}, counter == 0 ? 100 : 1000);
}
@@ -453,32 +445,21 @@ public class RuntimeStyleActivity extends AppCompatActivity {
}
// Set a zoom function to update the color of the water
- layer.setProperties(fillColor(
- zoom(
- exponential(
- stop(1, fillColor(Color.GREEN)),
- stop(4, fillColor(Color.BLUE)),
- stop(12, fillColor(Color.RED)),
- stop(20, fillColor(Color.BLACK))
- ).withBase(0.8f)
+ layer.setProperties(
+ fillColor(
+ interpolate(
+ exponential(0.8f),
+ zoom(),
+ stop(1, color(Color.GREEN)),
+ stop(4, color(Color.BLUE)),
+ stop(12, color(Color.RED)),
+ stop(20, color(Color.BLACK))
+ )
)
- ));
+ );
// do some animations to show it off properly
mapboxMap.animateCamera(CameraUpdateFactory.zoomTo(1), 1500);
-
- PropertyValue<String> fillColor = layer.getFillColor();
- Function<Float, String> function = (Function<Float, String>) fillColor.getFunction();
- if (function != null) {
- ExponentialStops<Float, String> stops = (ExponentialStops) function.getStops();
- Timber.d("Fill color base: %s", stops.getBase());
- Timber.d("Fill color #stops: %s", stops.size());
- if (function.getStops() != null) {
- for (Stop<Float, String> stop : stops) {
- Timber.d("Fill color #stops: %s", stop);
- }
- }
- }
}
private void addCustomTileSource() {
@@ -498,28 +479,25 @@ public class RuntimeStyleActivity extends AppCompatActivity {
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(31, -100), 3));
Handler handler = new Handler(getMainLooper());
- handler.postDelayed(new Runnable() {
- @Override
- public void run() {
- if (mapboxMap == null) {
- return;
- }
+ handler.postDelayed(() -> {
+ if (mapboxMap == null) {
+ return;
+ }
- Timber.d("Styling filtered fill layer");
+ Timber.d("Styling filtered fill layer");
- FillLayer states = (FillLayer) mapboxMap.getLayer("states");
+ FillLayer states = (FillLayer) mapboxMap.getLayer("states");
- if (states != null) {
- states.setFilter(eq("name", "Texas"));
- states.setFillOpacityTransition(new TransitionOptions(2500, 0));
- states.setFillColorTransition(new TransitionOptions(2500, 0));
- states.setProperties(
- fillColor(Color.RED),
- fillOpacity(0.25f)
- );
- } else {
- Toast.makeText(RuntimeStyleActivity.this, "No states layer in this style", Toast.LENGTH_SHORT).show();
- }
+ if (states != null) {
+ states.setFilter(eq("name", "Texas"));
+ states.setFillOpacityTransition(new TransitionOptions(2500, 0));
+ states.setFillColorTransition(new TransitionOptions(2500, 0));
+ states.setProperties(
+ fillColor(Color.RED),
+ fillOpacity(0.25f)
+ );
+ } else {
+ Toast.makeText(RuntimeStyleActivity.this, "No states layer in this style", Toast.LENGTH_SHORT).show();
}
}, 2000);
}
@@ -529,28 +507,25 @@ public class RuntimeStyleActivity extends AppCompatActivity {
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(40, -97), 5));
Handler handler = new Handler(getMainLooper());
- handler.postDelayed(new Runnable() {
- @Override
- public void run() {
- if (mapboxMap == null) {
- return;
- }
+ handler.postDelayed(() -> {
+ if (mapboxMap == null) {
+ return;
+ }
- Timber.d("Styling filtered line layer");
+ Timber.d("Styling filtered line layer");
- LineLayer counties = (LineLayer) mapboxMap.getLayer("counties");
+ LineLayer counties = (LineLayer) mapboxMap.getLayer("counties");
- if (counties != null) {
- counties.setFilter(eq("NAME10", "Washington"));
+ if (counties != null) {
+ counties.setFilter(eq("NAME10", "Washington"));
- counties.setProperties(
- lineColor(Color.RED),
- lineOpacity(0.75f),
- lineWidth(5f)
- );
- } else {
- Toast.makeText(RuntimeStyleActivity.this, "No counties layer in this style", Toast.LENGTH_SHORT).show();
- }
+ counties.setProperties(
+ lineColor(Color.RED),
+ lineOpacity(0.75f),
+ lineWidth(5f)
+ );
+ } else {
+ Toast.makeText(RuntimeStyleActivity.this, "No counties layer in this style", Toast.LENGTH_SHORT).show();
}
}, 2000);
}
@@ -560,27 +535,24 @@ public class RuntimeStyleActivity extends AppCompatActivity {
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(40, -97), 5));
Handler handler = new Handler(getMainLooper());
- handler.postDelayed(new Runnable() {
- @Override
- public void run() {
- if (mapboxMap == null) {
- return;
- }
+ handler.postDelayed(() -> {
+ if (mapboxMap == null) {
+ return;
+ }
- Timber.d("Styling numeric fill layer");
+ Timber.d("Styling numeric fill layer");
- FillLayer regions = (FillLayer) mapboxMap.getLayer("regions");
+ FillLayer regions = (FillLayer) mapboxMap.getLayer("regions");
- if (regions != null) {
- regions.setFilter(all(gte("HRRNUM", 200), lt("HRRNUM", 300)));
+ if (regions != null) {
+ regions.setFilter(all(gte("HRRNUM", 200), lt("HRRNUM", 300)));
- regions.setProperties(
- fillColor(Color.BLUE),
- fillOpacity(0.5f)
- );
- } else {
- Toast.makeText(RuntimeStyleActivity.this, "No regions layer in this style", Toast.LENGTH_SHORT).show();
- }
+ regions.setProperties(
+ fillColor(Color.BLUE),
+ fillOpacity(0.5f)
+ );
+ } else {
+ Toast.makeText(RuntimeStyleActivity.this, "No regions layer in this style", Toast.LENGTH_SHORT).show();
}
}, 2000);
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleTestActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleTestActivity.java
index 910233accf..53f0870d90 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleTestActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleTestActivity.java
@@ -5,7 +5,6 @@ import android.support.v7.app.AppCompatActivity;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.testapp.R;
/**
@@ -24,12 +23,7 @@ public class RuntimeStyleTestActivity extends AppCompatActivity {
// Initialize map as normal
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(MapboxMap mapboxMap) {
- RuntimeStyleTestActivity.this.mapboxMap = mapboxMap;
- }
- });
+ mapView.getMapAsync(mapboxMap -> RuntimeStyleTestActivity.this.mapboxMap = mapboxMap);
}
public MapboxMap getMapboxMap() {
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleTimingTestActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleTimingTestActivity.java
index 5057578731..e51a7ec8a0 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleTimingTestActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleTimingTestActivity.java
@@ -6,7 +6,6 @@ import android.support.v7.app.AppCompatActivity;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.style.layers.CircleLayer;
import com.mapbox.mapboxsdk.style.sources.VectorSource;
import com.mapbox.mapboxsdk.testapp.R;
@@ -32,23 +31,20 @@ public class RuntimeStyleTimingTestActivity extends AppCompatActivity {
// Initialize map as normal
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(MapboxMap mapboxMap) {
- RuntimeStyleTimingTestActivity.this.mapboxMap = mapboxMap;
- VectorSource museums = new VectorSource("museums_source", "mapbox://mapbox.2opop9hr");
- mapboxMap.addSource(museums);
-
- CircleLayer museumsLayer = new CircleLayer("museums", "museums_source");
- museumsLayer.setSourceLayer("museum-cusco");
- museumsLayer.setProperties(
- visibility(VISIBLE),
- circleRadius(8f),
- circleColor(Color.argb(1, 55, 148, 179))
- );
-
- mapboxMap.addLayer(museumsLayer);
- }
+ mapView.getMapAsync(mapboxMap -> {
+ RuntimeStyleTimingTestActivity.this.mapboxMap = mapboxMap;
+ VectorSource museums = new VectorSource("museums_source", "mapbox://mapbox.2opop9hr");
+ mapboxMap.addSource(museums);
+
+ CircleLayer museumsLayer = new CircleLayer("museums", "museums_source");
+ museumsLayer.setSourceLayer("museum-cusco");
+ museumsLayer.setProperties(
+ visibility(VISIBLE),
+ circleRadius(8f),
+ circleColor(Color.argb(1, 55, 148, 179))
+ );
+
+ mapboxMap.addLayer(museumsLayer);
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/StyleFileActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/StyleFileActivity.java
index 49015ec1e9..d2a46c63ae 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/StyleFileActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/StyleFileActivity.java
@@ -3,16 +3,13 @@ package com.mapbox.mapboxsdk.testapp.activity.style;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
-import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
-import android.view.View;
import android.widget.Toast;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.utils.ResourceUtils;
@@ -39,29 +36,16 @@ public class StyleFileActivity extends AppCompatActivity {
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull final MapboxMap map) {
- mapboxMap = map;
-
- FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab_file);
- fab.setColorFilter(ContextCompat.getColor(StyleFileActivity.this, R.color.primary));
- fab.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- new CreateStyleFileTask(view.getContext(), mapboxMap).execute();
- }
- });
-
- FloatingActionButton fabStyleJson = (FloatingActionButton) findViewById(R.id.fab_style_json);
- fabStyleJson.setColorFilter(ContextCompat.getColor(StyleFileActivity.this, R.color.primary));
- fabStyleJson.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- new LoadStyleFileTask(view.getContext(), mapboxMap).execute();
- }
- });
- }
+ mapView.getMapAsync(map -> {
+ mapboxMap = map;
+
+ FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab_file);
+ fab.setColorFilter(ContextCompat.getColor(StyleFileActivity.this, R.color.primary));
+ fab.setOnClickListener(view -> new CreateStyleFileTask(view.getContext(), mapboxMap).execute());
+
+ FloatingActionButton fabStyleJson = (FloatingActionButton) findViewById(R.id.fab_style_json);
+ fabStyleJson.setColorFilter(ContextCompat.getColor(StyleFileActivity.this, R.color.primary));
+ fabStyleJson.setOnClickListener(view -> new LoadStyleFileTask(view.getContext(), mapboxMap).execute());
});
}
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 6e9e45cfaa..1ef59db9b1 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
@@ -16,10 +16,10 @@ import android.widget.TextView;
import android.widget.Toast;
import com.google.gson.GsonBuilder;
-import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
+import com.mapbox.mapboxsdk.style.layers.Filter;
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
import com.mapbox.mapboxsdk.style.sources.Source;
@@ -38,8 +38,24 @@ import java.util.List;
import timber.log.Timber;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.concat;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.division;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.downcase;
+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.pi;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.product;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.upcase;
+import static com.mapbox.mapboxsdk.style.layers.Property.ICON_ANCHOR_BOTTOM;
+import static com.mapbox.mapboxsdk.style.layers.Property.TEXT_ANCHOR_TOP;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAllowOverlap;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAnchor;
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.iconSize;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textAnchor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textField;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textSize;
/**
* Test activity showcasing using a symbol generator that generates Bitmaps from Android SDK Views.
@@ -49,7 +65,10 @@ public class SymbolGeneratorActivity extends AppCompatActivity implements OnMapR
private static final String SOURCE_ID = "com.mapbox.mapboxsdk.style.layers.symbol.source.id";
private static final String LAYER_ID = "com.mapbox.mapboxsdk.style.layers.symbol.layer.id";
private static final String FEATURE_ID = "brk_name";
- private static final String FEATURE_VALUE = "name_sort";
+ private static final String FEATURE_RANK = "scalerank";
+ private static final String FEATURE_NAME = "name_sort";
+ private static final String FEATURE_TYPE = "type";
+ private static final String FEATURE_REGION = "continent";
private MapView mapView;
private MapboxMap mapboxMap;
@@ -68,23 +87,20 @@ public class SymbolGeneratorActivity extends AppCompatActivity implements OnMapR
public void onMapReady(final MapboxMap map) {
mapboxMap = map;
addSymbolClickListener();
- new LoadDataTask(map, SymbolGeneratorActivity.this).execute();
+ new LoadDataTask(this).execute();
}
private void addSymbolClickListener() {
- mapboxMap.setOnMapClickListener(new MapboxMap.OnMapClickListener() {
- @Override
- public void onMapClick(@NonNull LatLng point) {
- PointF screenPoint = mapboxMap.getProjection().toScreenLocation(point);
- List<Feature> features = mapboxMap.queryRenderedFeatures(screenPoint, LAYER_ID);
- if (!features.isEmpty()) {
- Feature feature = features.get(0);
- Timber.v("Feature was clicked with data: %s", feature.toJson());
- Toast.makeText(
- SymbolGeneratorActivity.this,
- "hello from: " + feature.getStringProperty(FEATURE_VALUE),
- Toast.LENGTH_LONG).show();
- }
+ mapboxMap.setOnMapClickListener(point -> {
+ PointF screenPoint = mapboxMap.getProjection().toScreenLocation(point);
+ List<Feature> features = mapboxMap.queryRenderedFeatures(screenPoint, LAYER_ID);
+ if (!features.isEmpty()) {
+ Feature feature = features.get(0);
+ Timber.v("Feature was clicked with data: %s", feature.toJson());
+ Toast.makeText(
+ SymbolGeneratorActivity.this,
+ "hello from: " + feature.getStringProperty(FEATURE_NAME),
+ Toast.LENGTH_LONG).show();
}
});
}
@@ -100,6 +116,12 @@ public class SymbolGeneratorActivity extends AppCompatActivity implements OnMapR
if (item.getItemId() == R.id.menu_action_icon_overlap) {
SymbolLayer layer = mapboxMap.getLayerAs(LAYER_ID);
layer.setProperties(iconAllowOverlap(!layer.getIconAllowOverlap().getValue()));
+ return true;
+ } else if (item.getItemId() == R.id.menu_action_filter) {
+ SymbolLayer layer = mapboxMap.getLayerAs(LAYER_ID);
+ layer.setFilter(Filter.eq(FEATURE_RANK, 1));
+ //layer.setFilter(eq(get(FEATURE_RANK), 1));
+ return true;
}
return super.onOptionsItemSelected(item);
}
@@ -178,19 +200,17 @@ public class SymbolGeneratorActivity extends AppCompatActivity implements OnMapR
private static class LoadDataTask extends AsyncTask<Void, Void, FeatureCollection> {
- private final MapboxMap mapboxMap;
- private final Context context;
+ private SymbolGeneratorActivity activity;
- LoadDataTask(MapboxMap mapboxMap, Context context) {
- this.mapboxMap = mapboxMap;
- this.context = context;
+ LoadDataTask(SymbolGeneratorActivity activity) {
+ this.activity = activity;
}
@Override
protected FeatureCollection doInBackground(Void... params) {
try {
// read local geojson from raw folder
- String tinyCountriesJson = ResourceUtils.readRawResource(context, R.raw.tiny_countries);
+ String tinyCountriesJson = ResourceUtils.readRawResource(activity, R.raw.tiny_countries);
// convert geojson to a model
FeatureCollection featureCollection = new GsonBuilder()
@@ -204,30 +224,54 @@ public class SymbolGeneratorActivity extends AppCompatActivity implements OnMapR
}
}
-
@Override
protected void onPostExecute(FeatureCollection featureCollection) {
super.onPostExecute(featureCollection);
- if (featureCollection == null) {
+ if (featureCollection == null || activity == null) {
return;
}
- // add a geojson to the map
- Source source = new GeoJsonSource(SOURCE_ID, featureCollection);
- mapboxMap.addSource(source);
-
- // create layer use
- mapboxMap.addLayer(new SymbolLayer(LAYER_ID, SOURCE_ID)
- .withProperties(
- iconImage("{" + FEATURE_ID + "}"), // { } is a token notation
- iconAllowOverlap(false)
- )
- );
-
- new GenerateSymbolTask(mapboxMap, context).execute(featureCollection);
+ activity.onDataLoaded(featureCollection);
}
}
+ public void onDataLoaded(@NonNull FeatureCollection featureCollection) {
+ // add a geojson to the map
+ Source source = new GeoJsonSource(SOURCE_ID, featureCollection);
+ mapboxMap.addSource(source);
+
+ // create layer use
+ mapboxMap.addLayer(new SymbolLayer(LAYER_ID, SOURCE_ID)
+ .withProperties(
+
+ // icon configuration
+ iconImage(get(literal(FEATURE_ID))),
+ iconAllowOverlap(false),
+ iconSize(
+ division(get(literal(FEATURE_RANK)), literal(2))
+ ),
+ iconAnchor(ICON_ANCHOR_BOTTOM),
+ iconOffset(new Float[] {0.0f, -5.0f}),
+
+ // text field configuration
+ textField(
+ concat(
+ upcase(literal("a ")),
+ get(literal(FEATURE_TYPE)),
+ downcase(literal(" IN ")),
+ get(literal(FEATURE_REGION))
+ )
+ ),
+ textSize(
+ product(get(literal(FEATURE_RANK)), pi())
+ ),
+ textAnchor(TEXT_ANCHOR_TOP)
+ )
+ );
+
+ new GenerateSymbolTask(mapboxMap, this).execute(featureCollection);
+ }
+
private static class GenerateSymbolTask extends AsyncTask<FeatureCollection, Void, HashMap<String, Bitmap>> {
private MapboxMap mapboxMap;
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolLayerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolLayerActivity.java
index 82da905413..d89d71e604 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolLayerActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolLayerActivity.java
@@ -15,7 +15,6 @@ import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
import com.mapbox.mapboxsdk.testapp.R;
@@ -51,43 +50,40 @@ public class SymbolLayerActivity extends AppCompatActivity implements MapboxMap.
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull final MapboxMap map) {
- mapboxMap = map;
-
- // Add a image for the makers
- mapboxMap.addImage(
- "my-marker-image",
- BitmapFactory.decodeResource(SymbolLayerActivity.this.getResources(),
- R.drawable.mapbox_marker_icon_default)
- );
-
- // Add a source
- FeatureCollection markers = FeatureCollection.fromFeatures(new Feature[] {
- Feature.fromGeometry(Point.fromCoordinates(new double[] {4.91638, 52.35673}), featureProperties("Marker 1")),
- Feature.fromGeometry(Point.fromCoordinates(new double[] {4.91638, 52.34673}), featureProperties("Marker 2"))
- });
- mapboxMap.addSource(new GeoJsonSource(MARKER_SOURCE, markers));
-
- // Add the symbol-layer
- mapboxMap.addLayer(
- new SymbolLayer(MARKER_LAYER, MARKER_SOURCE)
- .withProperties(
- iconImage("my-marker-image"),
- iconAllowOverlap(true),
- textField("{title}"),
- textColor(Color.RED),
- textSize(10f)
- )
- );
-
- // Show
- mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(52.35273, 4.91638), 14));
-
- // Set a click-listener so we can manipulate the map
- mapboxMap.setOnMapClickListener(SymbolLayerActivity.this);
- }
+ mapView.getMapAsync(map -> {
+ mapboxMap = map;
+
+ // Add a image for the makers
+ mapboxMap.addImage(
+ "my-marker-image",
+ BitmapFactory.decodeResource(SymbolLayerActivity.this.getResources(),
+ R.drawable.mapbox_marker_icon_default)
+ );
+
+ // Add a source
+ FeatureCollection markers = FeatureCollection.fromFeatures(new Feature[] {
+ Feature.fromGeometry(Point.fromCoordinates(new double[] {4.91638, 52.35673}), featureProperties("Marker 1")),
+ Feature.fromGeometry(Point.fromCoordinates(new double[] {4.91638, 52.34673}), featureProperties("Marker 2"))
+ });
+ mapboxMap.addSource(new GeoJsonSource(MARKER_SOURCE, markers));
+
+ // Add the symbol-layer
+ mapboxMap.addLayer(
+ new SymbolLayer(MARKER_LAYER, MARKER_SOURCE)
+ .withProperties(
+ iconImage("my-marker-image"),
+ iconAllowOverlap(true),
+ textField("{title}"),
+ textColor(Color.RED),
+ textSize(10f)
+ )
+ );
+
+ // Show
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(52.35273, 4.91638), 14));
+
+ // Set a click-listener so we can manipulate the map
+ mapboxMap.setOnMapClickListener(SymbolLayerActivity.this);
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/ZoomFunctionSymbolLayerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/ZoomFunctionSymbolLayerActivity.java
index abfd7ae529..4a6e62ef7d 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/ZoomFunctionSymbolLayerActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/ZoomFunctionSymbolLayerActivity.java
@@ -2,16 +2,13 @@ package com.mapbox.mapboxsdk.testapp.activity.style;
import android.graphics.PointF;
import android.os.Bundle;
-import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import com.google.gson.JsonObject;
-import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.style.layers.Property;
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
@@ -64,14 +61,11 @@ public class ZoomFunctionSymbolLayerActivity extends AppCompatActivity {
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull final MapboxMap map) {
- mapboxMap = map;
- updateSource();
- addLayer();
- addMapClickListener();
- }
+ mapView.getMapAsync(map -> {
+ mapboxMap = map;
+ updateSource();
+ addLayer();
+ addMapClickListener();
});
}
@@ -131,19 +125,16 @@ public class ZoomFunctionSymbolLayerActivity extends AppCompatActivity {
}
private void addMapClickListener() {
- mapboxMap.setOnMapClickListener(new MapboxMap.OnMapClickListener() {
- @Override
- public void onMapClick(@NonNull LatLng point) {
- PointF screenPoint = mapboxMap.getProjection().toScreenLocation(point);
- List<Feature> featureList = mapboxMap.queryRenderedFeatures(screenPoint, LAYER_ID);
- if (!featureList.isEmpty()) {
- Feature feature = featureList.get(0);
- boolean selectedNow = feature.getBooleanProperty(KEY_PROPERTY_SELECTED);
- isSelected = !selectedNow;
- updateSource();
- } else {
- Timber.e("No features found");
- }
+ mapboxMap.setOnMapClickListener(point -> {
+ PointF screenPoint = mapboxMap.getProjection().toScreenLocation(point);
+ List<Feature> featureList = mapboxMap.queryRenderedFeatures(screenPoint, LAYER_ID);
+ if (!featureList.isEmpty()) {
+ Feature feature = featureList.get(0);
+ boolean selectedNow = feature.getBooleanProperty(KEY_PROPERTY_SELECTED);
+ isSelected = !selectedNow;
+ updateSource();
+ } else {
+ Timber.e("No features found");
}
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/textureview/TextureViewAnimationActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/textureview/TextureViewAnimationActivity.java
index dc95373663..1c023e5780 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/textureview/TextureViewAnimationActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/textureview/TextureViewAnimationActivity.java
@@ -11,7 +11,6 @@ import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.testapp.R;
import java.util.Locale;
@@ -56,22 +55,19 @@ public class TextureViewAnimationActivity extends AppCompatActivity {
private void setupMapView(Bundle savedInstanceState) {
mapView = (MapView) findViewById(R.id.mapView);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(MapboxMap mapboxMap) {
- TextureViewAnimationActivity.this.mapboxMap = mapboxMap;
-
- setFpsView(mapboxMap);
-
- // Animate the map view
- ObjectAnimator animation = ObjectAnimator.ofFloat(mapView, "rotationY", 0.0f, 360f);
- animation.setDuration(3600);
- animation.setRepeatCount(ObjectAnimator.INFINITE);
- animation.start();
-
- // Start an animation on the map as well
- flyTo(mapboxMap, 0, 14);
- }
+ mapView.getMapAsync(mapboxMap -> {
+ TextureViewAnimationActivity.this.mapboxMap = mapboxMap;
+
+ setFpsView(mapboxMap);
+
+ // Animate the map view
+ ObjectAnimator animation = ObjectAnimator.ofFloat(mapView, "rotationY", 0.0f, 360f);
+ animation.setDuration(3600);
+ animation.setRepeatCount(ObjectAnimator.INFINITE);
+ animation.start();
+
+ // Start an animation on the map as well
+ flyTo(mapboxMap, 0, 14);
});
}
@@ -82,12 +78,9 @@ public class TextureViewAnimationActivity extends AppCompatActivity {
new MapboxMap.CancelableCallback() {
@Override
public void onCancel() {
- delayed = new Runnable() {
- @Override
- public void run() {
- delayed = null;
- flyTo(mapboxMap, place, zoom);
- }
+ delayed = () -> {
+ delayed = null;
+ flyTo(mapboxMap, place, zoom);
};
handler.postDelayed(delayed, 2000);
}
@@ -101,12 +94,7 @@ public class TextureViewAnimationActivity extends AppCompatActivity {
private void setFpsView(MapboxMap mapboxMap) {
final TextView fpsView = (TextView) findViewById(R.id.fpsView);
- mapboxMap.setOnFpsChangedListener(new MapboxMap.OnFpsChangedListener() {
- @Override
- public void onFpsChanged(double fps) {
- fpsView.setText(String.format(Locale.US, "FPS: %4.2f", fps));
- }
- });
+ mapboxMap.setOnFpsChangedListener(fps -> fpsView.setText(String.format(Locale.US, "FPS: %4.2f", fps)));
}
@Override
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/textureview/TextureViewDebugModeActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/textureview/TextureViewDebugModeActivity.java
index 87f78cf2c8..007e6c7f2e 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/textureview/TextureViewDebugModeActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/textureview/TextureViewDebugModeActivity.java
@@ -11,12 +11,10 @@ import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
-import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.constants.Style;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
@@ -82,13 +80,10 @@ public class TextureViewDebugModeActivity extends AppCompatActivity implements O
private void setupMapView(Bundle savedInstanceState) {
mapView = (MapView) findViewById(R.id.mapView);
- mapView.addOnMapChangedListener(new MapView.OnMapChangedListener() {
- @Override
- public void onMapChanged(int change) {
- if (change == MapView.DID_FINISH_LOADING_STYLE && mapboxMap != null) {
- Timber.v("New style loaded with JSON: %s", mapboxMap.getStyleJson());
- setupNavigationView(mapboxMap.getLayers());
- }
+ mapView.addOnMapChangedListener(change -> {
+ if (change == MapView.DID_FINISH_LOADING_STYLE && mapboxMap != null) {
+ Timber.v("New style loaded with JSON: %s", mapboxMap.getStyleJson());
+ setupNavigationView(mapboxMap.getLayers());
}
});
@@ -110,25 +105,17 @@ public class TextureViewDebugModeActivity extends AppCompatActivity implements O
private void setFpsView() {
final TextView fpsView = (TextView) findViewById(R.id.fpsView);
- mapboxMap.setOnFpsChangedListener(new MapboxMap.OnFpsChangedListener() {
- @Override
- public void onFpsChanged(double fps) {
- fpsView.setText(String.format(Locale.US,"FPS: %4.2f", fps));
- }
- });
+ mapboxMap.setOnFpsChangedListener(fps -> fpsView.setText(String.format(Locale.US,"FPS: %4.2f", fps)));
}
private void setupNavigationView(List<Layer> layerList) {
final LayerListAdapter adapter = new LayerListAdapter(this, layerList);
ListView listView = (ListView) findViewById(R.id.listView);
listView.setAdapter(adapter);
- listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- Layer clickedLayer = adapter.getItem(position);
- toggleLayerVisibility(clickedLayer);
- closeNavigationView();
- }
+ listView.setOnItemClickListener((parent, view, position, id) -> {
+ Layer clickedLayer = adapter.getItem(position);
+ toggleLayerVisibility(clickedLayer);
+ closeNavigationView();
});
}
@@ -148,44 +135,29 @@ public class TextureViewDebugModeActivity extends AppCompatActivity implements O
private void setupZoomView() {
final TextView textView = (TextView) findViewById(R.id.textZoom);
- mapboxMap.setOnCameraChangeListener(new MapboxMap.OnCameraChangeListener() {
- @Override
- public void onCameraChange(CameraPosition position) {
- textView.setText(String.format(getString(R.string.debug_zoom), position.zoom));
- }
- });
+ mapboxMap.setOnCameraChangeListener(position ->
+ textView.setText(String.format(getString(R.string.debug_zoom), position.zoom)));
}
private void setupDebugChangeView() {
FloatingActionButton fabDebug = (FloatingActionButton) findViewById(R.id.fabDebug);
- fabDebug.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (mapboxMap != null) {
- Timber.d("Debug FAB: isDebug Active? %s", mapboxMap.isDebugActive());
- mapboxMap.cycleDebugOptions();
- }
+ fabDebug.setOnClickListener(view -> {
+ if (mapboxMap != null) {
+ Timber.d("Debug FAB: isDebug Active? %s", mapboxMap.isDebugActive());
+ mapboxMap.cycleDebugOptions();
}
});
}
private void setupStyleChangeView() {
FloatingActionButton fabStyles = (FloatingActionButton) findViewById(R.id.fabStyles);
- fabStyles.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (mapboxMap != null) {
- currentStyleIndex++;
- if (currentStyleIndex == STYLES.length) {
- currentStyleIndex = 0;
- }
- mapboxMap.setStyleUrl(STYLES[currentStyleIndex], new MapboxMap.OnStyleLoadedListener() {
- @Override
- public void onStyleLoaded(String style) {
- Timber.d("Style loaded %s", style);
- }
- });
+ fabStyles.setOnClickListener(view -> {
+ if (mapboxMap != null) {
+ currentStyleIndex++;
+ if (currentStyleIndex == STYLES.length) {
+ currentStyleIndex = 0;
}
+ mapboxMap.setStyleUrl(STYLES[currentStyleIndex], style -> Timber.d("Style loaded %s", style));
}
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/textureview/TextureViewResizeActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/textureview/TextureViewResizeActivity.java
index 388774e6c8..788003d867 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/textureview/TextureViewResizeActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/textureview/TextureViewResizeActivity.java
@@ -9,7 +9,6 @@ import android.view.View;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.testapp.R;
/**
@@ -39,25 +38,17 @@ public class TextureViewResizeActivity extends AppCompatActivity {
private void setupMapView(Bundle savedInstanceState) {
mapView = (MapView) findViewById(R.id.mapView);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(MapboxMap mapboxMap) {
- TextureViewResizeActivity.this.mapboxMap = mapboxMap;
- }
- });
+ mapView.getMapAsync(mapboxMap -> TextureViewResizeActivity.this.mapboxMap = mapboxMap);
}
private void setupFab() {
FloatingActionButton fabDebug = (FloatingActionButton) findViewById(R.id.fabResize);
- fabDebug.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (mapView != null) {
- View parent = findViewById(R.id.coordinator_layout);
- int width = parent.getWidth() == mapView.getWidth() ? parent.getWidth() / 2 : parent.getWidth();
- int height = parent.getHeight() == mapView.getHeight() ? parent.getHeight() / 2 : parent.getHeight();
- mapView.setLayoutParams(new CoordinatorLayout.LayoutParams(width, height));
- }
+ fabDebug.setOnClickListener(view -> {
+ if (mapView != null) {
+ View parent = findViewById(R.id.coordinator_layout);
+ int width = parent.getWidth() == mapView.getWidth() ? parent.getWidth() / 2 : parent.getWidth();
+ int height = parent.getHeight() == mapView.getHeight() ? parent.getHeight() / 2 : parent.getHeight();
+ mapView.setLayoutParams(new CoordinatorLayout.LayoutParams(width, height));
}
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/CustomLocationEngineActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/CustomLocationEngineActivity.java
index 626f7c372d..ff2559089c 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/CustomLocationEngineActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/CustomLocationEngineActivity.java
@@ -4,12 +4,10 @@ import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.view.Menu;
import android.view.MenuItem;
-import android.view.View;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.testapp.R;
/**
@@ -28,21 +26,15 @@ public class CustomLocationEngineActivity extends BaseLocationActivity {
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(MapboxMap map) {
- mapboxMap = map;
- mapboxMap.setLocationSource(MockLocationEngine.getInstance());
- }
+ mapView.getMapAsync(map -> {
+ mapboxMap = map;
+ mapboxMap.setLocationSource(MockLocationEngine.getInstance());
});
locationToggleFab = (FloatingActionButton) findViewById(R.id.fabLocationToggle);
- locationToggleFab.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (mapboxMap != null) {
- enableLocation(!mapboxMap.isMyLocationEnabled());
- }
+ locationToggleFab.setOnClickListener(view -> {
+ if (mapboxMap != null) {
+ enableLocation(!mapboxMap.isMyLocationEnabled());
}
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MockLocationEngine.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MockLocationEngine.java
index df52ccf727..f4b54551bf 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MockLocationEngine.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MockLocationEngine.java
@@ -21,12 +21,9 @@ public class MockLocationEngine extends LocationEngine {
private static int counter;
MockLocationEngine(Location start, Location end) {
- locationAnimator = new LocationAnimator(start, end, new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- for (LocationEngineListener listener : locationListeners) {
- listener.onLocationChanged((Location) animation.getAnimatedValue());
- }
+ locationAnimator = new LocationAnimator(start, end, animation -> {
+ for (LocationEngineListener listener : locationListeners) {
+ listener.onLocationChanged((Location) animation.getAnimatedValue());
}
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationDrawableActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationDrawableActivity.java
index 62b4f4b987..000042306f 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationDrawableActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationDrawableActivity.java
@@ -14,7 +14,6 @@ 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.OnMapReadyCallback;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.services.android.telemetry.location.LocationEngineListener;
@@ -50,12 +49,9 @@ public class MyLocationDrawableActivity extends BaseLocationActivity implements
parent.addView(mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(MapboxMap map) {
- mapboxMap = map;
- toggleGps(true);
- }
+ mapView.getMapAsync(map -> {
+ mapboxMap = map;
+ toggleGps(true);
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTintActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTintActivity.java
index 9dc8c1a607..89774dc507 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTintActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTintActivity.java
@@ -15,7 +15,6 @@ import com.mapbox.mapboxsdk.constants.MyLocationTracking;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.TrackingSettings;
import com.mapbox.mapboxsdk.maps.widgets.MyLocationViewSettings;
import com.mapbox.mapboxsdk.testapp.R;
@@ -37,80 +36,65 @@ public class MyLocationTintActivity extends BaseLocationActivity implements Loca
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(MapboxMap map) {
- mapboxMap = map;
-
- // enable location updates
- toggleGps(true);
-
- // add some padding
- final MyLocationViewSettings myLocationViewSettings = mapboxMap.getMyLocationViewSettings();
- myLocationViewSettings.setPadding(0, 500, 0, 0);
-
- // enable tracking
- TrackingSettings settings = mapboxMap.getTrackingSettings();
- settings.setDismissLocationTrackingOnGesture(false);
- settings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW);
-
- // handle default button clicks
- ViewUtils.attachClickListener(
- MyLocationTintActivity.this,
- R.id.default_user_dot_coloring_button,
- new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- myLocationViewSettings.setAccuracyTintColor(ContextCompat.getColor(
- MyLocationTintActivity.this, R.color.mapbox_blue));
- myLocationViewSettings.setForegroundTintColor(ContextCompat.getColor(
- MyLocationTintActivity.this, R.color.mapbox_blue));
- myLocationViewSettings.setBackgroundTintColor(Color.WHITE);
- }
- });
-
- // handle tint user dot button clicks
- ViewUtils.attachClickListener(
- MyLocationTintActivity.this,
- R.id.tint_user_dot_button,
- new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- myLocationViewSettings.setAccuracyTintColor(
- ContextCompat.getColor(MyLocationTintActivity.this, R.color.mapboxGreen));
- myLocationViewSettings.setForegroundTintColor(
- ContextCompat.getColor(MyLocationTintActivity.this, R.color.mapboxGreen));
- myLocationViewSettings.setBackgroundTintColor(Color.WHITE);
- }
- });
-
- // handle tint accuracy ring button clicks
- ViewUtils.attachClickListener(
- MyLocationTintActivity.this,
- R.id.user_accuracy_ring_tint_button,
- new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- myLocationViewSettings.setAccuracyTintColor(
- ContextCompat.getColor(MyLocationTintActivity.this, R.color.accent));
- myLocationViewSettings.setForegroundTintColor(
- ContextCompat.getColor(MyLocationTintActivity.this, R.color.mapbox_blue));
- myLocationViewSettings.setBackgroundTintColor(Color.WHITE);
- }
- });
-
- ViewUtils.attachClickListener(
- MyLocationTintActivity.this,
- R.id.user_dot_transparent_button,
- new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- myLocationViewSettings.setForegroundTintColor(Color.TRANSPARENT);
- myLocationViewSettings.setBackgroundTintColor(Color.TRANSPARENT);
- }
- }
- );
- }
+ mapView.getMapAsync(map -> {
+ mapboxMap = map;
+
+ // enable location updates
+ toggleGps(true);
+
+ // add some padding
+ final MyLocationViewSettings myLocationViewSettings = mapboxMap.getMyLocationViewSettings();
+ myLocationViewSettings.setPadding(0, 500, 0, 0);
+
+ // enable tracking
+ TrackingSettings settings = mapboxMap.getTrackingSettings();
+ settings.setDismissLocationTrackingOnGesture(false);
+ settings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW);
+
+ // handle default button clicks
+ ViewUtils.attachClickListener(
+ MyLocationTintActivity.this,
+ R.id.default_user_dot_coloring_button,
+ view -> {
+ myLocationViewSettings.setAccuracyTintColor(ContextCompat.getColor(
+ MyLocationTintActivity.this, R.color.mapbox_blue));
+ myLocationViewSettings.setForegroundTintColor(ContextCompat.getColor(
+ MyLocationTintActivity.this, R.color.mapbox_blue));
+ myLocationViewSettings.setBackgroundTintColor(Color.WHITE);
+ });
+
+ // handle tint user dot button clicks
+ ViewUtils.attachClickListener(
+ MyLocationTintActivity.this,
+ R.id.tint_user_dot_button,
+ view -> {
+ myLocationViewSettings.setAccuracyTintColor(
+ ContextCompat.getColor(MyLocationTintActivity.this, R.color.mapboxGreen));
+ myLocationViewSettings.setForegroundTintColor(
+ ContextCompat.getColor(MyLocationTintActivity.this, R.color.mapboxGreen));
+ myLocationViewSettings.setBackgroundTintColor(Color.WHITE);
+ });
+
+ // handle tint accuracy ring button clicks
+ ViewUtils.attachClickListener(
+ MyLocationTintActivity.this,
+ R.id.user_accuracy_ring_tint_button,
+ view -> {
+ myLocationViewSettings.setAccuracyTintColor(
+ ContextCompat.getColor(MyLocationTintActivity.this, R.color.accent));
+ myLocationViewSettings.setForegroundTintColor(
+ ContextCompat.getColor(MyLocationTintActivity.this, R.color.mapbox_blue));
+ myLocationViewSettings.setBackgroundTintColor(Color.WHITE);
+ });
+
+ ViewUtils.attachClickListener(
+ MyLocationTintActivity.this,
+ R.id.user_dot_transparent_button,
+ view -> {
+ myLocationViewSettings.setForegroundTintColor(Color.TRANSPARENT);
+ myLocationViewSettings.setBackgroundTintColor(Color.TRANSPARENT);
+ }
+ );
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationToggleActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationToggleActivity.java
index 718c10c7cb..ea3a6f14bc 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationToggleActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationToggleActivity.java
@@ -2,11 +2,9 @@ package com.mapbox.mapboxsdk.testapp.activity.userlocation;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
-import android.view.View;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.testapp.R;
import timber.log.Timber;
@@ -27,20 +25,12 @@ public class MyLocationToggleActivity extends BaseLocationActivity {
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(MapboxMap map) {
- mapboxMap = map;
- }
- });
+ mapView.getMapAsync(map -> mapboxMap = map);
locationToggleFab = (FloatingActionButton) findViewById(R.id.fabLocationToggle);
- locationToggleFab.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (mapboxMap != null) {
- toggleGps(!mapboxMap.isMyLocationEnabled());
- }
+ locationToggleFab.setOnClickListener(view -> {
+ if (mapboxMap != null) {
+ toggleGps(!mapboxMap.isMyLocationEnabled());
}
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTrackingModeActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTrackingModeActivity.java
index d910a19d5d..5ebe43e68c 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTrackingModeActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTrackingModeActivity.java
@@ -125,41 +125,35 @@ public class MyLocationTrackingModeActivity extends AppCompatActivity implements
bearingSpinner.setOnItemSelectedListener(MyLocationTrackingModeActivity.this);
setCheckBoxes();
- mapboxMap.setOnMyLocationTrackingModeChangeListener(new MapboxMap.OnMyLocationTrackingModeChangeListener() {
- @Override
- public void onMyLocationTrackingModeChange(@MyLocationTracking.Mode int myLocationTrackingMode) {
- locationSpinner.setOnItemSelectedListener(null);
- switch (myLocationTrackingMode) {
- case MyLocationTracking.TRACKING_NONE:
- locationSpinner.setSelection(TRACKING_NONE_INDEX);
- break;
- case MyLocationTracking.TRACKING_FOLLOW:
- locationSpinner.setSelection(TRACKING_FOLLOW_INDEX);
- break;
- }
- locationSpinner.setOnItemSelectedListener(MyLocationTrackingModeActivity.this);
+ mapboxMap.setOnMyLocationTrackingModeChangeListener(myLocationTrackingMode -> {
+ locationSpinner.setOnItemSelectedListener(null);
+ switch (myLocationTrackingMode) {
+ case MyLocationTracking.TRACKING_NONE:
+ locationSpinner.setSelection(TRACKING_NONE_INDEX);
+ break;
+ case MyLocationTracking.TRACKING_FOLLOW:
+ locationSpinner.setSelection(TRACKING_FOLLOW_INDEX);
+ break;
}
+ locationSpinner.setOnItemSelectedListener(MyLocationTrackingModeActivity.this);
});
- mapboxMap.setOnMyBearingTrackingModeChangeListener(new MapboxMap.OnMyBearingTrackingModeChangeListener() {
- @Override
- public void onMyBearingTrackingModeChange(@MyBearingTracking.Mode int myBearingTrackingMode) {
- bearingSpinner.setOnItemSelectedListener(null);
- switch (myBearingTrackingMode) {
- case MyBearingTracking.NONE:
- bearingSpinner.setSelection(BEARING_NONE_INDEX);
- break;
-
- case MyBearingTracking.GPS:
- bearingSpinner.setSelection(BEARING_GPS_INDEX);
- break;
-
- case MyBearingTracking.COMPASS:
- bearingSpinner.setSelection(BEARING_COMPASS_INDEX);
- break;
- }
- bearingSpinner.setOnItemSelectedListener(MyLocationTrackingModeActivity.this);
+ mapboxMap.setOnMyBearingTrackingModeChangeListener(myBearingTrackingMode -> {
+ bearingSpinner.setOnItemSelectedListener(null);
+ switch (myBearingTrackingMode) {
+ case MyBearingTracking.NONE:
+ bearingSpinner.setSelection(BEARING_NONE_INDEX);
+ break;
+
+ case MyBearingTracking.GPS:
+ bearingSpinner.setSelection(BEARING_GPS_INDEX);
+ break;
+
+ case MyBearingTracking.COMPASS:
+ bearingSpinner.setSelection(BEARING_COMPASS_INDEX);
+ break;
}
+ bearingSpinner.setOnItemSelectedListener(MyLocationTrackingModeActivity.this);
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/adapter/FeatureSectionAdapter.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/adapter/FeatureSectionAdapter.java
index 1d89f89f08..65e2b4f185 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/adapter/FeatureSectionAdapter.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/adapter/FeatureSectionAdapter.java
@@ -14,7 +14,6 @@ import android.widget.TextView;
import com.mapbox.mapboxsdk.testapp.utils.FontCache;
import java.util.Arrays;
-import java.util.Comparator;
public class FeatureSectionAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
@@ -126,14 +125,9 @@ public class FeatureSectionAdapter extends RecyclerView.Adapter<RecyclerView.Vie
public void setSections(Section[] sections) {
this.sections.clear();
- Arrays.sort(sections, new Comparator<Section>() {
- @Override
- public int compare(Section section, Section section1) {
- return (section.firstPosition == section1.firstPosition)
- ? 0
- : ((section.firstPosition < section1.firstPosition) ? -1 : 1);
- }
- });
+ Arrays.sort(sections, (section, section1) -> (section.firstPosition == section1.firstPosition)
+ ? 0
+ : ((section.firstPosition < section1.firstPosition) ? -1 : 1));
int offset = 0;
for (Section section : sections) {
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineDownloadRegionDialog.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineDownloadRegionDialog.java
index c4aa934139..89096a0a6b 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineDownloadRegionDialog.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineDownloadRegionDialog.java
@@ -2,18 +2,16 @@ package com.mapbox.mapboxsdk.testapp.model.other;
import android.app.Activity;
import android.app.Dialog;
-import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
-
-import timber.log.Timber;
-
import android.widget.EditText;
import com.mapbox.mapboxsdk.testapp.R;
+import timber.log.Timber;
+
public class OfflineDownloadRegionDialog extends DialogFragment {
public interface DownloadRegionDialogListener {
@@ -39,18 +37,10 @@ public class OfflineDownloadRegionDialog extends DialogFragment {
builder.setTitle("Choose a name for the region")
.setIcon(R.drawable.ic_airplanemode_active_black)
.setView(regionNameEdit)
- .setPositiveButton("Start", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- String regionName = regionNameEdit.getText().toString();
- listener.onDownloadRegionDialogPositiveClick(regionName);
- }
- }).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- Timber.d("Download cancelled.");
- }
- });
+ .setPositiveButton("Start", (dialog, which) -> {
+ String regionName = regionNameEdit.getText().toString();
+ listener.onDownloadRegionDialogPositiveClick(regionName);
+ }).setNegativeButton("Cancel", (dialog, which) -> Timber.d("Download cancelled."));
return builder.create();
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineListRegionsDialog.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineListRegionsDialog.java
index 76f07ba526..dbaae589ef 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineListRegionsDialog.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineListRegionsDialog.java
@@ -1,18 +1,17 @@
package com.mapbox.mapboxsdk.testapp.model.other;
import android.app.Dialog;
-import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
-import timber.log.Timber;
-
import com.mapbox.mapboxsdk.testapp.R;
import java.util.ArrayList;
+import timber.log.Timber;
+
public class OfflineListRegionsDialog extends DialogFragment {
public static final String ITEMS = "ITEMS";
@@ -29,18 +28,8 @@ public class OfflineListRegionsDialog extends DialogFragment {
builder.setTitle("List of offline regions")
.setIcon(R.drawable.ic_airplanemode_active_black)
- .setItems(items, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- Timber.d("Selected item: %s", which);
- }
- })
- .setPositiveButton("Accept", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- Timber.d("Dialog dismissed");
- }
- });
+ .setItems(items, (dialog, which) -> Timber.d("Selected item: %s", which))
+ .setPositiveButton("Accept", (dialog, which) -> Timber.d("Dialog dismissed"));
return builder.create();
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/FontCache.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/FontCache.java
index 10ecf43bd3..a4352d0b1c 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/FontCache.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/FontCache.java
@@ -3,10 +3,10 @@ package com.mapbox.mapboxsdk.testapp.utils;
import android.content.Context;
import android.graphics.Typeface;
-import timber.log.Timber;
-
import java.util.Hashtable;
+import timber.log.Timber;
+
public class FontCache {
private static Hashtable<String, Typeface> fontCache = new Hashtable<>();
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/GeoParseUtil.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/GeoParseUtil.java
index 0d21fd2c71..97f70e33bb 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/GeoParseUtil.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/GeoParseUtil.java
@@ -2,12 +2,11 @@ package com.mapbox.mapboxsdk.testapp.utils;
import android.content.Context;
import android.text.TextUtils;
-
import com.mapbox.mapboxsdk.geometry.LatLng;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
+import com.mapbox.services.commons.geojson.Feature;
+import com.mapbox.services.commons.geojson.FeatureCollection;
+import com.mapbox.services.commons.geojson.Point;
+import com.mapbox.services.commons.models.Position;
import java.io.BufferedReader;
import java.io.IOException;
@@ -29,34 +28,13 @@ public class GeoParseUtil {
return readAll(rd);
}
- public static List<LatLng> parseGeoJsonCoordinates(String geojsonStr) throws JSONException {
+ public static List<LatLng> parseGeoJsonCoordinates(String geojsonStr) {
List<LatLng> latLngs = new ArrayList<>();
- JSONObject jsonObject = new JSONObject(geojsonStr);
- JSONArray features = jsonObject.getJSONArray("features");
- int featureLength = features.length();
- for (int j = 0; j < featureLength; ++j) {
- JSONObject feature = features.getJSONObject(j);
- JSONObject geometry = feature.getJSONObject("geometry");
- String type = geometry.getString("type");
- JSONArray coordinates;
- if (type.equals("Polygon")) {
- coordinates = geometry.getJSONArray("coordinates").getJSONArray(0);
- } else {
- coordinates = geometry.getJSONArray("coordinates");
- }
- int len = coordinates.length();
- for (int i = 0; i < len; ++i) {
- if (coordinates.get(i) instanceof JSONArray) {
- JSONArray coord = coordinates.getJSONArray(i);
- double lng = coord.getDouble(0);
- double lat = coord.getDouble(1);
- latLngs.add(new LatLng(lat, lng));
- } else {
- double lng = coordinates.getDouble(0);
- double lat = coordinates.getDouble(1);
- latLngs.add(new LatLng(lat, lng));
- break;
- }
+ FeatureCollection featureCollection = FeatureCollection.fromJson(geojsonStr);
+ for (Feature feature : featureCollection.getFeatures()) {
+ if (feature.getGeometry() instanceof Point) {
+ Position point = ((Point) feature.getGeometry()).getCoordinates();
+ latLngs.add(new LatLng(point.getLatitude(), point.getLongitude()));
}
}
return latLngs;
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/OfflineUtils.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/OfflineUtils.java
index 6220dc7e69..d4ec95ce5c 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/OfflineUtils.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/OfflineUtils.java
@@ -2,9 +2,10 @@ package com.mapbox.mapboxsdk.testapp.utils;
import android.support.annotation.NonNull;
-import timber.log.Timber;
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
-import org.json.JSONObject;
+import timber.log.Timber;
import static com.mapbox.mapboxsdk.testapp.activity.offline.OfflineActivity.JSON_CHARSET;
import static com.mapbox.mapboxsdk.testapp.activity.offline.OfflineActivity.JSON_FIELD_REGION_NAME;
@@ -14,24 +15,22 @@ public class OfflineUtils {
public static String convertRegionName(@NonNull byte[] metadata) {
try {
String json = new String(metadata, JSON_CHARSET);
- JSONObject jsonObject = new JSONObject(json);
- return jsonObject.getString(JSON_FIELD_REGION_NAME);
+ JsonObject jsonObject = new Gson().fromJson(json, JsonObject.class);
+ return jsonObject.get(JSON_FIELD_REGION_NAME).getAsString();
} catch (Exception exception) {
return null;
}
}
public static byte[] convertRegionName(String regionName) {
- byte[] metadata = null;
try {
- JSONObject jsonObject = new JSONObject();
- jsonObject.put(JSON_FIELD_REGION_NAME, regionName);
- String json = jsonObject.toString();
- metadata = json.getBytes(JSON_CHARSET);
+ JsonObject jsonObject = new JsonObject();
+ jsonObject.addProperty(JSON_FIELD_REGION_NAME, regionName);
+ return jsonObject.toString().getBytes(JSON_CHARSET);
} catch (Exception exception) {
Timber.e(exception, "Failed to encode metadata: ");
}
- return metadata;
+ return null;
}
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_data_driven_style.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_data_driven_style.xml
index 7454ce5860..2cbe20b47f 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_data_driven_style.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_data_driven_style.xml
@@ -9,4 +9,16 @@
android:layout_width="match_parent"
android:layout_height="match_parent"/>
+ <TextView
+ android:id="@+id/textZoom"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentRight="true"
+ android:layout_gravity="bottom|start"
+ android:layout_margin="8dp"
+ android:textIsSelectable="true"
+ android:textSize="14sp"/>
+
</RelativeLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_grid_source.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_grid_source.xml
new file mode 100644
index 0000000000..26b40b9ab6
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_grid_source.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <com.mapbox.mapboxsdk.maps.MapView
+ android:id="@id/mapView"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ app:mapbox_cameraTargetLat="41.9567"
+ app:mapbox_cameraTargetLng="-78.6430"
+ app:mapbox_cameraZoom="5"
+ app:mapbox_styleUrl="@string/mapbox_style_mapbox_streets"/>
+
+</RelativeLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_local_glyph.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_local_glyph.xml
index 1f8bc93d2c..856dd24752 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_local_glyph.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_local_glyph.xml
@@ -12,6 +12,6 @@
android:id="@id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
- app:mapbox_localIdeographFontFamily="sans-serif" />
+ app:mapbox_localIdeographFontFamily="Droid Sans" />
</LinearLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_generator_symbol.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_generator_symbol.xml
index 168361a263..613bdd21ef 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_generator_symbol.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_generator_symbol.xml
@@ -5,4 +5,8 @@
android:id="@+id/menu_action_icon_overlap"
android:title="@string/menuitem_change_icon_overlap"
app:showAsAction="never"/>
+ <item
+ android:id="@+id/menu_action_filter"
+ android:title="@string/menuitem_filter"
+ app:showAsAction="never"/>
</menu>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/actions.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/actions.xml
index 5c0828ab74..e7d140d7d4 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/actions.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/actions.xml
@@ -11,6 +11,7 @@
<string name="menuitem_title_change_location_source_mock">Change to mock location source</string>
<string name="menuitem_title_change_location_source_null">Reset location source to null</string>
<string name="menuitem_change_icon_overlap">Toggle icon overlap</string>
+ <string name="menuitem_filter">Filter layer</string>
<string name="menuitem_change_location">Change location</string>
<string name="menuitem_title_accelerate_decelerate">Accelerate/Decelerate interpolator</string>
<string name="menuitem_title_bounce">Bounce interpolator</string>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml
index a13dd5d876..e70c3410a8 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml
@@ -43,7 +43,7 @@
<string name="description_query_rendered_feature_properties_point">Query rendered feature properties on click</string>
<string name="description_query_rendered_features_box_count">Count all rendered features in box</string>
<string name="description_query_rendered_features_box_symbol_count">Count all rendered symbols in box</string>
- <string name="description_query_rendered_features_box_highlight">Hightligh buildings in box</string>
+ <string name="description_query_rendered_features_box_highlight">Highlight buildings in box</string>
<string name="description_query_source_features">Query source for features</string>
<string name="description_simple_map">Shows a simple map</string>
<string name="description_map_change">Logs map change events to Logcat</string>
@@ -67,5 +67,6 @@
<string name="description_textureview_debug">Use TextureView to render the map</string>
<string name="description_textureview_resize">Resize a map rendered on a TextureView</string>
<string name="description_textureview_animate">Animate a map rendered on a TextureView</string>
- <string name="description_local_glyph">Suzhou using local sans-serif for Chinese glyphs</string>
-</resources> \ No newline at end of file
+ <string name="description_grid_source">Example Custom Geometry Source</string>
+ <string name="description_local_glyph">Suzhou using Droid Sans for Chinese glyphs</string>
+</resources>
diff --git a/platform/android/README.md b/platform/android/README.md
index 3787ff85fe..1dbdeee343 100644
--- a/platform/android/README.md
+++ b/platform/android/README.md
@@ -2,9 +2,9 @@
[![Circle CI build status](https://circleci.com/gh/mapbox/mapbox-gl-native.svg?style=shield)](https://circleci.com/gh/mapbox/workflows/mapbox-gl-native/tree/master)
-A library based on [Mapbox GL Native](../../README.md) for embedding interactive map views with scalable, customizable vector maps into Java applications on Android devices.
+A library based on [Mapbox GL Native](../../README.md) for embedding interactive map views with scalable, customizable vector maps onto Android devices.
-## Getting Started
+## Getting Started
Alright. So, actually, you may be in the wrong place. From here on in, this README is going to be for people who are interested in working on and improving on Mapbox GL Native for Android.
@@ -23,79 +23,92 @@ Alright. So, actually, you may be in the wrong place. From here on in, this READ
Clone the git repository
```bash
-git clone https://github.com/mapbox/mapbox-gl-native.git
-cd mapbox-gl-native
+git clone git@github.com:mapbox/mapbox-gl-native.git && cd mapbox-gl-native
```
#### Installing dependencies
These dependencies are required for all operating systems and all platform targets.
-- Latest stable [Android Studio](https://developer.android.com/studio/index.html)
-- Update Android SDK with latest
- - Android SDK Build-Tools
+- Latest stable [Android Studio](https://developer.android.com/studio/index.html)
+- Update the Mapbox Maps SDK for Android with the latest
+ - Android SDK Build-Tools
- Android Platform-Tools
- Android SDK Tools
- CMake
- NDK
- LLDB
-
- Modern C++ compiler that supports `-std=c++14`\*
- clang++ 3.5 or later or
- g++-4.9 or later
-- [cURL](https://curl.haxx.se) (for build only)
-- [Node.js](https://nodejs.org/) or later (for build only)
-- [pkg-config](https://wiki.freedesktop.org/www/Software/pkg-config/) (for build only)
+- [Node.js](https://nodejs.org/)
+ - make sure [npm](https://www.npmjs.com) is installed as well
+- [ccache](https://ccache.samba.org/) (optional)
**Note**: We partially support C++14 because GCC 4.9 does not fully implement the
final draft of the C++14 standard. More information in [DEVELOPING.md](DEVELOPING.md).
-##### Additional Dependencies for Linux
+**Note**: On macOS you can install clang with installing the [Apple command line developer tools](https://developer.apple.com/download/).
+
+### Opening the project
-_These instructions were tested on Ubuntu 16.04 LTS (aka Xenial Xerus)._
+#### macOS
+
+Execute the following command in this repository's root folder to generate the required build files and open the project with Android Studio:
```
-$ sudo apt-get install -y build-essential curl lib32stdc++6 lib32z1 pkg-config python
+make aproj
```
-##### Additional Dependencies for macOS
+#### linux
-- Apple Command Line Tools (available at [Apple Developer](https://developer.apple.com/download/more/))
-- [xcpretty](https://github.com/supermarin/xcpretty) (`gem install xcpretty`)
+run `make android-configuration` in the root folder of the project and open the Android Studio project in `/platform/android`.
+If you are using Arch Linux, install [ncurses5-compat-libs](https://aur.archlinux.org/packages/ncurses5-compat-libs).
-#### Open project in Android Studio
+### Project configuration
-##### macOS
+#### Setup Checkstyle
-Execute the following to generate the required build files and open the project with Android Studio:
+Mapbox uses specific IDE settings related to code and check style.
+See [checkstyle guide](https://github.com/mapbox/mapbox-gl-native/wiki/Setting-up-Mapbox-checkstyle) for configuration details.
-```
-make aproj
-```
+##### Setting Mapbox Access Token
-##### linux
+_The test application (used for development purposes) uses Mapbox vector tiles, which require a Mapbox account and API access token. Obtain a free access token on the [Mapbox account page](https://www.mapbox.com/studio/account/tokens/)._
-Open Android Studio project in `/platform/android`, run `make android-configuration` in the root folder of the project.
+With the first gradle invocation, gradle will take the value of the `MAPBOX_ACCESS_TOKEN` environment variable and save it to `MapboxGLAndroidSDKTestApp/src/main/res/values/developer-config.xml`. If the environment variable wasn't set, you can edit `developer-config.xml` manually and add your access token to the `mapbox_access_token` resource.
-##### Setup Checkstyle
+### Running project
-Mapbox uses specific IDE settings related to code and check style.
-See [checkstyle guide](https://github.com/mapbox/mapbox-gl-native/wiki/Setting-up-Mapbox-checkstyle) for configuration details.
+Run the configuration for the `MapboxGLAndroidSDKTestApp` module and select a device or emulator to deploy on. Based on the selected device, the c++ code will be compiled for the related processor architecture. You can see the project compiling in the `View > Tool Windows > Gradle Console`.
-##### Setting Mapbox Access Token
+More information about building and distributing this project in [DISTRIBUTE.md](https://github.com/mapbox/mapbox-gl-native/blob/master/platform/android/DISTRIBUTE.md).
-_The test application (used for development purposes) uses Mapbox vector tiles, which require a Mapbox account and API access token. Obtain a free access token on the [Mapbox account page](https://www.mapbox.com/studio/account/tokens/)._
+### Additional resources
-With the first gradle invocation, gradle will take the value of the `MAPBOX_ACCESS_TOKEN` environment variable and save it to `MapboxGLAndroidSDKTestApp/src/main/res/values/developer-config.xml`. If the environement variable wasn't set, you can edit `developer-config.xml` manually and add your access token to the `mapbox_access_token` resource.
+#### Using the SDK snapshot
-#### Running project
+Instead of using the latest stable release of the Maps SDK for Android, you can use a "snapshot" or the beta version if there is one available. Our snapshots are built every time a Github pull request adds code to this repository's `master` branch. If you'd like to use a snapshot build, your Android project's gradle file should have -SNAPSHOT appended to the SDK version number. For example `5.2.0-SNAPSHOT` or:
-Run the configuration for the `MapboxGLAndroidSDKTestApp` module and select a device or emulator to deploy on. Based on the selected device, the c++ code will be compiled for the related processor architecture. You can see the project compiling in the `View > Tool Windows > Gradle Console`.
+```java
+// Mapbox SDK dependency
+compile('com.mapbox.mapboxsdk:mapbox-android-sdk:5.2.0-SNAPSHOT@aar') {
+ transitive = true
+}
+```
+You need to have the section below in your build.gradle root folder to be able to resolve the SNAPSHOT dependencies:
+```
+allprojects {
+ repositories {
+ jcenter()
+ maven { url "http://oss.sonatype.org/content/repositories/snapshots/" }
+ }
+}
+```
-More information about building and distributing this project in [DISTRIBUTE.md][https://github.com/mapbox/mapbox-gl-native/blob/master/platform/android/DISTRIBUTE.md].
#### Symbolicating native crashes
-When hitting native crashes you can use ndk-stack to symbolicate crashes.
-More information in [this](https://github.com/mapbox/mapbox-gl-native/wiki/Getting-line-numbers-from-an-Android-crash-with-ndk-stack) guide. \ No newline at end of file
+When hitting native crashes you can use ndk-stack to symbolicate crashes.
+More information in [this](https://github.com/mapbox/mapbox-gl-native/wiki/Getting-line-numbers-from-an-Android-crash-with-ndk-stack) guide.
diff --git a/platform/android/build.gradle b/platform/android/build.gradle
index f3301d0b5a..28d5363797 100644
--- a/platform/android/build.gradle
+++ b/platform/android/build.gradle
@@ -1,16 +1,17 @@
buildscript {
repositories {
jcenter()
+ google()
}
dependencies {
- classpath 'com.android.tools.build:gradle:2.3.1'
+ classpath 'com.android.tools.build:gradle:3.0.1'
}
}
allprojects {
repositories {
jcenter()
- maven { url 'https://maven.google.com' }
+ google()
maven { url "http://oss.sonatype.org/content/repositories/snapshots/" }
}
}
diff --git a/platform/android/config.cmake b/platform/android/config.cmake
index 34a8963042..f5de7a6052 100644
--- a/platform/android/config.cmake
+++ b/platform/android/config.cmake
@@ -1,5 +1,4 @@
add_definitions(-DMBGL_USE_GLES2=1)
-
include(cmake/test-files.cmake)
# Build thin archives.
@@ -8,6 +7,9 @@ set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> cruT <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_CXX_ARCHIVE_APPEND "<CMAKE_AR> ruT <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_C_ARCHIVE_APPEND "<CMAKE_AR> ruT <TARGET> <LINK_FLAGS> <OBJECTS>")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffunction-sections -fdata-sections")
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections")
+
if ((ANDROID_ABI STREQUAL "armeabi") OR (ANDROID_ABI STREQUAL "armeabi-v7a") OR (ANDROID_ABI STREQUAL "arm64-v8a") OR
(ANDROID_ABI STREQUAL "x86") OR (ANDROID_ABI STREQUAL "x86_64"))
# Use Identical Code Folding on platforms that support the gold linker.
@@ -15,6 +17,9 @@ if ((ANDROID_ABI STREQUAL "armeabi") OR (ANDROID_ABI STREQUAL "armeabi-v7a") OR
set(CMAKE_SHARED_LINKER_FLAGS "-fuse-ld=gold -Wl,--icf=safe ${CMAKE_SHARED_LINKER_FLAGS}")
endif()
+set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections -Wl,--version-script=${CMAKE_SOURCE_DIR}/platform/android/version-script")
+set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections -Wl,--version-script=${CMAKE_SOURCE_DIR}/platform/android/version-script")
+
mason_use(jni.hpp VERSION 3.0.0 HEADER_ONLY)
mason_use(nunicode VERSION 1.7.1)
mason_use(sqlite VERSION 3.14.2)
@@ -69,11 +74,11 @@ macro(mbgl_platform_core)
PRIVATE platform/default/mbgl/map/map_snapshotter.cpp
PRIVATE platform/default/mbgl/map/map_snapshotter.hpp
PRIVATE platform/linux/src/headless_backend_egl.cpp
- PRIVATE platform/linux/src/headless_display_egl.cpp
)
target_include_directories(mbgl-core
PUBLIC platform/default
+ PRIVATE platform/android
)
target_add_mason_package(mbgl-core PUBLIC nunicode)
@@ -82,12 +87,6 @@ macro(mbgl_platform_core)
target_add_mason_package(mbgl-core PUBLIC rapidjson)
target_add_mason_package(mbgl-core PRIVATE icu)
- target_compile_options(mbgl-core
- PRIVATE -fvisibility=hidden
- PRIVATE -ffunction-sections
- PRIVATE -fdata-sections
- )
-
target_link_libraries(mbgl-core
PUBLIC -llog
PUBLIC -landroid
@@ -116,12 +115,6 @@ macro(mbgl_filesource)
target_add_mason_package(mbgl-filesource PUBLIC sqlite)
target_add_mason_package(mbgl-filesource PUBLIC jni.hpp)
- target_compile_options(mbgl-filesource
- PRIVATE -fvisibility=hidden
- PRIVATE -ffunction-sections
- PRIVATE -fdata-sections
- )
-
target_link_libraries(mbgl-filesource
PUBLIC -llog
PUBLIC -landroid
@@ -148,7 +141,6 @@ add_library(mbgl-android STATIC
# Style conversion Java -> C++
platform/android/src/style/android_conversion.hpp
- platform/android/src/style/conversion/geojson.hpp
platform/android/src/style/value.cpp
platform/android/src/style/value.hpp
platform/android/src/style/conversion/url_or_tileset.hpp
@@ -180,10 +172,10 @@ add_library(mbgl-android STATIC
platform/android/src/style/layers/unknown_layer.hpp
platform/android/src/style/sources/geojson_source.cpp
platform/android/src/style/sources/geojson_source.hpp
+ platform/android/src/style/sources/custom_geometry_source.cpp
+ platform/android/src/style/sources/custom_geometry_source.hpp
platform/android/src/style/sources/source.cpp
platform/android/src/style/sources/source.hpp
- platform/android/src/style/sources/sources.cpp
- platform/android/src/style/sources/sources.hpp
platform/android/src/style/sources/raster_source.cpp
platform/android/src/style/sources/raster_source.hpp
platform/android/src/style/sources/unknown_source.cpp
@@ -312,12 +304,6 @@ add_library(mbgl-android STATIC
platform/android/src/jni.cpp
)
-target_compile_options(mbgl-android
- PRIVATE -fvisibility=hidden
- PRIVATE -ffunction-sections
- PRIVATE -fdata-sections
-)
-
target_link_libraries(mbgl-android
PUBLIC mbgl-filesource
PUBLIC mbgl-core
@@ -331,8 +317,6 @@ add_library(mapbox-gl SHARED
target_link_libraries(mapbox-gl
PRIVATE mbgl-android
- PRIVATE -Wl,--gc-sections
- PRIVATE -Wl,--version-script=${CMAKE_SOURCE_DIR}/platform/android/version-script
)
## Test library ##
@@ -344,25 +328,14 @@ macro(mbgl_platform_test)
# Main test entry point
platform/android/src/test/main.jni.cpp
-
- # Headless view
- platform/default/mbgl/gl/headless_frontend.cpp
- platform/default/mbgl/gl/headless_frontend.hpp
- platform/default/mbgl/gl/headless_backend.cpp
- platform/default/mbgl/gl/headless_backend.hpp
-
- platform/linux/src/headless_backend_egl.cpp
- platform/linux/src/headless_display_egl.cpp
)
- target_compile_options(mbgl-test
- PRIVATE -fvisibility=hidden
+ target_include_directories(mbgl-test
+ PRIVATE platform/android
)
target_link_libraries(mbgl-test
PRIVATE mbgl-android
- PRIVATE -Wl,--gc-sections
- PRIVATE -Wl,--version-script=${CMAKE_SOURCE_DIR}/platform/android/version-script
)
endmacro()
@@ -372,14 +345,6 @@ add_library(example-custom-layer SHARED
platform/android/src/example_custom_layer.cpp
)
-target_compile_options(example-custom-layer
- PRIVATE -fvisibility=hidden
- PRIVATE -ffunction-sections
- PRIVATE -fdata-sections
-)
-
target_link_libraries(example-custom-layer
PRIVATE mbgl-core
- PRIVATE -Wl,--gc-sections
- PRIVATE -Wl,--version-script=${CMAKE_SOURCE_DIR}/platform/android/version-script
)
diff --git a/platform/android/dependencies.gradle b/platform/android/dependencies.gradle
index 541b3c5236..a32e18166d 100644
--- a/platform/android/dependencies.gradle
+++ b/platform/android/dependencies.gradle
@@ -2,10 +2,10 @@ ext {
minSdkVersion = 14
targetSdkVersion = 25
compileSdkVersion = 25
- buildToolsVersion = "25.0.2"
+ buildToolsVersion = "26.0.3"
- versionCode = 11
- versionName = "5.0.0"
+ versionCode = 12
+ versionName = "6.0.0"
mapboxServicesVersion = "2.2.9"
supportLibVersion = "25.4.0"
diff --git a/platform/android/gradle/wrapper/gradle-wrapper.properties b/platform/android/gradle/wrapper/gradle-wrapper.properties
index 1d35abd7b2..bf1b63c346 100644
--- a/platform/android/gradle/wrapper/gradle-wrapper.properties
+++ b/platform/android/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,5 @@
-#Fri Mar 03 10:22:19 EST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip \ No newline at end of file
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
diff --git a/platform/android/mbgl/gl/gl_impl.hpp b/platform/android/mbgl/gl/gl_impl.hpp
new file mode 100644
index 0000000000..b9b5d8e315
--- /dev/null
+++ b/platform/android/mbgl/gl/gl_impl.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#define GL_GLEXT_PROTOTYPES
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
diff --git a/platform/android/src/android_renderer_backend.cpp b/platform/android/src/android_renderer_backend.cpp
index 9e49915650..ae35acc5da 100755
--- a/platform/android/src/android_renderer_backend.cpp
+++ b/platform/android/src/android_renderer_backend.cpp
@@ -21,7 +21,7 @@ void AndroidRendererBackend::bind() {
/**
* From mbgl::RendererBackend.
*/
-gl::ProcAddress AndroidRendererBackend::initializeExtension(const char* name) {
+gl::ProcAddress AndroidRendererBackend::getExtensionFunctionPointer(const char* name) {
assert(BackendScope::exists());
return eglGetProcAddress(name);
}
diff --git a/platform/android/src/android_renderer_backend.hpp b/platform/android/src/android_renderer_backend.hpp
index c5c552459f..d2c100dcc1 100755
--- a/platform/android/src/android_renderer_backend.hpp
+++ b/platform/android/src/android_renderer_backend.hpp
@@ -24,7 +24,7 @@ public:
protected:
// mbgl::RendererBackend //
- gl::ProcAddress initializeExtension(const char*) override;
+ gl::ProcAddress getExtensionFunctionPointer(const char*) override;
void activate() override {};
void deactivate() override {};
diff --git a/platform/android/src/jni.cpp b/platform/android/src/jni.cpp
index e75a9c6985..88ad0edb9e 100755
--- a/platform/android/src/jni.cpp
+++ b/platform/android/src/jni.cpp
@@ -47,7 +47,7 @@
#include "style/functions/interval_stops.hpp"
#include "style/functions/stop.hpp"
#include "style/layers/layers.hpp"
-#include "style/sources/sources.hpp"
+#include "style/sources/source.hpp"
#include "style/light.hpp"
#include "snapshotter/map_snapshotter.hpp"
#include "snapshotter/map_snapshot.hpp"
@@ -162,7 +162,7 @@ void registerNatives(JavaVM *vm) {
// Style
TransitionOptions::registerNative(env);
registerNativeLayers(env);
- registerNativeSources(env);
+ Source::registerNative(env);
Light::registerNative(env);
Position::registerNative(env);
Stop::registerNative(env);
diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp
index 04cbb21927..36a73fee35 100755
--- a/platform/android/src/native_map_view.cpp
+++ b/platform/android/src/native_map_view.cpp
@@ -856,9 +856,7 @@ jni::Array<jni::Object<Source>> NativeMapView::getSources(JNIEnv& env) {
jni::Array<jni::Object<Source>> jSources = jni::Array<jni::Object<Source>>::New(env, sources.size(), Source::javaClass);
int index = 0;
for (auto source : sources) {
- auto jSource = jni::Object<Source>(createJavaSourcePeer(env, *rendererFrontend, *source));
- jSources.Set(env, index, jSource);
- jni::DeleteLocalRef(env, jSource);
+ jSources.Set(env, index, Source::peerForCoreSource(env, *source, *rendererFrontend));
index++;
}
@@ -874,38 +872,25 @@ jni::Object<Source> NativeMapView::getSource(JNIEnv& env, jni::String sourceId)
}
// Create and return the source's native peer
- return jni::Object<Source>(createJavaSourcePeer(env, *rendererFrontend, *coreSource));
+ return Source::peerForCoreSource(env, *coreSource, *rendererFrontend);
}
-void NativeMapView::addSource(JNIEnv& env, jni::jlong sourcePtr) {
+void NativeMapView::addSource(JNIEnv& env, jni::Object<Source> obj, jlong sourcePtr) {
assert(sourcePtr != 0);
Source *source = reinterpret_cast<Source *>(sourcePtr);
try {
- source->addToMap(*map);
- source->setRendererFrontend(*rendererFrontend);
+ source->addToMap(env, obj, *map, *rendererFrontend);
} catch (const std::runtime_error& error) {
jni::ThrowNew(env, jni::FindClass(env, "com/mapbox/mapboxsdk/style/sources/CannotAddSourceException"), error.what());
}
}
-jni::Object<Source> NativeMapView::removeSourceById(JNIEnv& env, jni::String id) {
- std::unique_ptr<mbgl::style::Source> coreSource = map->getStyle().removeSource(jni::Make<std::string>(env, id));
- if (coreSource) {
- return jni::Object<Source>(createJavaSourcePeer(env, *rendererFrontend, *coreSource));
- } else {
- return jni::Object<Source>();
- }
-}
-
-void NativeMapView::removeSource(JNIEnv&, jlong sourcePtr) {
+void NativeMapView::removeSource(JNIEnv& env, jni::Object<Source> obj, jlong sourcePtr) {
assert(sourcePtr != 0);
mbgl::android::Source *source = reinterpret_cast<mbgl::android::Source *>(sourcePtr);
- std::unique_ptr<mbgl::style::Source> coreSource = map->getStyle().removeSource(source->get().getID());
- if (coreSource) {
- source->setSource(std::move(coreSource));
- }
+ source->removeFromMap(env, obj, *map);
}
void NativeMapView::addImage(JNIEnv& env, jni::String name, jni::jint w, jni::jint h, jni::jfloat scale, jni::Array<jbyte> pixels) {
@@ -1048,7 +1033,6 @@ void NativeMapView::registerNative(jni::JNIEnv& env) {
METHOD(&NativeMapView::getSources, "nativeGetSources"),
METHOD(&NativeMapView::getSource, "nativeGetSource"),
METHOD(&NativeMapView::addSource, "nativeAddSource"),
- METHOD(&NativeMapView::removeSourceById, "nativeRemoveSourceById"),
METHOD(&NativeMapView::removeSource, "nativeRemoveSource"),
METHOD(&NativeMapView::addImage, "nativeAddImage"),
METHOD(&NativeMapView::addImages, "nativeAddImages"),
diff --git a/platform/android/src/native_map_view.hpp b/platform/android/src/native_map_view.hpp
index d7e3b17b99..507d77ac5f 100755
--- a/platform/android/src/native_map_view.hpp
+++ b/platform/android/src/native_map_view.hpp
@@ -19,7 +19,7 @@
#include "geometry/lat_lng.hpp"
#include "geometry/projected_meters.hpp"
#include "style/layers/layers.hpp"
-#include "style/sources/sources.hpp"
+#include "style/sources/source.hpp"
#include "geometry/lat_lng_bounds.hpp"
#include "map/camera_position.hpp"
#include "map/image.hpp"
@@ -230,11 +230,11 @@ public:
jni::Object<Source> getSource(JNIEnv&, jni::String);
- void addSource(JNIEnv&, jni::jlong);
+ void addSource(JNIEnv&, jni::Object<Source>, jlong nativePtr);
jni::Object<Source> removeSourceById(JNIEnv&, jni::String);
- void removeSource(JNIEnv&, jlong);
+ void removeSource(JNIEnv&, jni::Object<Source>, jlong nativePtr);
void addImage(JNIEnv&, jni::String, jni::jint, jni::jint, jni::jfloat, jni::Array<jbyte>);
diff --git a/platform/android/src/style/android_conversion.hpp b/platform/android/src/style/android_conversion.hpp
index 082fe411e2..510a9f8444 100644
--- a/platform/android/src/style/android_conversion.hpp
+++ b/platform/android/src/style/android_conversion.hpp
@@ -4,8 +4,9 @@
#include <mbgl/util/feature.hpp>
#include <mbgl/util/logging.hpp>
-#include <mbgl/style/conversion.hpp>
#include <mbgl/util/optional.hpp>
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/conversion/geojson.hpp>
#include <jni/jni.hpp>
@@ -13,89 +14,105 @@ namespace mbgl {
namespace style {
namespace conversion {
-inline bool isUndefined(const mbgl::android::Value& value) {
- return value.isNull();
-}
+template <>
+class ConversionTraits<mbgl::android::Value> {
+public:
+ static bool isUndefined(const mbgl::android::Value& value) {
+ return value.isNull();
+ }
-inline bool isArray(const mbgl::android::Value& value) {
- return value.isArray();
-}
+ static bool isArray(const mbgl::android::Value& value) {
+ return value.isArray();
+ }
-inline bool isObject(const mbgl::android::Value& value) {
- return value.isObject();
-}
+ static bool isObject(const mbgl::android::Value& value) {
+ return value.isObject();
+ }
-inline std::size_t arrayLength(const mbgl::android::Value& value) {
- return value.getLength();;
-}
+ static std::size_t arrayLength(const mbgl::android::Value& value) {
+ return value.getLength();;
+ }
-inline mbgl::android::Value arrayMember(const mbgl::android::Value& value, std::size_t i) {
- return value.get(i);
-}
+ static mbgl::android::Value arrayMember(const mbgl::android::Value& value, std::size_t i) {
+ return value.get(i);
+ }
-inline optional<mbgl::android::Value> objectMember(const mbgl::android::Value& value, const char* key) {
- mbgl::android::Value member = value.get(key);
+ static optional<mbgl::android::Value> objectMember(const mbgl::android::Value& value, const char* key) {
+ mbgl::android::Value member = value.get(key);
+ if (!member.isNull()) {
+ return member;
+ } else {
+ return {};
+ }
+ }
- if (!member.isNull()) {
- return member;
- } else {
+ template <class Fn>
+ static optional<Error> eachMember(const mbgl::android::Value&, Fn&&) {
+ // TODO
+ mbgl::Log::Warning(mbgl::Event::Android, "eachMember not implemented");
return {};
}
-}
-template <class Fn>
-optional<Error> eachMember(const mbgl::android::Value&, Fn&&) {
- // TODO
- mbgl::Log::Warning(mbgl::Event::Android, "eachMember not implemented");
- return {};
-}
+ static optional<bool> toBool(const mbgl::android::Value& value) {
+ if (value.isBool()) {
+ return value.toBool();
+ } else {
+ return {};
+ }
+ }
-inline optional<bool> toBool(const mbgl::android::Value& value) {
- if (value.isBool()) {
- return value.toBool();
- } else {
- return {};
+ static optional<float> toNumber(const mbgl::android::Value& value) {
+ if (value.isNumber()) {
+ auto num = value.toFloat();
+ return num;
+ } else {
+ return {};
+ }
}
-}
-inline optional<float> toNumber(const mbgl::android::Value& value) {
- if (value.isNumber()) {
- auto num = value.toFloat();
- return num;
- } else {
- return {};
+ static optional<double> toDouble(const mbgl::android::Value& value) {
+ if (value.isNumber()) {
+ return value.toDouble();
+ } else {
+ return {};
+ }
}
-}
-inline optional<double> toDouble(const mbgl::android::Value& value) {
- if (value.isNumber()) {
- return value.toDouble();
- } else {
- return {};
+ static optional<std::string> toString(const mbgl::android::Value& value) {
+ if (value.isString()) {
+ return value.toString();
+ } else {
+ return {};
+ }
}
-}
-inline optional<std::string> toString(const mbgl::android::Value& value) {
- if (value.isString()) {
- return value.toString();
- } else {
- return {};
+ static optional<Value> toValue(const mbgl::android::Value& value) {
+ if (value.isNull()) {
+ return {};
+ } else if (value.isBool()) {
+ return { value.toBool() };
+ } else if (value.isString()) {
+ return { value.toString() };
+ } else if (value.isNumber()) {
+ auto doubleVal = value.toDouble();
+ return { doubleVal - (int) doubleVal > 0.0 ? doubleVal : value.toLong() };
+ } else {
+ return {};
+ }
}
-}
-inline optional<Value> toValue(const mbgl::android::Value& value) {
- if (value.isNull()) {
- return {};
- } else if (value.isBool()) {
- return { value.toBool() };
- } else if (value.isString()) {
- return { value.toString() };
- } else if (value.isNumber()) {
- auto doubleVal = value.toDouble();
- return { doubleVal - (int) doubleVal > 0.0 ? doubleVal : value.toLong() };
- } else {
- return {};
+ static optional<GeoJSON> toGeoJSON(const mbgl::android::Value &value, Error &error) {
+ if (value.isNull() || !value.isString()) {
+ error = { "no json data found" };
+ return {};
+ }
+ return parseGeoJSON(value.toString(), error);
}
+};
+
+template <class T, class...Args>
+optional<T> convert(mbgl::android::Value&& value, Error& error, Args&&...args) {
+ return convert<T>(Convertible(std::move(value)), error, std::forward<Args>(args)...);
}
} // namespace conversion
diff --git a/platform/android/src/style/conversion/filter.hpp b/platform/android/src/style/conversion/filter.hpp
index 1f0abcf3a4..c154e88e7c 100644
--- a/platform/android/src/style/conversion/filter.hpp
+++ b/platform/android/src/style/conversion/filter.hpp
@@ -16,9 +16,8 @@ namespace conversion {
inline optional<mbgl::style::Filter> toFilter(jni::JNIEnv& env, jni::Array<jni::Object<>> jfilter) {
mbgl::optional<mbgl::style::Filter> filter;
if (jfilter) {
- Value filterValue(env, jfilter);
mbgl::style::conversion::Error error;
- auto converted = mbgl::style::conversion::convert<mbgl::style::Filter>(filterValue, error);
+ auto converted = mbgl::style::conversion::convert<mbgl::style::Filter>(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/geojson.hpp b/platform/android/src/style/conversion/geojson.hpp
deleted file mode 100644
index 748fe7361e..0000000000
--- a/platform/android/src/style/conversion/geojson.hpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#pragma once
-
-#include <mapbox/geojson.hpp>
-#include <mbgl/style/conversion.hpp>
-#include <mbgl/style/conversion/geojson.hpp>
-#include <jni/jni.hpp>
-
-namespace mbgl {
-namespace style {
-namespace conversion {
-
-template <>
-optional<GeoJSON> Converter<GeoJSON>::operator()(const mbgl::android::Value& value, Error& error) const {
- if(value.isNull() || !value.isString()) {
- error = { "no json data found" };
- return {};
- }
-
- return convert<GeoJSON>(value.toString(), error);
-}
-
-} // namespace conversion
-} // namespace style
-} // namespace mbgl
diff --git a/platform/android/src/style/conversion/url_or_tileset.hpp b/platform/android/src/style/conversion/url_or_tileset.hpp
index 00ef913d41..92c1182a63 100644
--- a/platform/android/src/style/conversion/url_or_tileset.hpp
+++ b/platform/android/src/style/conversion/url_or_tileset.hpp
@@ -17,18 +17,19 @@ namespace android {
// This conversion is expected not to fail because it's used only in contexts where
// the value was originally a String or TileSet object on the Java side. If it fails
// to convert, it's a bug in our serialization or Java-side static typing.
-inline variant<std::string, Tileset> convertURLOrTileset(const Value& value) {
+inline variant<std::string, Tileset> convertURLOrTileset(mbgl::android::Value&& value) {
using namespace mbgl::style::conversion;
- if (isObject(value)) {
+ const Convertible convertible(std::move(value));
+ if (isObject(convertible)) {
Error error;
- optional<Tileset> tileset = convert<Tileset>(value, error);
+ optional<Tileset> tileset = convert<Tileset>(convertible, error);
if (!tileset) {
throw std::logic_error(error.message);
}
return { *tileset };
} else {
- return { *toString(value) };
+ return { *toString(convertible) };
}
}
diff --git a/platform/android/src/style/layers/layer.cpp b/platform/android/src/style/layers/layer.cpp
index 02a1f0be82..31032b117f 100644
--- a/platform/android/src/style/layers/layer.cpp
+++ b/platform/android/src/style/layers/layer.cpp
@@ -4,11 +4,20 @@
#include <jni/jni.hpp>
#include <mbgl/style/style.hpp>
+#include <mbgl/style/filter.hpp>
#include <mbgl/style/transition_options.hpp>
+#include <mbgl/style/layers/background_layer.hpp>
+#include <mbgl/style/layers/circle_layer.hpp>
+#include <mbgl/style/layers/fill_layer.hpp>
+#include <mbgl/style/layers/fill_extrusion_layer.hpp>
+#include <mbgl/style/layers/line_layer.hpp>
+#include <mbgl/style/layers/raster_layer.hpp>
+#include <mbgl/style/layers/symbol_layer.hpp>
#include <mbgl/util/logging.hpp>
// Java -> C++ conversion
#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/conversion/filter.hpp>
#include <mbgl/style/conversion/layer.hpp>
#include <mbgl/style/conversion/source.hpp>
@@ -78,10 +87,8 @@ namespace android {
}
void Layer::setLayoutProperty(jni::JNIEnv& env, jni::String jname, jni::Object<> jvalue) {
- Value value(env, jvalue);
-
// Convert and set property
- optional<mbgl::style::conversion::Error> error = mbgl::style::conversion::setLayoutProperty(layer, jni::Make<std::string>(env, jname), value);
+ optional<mbgl::style::conversion::Error> error = mbgl::style::conversion::setLayoutProperty(layer, jni::Make<std::string>(env, jname), Value(env, jvalue));
if (error) {
mbgl::Log::Error(mbgl::Event::JNI, "Error setting property: " + jni::Make<std::string>(env, jname) + " " + error->message);
return;
@@ -89,10 +96,8 @@ namespace android {
}
void Layer::setPaintProperty(jni::JNIEnv& env, jni::String jname, jni::Object<> jvalue) {
- Value value(env, jvalue);
-
// Convert and set property
- optional<mbgl::style::conversion::Error> error = mbgl::style::conversion::setPaintProperty(layer, jni::Make<std::string>(env, jname), value);
+ optional<mbgl::style::conversion::Error> error = mbgl::style::conversion::setPaintProperty(layer, jni::Make<std::string>(env, jname), Value(env, jvalue));
if (error) {
mbgl::Log::Error(mbgl::Event::JNI, "Error setting property: " + jni::Make<std::string>(env, jname) + " " + error->message);
return;
@@ -116,10 +121,8 @@ namespace android {
using namespace mbgl::style;
using namespace mbgl::style::conversion;
- Value wrapped(env, jfilter);
-
Error error;
- optional<Filter> converted = convert<Filter>(wrapped, error);
+ optional<Filter> converted = convert<Filter>(Value(env, jfilter), error);
if (!converted) {
mbgl::Log::Error(mbgl::Event::JNI, "Error setting filter: " + error.message);
return;
diff --git a/platform/android/src/style/sources/custom_geometry_source.cpp b/platform/android/src/style/sources/custom_geometry_source.cpp
new file mode 100644
index 0000000000..a60b962e45
--- /dev/null
+++ b/platform/android/src/style/sources/custom_geometry_source.cpp
@@ -0,0 +1,143 @@
+#include "custom_geometry_source.hpp"
+
+#include <mbgl/renderer/query.hpp>
+
+// Java -> C++ conversion
+#include "../android_conversion.hpp"
+#include "../conversion/filter.hpp"
+
+// C++ -> Java conversion
+#include "../../conversion/conversion.hpp"
+#include "../../conversion/collection.hpp"
+#include "../../geojson/conversion/feature.hpp"
+#include <mbgl/style/conversion/custom_geometry_source_options.hpp>
+
+#include <string>
+
+namespace mbgl {
+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::CustomGeometrySource::Options convertCustomGeometrySourceOptions(jni::JNIEnv& env,
+ jni::Object<> options,
+ style::TileFunction fetchFn,
+ style::TileFunction cancelFn) {
+ using namespace mbgl::style::conversion;
+ if (!options) {
+ return style::CustomGeometrySource::Options();
+ }
+ Error error;
+ optional<style::CustomGeometrySource::Options> result = convert<style::CustomGeometrySource::Options>(Value(env, options), error);
+ if (!result) {
+ throw std::logic_error(error.message);
+ }
+ result->fetchTileFunction = fetchFn;
+ result->cancelTileFunction = cancelFn;
+ return *result;
+ }
+
+ CustomGeometrySource::CustomGeometrySource(jni::JNIEnv& env,
+ jni::String sourceId,
+ jni::Object<> options)
+ : Source(env, std::make_unique<mbgl::style::CustomGeometrySource>(
+ jni::Make<std::string>(env, sourceId),
+ convertCustomGeometrySourceOptions(env, options,
+ std::bind(&CustomGeometrySource::fetchTile, this, std::placeholders::_1),
+ std::bind(&CustomGeometrySource::cancelTile, this, std::placeholders::_1)))) {
+ }
+
+ CustomGeometrySource::CustomGeometrySource(jni::JNIEnv& env,
+ mbgl::style::Source& coreSource,
+ AndroidRendererFrontend& frontend)
+ : Source(env, coreSource, createJavaPeer(env), frontend) {
+ }
+
+ CustomGeometrySource::~CustomGeometrySource() = default;
+
+ void CustomGeometrySource::fetchTile (const mbgl::CanonicalTileID& tileID) {
+ android::UniqueEnv _env = android::AttachEnv();
+
+ static auto fetchTile = javaClass.GetMethod<void (jni::jint, jni::jint, jni::jint)>(*_env, "fetchTile");
+
+ assert(javaPeer);
+
+ auto peer = jni::Cast(*_env, *javaPeer, javaClass);
+ 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 cancelTile = javaClass.GetMethod<void (jni::jint, jni::jint, jni::jint)>(*_env, "cancelTile");
+
+ assert(javaPeer);
+
+ auto peer = jni::Cast(*_env, *javaPeer, javaClass);
+ peer.Call(*_env, cancelTile, (int)tileID.z, (int)tileID.x, (int)tileID.y);
+ };
+
+ void CustomGeometrySource::setTileData(jni::JNIEnv& env,
+ jni::jint z,
+ jni::jint x,
+ jni::jint y,
+ jni::Object<geojson::FeatureCollection> jFeatures) {
+ using namespace mbgl::android::geojson;
+
+ // Convert the jni object
+ auto geometry = geojson::FeatureCollection::convert(env, jFeatures);
+
+ // Update the core source
+ source.as<mbgl::style::CustomGeometrySource>()->CustomGeometrySource::setTileData(CanonicalTileID(z, x, y), GeoJSON(geometry));
+ }
+
+ void CustomGeometrySource::invalidateTile(jni::JNIEnv&, jni::jint z, jni::jint x, jni::jint y) {
+ source.as<mbgl::style::CustomGeometrySource>()->CustomGeometrySource::invalidateTile(CanonicalTileID(z, x, y));
+ }
+
+ void CustomGeometrySource::invalidateBounds(jni::JNIEnv& env, jni::Object<LatLngBounds> jBounds) {
+ auto bounds = LatLngBounds::getLatLngBounds(env, jBounds);
+ source.as<mbgl::style::CustomGeometrySource>()->CustomGeometrySource::invalidateRegion(bounds);
+ }
+
+ jni::Array<jni::Object<geojson::Feature>> CustomGeometrySource::querySourceFeatures(jni::JNIEnv& env,
+ jni::Array<jni::Object<>> jfilter) {
+ using namespace mbgl::android::conversion;
+ using namespace mbgl::android::geojson;
+
+ std::vector<mbgl::Feature> features;
+ if (rendererFrontend) {
+ features = rendererFrontend->querySourceFeatures(source.getID(), { {}, toFilter(env, jfilter) });
+ }
+ return *convert<jni::Array<jni::Object<Feature>>, std::vector<mbgl::Feature>>(env, features);
+ }
+
+ jni::Class<CustomGeometrySource> CustomGeometrySource::javaClass;
+
+ jni::Object<Source> CustomGeometrySource::createJavaPeer(jni::JNIEnv& env) {
+ static auto constructor = CustomGeometrySource::javaClass.template GetConstructor<jni::jlong>(env);
+ return jni::Object<Source>(CustomGeometrySource::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)).Get());
+ }
+
+ void CustomGeometrySource::registerNative(jni::JNIEnv& env) {
+ // Lookup the class
+ CustomGeometrySource::javaClass = *jni::Class<CustomGeometrySource>::Find(env).NewGlobalRef(env).release();
+
+ #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
+
+ // Register the peer
+ jni::RegisterNativePeer<CustomGeometrySource>(
+ env, CustomGeometrySource::javaClass, "nativePtr",
+ std::make_unique<CustomGeometrySource, JNIEnv&, jni::String, jni::Object<>>,
+ "initialize",
+ "finalize",
+ METHOD(&CustomGeometrySource::querySourceFeatures, "querySourceFeatures"),
+ METHOD(&CustomGeometrySource::setTileData, "nativeSetTileData"),
+ METHOD(&CustomGeometrySource::invalidateTile, "nativeInvalidateTile"),
+ METHOD(&CustomGeometrySource::invalidateBounds, "nativeInvalidateBounds")
+ );
+ }
+
+} // namespace android
+} // namespace mbgl
diff --git a/platform/android/src/style/sources/custom_geometry_source.hpp b/platform/android/src/style/sources/custom_geometry_source.hpp
new file mode 100644
index 0000000000..1dc1c07b4f
--- /dev/null
+++ b/platform/android/src/style/sources/custom_geometry_source.hpp
@@ -0,0 +1,47 @@
+#pragma once
+
+#include "source.hpp"
+#include <mbgl/style/sources/custom_geometry_source.hpp>
+#include <mbgl/util/geojson.hpp>
+#include <mbgl/tile/tile_id.hpp>
+#include "../../geojson/geometry.hpp"
+#include "../../geojson/feature.hpp"
+#include "../../geojson/feature_collection.hpp"
+#include "../../geometry/lat_lng_bounds.hpp"
+#include <jni/jni.hpp>
+
+namespace mbgl {
+namespace android {
+
+class CustomGeometrySource : public Source {
+public:
+
+ static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/CustomGeometrySource"; };
+
+ static jni::Class<CustomGeometrySource> javaClass;
+
+ static void registerNative(jni::JNIEnv&);
+
+ CustomGeometrySource(jni::JNIEnv&, jni::String, jni::Object<>);
+
+ CustomGeometrySource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&);
+
+ ~CustomGeometrySource();
+
+ void fetchTile(const mbgl::CanonicalTileID& tileID);
+ void cancelTile(const mbgl::CanonicalTileID& tileID);
+ void setTileData(jni::JNIEnv& env, jni::jint z, jni::jint x, jni::jint y, jni::Object<geojson::FeatureCollection> jf);
+
+ void invalidateTile(jni::JNIEnv& env, jni::jint z, jni::jint x, jni::jint y);
+ void invalidateBounds(jni::JNIEnv& env, jni::Object<LatLngBounds> bounds);
+
+ jni::Array<jni::Object<geojson::Feature>> querySourceFeatures(jni::JNIEnv&,
+ jni::Array<jni::Object<>> );
+
+private:
+ jni::Object<Source> createJavaPeer(jni::JNIEnv&);
+
+}; // class CustomGeometrySource
+
+} // namespace android
+} // namespace mbgl
diff --git a/platform/android/src/style/sources/geojson_source.cpp b/platform/android/src/style/sources/geojson_source.cpp
index 90ef851eba..6d9ab9e22c 100644
--- a/platform/android/src/style/sources/geojson_source.cpp
+++ b/platform/android/src/style/sources/geojson_source.cpp
@@ -5,15 +5,15 @@
// Java -> C++ conversion
#include "../android_conversion.hpp"
#include "../conversion/filter.hpp"
-#include "../conversion/geojson.hpp"
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/conversion/geojson.hpp>
+#include <mbgl/style/conversion/geojson_options.hpp>
// C++ -> Java conversion
#include "../../conversion/conversion.hpp"
#include "../../conversion/collection.hpp"
#include "../../geojson/conversion/feature.hpp"
#include "../conversion/url_or_tileset.hpp"
-#include <mbgl/style/conversion.hpp>
-#include <mbgl/style/conversion/geojson_options.hpp>
#include <string>
@@ -29,7 +29,7 @@ namespace android {
return style::GeoJSONOptions();
}
Error error;
- optional<style::GeoJSONOptions> result = convert<style::GeoJSONOptions>(Value(env, options), error);
+ optional<style::GeoJSONOptions> result = convert<style::GeoJSONOptions>(mbgl::android::Value(env, options), error);
if (!result) {
throw std::logic_error(error.message);
}
@@ -43,8 +43,10 @@ namespace android {
) {
}
- GeoJSONSource::GeoJSONSource(mbgl::style::GeoJSONSource& coreSource)
- : Source(coreSource) {
+ GeoJSONSource::GeoJSONSource(jni::JNIEnv& env,
+ mbgl::style::Source& coreSource,
+ AndroidRendererFrontend& frontend)
+ : Source(env, coreSource, createJavaPeer(env), frontend) {
}
GeoJSONSource::~GeoJSONSource() = default;
@@ -54,7 +56,7 @@ namespace android {
// Convert the jni object
Error error;
- optional<GeoJSON> converted = convert<GeoJSON>(Value(env, json), error);
+ optional<GeoJSON> converted = convert<GeoJSON>(mbgl::android::Value(env, json), error);
if(!converted) {
mbgl::Log::Error(mbgl::Event::JNI, "Error setting geo json: " + error.message);
return;
@@ -118,9 +120,9 @@ namespace android {
jni::Class<GeoJSONSource> GeoJSONSource::javaClass;
- jni::jobject* GeoJSONSource::createJavaPeer(jni::JNIEnv& env) {
+ jni::Object<Source> GeoJSONSource::createJavaPeer(jni::JNIEnv& env) {
static auto constructor = GeoJSONSource::javaClass.template GetConstructor<jni::jlong>(env);
- return GeoJSONSource::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this));
+ return jni::Object<Source>(GeoJSONSource::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)).Get());
}
void GeoJSONSource::registerNative(jni::JNIEnv& env) {
diff --git a/platform/android/src/style/sources/geojson_source.hpp b/platform/android/src/style/sources/geojson_source.hpp
index 52dd632bfa..c46519b04a 100644
--- a/platform/android/src/style/sources/geojson_source.hpp
+++ b/platform/android/src/style/sources/geojson_source.hpp
@@ -21,7 +21,7 @@ public:
GeoJSONSource(jni::JNIEnv&, jni::String, jni::Object<>);
- GeoJSONSource(mbgl::style::GeoJSONSource&);
+ GeoJSONSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&);
~GeoJSONSource();
@@ -40,7 +40,8 @@ public:
jni::String getURL(jni::JNIEnv&);
- jni::jobject* createJavaPeer(jni::JNIEnv&);
+private:
+ jni::Object<Source> createJavaPeer(jni::JNIEnv&);
}; // class GeoJSONSource
diff --git a/platform/android/src/style/sources/image_source.cpp b/platform/android/src/style/sources/image_source.cpp
index d46b367c53..0cd6995969 100644
--- a/platform/android/src/style/sources/image_source.cpp
+++ b/platform/android/src/style/sources/image_source.cpp
@@ -23,8 +23,10 @@ namespace android {
) {
}
- ImageSource::ImageSource(mbgl::style::ImageSource& coreSource)
- : Source(coreSource) {
+ ImageSource::ImageSource(jni::JNIEnv& env,
+ mbgl::style::Source& coreSource,
+ AndroidRendererFrontend& frontend)
+ : Source(env, coreSource, createJavaPeer(env), frontend) {
}
ImageSource::~ImageSource() = default;
@@ -45,9 +47,9 @@ namespace android {
jni::Class<ImageSource> ImageSource::javaClass;
- jni::jobject* ImageSource::createJavaPeer(jni::JNIEnv& env) {
+ jni::Object<Source> ImageSource::createJavaPeer(jni::JNIEnv& env) {
static auto constructor = ImageSource::javaClass.template GetConstructor<jni::jlong>(env);
- return ImageSource::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this));
+ return jni::Object<Source>(ImageSource::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)).Get());
}
void ImageSource::registerNative(jni::JNIEnv& env) {
diff --git a/platform/android/src/style/sources/image_source.hpp b/platform/android/src/style/sources/image_source.hpp
index 9787a7294f..f0af28d357 100644
--- a/platform/android/src/style/sources/image_source.hpp
+++ b/platform/android/src/style/sources/image_source.hpp
@@ -21,7 +21,7 @@ public:
ImageSource(jni::JNIEnv&, jni::String, jni::Object<LatLngQuad>);
- ImageSource(mbgl::style::ImageSource&);
+ ImageSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&);
~ImageSource();
@@ -30,7 +30,8 @@ public:
void setImage(jni::JNIEnv&, jni::Object<Bitmap>);
- jni::jobject* createJavaPeer(jni::JNIEnv&);
+private:
+ jni::Object<Source> createJavaPeer(jni::JNIEnv&);
}; // class ImageSource
diff --git a/platform/android/src/style/sources/raster_source.cpp b/platform/android/src/style/sources/raster_source.cpp
index d45342a1ad..33223a5b69 100644
--- a/platform/android/src/style/sources/raster_source.cpp
+++ b/platform/android/src/style/sources/raster_source.cpp
@@ -22,8 +22,10 @@ namespace android {
) {
}
- RasterSource::RasterSource(mbgl::style::RasterSource& coreSource)
- : Source(coreSource) {
+ RasterSource::RasterSource(jni::JNIEnv& env,
+ mbgl::style::Source& coreSource,
+ AndroidRendererFrontend& frontend)
+ : Source(env, coreSource, createJavaPeer(env), frontend) {
}
RasterSource::~RasterSource() = default;
@@ -35,9 +37,9 @@ namespace android {
jni::Class<RasterSource> RasterSource::javaClass;
- jni::jobject* RasterSource::createJavaPeer(jni::JNIEnv& env) {
+ jni::Object<Source> RasterSource::createJavaPeer(jni::JNIEnv& env) {
static auto constructor = RasterSource::javaClass.template GetConstructor<jni::jlong>(env);
- return RasterSource::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this));
+ return jni::Object<Source>(RasterSource::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)).Get());
}
void RasterSource::registerNative(jni::JNIEnv& env) {
diff --git a/platform/android/src/style/sources/raster_source.hpp b/platform/android/src/style/sources/raster_source.hpp
index 84c49d7381..a1da22f40d 100644
--- a/platform/android/src/style/sources/raster_source.hpp
+++ b/platform/android/src/style/sources/raster_source.hpp
@@ -18,13 +18,14 @@ public:
RasterSource(jni::JNIEnv&, jni::String, jni::Object<>, jni::jint);
- RasterSource(mbgl::style::RasterSource&);
+ RasterSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&);
~RasterSource();
jni::String getURL(jni::JNIEnv&);
- jni::jobject* createJavaPeer(jni::JNIEnv&);
+private:
+ jni::Object<Source> createJavaPeer(jni::JNIEnv&);
}; // class RasterSource
diff --git a/platform/android/src/style/sources/source.cpp b/platform/android/src/style/sources/source.cpp
index 447b13019d..3b89b25d7d 100644
--- a/platform/android/src/style/sources/source.cpp
+++ b/platform/android/src/style/sources/source.cpp
@@ -15,29 +15,70 @@
#include <string>
+// Core Sources
+#include <mbgl/style/sources/geojson_source.hpp>
+#include <mbgl/style/sources/image_source.hpp>
+#include <mbgl/style/sources/raster_source.hpp>
+#include <mbgl/style/sources/vector_source.hpp>
+
+// Android Source peers
+#include "geojson_source.hpp"
+#include "image_source.hpp"
+#include "raster_source.hpp"
+#include "unknown_source.hpp"
+#include "vector_source.hpp"
+#include "custom_geometry_source.hpp"
+
namespace mbgl {
namespace android {
- /**
- * Invoked when the construction is initiated from the jvm through a subclass
- */
- Source::Source(jni::JNIEnv&, std::unique_ptr<mbgl::style::Source> coreSource)
- : ownedSource(std::move(coreSource))
- , source(*ownedSource) {
+ static std::unique_ptr<Source> createSourcePeer(jni::JNIEnv& env, mbgl::style::Source& coreSource, AndroidRendererFrontend& frontend) {
+ if (coreSource.is<mbgl::style::VectorSource>()) {
+ return std::make_unique<VectorSource>(env, *coreSource.as<mbgl::style::VectorSource>(), frontend);
+ } else if (coreSource.is<mbgl::style::RasterSource>()) {
+ return std::make_unique<RasterSource>(env, *coreSource.as<mbgl::style::RasterSource>(), frontend);
+ } else if (coreSource.is<mbgl::style::GeoJSONSource>()) {
+ return std::make_unique<GeoJSONSource>(env, *coreSource.as<mbgl::style::GeoJSONSource>(), frontend);
+ } else if (coreSource.is<mbgl::style::ImageSource>()) {
+ return std::make_unique<ImageSource>(env, *coreSource.as<mbgl::style::ImageSource>(), frontend);
+ } else {
+ return std::make_unique<UnknownSource>(env, coreSource, frontend);
+ }
}
- Source::Source(mbgl::style::Source& coreSource)
- : source(coreSource) {
+ jni::Object<Source> Source::peerForCoreSource(jni::JNIEnv& env, mbgl::style::Source& coreSource, AndroidRendererFrontend& frontend) {
+ if (!coreSource.peer.has_value()) {
+ coreSource.peer = createSourcePeer(env, coreSource, frontend);
+ }
+ return *mbgl::util::any_cast<std::unique_ptr<Source>>(&coreSource.peer)->get()->javaPeer;
}
- Source::~Source() = default;
+ Source::Source(jni::JNIEnv& env, mbgl::style::Source& coreSource, jni::Object<Source> obj, AndroidRendererFrontend& frontend)
+ : source(coreSource)
+ , javaPeer(obj.NewGlobalRef(env))
+ , rendererFrontend(&frontend) {
+ }
- style::Source& Source::get() {
- return source;
+ Source::Source(jni::JNIEnv&, std::unique_ptr<mbgl::style::Source> coreSource)
+ : ownedSource(std::move(coreSource))
+ , source(*ownedSource) {
}
- void Source::setSource(std::unique_ptr<style::Source> coreSource) {
- this->ownedSource = std::move(coreSource);
+ Source::~Source() {
+ // Before being added to a map, the Java peer owns this C++ peer and cleans
+ // up after itself correctly through the jni native peer bindings.
+ // After being added to the map, the ownership is flipped and the C++ peer has a strong reference
+ // to it's Java peer, preventing the Java peer from being GC'ed.
+ // In this case, the core source initiates the destruction, which requires releasing the Java peer,
+ // while also resetting it's nativePtr to 0 to prevent the subsequent GC of the Java peer from
+ // re-entering this dtor.
+ if (ownedSource.get() == nullptr && javaPeer.get() != nullptr) {
+ // Manually clear the java peer
+ android::UniqueEnv env = android::AttachEnv();
+ static auto nativePtrField = javaClass.GetField<jlong>(*env, "nativePtr");
+ javaPeer->Set(*env, nativePtrField, (jlong) 0);
+ javaPeer.reset();
+ }
}
jni::String Source::getId(jni::JNIEnv& env) {
@@ -49,23 +90,48 @@ namespace android {
return attribution ? jni::Make<jni::String>(env, attribution.value()) : jni::Make<jni::String>(env,"");
}
- void Source::addToMap(mbgl::Map& _map) {
+ void Source::addToMap(JNIEnv& env, jni::Object<Source> obj, mbgl::Map& map, AndroidRendererFrontend& frontend) {
// Check to see if we own the source first
if (!ownedSource) {
throw std::runtime_error("Cannot add source twice");
}
- // Add source to map
- _map.getStyle().addSource(releaseCoreSource());
- }
+ // Add source to map and release ownership
+ map.getStyle().addSource(std::move(ownedSource));
+
+ // Add peer to core source
+ source.peer = std::unique_ptr<Source>(this);
+
+ // Add strong reference to java source
+ javaPeer = obj.NewGlobalRef(env);
- void Source::setRendererFrontend(AndroidRendererFrontend& frontend_) {
- rendererFrontend = &frontend_;
+ rendererFrontend = &frontend;
}
- std::unique_ptr<mbgl::style::Source> Source::releaseCoreSource() {
- assert(ownedSource != nullptr);
- return std::move(ownedSource);
+ void Source::removeFromMap(JNIEnv&, jni::Object<Source>, mbgl::Map& map) {
+ // Cannot remove if not attached yet
+ if (ownedSource) {
+ throw std::runtime_error("Cannot remove detached source");
+ }
+
+ // Remove the source from the map and take ownership
+ ownedSource = map.getStyle().removeSource(source.getID());
+
+ // The source may not be removed if any layers still reference it
+ if (!ownedSource) {
+ return;
+ }
+
+ // Release the peer relationships. These will be re-established when the source is added to a map
+ assert(ownedSource->peer.has_value());
+ util::any_cast<std::unique_ptr<Source>>(&(ownedSource->peer))->release();
+ ownedSource->peer.reset();
+
+ // Release the strong reference to the java peer
+ assert(javaPeer);
+ javaPeer.release();
+
+ rendererFrontend = nullptr;
}
jni::Class<Source> Source::javaClass;
@@ -82,6 +148,13 @@ namespace android {
METHOD(&Source::getAttribution, "nativeGetAttribution")
);
+ // Register subclasses
+ GeoJSONSource::registerNative(env);
+ ImageSource::registerNative(env);
+ RasterSource::registerNative(env);
+ UnknownSource::registerNative(env);
+ VectorSource::registerNative(env);
+ CustomGeometrySource::registerNative(env);
}
} // namespace android
diff --git a/platform/android/src/style/sources/source.hpp b/platform/android/src/style/sources/source.hpp
index 383017b66f..718f60b381 100644
--- a/platform/android/src/style/sources/source.hpp
+++ b/platform/android/src/style/sources/source.hpp
@@ -21,48 +21,40 @@ public:
static void registerNative(jni::JNIEnv&);
+ static jni::Object<Source> peerForCoreSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&);
+
/*
- * Called when a Java object is created on the c++ side
+ * Called when a Java object is created for a core source that belongs to a map.
*/
- Source(mbgl::style::Source&);
+ Source(jni::JNIEnv&, mbgl::style::Source&, jni::Object<Source>, AndroidRendererFrontend&);
/*
- * Called when a Java object was created from the jvm side
+ * Called when a Java object is created for a new core source that does not belong to a map.
*/
Source(jni::JNIEnv&, std::unique_ptr<mbgl::style::Source>);
virtual ~Source();
- /**
- * Set core source (ie return ownership after remove)
- */
- void setSource(std::unique_ptr<style::Source>);
-
- style::Source& get();
-
- void addToMap(mbgl::Map&);
+ void addToMap(JNIEnv&, jni::Object<Source>, mbgl::Map&, AndroidRendererFrontend&);
- void setRendererFrontend(AndroidRendererFrontend&);
-
- virtual jni::jobject* createJavaPeer(jni::JNIEnv&) = 0;
+ void removeFromMap(JNIEnv&, jni::Object<Source>, mbgl::Map&);
jni::String getId(jni::JNIEnv&);
jni::String getAttribution(jni::JNIEnv&);
protected:
- // Release the owned view and return it
- std::unique_ptr<mbgl::style::Source> releaseCoreSource();
-
- // Set on newly created sources until added to the map
+ // Set on newly created sources until added to the map.
std::unique_ptr<mbgl::style::Source> ownedSource;
- // Raw pointer that is valid until the source is removed from the map
+ // Raw pointer that is valid at all times.
mbgl::style::Source& source;
- // RendererFrontend pointer is valid only when
- // added to the map
- AndroidRendererFrontend* rendererFrontend;
+ // Set when the source is added to a map.
+ jni::UniqueObject<Source> javaPeer;
+
+ // RendererFrontend pointer is valid only when added to the map.
+ AndroidRendererFrontend* rendererFrontend { nullptr };
};
} // namespace android
diff --git a/platform/android/src/style/sources/sources.cpp b/platform/android/src/style/sources/sources.cpp
deleted file mode 100644
index 9ab3ca8e84..0000000000
--- a/platform/android/src/style/sources/sources.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-#include "sources.hpp"
-
-#include <mbgl/style/source.hpp>
-#include <mbgl/style/sources/geojson_source.hpp>
-#include <mbgl/style/sources/image_source.hpp>
-#include <mbgl/style/sources/raster_source.hpp>
-#include <mbgl/style/sources/vector_source.hpp>
-
-#include "source.hpp"
-#include "geojson_source.hpp"
-#include "image_source.hpp"
-#include "raster_source.hpp"
-#include "unknown_source.hpp"
-#include "vector_source.hpp"
-
-namespace {
-
- using namespace mbgl::android;
-
- Source* initializeSourcePeer(mbgl::style::Source& coreSource) {
- Source* source;
- if (coreSource.is<mbgl::style::VectorSource>()) {
- source = new VectorSource(*coreSource.as<mbgl::style::VectorSource>());
- } else if (coreSource.is<mbgl::style::RasterSource>()) {
- source = new RasterSource(*coreSource.as<mbgl::style::RasterSource>());
- } else if (coreSource.is<mbgl::style::GeoJSONSource>()) {
- source = new GeoJSONSource(*coreSource.as<mbgl::style::GeoJSONSource>());
- } else if (coreSource.is<mbgl::style::ImageSource>()) {
- source = new ImageSource(*coreSource.as<mbgl::style::ImageSource>());
- } else {
- source = new UnknownSource(coreSource);
- }
-
- return source;
- }
-} // namespace
-
-namespace mbgl {
-namespace android {
-
-
-jni::jobject* createJavaSourcePeer(jni::JNIEnv& env, AndroidRendererFrontend& frontend, mbgl::style::Source& coreSource) {
- std::unique_ptr<Source> peerSource = std::unique_ptr<Source>(initializeSourcePeer(coreSource));
- peerSource->setRendererFrontend(frontend);
- jni::jobject* result = peerSource->createJavaPeer(env);
- peerSource.release();
- return result;
-}
-
-void registerNativeSources(jni::JNIEnv& env) {
- Source::registerNative(env);
- GeoJSONSource::registerNative(env);
- ImageSource::registerNative(env);
- RasterSource::registerNative(env);
- UnknownSource::registerNative(env);
- VectorSource::registerNative(env);
-}
-
-}
-}
diff --git a/platform/android/src/style/sources/sources.hpp b/platform/android/src/style/sources/sources.hpp
deleted file mode 100644
index c7b36818b2..0000000000
--- a/platform/android/src/style/sources/sources.hpp
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma once
-
-#include <mbgl/style/source.hpp>
-
-#include "source.hpp"
-#include "../../android_renderer_frontend.hpp"
-
-#include <jni/jni.hpp>
-
-namespace mbgl {
-namespace android {
-
- jni::jobject* createJavaSourcePeer(jni::JNIEnv&, AndroidRendererFrontend&, mbgl::style::Source&);
-
- void registerNativeSources(jni::JNIEnv&);
-
-} // namespace android
-} // namespace mbgl
diff --git a/platform/android/src/style/sources/unknown_source.cpp b/platform/android/src/style/sources/unknown_source.cpp
index 79f27bdfbf..4b5510c1db 100644
--- a/platform/android/src/style/sources/unknown_source.cpp
+++ b/platform/android/src/style/sources/unknown_source.cpp
@@ -12,15 +12,17 @@ namespace {
namespace mbgl {
namespace android {
- UnknownSource::UnknownSource(mbgl::style::Source& coreSource)
- : Source(coreSource) {
+ UnknownSource::UnknownSource(jni::JNIEnv& env,
+ mbgl::style::Source& coreSource,
+ AndroidRendererFrontend& frontend)
+ : Source(env, coreSource, createJavaPeer(env), frontend) {
}
jni::Class<UnknownSource> UnknownSource::javaClass;
- jni::jobject* UnknownSource::createJavaPeer(jni::JNIEnv& env) {
+ jni::Object<Source> UnknownSource::createJavaPeer(jni::JNIEnv& env) {
static auto constructor = UnknownSource::javaClass.template GetConstructor<jni::jlong>(env);
- return UnknownSource::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this));
+ return jni::Object<Source>(UnknownSource::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)).Get());
}
void UnknownSource::registerNative(jni::JNIEnv& env) {
diff --git a/platform/android/src/style/sources/unknown_source.hpp b/platform/android/src/style/sources/unknown_source.hpp
index 4a003c9a7f..414d420c61 100644
--- a/platform/android/src/style/sources/unknown_source.hpp
+++ b/platform/android/src/style/sources/unknown_source.hpp
@@ -16,11 +16,12 @@ public:
static void registerNative(jni::JNIEnv&);
- UnknownSource(mbgl::style::Source&);
+ UnknownSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&);
~UnknownSource() = default;
- jni::jobject* createJavaPeer(jni::JNIEnv&);
+private:
+ jni::Object<Source> createJavaPeer(jni::JNIEnv&);
}; // class UnknownSource
diff --git a/platform/android/src/style/sources/vector_source.cpp b/platform/android/src/style/sources/vector_source.cpp
index 7fe45441bd..9a9548d283 100644
--- a/platform/android/src/style/sources/vector_source.cpp
+++ b/platform/android/src/style/sources/vector_source.cpp
@@ -30,8 +30,10 @@ namespace android {
) {
}
- VectorSource::VectorSource(mbgl::style::VectorSource& coreSource)
- : Source(coreSource) {
+ VectorSource::VectorSource(jni::JNIEnv& env,
+ mbgl::style::Source& coreSource,
+ AndroidRendererFrontend& frontend)
+ : Source(env, coreSource, createJavaPeer(env), frontend) {
}
VectorSource::~VectorSource() = default;
@@ -56,9 +58,9 @@ namespace android {
jni::Class<VectorSource> VectorSource::javaClass;
- jni::jobject* VectorSource::createJavaPeer(jni::JNIEnv& env) {
+ jni::Object<Source> VectorSource::createJavaPeer(jni::JNIEnv& env) {
static auto constructor = VectorSource::javaClass.template GetConstructor<jni::jlong>(env);
- return VectorSource::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this));
+ return jni::Object<Source>(VectorSource::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)).Get());
}
void VectorSource::registerNative(jni::JNIEnv& env) {
diff --git a/platform/android/src/style/sources/vector_source.hpp b/platform/android/src/style/sources/vector_source.hpp
index 509fe068d1..16049f5c77 100644
--- a/platform/android/src/style/sources/vector_source.hpp
+++ b/platform/android/src/style/sources/vector_source.hpp
@@ -19,7 +19,7 @@ public:
VectorSource(jni::JNIEnv&, jni::String, jni::Object<>);
- VectorSource(mbgl::style::VectorSource&);
+ VectorSource(jni::JNIEnv&, mbgl::style::Source&, AndroidRendererFrontend&);
~VectorSource();
@@ -28,7 +28,8 @@ public:
jni::String getURL(jni::JNIEnv&);
- jni::jobject* createJavaPeer(jni::JNIEnv&);
+private:
+ jni::Object<Source> createJavaPeer(jni::JNIEnv&);
}; // class VectorSource
diff --git a/platform/android/src/style/value.cpp b/platform/android/src/style/value.cpp
index e1cd81d7fd..70bdea6677 100644
--- a/platform/android/src/style/value.cpp
+++ b/platform/android/src/style/value.cpp
@@ -24,8 +24,6 @@ namespace android {
Value::Value(jni::JNIEnv& _env, jni::jobject* _value) : env(_env), value(_value, ObjectDeleter(env)) {}
- Value::~Value() = default;
-
bool Value::isNull() const {
return value == nullptr;
}
diff --git a/platform/android/src/style/value.hpp b/platform/android/src/style/value.hpp
index 7464bae832..2057b93454 100644
--- a/platform/android/src/style/value.hpp
+++ b/platform/android/src/style/value.hpp
@@ -9,9 +9,13 @@ namespace android {
class Value {
public:
-
Value(jni::JNIEnv&, jni::jobject*);
- virtual ~Value();
+
+ Value(Value&&) = default;
+ Value& operator=(Value&&) = default;
+
+ Value(const Value&) = delete;
+ Value& operator=(const Value&) = delete;
bool isNull() const;
bool isArray() const;
diff --git a/platform/darwin/docs/theme/assets/css/jazzy.css.scss b/platform/darwin/docs/theme/assets/css/jazzy.css.scss
index ad0a3b7082..103ba601dc 100644
--- a/platform/darwin/docs/theme/assets/css/jazzy.css.scss
+++ b/platform/darwin/docs/theme/assets/css/jazzy.css.scss
@@ -386,6 +386,7 @@ pre code {
.nav-group-task[data-name="MGLStyleFunction"],
.nav-group-task[data-name="MGLStyleLayer"],
.nav-group-task[data-name="MGLTileSource"],
+.nav-group-task[data-name="MGLAbstractShapeSource"],
.nav-group-task[data-name="MGLVectorStyleLayer"] {
.nav-group-task-link::after {
@extend %nav-group-task-gloss;
diff --git a/platform/darwin/mbgl/gl/gl_impl.hpp b/platform/darwin/mbgl/gl/gl_impl.hpp
new file mode 100644
index 0000000000..b4c062a474
--- /dev/null
+++ b/platform/darwin/mbgl/gl/gl_impl.hpp
@@ -0,0 +1,16 @@
+#pragma once
+
+#include "TargetConditionals.h"
+#if TARGET_OS_IPHONE
+ #include <OpenGLES/ES2/gl.h>
+ #include <OpenGLES/ES2/glext.h>
+#elif TARGET_IPHONE_SIMULATOR
+ #include <OpenGLES/ES2/gl.h>
+ #include <OpenGLES/ES2/glext.h>
+#elif TARGET_OS_MAC
+ #include <OpenGL/OpenGL.h>
+ #include <OpenGL/gl.h>
+ #include <OpenGL/glext.h>
+#else
+ #error Unsupported Apple platform
+#endif
diff --git a/platform/darwin/mbgl/util/image+MGLAdditions.hpp b/platform/darwin/mbgl/util/image+MGLAdditions.hpp
index c738b4523d..c5343af4de 100644
--- a/platform/darwin/mbgl/util/image+MGLAdditions.hpp
+++ b/platform/darwin/mbgl/util/image+MGLAdditions.hpp
@@ -5,7 +5,7 @@
#include <CoreGraphics/CGImage.h>
// Creates a CGImage from a PremultipliedImage, taking over the memory ownership.
-CGImageRef CGImageFromMGLPremultipliedImage(mbgl::PremultipliedImage&&);
+CGImageRef CGImageCreateWithMGLPremultipliedImage(mbgl::PremultipliedImage&&);
// Creates a PremultipliedImage by copying the pixels of the CGImage.
// Does not alter the retain count of the supplied CGImage.
diff --git a/platform/darwin/src/MGLAbstractShapeSource.h b/platform/darwin/src/MGLAbstractShapeSource.h
new file mode 100644
index 0000000000..3b35986b3f
--- /dev/null
+++ b/platform/darwin/src/MGLAbstractShapeSource.h
@@ -0,0 +1,99 @@
+#import "MGLSource.h"
+
+/**
+ Options for `MGLShapeSource` objects.
+ */
+typedef NSString *MGLShapeSourceOption NS_STRING_ENUM;
+
+/**
+ An `NSNumber` object containing a Boolean enabling or disabling clustering.
+ If the `shape` property contains point shapes, setting this option to
+ `YES` clusters the points by radius into groups. The default value is `NO`.
+
+ This attribute corresponds to the
+ <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-cluster"><code>cluster</code></a>
+ source property in the Mapbox Style Specification.
+
+ This option only affects point features within a shape source.
+ */
+extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionClustered;
+
+/**
+ An `NSNumber` object containing an integer; specifies the radius of each
+ cluster if clustering is enabled. A value of 512 produces a radius equal to
+ the width of a tile. The default value is 50.
+ */
+extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionClusterRadius;
+
+/**
+ An `NSNumber` object containing an integer; specifies the maximum zoom level at
+ which to cluster points if clustering is enabled. Defaults to one zoom level
+ less than the value of `MGLShapeSourceOptionMaximumZoomLevel` so that, at the
+ maximum zoom level, the shapes are not clustered.
+
+ This attribute corresponds to the
+ <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-clusterMaxZoom"><code>clusterMaxZoom</code></a>
+ source property in the Mapbox Style Specification.
+ */
+extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevelForClustering;
+
+/**
+ An `NSNumber` object containing an integer; specifies the minimum zoom level at
+ which to create vector tiles. The default value is 0.
+
+ This attribute corresponds to the
+ <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-minzoom"><code>minzoom</code></a>
+ source property in the Mapbox Style Specification.
+ */
+extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionMinimumZoomLevel;
+
+/**
+ An `NSNumber` object containing an integer; specifies the maximum zoom level at
+ which to create vector tiles. A greater value produces greater detail at high
+ zoom levels. The default value is 18.
+
+ This attribute corresponds to the
+ <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-maxzoom"><code>maxzoom</code></a>
+ source property in the Mapbox Style Specification.
+ */
+extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevel;
+
+/**
+ An `NSNumber` object containing an integer; specifies the size of the tile
+ buffer on each side. A value of 0 produces no buffer. A value of 512 produces a
+ buffer as wide as the tile itself. Larger values produce fewer rendering
+ artifacts near tile edges and slower performance. The default value is 128.
+
+ This attribute corresponds to the
+ <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-buffer"><code>buffer</code></a>
+ source property in the Mapbox Style Specification.
+ */
+extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionBuffer;
+
+/**
+ An `NSNumber` object containing a double; specifies the Douglas-Peucker
+ simplification tolerance. A greater value produces simpler geometries and
+ improves performance. The default value is 0.375.
+
+ This attribute corresponds to the
+ <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-tolerance"><code>tolerance</code></a>
+ source property in the Mapbox Style Specification.
+ */
+extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance;
+
+/**
+ `MGLAbstractShapeSource` is an abstract base class for map content sources that
+ supply vector shapes to be shown on the map. A shape source is added to an
+ `MGLStyle` object along with an `MGLVectorStyleLayer` object. The vector style
+ layer defines the appearance of any content supplied by the shape source.
+
+
+ Do not create instances of this class directly, and do not create your own
+ subclasses of this class. Instead, create instances of `MGLShapeSource` or
+ `MGLComputedShapeSource`.
+ */
+MGL_EXPORT
+@interface MGLAbstractShapeSource : MGLSource
+
+
+@end
diff --git a/platform/darwin/src/MGLAbstractShapeSource.mm b/platform/darwin/src/MGLAbstractShapeSource.mm
new file mode 100644
index 0000000000..755d040387
--- /dev/null
+++ b/platform/darwin/src/MGLAbstractShapeSource.mm
@@ -0,0 +1,117 @@
+#import "MGLAbstractShapeSource.h"
+#import "MGLAbstractShapeSource_Private.h"
+
+const MGLShapeSourceOption MGLShapeSourceOptionBuffer = @"MGLShapeSourceOptionBuffer";
+const MGLShapeSourceOption MGLShapeSourceOptionClusterRadius = @"MGLShapeSourceOptionClusterRadius";
+const MGLShapeSourceOption MGLShapeSourceOptionClustered = @"MGLShapeSourceOptionClustered";
+const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevel = @"MGLShapeSourceOptionMaximumZoomLevel";
+const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevelForClustering = @"MGLShapeSourceOptionMaximumZoomLevelForClustering";
+const MGLShapeSourceOption MGLShapeSourceOptionMinimumZoomLevel = @"MGLShapeSourceOptionMinimumZoomLevel";
+const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance = @"MGLShapeSourceOptionSimplificationTolerance";
+
+@interface MGLAbstractShapeSource ()
+
+@end
+
+@implementation MGLAbstractShapeSource
+
+@end
+
+mbgl::style::GeoJSONOptions MGLGeoJSONOptionsFromDictionary(NS_DICTIONARY_OF(MGLShapeSourceOption, id) *options) {
+ auto geoJSONOptions = mbgl::style::GeoJSONOptions();
+
+ if (NSNumber *value = options[MGLShapeSourceOptionMinimumZoomLevel]) {
+ if (![value isKindOfClass:[NSNumber class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"MGLShapeSourceOptionMaximumZoomLevel must be an NSNumber."];
+ }
+ geoJSONOptions.minzoom = value.integerValue;
+ }
+
+ if (NSNumber *value = options[MGLShapeSourceOptionMaximumZoomLevel]) {
+ if (![value isKindOfClass:[NSNumber class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"MGLShapeSourceOptionMaximumZoomLevel must be an NSNumber."];
+ }
+ geoJSONOptions.maxzoom = value.integerValue;
+ }
+
+ if (NSNumber *value = options[MGLShapeSourceOptionBuffer]) {
+ if (![value isKindOfClass:[NSNumber class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"MGLShapeSourceOptionBuffer must be an NSNumber."];
+ }
+ geoJSONOptions.buffer = value.integerValue;
+ }
+
+ if (NSNumber *value = options[MGLShapeSourceOptionSimplificationTolerance]) {
+ if (![value isKindOfClass:[NSNumber class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"MGLShapeSourceOptionSimplificationTolerance must be an NSNumber."];
+ }
+ geoJSONOptions.tolerance = value.doubleValue;
+ }
+
+ if (NSNumber *value = options[MGLShapeSourceOptionClusterRadius]) {
+ if (![value isKindOfClass:[NSNumber class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"MGLShapeSourceOptionClusterRadius must be an NSNumber."];
+ }
+ geoJSONOptions.clusterRadius = value.integerValue;
+ }
+
+ if (NSNumber *value = options[MGLShapeSourceOptionMaximumZoomLevelForClustering]) {
+ if (![value isKindOfClass:[NSNumber class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"MGLShapeSourceOptionMaximumZoomLevelForClustering must be an NSNumber."];
+ }
+ geoJSONOptions.clusterMaxZoom = value.integerValue;
+ }
+
+ if (NSNumber *value = options[MGLShapeSourceOptionClustered]) {
+ if (![value isKindOfClass:[NSNumber class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"MGLShapeSourceOptionClustered must be an NSNumber."];
+ }
+ geoJSONOptions.cluster = value.boolValue;
+ }
+
+ return geoJSONOptions;
+}
+
+mbgl::style::CustomGeometrySource::Options MBGLCustomGeometrySourceOptionsFromDictionary(NS_DICTIONARY_OF(MGLShapeSourceOption, id) *options) {
+ mbgl::style::CustomGeometrySource::Options sourceOptions;
+
+ if (NSNumber *value = options[MGLShapeSourceOptionMinimumZoomLevel]) {
+ if (![value isKindOfClass:[NSNumber class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"MGLShapeSourceOptionMaximumZoomLevelForClustering must be an NSNumber."];
+ }
+ sourceOptions.zoomRange.min = value.integerValue;
+ }
+
+ if (NSNumber *value = options[MGLShapeSourceOptionMaximumZoomLevel]) {
+ if (![value isKindOfClass:[NSNumber class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"MGLShapeSourceOptionMaximumZoomLevel must be an NSNumber."];
+ }
+ sourceOptions.zoomRange.max = value.integerValue;
+ }
+
+ if (NSNumber *value = options[MGLShapeSourceOptionBuffer]) {
+ if (![value isKindOfClass:[NSNumber class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"MGLShapeSourceOptionBuffer must be an NSNumber."];
+ }
+ sourceOptions.tileOptions.buffer = value.integerValue;
+ }
+
+ if (NSNumber *value = options[MGLShapeSourceOptionSimplificationTolerance]) {
+ if (![value isKindOfClass:[NSNumber class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"MGLShapeSourceOptionSimplificationTolerance must be an NSNumber."];
+ }
+ sourceOptions.tileOptions.tolerance = value.doubleValue;
+ }
+ return sourceOptions;
+}
diff --git a/platform/darwin/src/MGLAbstractShapeSource_Private.h b/platform/darwin/src/MGLAbstractShapeSource_Private.h
new file mode 100644
index 0000000000..ddde55b149
--- /dev/null
+++ b/platform/darwin/src/MGLAbstractShapeSource_Private.h
@@ -0,0 +1,22 @@
+#import "MGLAbstractShapeSource.h"
+
+#import "MGLFoundation.h"
+#import "MGLTypes.h"
+#import "MGLShape.h"
+
+#include <mbgl/style/sources/geojson_source.hpp>
+#include <mbgl/style/sources/custom_geometry_source.hpp>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface MGLAbstractShapeSource (Private)
+
+MGL_EXPORT
+
+mbgl::style::GeoJSONOptions MGLGeoJSONOptionsFromDictionary(NS_DICTIONARY_OF(MGLShapeSourceOption, id) *options);
+
+MGL_EXPORT
+mbgl::style::CustomGeometrySource::Options MBGLCustomGeometrySourceOptionsFromDictionary(NS_DICTIONARY_OF(MGLShapeSourceOption, id) *options);
+
+@end
+NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLAccountManager.m b/platform/darwin/src/MGLAccountManager.m
index 7e55779d04..729caeaa31 100644
--- a/platform/darwin/src/MGLAccountManager.m
+++ b/platform/darwin/src/MGLAccountManager.m
@@ -39,7 +39,7 @@
}
static dispatch_once_t onceToken;
static MGLAccountManager *_sharedManager;
- void (^setupBlock)() = ^{
+ void (^setupBlock)(void) = ^{
dispatch_once(&onceToken, ^{
_sharedManager = [[self alloc] init];
});
diff --git a/platform/darwin/src/MGLAttributionInfo.mm b/platform/darwin/src/MGLAttributionInfo.mm
index 52a83fd18e..73147270c1 100644
--- a/platform/darwin/src/MGLAttributionInfo.mm
+++ b/platform/darwin/src/MGLAttributionInfo.mm
@@ -160,6 +160,7 @@
[NSURLQueryItem queryItemWithName:@"owner" value:stylePathComponents[1]],
[NSURLQueryItem queryItemWithName:@"id" value:stylePathComponents[2]],
[NSURLQueryItem queryItemWithName:@"access_token" value:[MGLAccountManager accessToken]],
+ [NSURLQueryItem queryItemWithName:@"map_sdk_version" value:[NSBundle mgl_frameworkInfoDictionary][@"MGLSemanticVersionString"]],
]];
}
}
diff --git a/platform/darwin/src/MGLComputedShapeSource.h b/platform/darwin/src/MGLComputedShapeSource.h
new file mode 100644
index 0000000000..f90f2c94b1
--- /dev/null
+++ b/platform/darwin/src/MGLComputedShapeSource.h
@@ -0,0 +1,113 @@
+#import "MGLAbstractShapeSource.h"
+
+#import "MGLFoundation.h"
+#import "MGLGeometry.h"
+#import "MGLTypes.h"
+#import "MGLShape.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@protocol MGLFeature;
+
+/**
+ Data source for `MGLComputedShapeSource`. This protocol defines two optional methods for fetching
+ data, one based on tile coordinates, and one based on a bounding box. Classes that implement this
+ protocol must implement one, and only one of the methods. Methods on this protocol will not be
+ called on main thread, they will be called on the caller's `requestQueue`.
+ */
+@protocol MGLComputedShapeSourceDataSource <NSObject>
+
+@optional
+/**
+ Fetch features for a tile. This method will not be invoked on the main queue, it
+ will be invoked on the caller's `requestQueue`.
+ @param x Tile X coordinate.
+ @param y Tile Y coordinate.
+ @param zoomLevel Tile zoom level.
+ */
+- (NSArray<MGLShape <MGLFeature> *>*)featuresInTileAtX:(NSUInteger)x y:(NSUInteger)y zoomLevel:(NSUInteger)zoomLevel;
+
+/**
+ Fetch features for a tile. This method will not be invoked on the main queue, it
+ will be invoked on the caller's `requestQueue`.
+ @param bounds The bounds to fetch data for.
+ @param zoomLevel Tile zoom level.
+ */
+- (NSArray<MGLShape <MGLFeature> *>*)featuresInCoordinateBounds:(MGLCoordinateBounds)bounds zoomLevel:(NSUInteger)zoomLevel;
+
+@end
+
+/**
+ A source for vector data that is fetched one tile at a time. Useful for sources that are
+ too large to fit in memory, or are already divided into tiles, but not in Mapbox Vector Tile format.
+
+ Supported options are `MGLShapeSourceOptionMinimumZoomLevel`, `MGLShapeSourceOptionMaximumZoomLevel`,
+ `MGLShapeSourceOptionBuffer`, and `MGLShapeSourceOptionSimplificationTolerance.` This source does
+ not support clustering.
+ */
+MGL_EXPORT
+@interface MGLComputedShapeSource : MGLAbstractShapeSource
+
+/**
+ Returns a custom shape data source initialized with an identifier, and a
+ dictionary of options for the source according to the
+ <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson">style
+ specification</a>.
+
+ @param identifier A string that uniquely identifies the source.
+ @param options An `NSDictionary` of options for this source.
+ */
+- (instancetype)initWithIdentifier:(NSString *)identifier options:(nullable NS_DICTIONARY_OF(MGLShapeSourceOption, id) *)options NS_DESIGNATED_INITIALIZER;
+
+/**
+ Returns a custom shape data source initialized with an identifier, data source, and a
+ dictionary of options for the source according to the
+ <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson">style
+ specification</a>.
+
+ @param identifier A string that uniquely identifies the source.
+ @param options An `NSDictionary` of options for this source.
+ */
+- (instancetype)initWithIdentifier:(NSString *)identifier dataSource:(id<MGLComputedShapeSourceDataSource>)dataSource options:(nullable NS_DICTIONARY_OF(MGLShapeSourceOption, id) *)options;
+
+/**
+ Invalidates all the features and properties intersecting with or contained in
+ the specified bounds. New fetch requests will immediately be invoked on the
+ `MGLComputedShapeSourceDataSource`.
+ @param bounds Coordinate bounds to invalidate.
+ */
+- (void) invalidateBounds:(MGLCoordinateBounds)bounds;
+
+/**
+ Invalidates all the feautres and properties of a given tile. A new fetch request
+ will immediately be invoked on the `MGLComputedShapeSourceDataSource`.
+ @param x Tile X coordinate.
+ @param y Tile Y coordinate.
+ @param zoomLevel Tile zoom level.
+ */
+- (void) invalidateTileAtX:(NSUInteger)x y:(NSUInteger)y zoomLevel:(NSUInteger)zoomLevel;
+
+/**
+ Set a new set of features for a tile. This method can be invkoed from background threads.
+ For best performance, use this method only to update tiles that have already been requested
+ through `MGLComputedShapeSourceDataSource.`
+ @param features Features for the tile.
+ @param x Tile X coordinate.
+ @param y Tile Y coordinate.
+ @param zoomLevel Tile zoom level.
+ */
+- (void) setFeatures:(NSArray<MGLShape <MGLFeature> *>*)features inTileAtX:(NSUInteger)x y:(NSUInteger)y zoomLevel:(NSUInteger)zoomLevel;
+
+/**
+ An object that implements the `MGLComputedShapeSourceDataSource` protocol that will be queried for tile data.
+ */
+@property (nonatomic, weak, nullable) id<MGLComputedShapeSourceDataSource> dataSource;
+
+/**
+ A queue that calls to the data source will be made on.
+ */
+@property (nonatomic, readonly) NSOperationQueue *requestQueue;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLComputedShapeSource.mm b/platform/darwin/src/MGLComputedShapeSource.mm
new file mode 100644
index 0000000000..0a3c92bb97
--- /dev/null
+++ b/platform/darwin/src/MGLComputedShapeSource.mm
@@ -0,0 +1,169 @@
+#import "MGLComputedShapeSource.h"
+
+#import "MGLMapView_Private.h"
+#import "MGLSource_Private.h"
+#import "MGLShape_Private.h"
+#import "MGLAbstractShapeSource_Private.h"
+#import "MGLGeometry_Private.h"
+
+#include <mbgl/map/map.hpp>
+#include <mbgl/style/sources/custom_geometry_source.hpp>
+#include <mbgl/tile/tile_id.hpp>
+#include <mbgl/util/geojson.hpp>
+
+@interface MGLComputedShapeSource () {
+ std::unique_ptr<mbgl::style::CustomGeometrySource> _pendingSource;
+}
+
+@property (nonatomic, readwrite) NSDictionary *options;
+@property (nonatomic, assign) BOOL dataSourceImplementsFeaturesForTile;
+@property (nonatomic, assign) BOOL dataSourceImplementsFeaturesForBounds;
+
+@end
+
+@interface MGLComputedShapeSourceFetchOperation : NSOperation
+
+@property (nonatomic, readonly) uint8_t z;
+@property (nonatomic, readonly) uint32_t x;
+@property (nonatomic, readonly) uint32_t y;
+@property (nonatomic, assign) BOOL dataSourceImplementsFeaturesForTile;
+@property (nonatomic, assign) BOOL dataSourceImplementsFeaturesForBounds;
+@property (nonatomic, weak, nullable) id<MGLComputedShapeSourceDataSource> dataSource;
+@property (nonatomic, nullable) mbgl::style::CustomGeometrySource *rawSource;
+
+- (instancetype)initForSource:(MGLComputedShapeSource*)source tile:(const mbgl::CanonicalTileID&)tileId;
+
+@end
+
+@implementation MGLComputedShapeSourceFetchOperation
+
+- (instancetype)initForSource:(MGLComputedShapeSource*)source tile:(const mbgl::CanonicalTileID&)tileID {
+ self = [super init];
+ _z = tileID.z;
+ _x = tileID.x;
+ _y = tileID.y;
+ _dataSourceImplementsFeaturesForTile = source.dataSourceImplementsFeaturesForTile;
+ _dataSourceImplementsFeaturesForBounds = source.dataSourceImplementsFeaturesForBounds;
+ _dataSource = source.dataSource;
+ mbgl::style::CustomGeometrySource *rawSource = static_cast<mbgl::style::CustomGeometrySource *>(source.rawSource);
+ _rawSource = rawSource;
+ return self;
+}
+
+- (void)main {
+ if ([self isCancelled]) {
+ return;
+ }
+
+ NSArray<MGLShape <MGLFeature> *> *data;
+ if(!self.dataSource) {
+ data = nil;
+ } else if(self.dataSourceImplementsFeaturesForTile) {
+ data = [self.dataSource featuresInTileAtX:self.x
+ y:self.y
+ zoomLevel:self.z];
+ } else {
+ mbgl::CanonicalTileID tileID = mbgl::CanonicalTileID(self.z, self.x, self.y);
+ mbgl::LatLngBounds tileBounds = mbgl::LatLngBounds(tileID);
+ data = [self.dataSource featuresInCoordinateBounds:MGLCoordinateBoundsFromLatLngBounds(tileBounds)
+ zoomLevel:self.z];
+ }
+
+ if(![self isCancelled]) {
+ mbgl::FeatureCollection featureCollection;
+ featureCollection.reserve(data.count);
+ for (MGLShape <MGLFeature> * feature in data) {
+ mbgl::Feature geoJsonObject = [feature geoJSONObject].get<mbgl::Feature>();
+ featureCollection.push_back(geoJsonObject);
+ }
+ const auto geojson = mbgl::GeoJSON{featureCollection};
+ if(![self isCancelled] && self.rawSource) {
+ self.rawSource->setTileData(mbgl::CanonicalTileID(self.z, self.x, self.y), geojson);
+ }
+ }
+}
+
+- (void)cancel {
+ [super cancel];
+ self.rawSource = NULL;
+}
+
+@end
+
+@implementation MGLComputedShapeSource
+
+- (instancetype)initWithIdentifier:(NSString *)identifier options:(NS_DICTIONARY_OF(MGLShapeSourceOption, id) *)options {
+ NSOperationQueue *requestQueue = [[NSOperationQueue alloc] init];
+ requestQueue.name = [NSString stringWithFormat:@"mgl.MGLComputedShapeSource.%@", identifier];
+ requestQueue.qualityOfService = NSQualityOfServiceUtility;
+ requestQueue.maxConcurrentOperationCount = 4;
+
+ auto sourceOptions = MBGLCustomGeometrySourceOptionsFromDictionary(options);
+ sourceOptions.fetchTileFunction = ^void(const mbgl::CanonicalTileID& tileID) {
+ NSOperation *operation = [[MGLComputedShapeSourceFetchOperation alloc] initForSource:self tile:tileID];
+ [requestQueue addOperation:operation];
+ };
+
+ sourceOptions.cancelTileFunction = ^void(const mbgl::CanonicalTileID& tileID) {
+ for (MGLComputedShapeSourceFetchOperation *operation in requestQueue.operations) {
+ if (operation.x == tileID.x && operation.y == tileID.y && operation.z == tileID.z) {
+ [operation cancel];
+ }
+ }
+ };
+
+ auto source = std::make_unique<mbgl::style::CustomGeometrySource>(identifier.UTF8String, sourceOptions);
+
+ if (self = [super initWithPendingSource:std::move(source)]) {
+ _requestQueue = requestQueue;
+ }
+ return self;
+}
+
+- (instancetype)initWithIdentifier:(NSString *)identifier dataSource:(id<MGLComputedShapeSourceDataSource>)dataSource options:(NS_DICTIONARY_OF(MGLShapeSourceOption, id) *)options {
+ if (self = [self initWithIdentifier:identifier options:options]) {
+ [self setDataSource:dataSource];
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [self.requestQueue cancelAllOperations];
+}
+
+- (void)setFeatures:(NSArray<MGLShape <MGLFeature> *>*)features inTileAtX:(NSUInteger)x y:(NSUInteger)y zoomLevel:(NSUInteger)zoomLevel {
+ mbgl::CanonicalTileID tileID = mbgl::CanonicalTileID((uint8_t)zoomLevel, (uint32_t)x, (uint32_t)y);
+ mbgl::FeatureCollection featureCollection;
+ featureCollection.reserve(features.count);
+ for (MGLShape <MGLFeature> * feature in features) {
+ mbgl::Feature geoJsonObject = [feature geoJSONObject].get<mbgl::Feature>();
+ featureCollection.push_back(geoJsonObject);
+ }
+ const auto geojson = mbgl::GeoJSON{featureCollection};
+ static_cast<mbgl::style::CustomGeometrySource *>(self.rawSource)->setTileData(tileID, geojson);
+}
+
+- (void)setDataSource:(id<MGLComputedShapeSourceDataSource>)dataSource {
+ [self.requestQueue cancelAllOperations];
+ // Check which method the datasource implements, to avoid having to check for each tile
+ self.dataSourceImplementsFeaturesForTile = [dataSource respondsToSelector:@selector(featuresInTileAtX:y:zoomLevel:)];
+ self.dataSourceImplementsFeaturesForBounds = [dataSource respondsToSelector:@selector(featuresInCoordinateBounds:zoomLevel:)];
+
+ if(!self.dataSourceImplementsFeaturesForBounds && !self.dataSourceImplementsFeaturesForTile) {
+ [NSException raise:@"Invalid Datasource" format:@"Datasource does not implement any MGLComputedShapeSourceDataSource methods"];
+ } else if(self.dataSourceImplementsFeaturesForBounds && self.dataSourceImplementsFeaturesForTile) {
+ [NSException raise:@"Invalid Datasource" format:@"Datasource implements multiple MGLComputedShapeSourceDataSource methods"];
+ }
+
+ _dataSource = dataSource;
+}
+
+- (void) invalidateBounds:(MGLCoordinateBounds)bounds {
+ ((mbgl::style::CustomGeometrySource *)self.rawSource)->invalidateRegion(MGLLatLngBoundsFromCoordinateBounds(bounds));
+}
+
+- (void) invalidateTileAtX:(NSUInteger)x y:(NSUInteger)y zoomLevel:(NSUInteger)z {
+ ((mbgl::style::CustomGeometrySource *)self.rawSource)->invalidateTile(mbgl::CanonicalTileID(z, (unsigned int)x, (unsigned int)y));
+}
+
+@end
diff --git a/platform/darwin/src/MGLConversion.h b/platform/darwin/src/MGLConversion.h
index d6363b28eb..0d18d4e716 100644
--- a/platform/darwin/src/MGLConversion.h
+++ b/platform/darwin/src/MGLConversion.h
@@ -1,9 +1,4 @@
-#import <Foundation/Foundation.h>
-
-#include <mbgl/util/logging.hpp>
#include <mbgl/style/conversion.hpp>
-#include <mbgl/util/feature.hpp>
-#include <mbgl/util/optional.hpp>
NS_ASSUME_NONNULL_BEGIN
@@ -11,128 +6,147 @@ namespace mbgl {
namespace style {
namespace conversion {
-/**
- A minimal wrapper class conforming to the requirements for `objectMember(v, name)` (see mbgl/style/conversion.hpp)
- This is necessary because using `NSObject*` as the value type in `optional<NSObject*>` causes problems for the ARC,
- due to things like `optional(const value_type& __v)`
- */
-class OptionalNSObjectValue {
+// A wrapper class for `id`, so as not to confuse ARC.
+class Holder {
public:
- OptionalNSObjectValue(NSObject * _Nullable _value) : value(_value) {}
-
- explicit operator bool() const {
- return value;
+ Holder(const id v) : value(v) {}
+ const id value;
+};
+
+template <>
+class ConversionTraits<Holder> {
+public:
+ static bool isUndefined(const Holder& holder) {
+ const id value = holder.value;
+ return !value || value == [NSNull null];
}
-
- NSObject * _Nullable operator*() {
- NSCAssert(this, @"Expected non-null value.");
- return value;
+
+ static bool isArray(const Holder& holder) {
+ const id value = holder.value;
+ return [value isKindOfClass:[NSArray class]];
}
-private:
- NSObject * _Nullable value;
-};
-inline bool isUndefined(const id value) {
- return !value || value == [NSNull null];
-}
+ static bool isObject(const Holder& holder) {
+ const id value = holder.value;
+ return [value isKindOfClass:[NSDictionary class]];
+ }
-inline bool isArray(const id value) {
- return [value isKindOfClass:[NSArray class]];
-}
+ static std::size_t arrayLength(const Holder& holder) {
+ const id value = holder.value;
+ NSCAssert([value isKindOfClass:[NSArray class]], @"Value must be an NSArray for getLength().");
+ NSArray *array = value;
+ auto length = [array count];
+ NSCAssert(length <= std::numeric_limits<size_t>::max(), @"Array length out of bounds.");
+ return length;
+ }
-inline bool isObject(const id value) {
- return [value isKindOfClass:[NSDictionary class]];
-}
+ static Holder arrayMember(const Holder& holder, std::size_t i) {
+ const id value = holder.value;
+ NSCAssert([value isKindOfClass:[NSArray class]], @"Value must be an NSArray for get(int).");
+ NSCAssert(i < NSUIntegerMax, @"Index must be less than NSUIntegerMax");
+ return {[value objectAtIndex: i]};
+ }
-inline std::size_t arrayLength(const id value) {
- NSCAssert([value isKindOfClass:[NSArray class]], @"Value must be an NSArray for getLength().");
- NSArray *array = value;
- auto length = [array count];
- NSCAssert(length <= std::numeric_limits<size_t>::max(), @"Array length out of bounds.");
- return length;
-}
+ static optional<Holder> objectMember(const Holder& holder, const char *key) {
+ const id value = holder.value;
+ NSCAssert([value isKindOfClass:[NSDictionary class]], @"Value must be an NSDictionary for get(string).");
+ NSObject *member = [value objectForKey: @(key)];
+ if (member && member != [NSNull null]) {
+ return {member};
+ } else {
+ return {};
+ }
+ }
-inline NSObject *arrayMember(const id value, std::size_t i) {
- NSCAssert([value isKindOfClass:[NSArray class]], @"Value must be an NSArray for get(int).");
- NSCAssert(i < NSUIntegerMax, @"Index must be less than NSUIntegerMax");
- return [value objectAtIndex: i];
-}
+// Compiler is wrong about `Fn` parameter missing a nullability specifier.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wnullability-completeness"
+ template <class Fn>
+ static optional<Error> eachMember(const Holder&, Fn&&) {
+#pragma clang diagnostic pop
+ // Not implemented (unneeded for MGLStyleFunction conversion).
+ NSCAssert(NO, @"eachMember not implemented");
+ return {};
+ }
-inline OptionalNSObjectValue objectMember(const id value, const char *key) {
- NSCAssert([value isKindOfClass:[NSDictionary class]], @"Value must be an NSDictionary for get(string).");
- NSObject *member = [value objectForKey: @(key)];
- if (member && member != [NSNull null]) {
- return { member };
- } else {
- return { nullptr };
+ static optional<bool> toBool(const Holder& holder) {
+ const id value = holder.value;
+ if (_isBool(value)) {
+ return ((NSNumber *)value).boolValue;
+ } else {
+ return {};
+ }
}
-}
-// Not implemented (unneeded for MGLStyleFunction conversion):
-// optional<Error> eachMember(const NSObject*, Fn&&)
+ static optional<float> toNumber(const Holder& holder) {
+ const id value = holder.value;
+ if (_isNumber(value)) {
+ return ((NSNumber *)value).floatValue;
+ } else {
+ return {};
+ }
+ }
-inline bool _isBool(const id value) {
- if (![value isKindOfClass:[NSNumber class]]) return false;
- // char: 32-bit boolean
- // BOOL: 64-bit boolean
- NSNumber *number = value;
- return ((strcmp([number objCType], @encode(char)) == 0) ||
- (strcmp([number objCType], @encode(BOOL)) == 0));
-}
-
-inline bool _isNumber(const id value) {
- return [value isKindOfClass:[NSNumber class]] && !_isBool(value);
-}
-
-inline bool _isString(const id value) {
- return [value isKindOfClass:[NSString class]];
-}
+ static optional<double> toDouble(const Holder& holder) {
+ const id value = holder.value;
+ if (_isNumber(value)) {
+ return ((NSNumber *)value).doubleValue;
+ } else {
+ return {};
+ }
+ }
-inline optional<bool> toBool(const id value) {
- if (_isBool(value)) {
- return ((NSNumber *)value).boolValue;
- } else {
- return {};
+ static optional<std::string> toString(const Holder& holder) {
+ const id value = holder.value;
+ if (_isString(value)) {
+ return std::string(static_cast<const char *>([value UTF8String]));
+ } else {
+ return {};
+ }
}
-}
-inline optional<float> toNumber(const id value) {
- if (_isNumber(value)) {
- return ((NSNumber *)value).floatValue;
- } else {
- return {};
+ static optional<mbgl::Value> toValue(const Holder& holder) {
+ const id value = holder.value;
+ if (isUndefined(value)) {
+ return {};
+ } else if (_isBool(value)) {
+ return { *toBool(holder) };
+ } else if ( _isString(value)) {
+ return { *toString(holder) };
+ } else if (_isNumber(value)) {
+ // Need to cast to a double here as the float is otherwise considered a bool...
+ return { static_cast<double>(*toNumber(holder)) };
+ } else {
+ return {};
+ }
}
-}
-inline optional<double> toDouble(const id value) {
- if (_isNumber(value)) {
- return ((NSNumber *)value).doubleValue;
- } else {
+ static optional<GeoJSON> toGeoJSON(const Holder& holder, Error& error) {
+ error = { "toGeoJSON not implemented" };
return {};
}
-}
-inline optional<std::string> toString(const id value) {
- if (_isString(value)) {
- return std::string(static_cast<const char *>([value UTF8String]));
- } else {
- return {};
+private:
+ static bool _isBool(const id value) {
+ if (![value isKindOfClass:[NSNumber class]]) return false;
+ // char: 32-bit boolean
+ // BOOL: 64-bit boolean
+ NSNumber *number = value;
+ return ((strcmp([number objCType], @encode(char)) == 0) ||
+ (strcmp([number objCType], @encode(BOOL)) == 0));
}
-}
-inline optional<mbgl::Value> toValue(const id value) {
- if (isUndefined(value)) {
- return {};
- } else if (_isBool(value)) {
- return { *toBool(value) };
- } else if ( _isString(value)) {
- return { *toString(value) };
- } else if (_isNumber(value)) {
- // Need to cast to a double here as the float is otherwise considered a bool...
- return { static_cast<double>(*toNumber(value)) };
- } else {
- return {};
+ static bool _isNumber(const id value) {
+ return [value isKindOfClass:[NSNumber class]] && !_isBool(value);
}
+
+ static bool _isString(const id value) {
+ return [value isKindOfClass:[NSString class]];
+ }
+};
+
+inline Convertible makeConvertible(const id value) {
+ return Convertible(Holder(value));
}
} // namespace conversion
@@ -140,4 +154,3 @@ inline optional<mbgl::Value> toValue(const id value) {
} // namespace mbgl
NS_ASSUME_NONNULL_END
-
diff --git a/platform/darwin/src/MGLFeature.mm b/platform/darwin/src/MGLFeature.mm
index 84f1a1ff25..033052bda8 100644
--- a/platform/darwin/src/MGLFeature.mm
+++ b/platform/darwin/src/MGLFeature.mm
@@ -7,11 +7,11 @@
#import "MGLShape_Private.h"
#import "MGLPointCollection_Private.h"
-#import "MGLPolyline+MGLAdditions.h"
-#import "MGLPolygon+MGLAdditions.h"
+#import "MGLPolyline_Private.h"
+#import "MGLPolygon_Private.h"
+
#import "NSDictionary+MGLAdditions.h"
#import "NSArray+MGLAdditions.h"
-
#import "NSExpression+MGLAdditions.h"
#import <mbgl/util/geometry.hpp>
diff --git a/platform/darwin/src/MGLMapSnapshotter.mm b/platform/darwin/src/MGLMapSnapshotter.mm
index 15a8f6c8ca..967706ac2e 100644
--- a/platform/darwin/src/MGLMapSnapshotter.mm
+++ b/platform/darwin/src/MGLMapSnapshotter.mm
@@ -332,6 +332,7 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
#else
image = [[NSImage alloc] initWithCGImage:cgimg size:[backgroundImage extent].size];
#endif
+
CGImageRelease(cgimg);
return image;
}
diff --git a/platform/darwin/src/MGLNetworkConfiguration.m b/platform/darwin/src/MGLNetworkConfiguration.m
index 82d333dc99..4cfa405a1a 100644
--- a/platform/darwin/src/MGLNetworkConfiguration.m
+++ b/platform/darwin/src/MGLNetworkConfiguration.m
@@ -13,7 +13,7 @@
+ (instancetype)sharedManager {
static dispatch_once_t onceToken;
static MGLNetworkConfiguration *_sharedManager;
- void (^setupBlock)() = ^{
+ void (^setupBlock)(void) = ^{
dispatch_once(&onceToken, ^{
_sharedManager = [[self alloc] init];
});
diff --git a/platform/darwin/src/MGLPolygon+MGLAdditions.h b/platform/darwin/src/MGLPolygon+MGLAdditions.h
deleted file mode 100644
index f409fb96ca..0000000000
--- a/platform/darwin/src/MGLPolygon+MGLAdditions.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#import <Mapbox/Mapbox.h>
-
-@interface MGLPolygon (MGLAdditions)
-
-- (NS_ARRAY_OF(id) *)mgl_coordinates;
-
-@end
diff --git a/platform/darwin/src/MGLPolygon+MGLAdditions.m b/platform/darwin/src/MGLPolygon+MGLAdditions.m
deleted file mode 100644
index 3e76a37157..0000000000
--- a/platform/darwin/src/MGLPolygon+MGLAdditions.m
+++ /dev/null
@@ -1,27 +0,0 @@
-#import "MGLPolygon+MGLAdditions.h"
-
-@implementation MGLPolygon (MGLAdditions)
-
-- (NS_ARRAY_OF(id) *)mgl_coordinates {
- NSMutableArray *coordinates = [NSMutableArray array];
-
- NSMutableArray *exteriorRing = [NSMutableArray array];
- for (NSUInteger index = 0; index < self.pointCount; index++) {
- CLLocationCoordinate2D coordinate = self.coordinates[index];
- [exteriorRing addObject:@[@(coordinate.longitude), @(coordinate.latitude)]];
- }
- [coordinates addObject:exteriorRing];
-
- for (MGLPolygon *interiorPolygon in self.interiorPolygons) {
- NSMutableArray *interiorRing = [NSMutableArray array];
- for (int index = 0; index < interiorPolygon.pointCount; index++) {
- CLLocationCoordinate2D coordinate = interiorPolygon.coordinates[index];
- [interiorRing addObject:@[@(coordinate.longitude), @(coordinate.latitude)]];
- }
- [coordinates addObject:interiorRing];
- }
-
- return [coordinates copy];
-}
-
-@end
diff --git a/platform/darwin/src/MGLPolygon.mm b/platform/darwin/src/MGLPolygon.mm
index e7843224e9..2af768d514 100644
--- a/platform/darwin/src/MGLPolygon.mm
+++ b/platform/darwin/src/MGLPolygon.mm
@@ -1,9 +1,9 @@
-#import "MGLPolygon.h"
+#import "MGLPolygon_Private.h"
#import "MGLMultiPoint_Private.h"
#import "MGLGeometry_Private.h"
-#import "MGLPolygon+MGLAdditions.h"
+#import "MGLFeature.h"
#import <mbgl/util/geojson.hpp>
#import <mapbox/polylabel.hpp>
@@ -102,6 +102,28 @@
@"coordinates": self.mgl_coordinates};
}
+- (NS_ARRAY_OF(id) *)mgl_coordinates {
+ NSMutableArray *coordinates = [NSMutableArray array];
+
+ NSMutableArray *exteriorRing = [NSMutableArray array];
+ for (NSUInteger index = 0; index < self.pointCount; index++) {
+ CLLocationCoordinate2D coordinate = self.coordinates[index];
+ [exteriorRing addObject:@[@(coordinate.longitude), @(coordinate.latitude)]];
+ }
+ [coordinates addObject:exteriorRing];
+
+ for (MGLPolygon *interiorPolygon in self.interiorPolygons) {
+ NSMutableArray *interiorRing = [NSMutableArray array];
+ for (int index = 0; index < interiorPolygon.pointCount; index++) {
+ CLLocationCoordinate2D coordinate = interiorPolygon.coordinates[index];
+ [interiorRing addObject:@[@(coordinate.longitude), @(coordinate.latitude)]];
+ }
+ [coordinates addObject:interiorRing];
+ }
+
+ return [coordinates copy];
+}
+
@end
@interface MGLMultiPolygon ()
diff --git a/platform/darwin/src/MGLPolygon_Private.h b/platform/darwin/src/MGLPolygon_Private.h
new file mode 100644
index 0000000000..75afcd61f6
--- /dev/null
+++ b/platform/darwin/src/MGLPolygon_Private.h
@@ -0,0 +1,11 @@
+#import "MGLPolygon.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface MGLPolygon (Private)
+
+- (NS_ARRAY_OF(id) *)mgl_coordinates;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLPolyline+MGLAdditions.h b/platform/darwin/src/MGLPolyline+MGLAdditions.h
deleted file mode 100644
index 4cdbbf17f9..0000000000
--- a/platform/darwin/src/MGLPolyline+MGLAdditions.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#import <Mapbox/Mapbox.h>
-
-@interface MGLPolyline (MGLAdditions)
-
-- (NS_ARRAY_OF(id) *)mgl_coordinates;
-
-@end
diff --git a/platform/darwin/src/MGLPolyline+MGLAdditions.m b/platform/darwin/src/MGLPolyline+MGLAdditions.m
deleted file mode 100644
index d1db2c58a0..0000000000
--- a/platform/darwin/src/MGLPolyline+MGLAdditions.m
+++ /dev/null
@@ -1,14 +0,0 @@
-#import "MGLPolyline+MGLAdditions.h"
-
-@implementation MGLPolyline (MGLAdditions)
-
-- (NS_ARRAY_OF(id) *)mgl_coordinates {
- NSMutableArray *coordinates = [[NSMutableArray alloc] initWithCapacity:self.pointCount];
- for (NSUInteger index = 0; index < self.pointCount; index++) {
- CLLocationCoordinate2D coordinate = self.coordinates[index];
- [coordinates addObject:@[@(coordinate.longitude), @(coordinate.latitude)]];
- }
- return [coordinates copy];
-}
-
-@end
diff --git a/platform/darwin/src/MGLPolyline.mm b/platform/darwin/src/MGLPolyline.mm
index 0e371a4dda..e011d09215 100644
--- a/platform/darwin/src/MGLPolyline.mm
+++ b/platform/darwin/src/MGLPolyline.mm
@@ -1,9 +1,9 @@
-#import "MGLPolyline.h"
+#import "MGLPolyline_Private.h"
#import "MGLMultiPoint_Private.h"
#import "MGLGeometry_Private.h"
-#import "MGLPolyline+MGLAdditions.h"
+#import "MGLFeature.h"
#import <mbgl/util/geojson.hpp>
#import <mapbox/polylabel.hpp>
@@ -49,6 +49,15 @@
@"coordinates": self.mgl_coordinates};
}
+- (NS_ARRAY_OF(id) *)mgl_coordinates {
+ NSMutableArray *coordinates = [[NSMutableArray alloc] initWithCapacity:self.pointCount];
+ for (NSUInteger index = 0; index < self.pointCount; index++) {
+ CLLocationCoordinate2D coordinate = self.coordinates[index];
+ [coordinates addObject:@[@(coordinate.longitude), @(coordinate.latitude)]];
+ }
+ return [coordinates copy];
+}
+
- (BOOL)isEqual:(id)other {
return self == other || ([other isKindOfClass:[MGLPolyline class]] && [super isEqual:other]);
}
diff --git a/platform/darwin/src/MGLPolyline_Private.h b/platform/darwin/src/MGLPolyline_Private.h
new file mode 100644
index 0000000000..405a0c5bc9
--- /dev/null
+++ b/platform/darwin/src/MGLPolyline_Private.h
@@ -0,0 +1,12 @@
+#import "MGLPolyline.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface MGLPolyline (Private)
+
+- (NS_ARRAY_OF(id) *)mgl_coordinates;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
diff --git a/platform/darwin/src/MGLRendererConfiguration.h b/platform/darwin/src/MGLRendererConfiguration.h
index fbc6fc564d..31aad0a742 100644
--- a/platform/darwin/src/MGLRendererConfiguration.h
+++ b/platform/darwin/src/MGLRendererConfiguration.h
@@ -1,6 +1,6 @@
#import <Foundation/Foundation.h>
#import <mbgl/storage/default_file_source.hpp>
-#import <mbgl/map/mode.hpp>
+#import <mbgl/renderer/mode.hpp>
NS_ASSUME_NONNULL_BEGIN
diff --git a/platform/darwin/src/MGLShapeSource.h b/platform/darwin/src/MGLShapeSource.h
index 7460c83f50..ca150edac1 100644
--- a/platform/darwin/src/MGLShapeSource.h
+++ b/platform/darwin/src/MGLShapeSource.h
@@ -1,4 +1,4 @@
-#import "MGLSource.h"
+#import "MGLAbstractShapeSource.h"
#import "MGLFoundation.h"
#import "MGLTypes.h"
@@ -14,72 +14,6 @@ NS_ASSUME_NONNULL_BEGIN
typedef NSString *MGLShapeSourceOption NS_STRING_ENUM;
/**
- An `NSNumber` object containing a Boolean enabling or disabling clustering.
- If the `shape` property contains point shapes, setting this option to
- `YES` clusters the points by radius into groups. The default value is `NO`.
-
- This attribute corresponds to the
- <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-cluster"><code>cluster</code></a>
- source property in the Mapbox Style Specification.
-
- This option only affects point features within a shape source.
- */
-extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionClustered;
-
-/**
- An `NSNumber` object containing an integer; specifies the radius of each
- cluster if clustering is enabled. A value of 512 produces a radius equal to
- the width of a tile. The default value is 50.
- */
-extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionClusterRadius;
-
-/**
- An `NSNumber` object containing an integer; specifies the maximum zoom level at
- which to cluster points if clustering is enabled. Defaults to one zoom level
- less than the value of `MGLShapeSourceOptionMaximumZoomLevel` so that, at the
- maximum zoom level, the shapes are not clustered.
-
- This attribute corresponds to the
- <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-clusterMaxZoom"><code>clusterMaxZoom</code></a>
- source property in the Mapbox Style Specification.
- */
-extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevelForClustering;
-
-/**
- An `NSNumber` object containing an integer; specifies the maximum zoom level at
- which to create vector tiles. A greater value produces greater detail at high
- zoom levels. The default value is 18.
-
- This attribute corresponds to the
- <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-maxzoom"><code>maxzoom</code></a>
- source property in the Mapbox Style Specification.
- */
-extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevel;
-
-/**
- An `NSNumber` object containing an integer; specifies the size of the tile
- buffer on each side. A value of 0 produces no buffer. A value of 512 produces a
- buffer as wide as the tile itself. Larger values produce fewer rendering
- artifacts near tile edges and slower performance. The default value is 128.
-
- This attribute corresponds to the
- <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-buffer"><code>buffer</code></a>
- source property in the Mapbox Style Specification.
- */
-extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionBuffer;
-
-/**
- An `NSNumber` object containing a double; specifies the Douglas-Peucker
- simplification tolerance. A greater value produces simpler geometries and
- improves performance. The default value is 0.375.
-
- This attribute corresponds to the
- <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-tolerance"><code>tolerance</code></a>
- source property in the Mapbox Style Specification.
- */
-extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance;
-
-/**
`MGLShapeSource` is a map content source that supplies vector shapes to be
shown on the map. The shapes may be instances of `MGLShape` or `MGLFeature`,
or they may be defined by local or external
@@ -112,7 +46,7 @@ extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionSimplificationT
```
*/
MGL_EXPORT
-@interface MGLShapeSource : MGLSource
+@interface MGLShapeSource : MGLAbstractShapeSource
#pragma mark Initializing a Source
diff --git a/platform/darwin/src/MGLShapeSource.mm b/platform/darwin/src/MGLShapeSource.mm
index 571cbdcc62..8fbb9a18ef 100644
--- a/platform/darwin/src/MGLShapeSource.mm
+++ b/platform/darwin/src/MGLShapeSource.mm
@@ -1,4 +1,5 @@
#import "MGLShapeSource_Private.h"
+#import "MGLAbstractShapeSource_Private.h"
#import "MGLStyle_Private.h"
#import "MGLMapView_Private.h"
@@ -13,12 +14,7 @@
#include <mbgl/style/sources/geojson_source.hpp>
#include <mbgl/renderer/renderer.hpp>
-const MGLShapeSourceOption MGLShapeSourceOptionClustered = @"MGLShapeSourceOptionClustered";
-const MGLShapeSourceOption MGLShapeSourceOptionClusterRadius = @"MGLShapeSourceOptionClusterRadius";
-const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevelForClustering = @"MGLShapeSourceOptionMaximumZoomLevelForClustering";
-const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevel = @"MGLShapeSourceOptionMaximumZoomLevel";
-const MGLShapeSourceOption MGLShapeSourceOptionBuffer = @"MGLShapeSourceOptionBuffer";
-const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance = @"MGLShapeSourceOptionSimplificationTolerance";
+
@interface MGLShapeSource ()
@@ -105,57 +101,3 @@ const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance = @"MGLSh
}
@end
-
-mbgl::style::GeoJSONOptions MGLGeoJSONOptionsFromDictionary(NS_DICTIONARY_OF(MGLShapeSourceOption, id) *options) {
- auto geoJSONOptions = mbgl::style::GeoJSONOptions();
-
- if (NSNumber *value = options[MGLShapeSourceOptionMaximumZoomLevel]) {
- if (![value isKindOfClass:[NSNumber class]]) {
- [NSException raise:NSInvalidArgumentException
- format:@"MGLShapeSourceOptionMaximumZoomLevel must be an NSNumber."];
- }
- geoJSONOptions.maxzoom = value.integerValue;
- }
-
- if (NSNumber *value = options[MGLShapeSourceOptionBuffer]) {
- if (![value isKindOfClass:[NSNumber class]]) {
- [NSException raise:NSInvalidArgumentException
- format:@"MGLShapeSourceOptionBuffer must be an NSNumber."];
- }
- geoJSONOptions.buffer = value.integerValue;
- }
-
- if (NSNumber *value = options[MGLShapeSourceOptionSimplificationTolerance]) {
- if (![value isKindOfClass:[NSNumber class]]) {
- [NSException raise:NSInvalidArgumentException
- format:@"MGLShapeSourceOptionSimplificationTolerance must be an NSNumber."];
- }
- geoJSONOptions.tolerance = value.doubleValue;
- }
-
- if (NSNumber *value = options[MGLShapeSourceOptionClusterRadius]) {
- if (![value isKindOfClass:[NSNumber class]]) {
- [NSException raise:NSInvalidArgumentException
- format:@"MGLShapeSourceOptionClusterRadius must be an NSNumber."];
- }
- geoJSONOptions.clusterRadius = value.integerValue;
- }
-
- if (NSNumber *value = options[MGLShapeSourceOptionMaximumZoomLevelForClustering]) {
- if (![value isKindOfClass:[NSNumber class]]) {
- [NSException raise:NSInvalidArgumentException
- format:@"MGLShapeSourceOptionMaximumZoomLevelForClustering must be an NSNumber."];
- }
- geoJSONOptions.clusterMaxZoom = value.integerValue;
- }
-
- if (NSNumber *value = options[MGLShapeSourceOptionClustered]) {
- if (![value isKindOfClass:[NSNumber class]]) {
- [NSException raise:NSInvalidArgumentException
- format:@"MGLShapeSourceOptionClustered must be an NSNumber."];
- }
- geoJSONOptions.cluster = value.boolValue;
- }
-
- return geoJSONOptions;
-}
diff --git a/platform/darwin/src/MGLShapeSource_Private.h b/platform/darwin/src/MGLShapeSource_Private.h
index 84eb5deed4..1ea2c39b8e 100644
--- a/platform/darwin/src/MGLShapeSource_Private.h
+++ b/platform/darwin/src/MGLShapeSource_Private.h
@@ -12,7 +12,4 @@ namespace mbgl {
@interface MGLShapeSource (Private)
@end
-MGL_EXPORT
-mbgl::style::GeoJSONOptions MGLGeoJSONOptionsFromDictionary(NS_DICTIONARY_OF(MGLShapeSourceOption, id) *options);
-
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLStyle.mm b/platform/darwin/src/MGLStyle.mm
index 987ae5f063..5221e838f8 100644
--- a/platform/darwin/src/MGLStyle.mm
+++ b/platform/darwin/src/MGLStyle.mm
@@ -17,7 +17,7 @@
#import "MGLLight_Private.h"
#import "MGLTileSource_Private.h"
#import "MGLVectorSource.h"
-#import "MGLVectorSource+MGLAdditions.h"
+#import "MGLVectorSource_Private.h"
#import "MGLRasterSource.h"
#import "MGLShapeSource.h"
#import "MGLImageSource.h"
@@ -219,7 +219,7 @@ static NSURL *MGLStyleURL_trafficNight;
}
- (MGLSource *)sourceFromMBGLSource:(mbgl::style::Source *)rawSource {
- if (MGLSource *source = rawSource->peer.empty() ? nil : mbgl::any_cast<SourceWrapper>(rawSource->peer).source) {
+ if (MGLSource *source = rawSource->peer.has_value() ? mbgl::util::any_cast<SourceWrapper>(rawSource->peer).source : nil) {
return source;
}
@@ -381,7 +381,7 @@ static NSURL *MGLStyleURL_trafficNight;
{
NSParameterAssert(rawLayer);
- if (MGLStyleLayer *layer = rawLayer->peer.empty() ? nil : mbgl::any_cast<LayerWrapper>(rawLayer->peer).layer) {
+ if (MGLStyleLayer *layer = rawLayer->peer.has_value() ? mbgl::util::any_cast<LayerWrapper>(&(rawLayer->peer))->layer : nil) {
return layer;
}
diff --git a/platform/darwin/src/MGLStyleValue_Private.h b/platform/darwin/src/MGLStyleValue_Private.h
index 2155c657bd..5914e0a2aa 100644
--- a/platform/darwin/src/MGLStyleValue_Private.h
+++ b/platform/darwin/src/MGLStyleValue_Private.h
@@ -124,9 +124,9 @@ public:
if ([value isKindOfClass:[MGLConstantStyleValue class]]) {
return toMBGLConstantValue((MGLConstantStyleValue<ObjCType> *)value);
} else if ([value isKindOfClass:[MGLStyleFunction class]]) {
- auto rawValue = toRawStyleSpecValue((MGLStyleFunction<ObjCType> *) value);
mbgl::style::conversion::Error error;
- auto result = mbgl::style::conversion::convert<mbgl::style::DataDrivenPropertyValue<MBGLType>>(rawValue, error);
+ auto result = mbgl::style::conversion::convert<mbgl::style::DataDrivenPropertyValue<MBGLType>>(
+ mbgl::style::conversion::makeConvertible(toRawStyleSpecValue((MGLStyleFunction<ObjCType> *) value)), error);
NSCAssert(result, @(error.message.c_str()));
return *result;
} else {
diff --git a/platform/darwin/src/MGLVectorSource+MGLAdditions.h b/platform/darwin/src/MGLVectorSource+MGLAdditions.h
deleted file mode 100644
index 43b0aba747..0000000000
--- a/platform/darwin/src/MGLVectorSource+MGLAdditions.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#import <Mapbox/Mapbox.h>
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface MGLVectorSource (MGLAdditions)
-
-+ (NSString *)preferredMapboxStreetsLanguage;
-
-- (NS_DICTIONARY_OF(NSString *, NSString *) *)localizedKeysByKeyForPreferredLanguage:(nullable NSString *)preferredLanguage;
-
-@property (nonatomic, readonly, getter=isMapboxStreets) BOOL mapboxStreets;
-
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLVectorSource+MGLAdditions.m b/platform/darwin/src/MGLVectorSource+MGLAdditions.m
deleted file mode 100644
index a305388117..0000000000
--- a/platform/darwin/src/MGLVectorSource+MGLAdditions.m
+++ /dev/null
@@ -1,53 +0,0 @@
-#import "MGLVectorSource+MGLAdditions.h"
-
-@implementation MGLVectorSource (MGLAdditions)
-
-+ (NS_SET_OF(NSString *) *)mapboxStreetsLanguages {
- // https://www.mapbox.com/vector-tiles/mapbox-streets-v7/#overview
- static dispatch_once_t onceToken;
- static NS_SET_OF(NSString *) *mapboxStreetsLanguages;
- dispatch_once(&onceToken, ^{
- // https://www.mapbox.com/vector-tiles/mapbox-streets-v7/#overview
- mapboxStreetsLanguages = [NSSet setWithObjects:@"ar", @"de", @"en", @"es", @"fr", @"pt", @"ru", @"zh", @"zh-Hans", nil];
- });
- return mapboxStreetsLanguages;
-}
-
-+ (NSString *)preferredMapboxStreetsLanguage {
- NSArray<NSString *> *supportedLanguages = [MGLVectorSource mapboxStreetsLanguages].allObjects;
- NSArray<NSString *> *preferredLanguages = [NSBundle preferredLocalizationsFromArray:supportedLanguages
- forPreferences:[NSLocale preferredLanguages]];
- NSString *mostSpecificLanguage;
- for (NSString *language in preferredLanguages) {
- if (language.length > mostSpecificLanguage.length) {
- mostSpecificLanguage = language;
- }
- }
- return mostSpecificLanguage ?: @"en";
-}
-
-- (BOOL)isMapboxStreets {
- NSURL *url = self.configurationURL;
- if (![url.scheme isEqualToString:@"mapbox"]) {
- return NO;
- }
- NSArray *identifiers = [url.host componentsSeparatedByString:@","];
- return [identifiers containsObject:@"mapbox.mapbox-streets-v7"] || [identifiers containsObject:@"mapbox.mapbox-streets-v6"];
-}
-
-- (NS_DICTIONARY_OF(NSString *, NSString *) *)localizedKeysByKeyForPreferredLanguage:(nullable NSString *)preferredLanguage {
- if (!self.mapboxStreets) {
- return @{};
- }
-
- // Replace {name} and {name_*} with the matching localized name tag.
- NSString *localizedKey = preferredLanguage ? [NSString stringWithFormat:@"name_%@", preferredLanguage] : @"name";
- NSMutableDictionary *localizedKeysByKey = [NSMutableDictionary dictionaryWithObject:localizedKey forKey:@"name"];
- for (NSString *languageCode in [MGLVectorSource mapboxStreetsLanguages]) {
- NSString *key = [NSString stringWithFormat:@"name_%@", languageCode];
- localizedKeysByKey[key] = localizedKey;
- }
- return localizedKeysByKey;
-}
-
-@end
diff --git a/platform/darwin/src/MGLVectorSource.mm b/platform/darwin/src/MGLVectorSource.mm
index b1bda56f2d..90ffe6f98b 100644
--- a/platform/darwin/src/MGLVectorSource.mm
+++ b/platform/darwin/src/MGLVectorSource.mm
@@ -5,6 +5,7 @@
#import "MGLTileSource_Private.h"
#import "MGLStyle_Private.h"
#import "MGLMapView_Private.h"
+
#import "NSPredicate+MGLAdditions.h"
#import "NSURL+MGLAdditions.h"
@@ -71,3 +72,55 @@
}
@end
+
+@implementation MGLVectorSource (Private)
+
++ (NS_SET_OF(NSString *) *)mapboxStreetsLanguages {
+ // https://www.mapbox.com/vector-tiles/mapbox-streets-v7/#overview
+ static dispatch_once_t onceToken;
+ static NS_SET_OF(NSString *) *mapboxStreetsLanguages;
+ dispatch_once(&onceToken, ^{
+ // https://www.mapbox.com/vector-tiles/mapbox-streets-v7/#overview
+ mapboxStreetsLanguages = [NSSet setWithObjects:@"ar", @"de", @"en", @"es", @"fr", @"pt", @"ru", @"zh", @"zh-Hans", nil];
+ });
+ return mapboxStreetsLanguages;
+}
+
++ (NSString *)preferredMapboxStreetsLanguage {
+ NSArray<NSString *> *supportedLanguages = [MGLVectorSource mapboxStreetsLanguages].allObjects;
+ NSArray<NSString *> *preferredLanguages = [NSBundle preferredLocalizationsFromArray:supportedLanguages
+ forPreferences:[NSLocale preferredLanguages]];
+ NSString *mostSpecificLanguage;
+ for (NSString *language in preferredLanguages) {
+ if (language.length > mostSpecificLanguage.length) {
+ mostSpecificLanguage = language;
+ }
+ }
+ return mostSpecificLanguage ?: @"en";
+}
+
+- (BOOL)isMapboxStreets {
+ NSURL *url = self.configurationURL;
+ if (![url.scheme isEqualToString:@"mapbox"]) {
+ return NO;
+ }
+ NSArray *identifiers = [url.host componentsSeparatedByString:@","];
+ return [identifiers containsObject:@"mapbox.mapbox-streets-v7"] || [identifiers containsObject:@"mapbox.mapbox-streets-v6"];
+}
+
+- (NS_DICTIONARY_OF(NSString *, NSString *) *)localizedKeysByKeyForPreferredLanguage:(nullable NSString *)preferredLanguage {
+ if (!self.mapboxStreets) {
+ return @{};
+ }
+
+ // Replace {name} and {name_*} with the matching localized name tag.
+ NSString *localizedKey = preferredLanguage ? [NSString stringWithFormat:@"name_%@", preferredLanguage] : @"name";
+ NSMutableDictionary *localizedKeysByKey = [NSMutableDictionary dictionaryWithObject:localizedKey forKey:@"name"];
+ for (NSString *languageCode in [MGLVectorSource mapboxStreetsLanguages]) {
+ NSString *key = [NSString stringWithFormat:@"name_%@", languageCode];
+ localizedKeysByKey[key] = localizedKey;
+ }
+ return localizedKeysByKey;
+}
+
+@end
diff --git a/platform/darwin/src/MGLVectorSource_Private.h b/platform/darwin/src/MGLVectorSource_Private.h
index 335743173e..233809aea2 100644
--- a/platform/darwin/src/MGLVectorSource_Private.h
+++ b/platform/darwin/src/MGLVectorSource_Private.h
@@ -3,6 +3,13 @@
NS_ASSUME_NONNULL_BEGIN
@interface MGLVectorSource (Private)
+
+@property (nonatomic, readonly, getter=isMapboxStreets) BOOL mapboxStreets;
+
++ (NSString *)preferredMapboxStreetsLanguage;
+
+- (NS_DICTIONARY_OF(NSString *, NSString *) *)localizedKeysByKeyForPreferredLanguage:(nullable NSString *)preferredLanguage;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/headless_backend_cgl.cpp b/platform/darwin/src/headless_backend_cgl.cpp
index 3b0c3aaf35..46a5beb870 100644
--- a/platform/darwin/src/headless_backend_cgl.cpp
+++ b/platform/darwin/src/headless_backend_cgl.cpp
@@ -1,5 +1,5 @@
#include <mbgl/gl/headless_backend.hpp>
-#include <mbgl/gl/headless_display.hpp>
+#include <mbgl/util/logging.hpp>
#include <OpenGL/OpenGL.h>
#include <CoreFoundation/CoreFoundation.h>
@@ -9,14 +9,96 @@
namespace mbgl {
-struct CGLImpl : public HeadlessBackend::Impl {
- CGLImpl(CGLContextObj glContext_) : glContext(glContext_) {
+// This class provides a singleton that contains information about the pixel format used for
+// instantiating new headless rendering contexts.
+class CGLDisplayConfig {
+private:
+ // Key for singleton construction.
+ struct Key { explicit Key() = default; };
+
+public:
+ CGLDisplayConfig(Key) {
+ // TODO: test if OpenGL 4.1 with GL_ARB_ES2_compatibility is supported
+ // If it is, use kCGLOGLPVersion_3_2_Core and enable that extension.
+ CGLPixelFormatAttribute attributes[] = {
+ kCGLPFAOpenGLProfile, static_cast<CGLPixelFormatAttribute>(kCGLOGLPVersion_Legacy),
+ // Not adding kCGLPFAAccelerated, as this will make headless rendering impossible when running in VMs.
+ kCGLPFAClosestPolicy,
+ kCGLPFAAccumSize, static_cast<CGLPixelFormatAttribute>(32),
+ kCGLPFAColorSize, static_cast<CGLPixelFormatAttribute>(24),
+ kCGLPFAAlphaSize, static_cast<CGLPixelFormatAttribute>(8),
+ kCGLPFADepthSize, static_cast<CGLPixelFormatAttribute>(16),
+ kCGLPFAStencilSize, static_cast<CGLPixelFormatAttribute>(8),
+ kCGLPFASupportsAutomaticGraphicsSwitching,
+ kCGLPFAAllowOfflineRenderers, // Allows using the integrated GPU
+ static_cast<CGLPixelFormatAttribute>(0)
+ };
+
+ GLint num;
+ // TODO: obtain all configurations and choose the best one.
+ const CGLError error = CGLChoosePixelFormat(attributes, &pixelFormat, &num);
+ if (error != kCGLNoError) {
+ throw std::runtime_error(std::string("Error choosing pixel format:") + CGLErrorString(error) + "\n");
+ }
+ if (num <= 0) {
+ throw std::runtime_error("No pixel formats found.");
+ }
+ }
+
+ ~CGLDisplayConfig() {
+ const CGLError error = CGLDestroyPixelFormat(pixelFormat);
+ if (error != kCGLNoError) {
+ Log::Error(Event::OpenGL, std::string("Error destroying pixel format:") + CGLErrorString(error));
+ }
+ }
+
+ static std::shared_ptr<const CGLDisplayConfig> create() {
+ static std::weak_ptr<const CGLDisplayConfig> instance;
+ auto shared = instance.lock();
+ if (!shared) {
+ instance = shared = std::make_shared<CGLDisplayConfig>(Key{});
+ }
+ return shared;
+ }
+
+public:
+ CGLPixelFormatObj pixelFormat = nullptr;
+};
+
+class CGLBackendImpl : public HeadlessBackend::Impl {
+public:
+ CGLBackendImpl() {
+ CGLError error = CGLCreateContext(cglDisplay->pixelFormat, nullptr, &glContext);
+ if (error != kCGLNoError) {
+ throw std::runtime_error(std::string("Error creating GL context object:") +
+ CGLErrorString(error) + "\n");
+ }
+
+ error = CGLEnable(glContext, kCGLCEMPEngine);
+ if (error != kCGLNoError) {
+ throw std::runtime_error(std::string("Error enabling OpenGL multithreading:") +
+ CGLErrorString(error) + "\n");
+ }
}
- ~CGLImpl() {
+ ~CGLBackendImpl() final {
CGLDestroyContext(glContext);
}
+ gl::ProcAddress getExtensionFunctionPointer(const char* name) final {
+ static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
+ if (!framework) {
+ throw std::runtime_error("Failed to load OpenGL framework.");
+ }
+
+ CFStringRef str =
+ CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII);
+ void* symbol = CFBundleGetFunctionPointerForName(framework, str);
+ CFRelease(str);
+
+ return reinterpret_cast<gl::ProcAddress>(symbol);
+ }
+
void activateContext() final {
CGLError error = CGLSetCurrentContext(glContext);
if (error != kCGLNoError) {
@@ -33,46 +115,14 @@ struct CGLImpl : public HeadlessBackend::Impl {
}
}
+private:
+ const std::shared_ptr<const CGLDisplayConfig> cglDisplay = CGLDisplayConfig::create();
CGLContextObj glContext = nullptr;
};
-gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) {
- static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
- if (!framework) {
- throw std::runtime_error("Failed to load OpenGL framework.");
- }
-
- CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII);
- void* symbol = CFBundleGetFunctionPointerForName(framework, str);
- CFRelease(str);
-
- return reinterpret_cast<gl::ProcAddress>(symbol);
-}
-
-bool HeadlessBackend::hasDisplay() {
- if (!display) {
- display = HeadlessDisplay::create();
- }
- return bool(display);
-}
-
-void HeadlessBackend::createContext() {
- assert(!hasContext());
-
- CGLContextObj glContext = nullptr;
- CGLError error = CGLCreateContext(display->attribute<CGLPixelFormatObj>(), nullptr, &glContext);
- if (error != kCGLNoError) {
- throw std::runtime_error(std::string("Error creating GL context object:") +
- CGLErrorString(error) + "\n");
- }
-
- error = CGLEnable(glContext, kCGLCEMPEngine);
- if (error != kCGLNoError) {
- throw std::runtime_error(std::string("Error enabling OpenGL multithreading:") +
- CGLErrorString(error) + "\n");
- }
-
- impl.reset(new CGLImpl(glContext));
+void HeadlessBackend::createImpl() {
+ assert(!impl);
+ impl = std::make_unique<CGLBackendImpl>();
}
} // namespace mbgl
diff --git a/platform/darwin/src/headless_backend_eagl.mm b/platform/darwin/src/headless_backend_eagl.mm
index 1daaeaf54c..050fa62c78 100644
--- a/platform/darwin/src/headless_backend_eagl.mm
+++ b/platform/darwin/src/headless_backend_eagl.mm
@@ -6,51 +6,48 @@
namespace mbgl {
-struct EAGLImpl : public HeadlessBackend::Impl {
- EAGLImpl(EAGLContext* glContext_) : glContext(glContext_) {
- [reinterpret_cast<EAGLContext*>(glContext) retain];
- reinterpret_cast<EAGLContext*>(glContext).multiThreaded = YES;
+class EAGLBackendImpl : public HeadlessBackend::Impl {
+public:
+ EAGLBackendImpl() {
+ glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
+ if (glContext == nil) {
+ throw std::runtime_error("Error creating GL context object");
+ }
+ glContext.multiThreaded = YES;
}
- ~EAGLImpl() {
- [glContext release];
+ // Required for ARC to deallocate correctly.
+ ~EAGLBackendImpl() final = default;
+
+ gl::ProcAddress getExtensionFunctionPointer(const char* name) final {
+ static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengles"));
+ if (!framework) {
+ throw std::runtime_error("Failed to load OpenGL framework.");
+ }
+
+ CFStringRef str =
+ CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII);
+ void* symbol = CFBundleGetFunctionPointerForName(framework, str);
+ CFRelease(str);
+
+ return reinterpret_cast<gl::ProcAddress>(symbol);
}
- void activateContext() {
+ void activateContext() final {
[EAGLContext setCurrentContext:glContext];
}
- void deactivateContext() {
+ void deactivateContext() final {
[EAGLContext setCurrentContext:nil];
}
+private:
EAGLContext* glContext = nullptr;
};
-gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) {
- static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengles"));
- if (!framework) {
- throw std::runtime_error("Failed to load OpenGL framework.");
- }
-
- CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII);
- void* symbol = CFBundleGetFunctionPointerForName(framework, str);
- CFRelease(str);
-
- return reinterpret_cast<gl::ProcAddress>(symbol);
-}
-
-bool HeadlessBackend::hasDisplay() {
- return true;
-}
-
-void HeadlessBackend::createContext() {
- EAGLContext* glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
- if (glContext == nil) {
- throw std::runtime_error("Error creating GL context object");
- }
-
- impl.reset(new EAGLImpl(glContext));
+void HeadlessBackend::createImpl() {
+ assert(!impl);
+ impl = std::make_unique<EAGLBackendImpl>();
}
} // namespace mbgl
diff --git a/platform/darwin/src/headless_display_cgl.cpp b/platform/darwin/src/headless_display_cgl.cpp
deleted file mode 100644
index 5b7a1f2bac..0000000000
--- a/platform/darwin/src/headless_display_cgl.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-#include <mbgl/gl/headless_display.hpp>
-
-#include <OpenGL/OpenGL.h>
-
-#include <stdexcept>
-#include <string>
-
-namespace mbgl {
-
-class HeadlessDisplay::Impl {
-public:
- Impl();
- ~Impl();
- CGLPixelFormatObj pixelFormat = nullptr;
-};
-
-HeadlessDisplay::Impl::Impl() {
- // TODO: test if OpenGL 4.1 with GL_ARB_ES2_compatibility is supported
- // If it is, use kCGLOGLPVersion_3_2_Core and enable that extension.
- CGLPixelFormatAttribute attributes[] = {
- kCGLPFAOpenGLProfile, static_cast<CGLPixelFormatAttribute>(kCGLOGLPVersion_Legacy),
- // Not adding kCGLPFAAccelerated, as this will make headless rendering impossible when running in VMs.
- kCGLPFAClosestPolicy,
- kCGLPFAAccumSize, static_cast<CGLPixelFormatAttribute>(32),
- kCGLPFAColorSize, static_cast<CGLPixelFormatAttribute>(24),
- kCGLPFAAlphaSize, static_cast<CGLPixelFormatAttribute>(8),
- kCGLPFADepthSize, static_cast<CGLPixelFormatAttribute>(16),
- kCGLPFAStencilSize, static_cast<CGLPixelFormatAttribute>(8),
- kCGLPFASupportsAutomaticGraphicsSwitching,
- kCGLPFAAllowOfflineRenderers, // Allows using the integrated GPU
- static_cast<CGLPixelFormatAttribute>(0)
- };
-
- GLint num;
- CGLError error = CGLChoosePixelFormat(attributes, &pixelFormat, &num);
- if (error != kCGLNoError) {
- throw std::runtime_error(std::string("Error choosing pixel format:") + CGLErrorString(error) + "\n");
- }
- if (num <= 0) {
- throw std::runtime_error("No pixel formats found.");
- }
-}
-
-HeadlessDisplay::Impl::~Impl() {
- CGLDestroyPixelFormat(pixelFormat);
-}
-
-template <>
-CGLPixelFormatObj HeadlessDisplay::attribute() const {
- return impl->pixelFormat;
-}
-
-HeadlessDisplay::HeadlessDisplay()
- : impl(std::make_unique<Impl>()) {
-}
-
-HeadlessDisplay::~HeadlessDisplay() {
-}
-
-} // namespace mbgl
diff --git a/platform/darwin/src/image.mm b/platform/darwin/src/image.mm
index 8c0d5fa484..3a5adcca0a 100644
--- a/platform/darwin/src/image.mm
+++ b/platform/darwin/src/image.mm
@@ -11,7 +11,7 @@ using CGDataProviderHandle = CFHandle<CGDataProviderRef, CGDataProviderRef, CGDa
using CGColorSpaceHandle = CFHandle<CGColorSpaceRef, CGColorSpaceRef, CGColorSpaceRelease>;
using CGContextHandle = CFHandle<CGContextRef, CGContextRef, CGContextRelease>;
-CGImageRef CGImageFromMGLPremultipliedImage(mbgl::PremultipliedImage&& src) {
+CGImageRef CGImageCreateWithMGLPremultipliedImage(mbgl::PremultipliedImage&& src) {
// We're converting the PremultipliedImage's backing store to a CGDataProvider, and are taking
// over ownership of the memory.
CGDataProviderHandle provider(CGDataProviderCreateWithData(
diff --git a/platform/darwin/test/MGLAttributionInfoTests.m b/platform/darwin/test/MGLAttributionInfoTests.m
index ed4927d44b..eccc6ceece 100644
--- a/platform/darwin/test/MGLAttributionInfoTests.m
+++ b/platform/darwin/test/MGLAttributionInfoTests.m
@@ -51,12 +51,12 @@
XCTAssertEqualObjects([infos[3] feedbackURLAtCenterCoordinate:mapbox zoomLevel:14],
[NSURL URLWithString:@"https://www.mapbox.com/feedback/?referrer=com.mapbox.sdk.ios#/77.63680/12.98108/14.00/0.0/0"]);
XCTAssertEqualObjects([infos[3] feedbackURLForStyleURL:styleURL atCenterCoordinate:mapbox zoomLevel:3.14159 direction:90.9 pitch:12.5],
- [NSURL URLWithString:@"https://www.mapbox.com/feedback/?referrer=com.mapbox.sdk.ios&owner=mapbox&id=satellite-streets-v99&access_token#/77.63680/12.98108/3.14/90.9/13"]);
+ [NSURL URLWithString:@"https://www.mapbox.com/feedback/?referrer=com.mapbox.sdk.ios&owner=mapbox&id=satellite-streets-v99&access_token&map_sdk_version=1.0.0#/77.63680/12.98108/3.14/90.9/13"]);
#else
XCTAssertEqualObjects([infos[3] feedbackURLAtCenterCoordinate:mapbox zoomLevel:14],
[NSURL URLWithString:@"https://www.mapbox.com/feedback/?referrer=com.mapbox.MapboxGL#/77.63680/12.98108/14.00/0.0/0"]);
XCTAssertEqualObjects([infos[3] feedbackURLForStyleURL:styleURL atCenterCoordinate:mapbox zoomLevel:3.14159 direction:90.9 pitch:12.5],
- [NSURL URLWithString:@"https://www.mapbox.com/feedback/?referrer=com.mapbox.MapboxGL&owner=mapbox&id=satellite-streets-v99&access_token#/77.63680/12.98108/3.14/90.9/13"]);
+ [NSURL URLWithString:@"https://www.mapbox.com/feedback/?referrer=com.mapbox.MapboxGL&owner=mapbox&id=satellite-streets-v99&access_token&map_sdk_version=1.0.0#/77.63680/12.98108/3.14/90.9/13"]);
#endif
}
diff --git a/platform/darwin/test/MGLComputedShapeSourceTests.m b/platform/darwin/test/MGLComputedShapeSourceTests.m
new file mode 100644
index 0000000000..6eb45913d6
--- /dev/null
+++ b/platform/darwin/test/MGLComputedShapeSourceTests.m
@@ -0,0 +1,24 @@
+#import <XCTest/XCTest.h>
+
+#import <Mapbox/Mapbox.h>
+
+
+@interface MGLComputedShapeSourceTests : XCTestCase
+@end
+
+@implementation MGLComputedShapeSourceTests
+
+- (void)testInitializer {
+ MGLComputedShapeSource *source = [[MGLComputedShapeSource alloc] initWithIdentifier:@"id" options:@{}];
+ XCTAssertNotNil(source);
+ XCTAssertNotNil(source.requestQueue);
+ XCTAssertNil(source.dataSource);
+}
+
+- (void)testNilOptions {
+ MGLComputedShapeSource *source = [[MGLComputedShapeSource alloc] initWithIdentifier:@"id" options:nil];
+ XCTAssertNotNil(source);
+}
+
+
+@end
diff --git a/platform/darwin/test/MGLShapeSourceTests.mm b/platform/darwin/test/MGLShapeSourceTests.mm
index 561af7f3d0..60500959b6 100644
--- a/platform/darwin/test/MGLShapeSourceTests.mm
+++ b/platform/darwin/test/MGLShapeSourceTests.mm
@@ -2,6 +2,7 @@
#import <Mapbox/Mapbox.h>
#import "MGLFeature_Private.h"
+#import "MGLAbstractShapeSource_Private.h"
#import "MGLShapeSource_Private.h"
#import "MGLSource_Private.h"
diff --git a/platform/default/headless_backend_osmesa.cpp b/platform/default/headless_backend_osmesa.cpp
index 5042f5ed10..0da1caf9af 100644
--- a/platform/default/headless_backend_osmesa.cpp
+++ b/platform/default/headless_backend_osmesa.cpp
@@ -7,45 +7,41 @@
namespace mbgl {
-struct OSMesaImpl : public HeadlessBackend::Impl {
- OSMesaImpl(OSMesaContext glContext_) : glContext(glContext_) {
+class OSMesaBackendImpl : public HeadlessBackend::Impl {
+public:
+ OSMesaBackendImpl() {
+#if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305
+ glContext = OSMesaCreateContextExt(OSMESA_RGBA, 16, 0, 0, nullptr);
+#else
+ glContext = OSMesaCreateContext(OSMESA_RGBA, nullptr);
+#endif
+ if (glContext == nullptr) {
+ throw std::runtime_error("Error creating GL context object.");
+ }
}
- ~OSMesaImpl() {
+ ~OSMesaBackendImpl() final {
OSMesaDestroyContext(glContext);
}
+ gl::ProcAddress getExtensionFunctionPointer(const char* name) final {
+ return OSMesaGetProcAddress(name);
+ }
+
void activateContext() final {
if (!OSMesaMakeCurrent(glContext, &fakeBuffer, GL_UNSIGNED_BYTE, 1, 1)) {
throw std::runtime_error("Switching OpenGL context failed.\n");
}
}
+private:
OSMesaContext glContext = nullptr;
GLubyte fakeBuffer = 0;
};
-gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) {
- return OSMesaGetProcAddress(name);
-}
-
-bool HeadlessBackend::hasDisplay() {
- return true;
-};
-
-void HeadlessBackend::createContext() {
- assert(!hasContext());
-
-#if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305
- OSMesaContext glContext = OSMesaCreateContextExt(OSMESA_RGBA, 16, 0, 0, nullptr);
-#else
- OSMesaContext glContext = OSMesaCreateContext(OSMESA_RGBA, nullptr);
-#endif
- if (glContext == nullptr) {
- throw std::runtime_error("Error creating GL context object.");
- }
-
- impl.reset(new OSMesaImpl(glContext));
+void HeadlessBackend::createImpl() {
+ assert(!impl);
+ impl = std::make_unique<OSMesaBackendImpl>();
}
} // namespace mbgl
diff --git a/platform/default/mbgl/gl/headless_backend.cpp b/platform/default/mbgl/gl/headless_backend.cpp
index edf637a560..ba08aecab7 100644
--- a/platform/default/mbgl/gl/headless_backend.cpp
+++ b/platform/default/mbgl/gl/headless_backend.cpp
@@ -1,5 +1,4 @@
#include <mbgl/gl/headless_backend.hpp>
-#include <mbgl/gl/headless_display.hpp>
#include <mbgl/gl/context.hpp>
#include <mbgl/renderer/backend_scope.hpp>
@@ -32,22 +31,24 @@ HeadlessBackend::~HeadlessBackend() {
context.reset();
}
+gl::ProcAddress HeadlessBackend::getExtensionFunctionPointer(const char* name) {
+ assert(impl);
+ return impl->getExtensionFunctionPointer(name);
+}
+
void HeadlessBackend::activate() {
active = true;
- if (!hasContext()) {
- if (!hasDisplay()) {
- throw std::runtime_error("Display is not set");
- }
- createContext();
+ if (!impl) {
+ createImpl();
}
- assert(hasContext());
+ assert(impl);
impl->activateContext();
}
void HeadlessBackend::deactivate() {
- assert(hasContext());
+ assert(impl);
impl->deactivateContext();
active = false;
}
diff --git a/platform/default/mbgl/gl/headless_backend.hpp b/platform/default/mbgl/gl/headless_backend.hpp
index 66f861e213..7757037533 100644
--- a/platform/default/mbgl/gl/headless_backend.hpp
+++ b/platform/default/mbgl/gl/headless_backend.hpp
@@ -7,8 +7,6 @@
namespace mbgl {
-class HeadlessDisplay;
-
class HeadlessBackend : public RendererBackend {
public:
HeadlessBackend(Size = { 256, 256 });
@@ -21,25 +19,24 @@ public:
void setSize(Size);
PremultipliedImage readStillImage();
- struct Impl {
+ class Impl {
+ public:
virtual ~Impl() = default;
+ virtual gl::ProcAddress getExtensionFunctionPointer(const char*) = 0;
virtual void activateContext() = 0;
virtual void deactivateContext() {}
};
private:
// Implementation specific functions
- gl::ProcAddress initializeExtension(const char*) override;
+ gl::ProcAddress getExtensionFunctionPointer(const char*) override;
void activate() override;
void deactivate() override;
- bool hasContext() const { return bool(impl); }
- bool hasDisplay();
-
- void createContext();
+ void createImpl();
- std::shared_ptr<HeadlessDisplay> display;
+private:
std::unique_ptr<Impl> impl;
Size size;
diff --git a/platform/default/mbgl/gl/headless_display.cpp b/platform/default/mbgl/gl/headless_display.cpp
deleted file mode 100644
index 6247046c29..0000000000
--- a/platform/default/mbgl/gl/headless_display.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <mbgl/gl/headless_display.hpp>
-
-namespace mbgl {
-
-class HeadlessDisplay::Impl {};
-
-HeadlessDisplay::HeadlessDisplay() {
- // no-op
-}
-
-HeadlessDisplay::~HeadlessDisplay() {
- // no-op
-}
-
-} // namespace mbgl
diff --git a/platform/default/mbgl/gl/headless_display.hpp b/platform/default/mbgl/gl/headless_display.hpp
deleted file mode 100644
index 8c294655e5..0000000000
--- a/platform/default/mbgl/gl/headless_display.hpp
+++ /dev/null
@@ -1,34 +0,0 @@
-#pragma once
-
-#include <memory>
-
-namespace mbgl {
-
-class HeadlessDisplay {
-public:
- static std::shared_ptr<HeadlessDisplay> create() {
- static std::weak_ptr<HeadlessDisplay> instance;
-
- auto shared = instance.lock();
-
- if (!shared) {
- instance = shared = std::shared_ptr<HeadlessDisplay>(new HeadlessDisplay());
- }
-
- return shared;
- }
-
-
- ~HeadlessDisplay();
-
- template <typename DisplayAttribute>
- DisplayAttribute attribute() const;
-
-private:
- HeadlessDisplay();
-
- class Impl;
- std::unique_ptr<Impl> impl;
-};
-
-} // namespace mbgl
diff --git a/platform/default/mbgl/gl/headless_frontend.cpp b/platform/default/mbgl/gl/headless_frontend.cpp
index 2cbb624bd0..4263d2b148 100644
--- a/platform/default/mbgl/gl/headless_frontend.cpp
+++ b/platform/default/mbgl/gl/headless_frontend.cpp
@@ -7,11 +7,11 @@
namespace mbgl {
-HeadlessFrontend::HeadlessFrontend(float pixelRatio_, FileSource& fileSource, Scheduler& scheduler, const optional<std::string> programCacheDir)
- : HeadlessFrontend({ 256, 256 }, pixelRatio_, fileSource, scheduler, programCacheDir) {
+HeadlessFrontend::HeadlessFrontend(float pixelRatio_, FileSource& fileSource, Scheduler& scheduler, const optional<std::string> programCacheDir, GLContextMode mode, const optional<std::string> localFontFamily)
+ : HeadlessFrontend({ 256, 256 }, pixelRatio_, fileSource, scheduler, programCacheDir, mode, localFontFamily) {
}
-HeadlessFrontend::HeadlessFrontend(Size size_, float pixelRatio_, FileSource& fileSource, Scheduler& scheduler, const optional<std::string> programCacheDir)
+HeadlessFrontend::HeadlessFrontend(Size size_, float pixelRatio_, FileSource& fileSource, Scheduler& scheduler, const optional<std::string> programCacheDir, GLContextMode mode, const optional<std::string> localFontFamily)
: size(size_),
pixelRatio(pixelRatio_),
backend({ static_cast<uint32_t>(size.width * pixelRatio),
@@ -22,7 +22,7 @@ HeadlessFrontend::HeadlessFrontend(Size size_, float pixelRatio_, FileSource& fi
renderer->render(*updateParameters);
}
}),
- renderer(std::make_unique<Renderer>(backend, pixelRatio, fileSource, scheduler, GLContextMode::Unique, programCacheDir)) {
+ renderer(std::make_unique<Renderer>(backend, pixelRatio, fileSource, scheduler, mode, programCacheDir, localFontFamily)) {
}
HeadlessFrontend::~HeadlessFrontend() = default;
diff --git a/platform/default/mbgl/gl/headless_frontend.hpp b/platform/default/mbgl/gl/headless_frontend.hpp
index 4d1116904e..8ae617d37b 100644
--- a/platform/default/mbgl/gl/headless_frontend.hpp
+++ b/platform/default/mbgl/gl/headless_frontend.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include <mbgl/renderer/mode.hpp>
#include <mbgl/renderer/renderer_frontend.hpp>
#include <mbgl/gl/headless_backend.hpp>
#include <mbgl/util/async_task.hpp>
@@ -18,8 +19,8 @@ class TransformState;
class HeadlessFrontend : public RendererFrontend {
public:
- HeadlessFrontend(float pixelRatio_, FileSource&, Scheduler&, const optional<std::string> programCacheDir = {});
- HeadlessFrontend(Size, float pixelRatio_, FileSource&, Scheduler&, const optional<std::string> programCacheDir = {});
+ HeadlessFrontend(float pixelRatio_, FileSource&, Scheduler&, const optional<std::string> programCacheDir = {}, GLContextMode mode = GLContextMode::Unique, const optional<std::string> localFontFamily = {});
+ HeadlessFrontend(Size, float pixelRatio_, FileSource&, Scheduler&, const optional<std::string> programCacheDir = {}, GLContextMode mode = GLContextMode::Unique, const optional<std::string> localFontFamily = {});
~HeadlessFrontend() override;
void reset() override;
diff --git a/platform/default/mbgl/map/map_snapshotter.cpp b/platform/default/mbgl/map/map_snapshotter.cpp
index 7b4ec5913b..9341c23cfd 100644
--- a/platform/default/mbgl/map/map_snapshotter.cpp
+++ b/platform/default/mbgl/map/map_snapshotter.cpp
@@ -50,7 +50,7 @@ MapSnapshotter::Impl::Impl(FileSource& fileSource,
const optional<LatLngBounds> region,
const optional<std::string> programCacheDir)
: frontend(size, pixelRatio, fileSource, scheduler, programCacheDir)
- , map(frontend, MapObserver::nullObserver(), size, pixelRatio, fileSource, scheduler, MapMode::Still) {
+ , map(frontend, MapObserver::nullObserver(), size, pixelRatio, fileSource, scheduler, MapMode::Static) {
map.getStyle().loadURL(styleURL);
diff --git a/platform/default/mbgl/storage/offline.cpp b/platform/default/mbgl/storage/offline.cpp
index 9ec789f725..7670790be9 100644
--- a/platform/default/mbgl/storage/offline.cpp
+++ b/platform/default/mbgl/storage/offline.cpp
@@ -24,7 +24,7 @@ OfflineTilePyramidRegionDefinition::OfflineTilePyramidRegionDefinition(
}
}
-std::vector<CanonicalTileID> OfflineTilePyramidRegionDefinition::tileCover(SourceType type, uint16_t tileSize, const Range<uint8_t>& zoomRange) const {
+std::vector<CanonicalTileID> OfflineTilePyramidRegionDefinition::tileCover(style::SourceType type, uint16_t tileSize, const Range<uint8_t>& zoomRange) const {
const Range<uint8_t> clampedZoomRange = coveringZoomRange(type, tileSize, zoomRange);
std::vector<CanonicalTileID> result;
@@ -38,7 +38,7 @@ std::vector<CanonicalTileID> OfflineTilePyramidRegionDefinition::tileCover(Sourc
return result;
}
-uint64_t OfflineTilePyramidRegionDefinition::tileCount(SourceType type, uint16_t tileSize, const Range<uint8_t>& zoomRange) const {
+uint64_t OfflineTilePyramidRegionDefinition::tileCount(style::SourceType type, uint16_t tileSize, const Range<uint8_t>& zoomRange) const {
const Range<uint8_t> clampedZoomRange = coveringZoomRange(type, tileSize, zoomRange);
unsigned long result = 0;;
@@ -49,7 +49,7 @@ uint64_t OfflineTilePyramidRegionDefinition::tileCount(SourceType type, uint16_t
return result;
}
-Range<uint8_t> OfflineTilePyramidRegionDefinition::coveringZoomRange(SourceType type, uint16_t tileSize, const Range<uint8_t>& zoomRange) const {
+Range<uint8_t> OfflineTilePyramidRegionDefinition::coveringZoomRange(style::SourceType type, uint16_t tileSize, const Range<uint8_t>& zoomRange) const {
double minZ = std::max<double>(util::coveringZoomLevel(minZoom, type, tileSize), zoomRange.min);
double maxZ = std::min<double>(util::coveringZoomLevel(maxZoom, type, tileSize), zoomRange.max);
diff --git a/platform/default/mbgl/storage/offline_download.cpp b/platform/default/mbgl/storage/offline_download.cpp
index ff61114888..8bb16993a5 100644
--- a/platform/default/mbgl/storage/offline_download.cpp
+++ b/platform/default/mbgl/storage/offline_download.cpp
@@ -129,6 +129,7 @@ OfflineRegionStatus OfflineDownload::getStatus() const {
case SourceType::Video:
case SourceType::Annotations:
+ case SourceType::CustomVector:
break;
}
}
@@ -214,6 +215,7 @@ void OfflineDownload::activateDownload() {
case SourceType::Video:
case SourceType::Annotations:
+ case SourceType::CustomVector:
break;
}
}
diff --git a/platform/default/mbgl/storage/offline_download.hpp b/platform/default/mbgl/storage/offline_download.hpp
index c978ded931..437f221c11 100644
--- a/platform/default/mbgl/storage/offline_download.hpp
+++ b/platform/default/mbgl/storage/offline_download.hpp
@@ -60,7 +60,7 @@ private:
std::deque<Resource> resourcesRemaining;
void queueResource(Resource);
- void queueTiles(SourceType, uint16_t tileSize, const Tileset&);
+ void queueTiles(style::SourceType, uint16_t tileSize, const Tileset&);
};
} // namespace mbgl
diff --git a/platform/glfw/glfw_view.cpp b/platform/glfw/glfw_view.cpp
index d591f897e0..8fc2fba283 100644
--- a/platform/glfw/glfw_view.cpp
+++ b/platform/glfw/glfw_view.cpp
@@ -540,7 +540,7 @@ mbgl::Size GLFWView::getFramebufferSize() const {
return { static_cast<uint32_t>(fbWidth), static_cast<uint32_t>(fbHeight) };
}
-mbgl::gl::ProcAddress GLFWView::initializeExtension(const char* name) {
+mbgl::gl::ProcAddress GLFWView::getExtensionFunctionPointer(const char* name) {
return glfwGetProcAddress(name);
}
diff --git a/platform/glfw/glfw_view.hpp b/platform/glfw/glfw_view.hpp
index d3257f6b9a..35f17b723a 100644
--- a/platform/glfw/glfw_view.hpp
+++ b/platform/glfw/glfw_view.hpp
@@ -52,7 +52,7 @@ public:
protected:
// mbgl::Backend implementation
- mbgl::gl::ProcAddress initializeExtension(const char*) override;
+ mbgl::gl::ProcAddress getExtensionFunctionPointer(const char*) override;
void activate() override;
void deactivate() override;
diff --git a/platform/glfw/main.cpp b/platform/glfw/main.cpp
index dadd88c705..c4e0ecf692 100644
--- a/platform/glfw/main.cpp
+++ b/platform/glfw/main.cpp
@@ -10,10 +10,11 @@
#include <mbgl/style/style.hpp>
#include <mbgl/renderer/renderer.hpp>
+#include <args/args.hxx>
+
#include <csignal>
-#include <getopt.h>
#include <fstream>
-#include <sstream>
+#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <array>
@@ -34,64 +35,47 @@ void quit_handler(int) {
}
int main(int argc, char *argv[]) {
+ args::ArgumentParser argumentParser("Mapbox GL GLFW example");
+ args::HelpFlag helpFlag(argumentParser, "help", "Display this help menu", {'h', "help"});
+
+ args::Flag fullscreenFlag(argumentParser, "fullscreen", "Toggle fullscreen", {'f', "fullscreen"});
+ args::Flag benchmarkFlag(argumentParser, "benchmark", "Toggle benchmark", {'b', "benchmark"});
+ args::Flag offlineFlag(argumentParser, "offline", "Toggle offline", {'o', "offline"});
+
+ args::ValueFlag<std::string> styleValue(argumentParser, "URL", "Map stylesheet", {'s', "style"});
+ args::ValueFlag<double> lonValue(argumentParser, "degrees", "Longitude", {'x', "lon"});
+ args::ValueFlag<double> latValue(argumentParser, "degrees", "Latitude", {'y', "lat"});
+ args::ValueFlag<double> zoomValue(argumentParser, "number", "Zoom level", {'z', "zoom"});
+ args::ValueFlag<double> bearingValue(argumentParser, "degrees", "Bearing", {'b', "bearing"});
+ args::ValueFlag<double> pitchValue(argumentParser, "degrees", "Pitch", {'p', "pitch"});
+
+ try {
+ argumentParser.ParseCLI(argc, argv);
+ } catch (args::Help) {
+ std::cout << argumentParser;
+ exit(0);
+ } catch (args::ParseError e) {
+ std::cerr << e.what() << std::endl;
+ std::cerr << argumentParser;
+ exit(1);
+ } catch (args::ValidationError e) {
+ std::cerr << e.what() << std::endl;
+ std::cerr << argumentParser;
+ exit(2);
+ }
+
// Load settings
mbgl::Settings_JSON settings;
-
- bool fullscreen = false;
- bool benchmark = false;
- std::string style;
-
- const struct option long_options[] = {
- {"fullscreen", no_argument, nullptr, 'f'},
- {"benchmark", no_argument, nullptr, 'b'},
- {"offline", no_argument, nullptr, 'o'},
- {"style", required_argument, nullptr, 's'},
- {"lon", required_argument, nullptr, 'x'},
- {"lat", required_argument, nullptr, 'y'},
- {"zoom", required_argument, nullptr, 'z'},
- {"bearing", required_argument, nullptr, 'r'},
- {"pitch", required_argument, nullptr, 'p'},
- {nullptr, 0, nullptr, 0}
- };
-
- while (true) {
- int option_index = 0;
- int opt = getopt_long(argc, argv, "fbs:", long_options, &option_index);
- if (opt == -1) break;
- switch (opt)
- {
- case 'f':
- fullscreen = true;
- break;
- case 'b':
- benchmark = true;
- break;
- case 'o':
- settings.online = false;
- break;
- case 's':
- style = std::string(optarg);
- break;
- case 'x':
- settings.longitude = atof(optarg);
- break;
- case 'y':
- settings.latitude = atof(optarg);
- break;
- case 'z':
- settings.zoom = atof(optarg);
- break;
- case 'r':
- settings.bearing = atof(optarg);
- break;
- case 'p':
- settings.pitch = atof(optarg);
- break;
- default:
- break;
- }
-
- }
+ settings.online = !offlineFlag;
+ if (lonValue) settings.longitude = args::get(lonValue);
+ if (latValue) settings.latitude = args::get(latValue);
+ if (zoomValue) settings.zoom = args::get(zoomValue);
+ if (bearingValue) settings.bearing = args::get(bearingValue);
+ if (pitchValue) settings.pitch = args::get(pitchValue);
+
+ const bool fullscreen = fullscreenFlag ? args::get(fullscreenFlag) : false;
+ const bool benchmark = benchmarkFlag ? args::get(benchmarkFlag) : false;
+ std::string style = styleValue ? args::get(styleValue) : "";
// sigint handling
struct sigaction sigIntHandler;
diff --git a/platform/glfw/settings_json.hpp b/platform/glfw/settings_json.hpp
index 49ea00e3e1..c89accb8af 100644
--- a/platform/glfw/settings_json.hpp
+++ b/platform/glfw/settings_json.hpp
@@ -17,6 +17,9 @@ public:
double zoom = 0;
double bearing = 0;
double pitch = 0;
+ bool axonometric = false;
+ double xSkew = 0.0;
+ double ySkew = 1.0;
EnumType debug = 0;
bool online = true;
diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md
index e3e2768e21..b152aae9b8 100644
--- a/platform/ios/CHANGELOG.md
+++ b/platform/ios/CHANGELOG.md
@@ -2,6 +2,17 @@
Mapbox welcomes participation and contributions from everyone. Please read [CONTRIBUTING.md](../../CONTRIBUTING.md) to get started.
+## master
+
+### Annotations and user interaction
+
+* Increased the default maximum zoom level from 20 to 22. ([#9835](https://github.com/mapbox/mapbox-gl-native/pull/9835))
+
+### Styles
+
+* Fixed an issue preventing a dynamically-added `MGLRasterStyleLayer` from drawing until the map pans. ([#10270](https://github.com/mapbox/mapbox-gl-native/pull/10270))
+* Added `MGLComputedShapeSource` source class that allows applications to supply vector data on a per-tile basis.
+
## 3.7.2 - December 21, 2017
### Packaging
diff --git a/platform/ios/DEVELOPING.md b/platform/ios/DEVELOPING.md
index 40d45e2e56..10a94c73f3 100644
--- a/platform/ios/DEVELOPING.md
+++ b/platform/ios/DEVELOPING.md
@@ -6,7 +6,7 @@ This document explains how to build the Mapbox Maps SDK for iOS from source. It
The Mapbox Maps SDK for iOS and iosapp demo application require iOS 8.0 or above.
-The Mapbox Maps SDK for iOS requires Xcode 8.0 or above.
+The Mapbox Maps SDK for iOS requires Xcode 9.1 or above to compile from source.
## Building the SDK
@@ -30,7 +30,7 @@ Before building, use the scheme picker button in the toolbar to change the schem
* **static** builds the SDK as a static library and separate resource bundle.
* **dynamic+static** is a combination of the **dynamic** and **static** schemes.
-If you don’t have an Apple Developer account, change the destination to a simulator such as “iPhone 6s” before you run and build the app.
+If you don’t have an Apple Developer account, change the destination to a simulator such as “iPhone 6s” before you build and run the app.
### Packaging builds
@@ -52,12 +52,12 @@ You can customize the build output by passing the following arguments into the `
* `BUILDTYPE=Release` will optimize for distribution. Defaults to `Debug`.
* `BUILD_DEVICE=false` builds only for the iOS Simulator.
* `FORMAT=dynamic` builds only a dynamic framework. `FORMAT=static` builds only a static framework, for legacy compatibility.
-* `SYMBOLS=NO` strips the build output of any debug symbols, yielding much smaller binaries. Defaults to `YES`.
+* `SYMBOLS=NO` strips the build output of any debug symbols, yielding smaller binaries. Defaults to `YES`.
An example command that creates a dynamic framework suitable for eventual App Store distribution:
```bash
-make iframework BUILDTYPE=Release SYMBOLS=NO
+make iframework BUILDTYPE=Release
```
The products of these build commands can be found in the `build/ios/pkg` folder at the base of the repository.
@@ -168,5 +168,5 @@ The included applications use Mapbox vector tiles, which require a Mapbox accoun
- Use two fingers to rotate
- Double-tap to zoom in one level
- Two-finger single-tap to zoom out one level
-- Double-tap, long-pressing the second, then pan up and down to "quick zoom" (iPhone only, meant for one-handed use)
+- Double-tap, long-pressing the second, then pan up and down to "quick zoom" (meant for one-handed use)
- Use the debug menu to add test annotations, reset position, and cycle through the debug options.
diff --git a/platform/ios/INSTALL.md b/platform/ios/INSTALL.md
index b0d7be83d5..f8cd7b3754 100644
--- a/platform/ios/INSTALL.md
+++ b/platform/ios/INSTALL.md
@@ -13,6 +13,7 @@ The Mapbox Maps SDK for iOS is intended to run on iOS 8.0 and above on the follo
Note that debugging in 32-bit simulators (such as the iPhone 5 or iPad 2) is only partially supported. Support for these simulators will be removed entirely in a future release of this SDK.
The Mapbox Maps SDK for iOS requires Xcode 8.0 or higher. 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.
+* Xcode 8.0 or higher to integrate the compiled framework into an application
### Building the SDK
@@ -24,9 +25,8 @@ The Mapbox Maps SDK for iOS requires Xcode 8.0 or higher. To use this SDK with X
[sudo] gem install jazzy
```
-1. Run `make ipackage`. The packaging script will produce a `build/ios/pkg/` folder containing:
+1. Run `make iframework BUILDTYPE=Release`. The packaging script will produce a `build/ios/pkg/` folder containing:
- a `dynamic` folder containing a dynamically-linked fat framework with debug symbols for devices and the iOS Simulator
- - a `static` folder containing a statically-linked framework with debug symbols for devices and the iOS Simulator
- a `documentation` folder with HTML API documentation
- an example `Settings.bundle` containing an optional Mapbox Telemetry opt-out setting
@@ -60,7 +60,7 @@ A nightly build of the dynamic framework, based on the master branch, is availab
You can alternatively install the SDK as a static framework:
-1. Build from source manually, per above.
+1. Build from source using the `make ipackage` command.
1. Drag the Mapbox.bundle and Mapbox.framework from the `build/ios/pkg/static/` directory into the Project navigator. In the sheet that appears, make sure “Copy items if needed” is checked, then click Finish. Open the project editor and select your application target to verify that the following changes occurred automatically:
diff --git a/platform/ios/README.md b/platform/ios/README.md
index 40e27c2d3f..3ca5b84dde 100644
--- a/platform/ios/README.md
+++ b/platform/ios/README.md
@@ -7,6 +7,7 @@ A library based on [Mapbox GL Native](../../README.md) for embedding interactive
This repository is for day-to-day development of the SDK. Building the SDK yourself requires [a number of dependencies and steps](../../INSTALL.md) that are unnecessary for developing production applications. For production applications, please consider installing an official, prebuilt release instead; see the [Mapbox iOS SDK website](https://www.mapbox.com/ios-sdk/) for installation instructions.
* [Integrate the Mapbox Maps SDK for iOS into your application](https://www.mapbox.com/install/ios/).
+* [Learn about custom builds](INSTALL.md)
* [Contribute to the Mapbox Maps SDK for iOS](DEVELOPING.md)
![](docs/img/screenshot.png)
diff --git a/platform/ios/app/Assets.xcassets/AppIcon.appiconset/Contents.json b/platform/ios/app/Assets.xcassets/AppIcon.appiconset/Contents.json
index f4e2027f0f..ccfb66f047 100644
--- a/platform/ios/app/Assets.xcassets/AppIcon.appiconset/Contents.json
+++ b/platform/ios/app/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -99,8 +99,9 @@
"scale" : "2x"
},
{
- "idiom" : "ios-marketing",
"size" : "1024x1024",
+ "idiom" : "ios-marketing",
+ "filename" : "Icon-1024.png",
"scale" : "1x"
}
],
diff --git a/platform/ios/app/Assets.xcassets/AppIcon.appiconset/Icon-1024.png b/platform/ios/app/Assets.xcassets/AppIcon.appiconset/Icon-1024.png
new file mode 100644
index 0000000000..d1cb5c50f7
--- /dev/null
+++ b/platform/ios/app/Assets.xcassets/AppIcon.appiconset/Icon-1024.png
Binary files differ
diff --git a/platform/ios/app/Info.plist b/platform/ios/app/Info.plist
index 0bf66cb8da..ea70ecd629 100644
--- a/platform/ios/app/Info.plist
+++ b/platform/ios/app/Info.plist
@@ -27,7 +27,7 @@
<key>MGLIdeographicFontFamilyName</key>
<string>PingFang TC</string>
<key>NSHumanReadableCopyright</key>
- <string>© 2014–2017 Mapbox</string>
+ <string>© 2014–2018 Mapbox</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>The map will display your location. The map may also use your location when it isn’t visible in order to improve OpenStreetMap and Mapbox products.</string>
<key>NSLocationWhenInUseUsageDescription</key>
diff --git a/platform/ios/app/MBXViewController.m b/platform/ios/app/MBXViewController.m
index 2c3d26b489..4306354030 100644
--- a/platform/ios/app/MBXViewController.m
+++ b/platform/ios/app/MBXViewController.m
@@ -75,6 +75,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsRuntimeStylingRows) {
MBXSettingsRuntimeStylingImageSource,
MBXSettingsRuntimeStylingRouteLine,
MBXSettingsRuntimeStylingDDSPolygon,
+ MBXSettingsRuntimeStylingCustomLatLonGrid,
};
typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
@@ -111,7 +112,8 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
@interface MBXViewController () <UITableViewDelegate,
UITableViewDataSource,
- MGLMapViewDelegate>
+ MGLMapViewDelegate,
+ MGLComputedShapeSourceDataSource>
@property (nonatomic) IBOutlet MGLMapView *mapView;
@@ -353,6 +355,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
@"Style Image Source",
@"Add Route Line",
@"Dynamically Style Polygon",
+ @"Add Custom Lat/Lon Grid",
]];
break;
case MBXSettingsMiscellaneous:
@@ -529,6 +532,9 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
case MBXSettingsRuntimeStylingDDSPolygon:
[self stylePolygonWithDDS];
break;
+ case MBXSettingsRuntimeStylingCustomLatLonGrid:
+ [self addLatLonGrid];
+ break;
default:
NSAssert(NO, @"All runtime styling setting rows should be implemented");
break;
@@ -1445,6 +1451,54 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
[self.mapView.style addLayer:fillStyleLayer];
}
+- (void)addLatLonGrid
+{
+ MGLComputedShapeSource *source = [[MGLComputedShapeSource alloc] initWithIdentifier:@"latlon"
+ options:@{MGLShapeSourceOptionMaximumZoomLevel:@14}];
+ source.dataSource = self;
+ [self.mapView.style addSource:source];
+ MGLLineStyleLayer *lineLayer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"latlonlines"
+ source:source];
+ [self.mapView.style addLayer:lineLayer];
+ MGLSymbolStyleLayer *labelLayer = [[MGLSymbolStyleLayer alloc] initWithIdentifier:@"latlonlabels"
+ source:source];
+ labelLayer.text = [MGLStyleValue valueWithRawValue:@"{value}"];
+ [self.mapView.style addLayer:labelLayer];
+}
+
+- (void)styleLabelLanguageForLayersNamed:(NSArray<NSString *> *)layers
+{
+ _usingLocaleBasedCountryLabels = !_usingLocaleBasedCountryLabels;
+ NSString *bestLanguageForUser = [NSString stringWithFormat:@"{name_%@}", [self bestLanguageForUser]];
+ NSString *language = _usingLocaleBasedCountryLabels ? bestLanguageForUser : @"{name}";
+
+ for (NSString *layerName in layers) {
+ MGLSymbolStyleLayer *layer = (MGLSymbolStyleLayer *)[self.mapView.style layerWithIdentifier:layerName];
+
+ if ([layer isKindOfClass:[MGLSymbolStyleLayer class]]) {
+ if ([layer.text isKindOfClass:[MGLStyleConstantValue class]]) {
+ MGLStyleConstantValue *label = (MGLStyleConstantValue<NSString *> *)layer.text;
+ if ([label.rawValue hasPrefix:@"{name"]) {
+ layer.text = [MGLStyleValue valueWithRawValue:language];
+ }
+ }
+ else if ([layer.text isKindOfClass:[MGLCameraStyleFunction class]]) {
+ MGLCameraStyleFunction *function = (MGLCameraStyleFunction<NSString *> *)layer.text;
+ NSMutableDictionary *stops = function.stops.mutableCopy;
+ [stops enumerateKeysAndObjectsUsingBlock:^(NSNumber *zoomLevel, MGLStyleConstantValue<NSString *> *stop, BOOL *done) {
+ if ([stop.rawValue hasPrefix:@"{name"]) {
+ stops[zoomLevel] = [MGLStyleValue<NSString *> valueWithRawValue:language];
+ }
+ }];
+ function.stops = stops;
+ layer.text = function;
+ }
+ } else {
+ NSLog(@"%@ is not a symbol style layer", layerName);
+ }
+ }
+}
+
- (NSString *)bestLanguageForUser
{
// https://www.mapbox.com/vector-tiles/mapbox-streets-v7/#overview
@@ -1910,4 +1964,52 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
[self.hudLabel setTitle:hudString forState:UIControlStateNormal];
}
+#pragma mark - MGLComputedShapeSourceDataSource
+
+- (NSArray<id <MGLFeature>>*)featuresInCoordinateBounds:(MGLCoordinateBounds)bounds zoomLevel:(NSUInteger)zoom {
+ double gridSpacing;
+ if(zoom >= 13) {
+ gridSpacing = 0.01;
+ } else if(zoom >= 11) {
+ gridSpacing = 0.05;
+ } else if(zoom == 10) {
+ gridSpacing = .1;
+ } else if(zoom == 9) {
+ gridSpacing = 0.25;
+ } else if(zoom == 8) {
+ gridSpacing = 0.5;
+ } else if (zoom >= 6) {
+ gridSpacing = 1;
+ } else if(zoom == 5) {
+ gridSpacing = 2;
+ } else if(zoom >= 4) {
+ gridSpacing = 5;
+ } else if(zoom == 2) {
+ gridSpacing = 10;
+ } else {
+ gridSpacing = 20;
+ }
+
+ NSMutableArray <id <MGLFeature>> * features = [NSMutableArray array];
+ CLLocationCoordinate2D coords[2];
+
+ for (double y = ceil(bounds.ne.latitude / gridSpacing) * gridSpacing; y >= floor(bounds.sw.latitude / gridSpacing) * gridSpacing; y -= gridSpacing) {
+ coords[0] = CLLocationCoordinate2DMake(y, bounds.sw.longitude);
+ coords[1] = CLLocationCoordinate2DMake(y, bounds.ne.longitude);
+ MGLPolylineFeature *feature = [MGLPolylineFeature polylineWithCoordinates:coords count:2];
+ feature.attributes = @{@"value": @(y)};
+ [features addObject:feature];
+ }
+
+ for (double x = floor(bounds.sw.longitude / gridSpacing) * gridSpacing; x <= ceil(bounds.ne.longitude / gridSpacing) * gridSpacing; x += gridSpacing) {
+ coords[0] = CLLocationCoordinate2DMake(bounds.sw.latitude, x);
+ coords[1] = CLLocationCoordinate2DMake(bounds.ne.latitude, x);
+ MGLPolylineFeature *feature = [MGLPolylineFeature polylineWithCoordinates:coords count:2];
+ feature.attributes = @{@"value": @(x)};
+ [features addObject:feature];
+ }
+
+ return features;
+}
+
@end
diff --git a/platform/ios/benchmark/Info.plist b/platform/ios/benchmark/Info.plist
index 35d3658a1c..b35cb572ab 100644
--- a/platform/ios/benchmark/Info.plist
+++ b/platform/ios/benchmark/Info.plist
@@ -25,7 +25,7 @@
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSHumanReadableCopyright</key>
- <string>© 2015–2017 Mapbox</string>
+ <string>© 2015–2018 Mapbox</string>
<key>UIApplicationExitsOnSuspend</key>
<true/>
<key>UILaunchStoryboardName</key>
diff --git a/platform/ios/config.cmake b/platform/ios/config.cmake
index 55de8bc398..1caf372b25 100644
--- a/platform/ios/config.cmake
+++ b/platform/ios/config.cmake
@@ -48,8 +48,6 @@ macro(mbgl_platform_core)
PRIVATE platform/default/mbgl/gl/headless_backend.cpp
PRIVATE platform/default/mbgl/gl/headless_backend.hpp
PRIVATE platform/darwin/src/headless_backend_eagl.mm
- PRIVATE platform/default/mbgl/gl/headless_display.cpp
- PRIVATE platform/default/mbgl/gl/headless_display.hpp
# Snapshotting
PRIVATE platform/default/mbgl/map/map_snapshotter.cpp
@@ -66,17 +64,6 @@ macro(mbgl_platform_core)
target_add_mason_package(mbgl-core PUBLIC polylabel)
target_add_mason_package(mbgl-core PRIVATE icu)
- target_compile_options(mbgl-core
- PRIVATE -fvisibility=hidden
- )
-
- # TODO: Remove this by converting to ARC
- set_source_files_properties(
- platform/darwin/src/headless_backend_eagl.mm
- PROPERTIES
- COMPILE_FLAGS -fno-objc-arc
- )
-
target_include_directories(mbgl-core
PUBLIC platform/darwin
PUBLIC platform/default
@@ -106,10 +93,6 @@ macro(mbgl_filesource)
PRIVATE platform/default/sqlite3.cpp
)
- target_compile_options(mbgl-filesource
- PRIVATE -fvisibility=hidden
- )
-
target_link_libraries(mbgl-filesource
PUBLIC "-lsqlite3"
PUBLIC "-framework Foundation"
diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj
index c405e92d35..95bbff5bbf 100644
--- a/platform/ios/ios.xcodeproj/project.pbxproj
+++ b/platform/ios/ios.xcodeproj/project.pbxproj
@@ -12,6 +12,14 @@
071BBB031EE76146001FB02A /* MGLImageSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 071BBAFC1EE75CD4001FB02A /* MGLImageSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
071BBB041EE76147001FB02A /* MGLImageSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 071BBAFC1EE75CD4001FB02A /* MGLImageSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
071BBB071EE77631001FB02A /* MGLImageSourceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 071BBB051EE7761A001FB02A /* MGLImageSourceTests.m */; };
+ 0778DD431F67556700A73B34 /* MGLComputedShapeSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 0778DD401F67555F00A73B34 /* MGLComputedShapeSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 0778DD441F67556C00A73B34 /* MGLComputedShapeSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0778DD411F67555F00A73B34 /* MGLComputedShapeSource.mm */; };
+ 07D8C6FB1F67560100381808 /* MGLComputedShapeSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0778DD411F67555F00A73B34 /* MGLComputedShapeSource.mm */; };
+ 07D8C6FC1F67560400381808 /* MGLAbstractShapeSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 07D947501F67487E00E37934 /* MGLAbstractShapeSource.mm */; };
+ 07D8C6FF1F67562C00381808 /* MGLComputedShapeSourceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 07D8C6FD1F67562800381808 /* MGLComputedShapeSourceTests.m */; };
+ 07D947521F67488800E37934 /* MGLAbstractShapeSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 07D9474F1F67487E00E37934 /* MGLAbstractShapeSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 07D947531F67488E00E37934 /* MGLAbstractShapeSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 07D9474E1F67487E00E37934 /* MGLAbstractShapeSource_Private.h */; };
+ 07D947541F67489200E37934 /* MGLAbstractShapeSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 07D947501F67487E00E37934 /* MGLAbstractShapeSource.mm */; };
1753ED421E53CE6F00A9FD90 /* MGLConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 1753ED411E53CE6F00A9FD90 /* MGLConversion.h */; };
1753ED431E53CE6F00A9FD90 /* MGLConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 1753ED411E53CE6F00A9FD90 /* MGLConversion.h */; };
1F06668A1EC64F8E001C16D7 /* MGLLight.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F0666881EC64F8E001C16D7 /* MGLLight.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -22,10 +30,6 @@
1F7454971ECD450D00021D39 /* MGLLight_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F7454941ECD450D00021D39 /* MGLLight_Private.h */; };
1F7454A91ED08AB400021D39 /* MGLLightTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F7454A61ED08AB400021D39 /* MGLLightTest.mm */; };
1F95931D1E6DE2E900D5B294 /* MGLNSDateAdditionsTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F95931C1E6DE2E900D5B294 /* MGLNSDateAdditionsTests.mm */; };
- 1FB7DAAF1F2A4DBD00410606 /* MGLVectorSource+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FDD9D6D1F26936400252B09 /* MGLVectorSource+MGLAdditions.h */; };
- 1FB7DAB01F2A4DC200410606 /* MGLVectorSource+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FDD9D6D1F26936400252B09 /* MGLVectorSource+MGLAdditions.h */; };
- 1FB7DAB11F2A4DC800410606 /* MGLVectorSource+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FDD9D6E1F26936400252B09 /* MGLVectorSource+MGLAdditions.m */; };
- 1FB7DAB21F2A4DC900410606 /* MGLVectorSource+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FDD9D6E1F26936400252B09 /* MGLVectorSource+MGLAdditions.m */; };
30E578171DAA85520050F07E /* UIImage+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 30E578111DAA7D690050F07E /* UIImage+MGLAdditions.h */; };
30E578181DAA85520050F07E /* UIImage+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 30E578111DAA7D690050F07E /* UIImage+MGLAdditions.h */; };
30E578191DAA855E0050F07E /* UIImage+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 30E578121DAA7D690050F07E /* UIImage+MGLAdditions.mm */; };
@@ -215,14 +219,6 @@
55E2AD131E5B125400E8C587 /* MGLOfflineStorageTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 55E2AD121E5B125400E8C587 /* MGLOfflineStorageTests.mm */; };
632281DF1E6F855900D75A5D /* MBXEmbeddedMapViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 632281DE1E6F855900D75A5D /* MBXEmbeddedMapViewController.m */; };
6407D6701E0085FD00F6A9C3 /* MGLDocumentationExampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6407D66F1E0085FD00F6A9C3 /* MGLDocumentationExampleTests.swift */; };
- 7E016D7E1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E016D7C1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.h */; };
- 7E016D7F1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E016D7C1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.h */; };
- 7E016D801D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E016D7D1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.m */; };
- 7E016D811D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E016D7D1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.m */; };
- 7E016D841D9E890300A29A21 /* MGLPolygon+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E016D821D9E890300A29A21 /* MGLPolygon+MGLAdditions.h */; };
- 7E016D851D9E890300A29A21 /* MGLPolygon+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E016D821D9E890300A29A21 /* MGLPolygon+MGLAdditions.h */; };
- 7E016D861D9E890300A29A21 /* MGLPolygon+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E016D831D9E890300A29A21 /* MGLPolygon+MGLAdditions.m */; };
- 7E016D871D9E890300A29A21 /* MGLPolygon+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E016D831D9E890300A29A21 /* MGLPolygon+MGLAdditions.m */; };
920A3E5D1E6F995200C16EFC /* MGLSourceQueryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 920A3E5C1E6F995200C16EFC /* MGLSourceQueryTests.m */; };
927FBCFC1F4DAA8300F8BF1F /* MBXSnapshotsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 927FBCFB1F4DAA8300F8BF1F /* MBXSnapshotsViewController.m */; };
927FBCFF1F4DB05500F8BF1F /* MGLMapSnapshotter.h in Headers */ = {isa = PBXBuildFile; fileRef = 927FBCFD1F4DB05500F8BF1F /* MGLMapSnapshotter.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -237,6 +233,8 @@
9620BB391E69FE1700705A1D /* MGLSDKUpdateChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = 9620BB361E69FE1700705A1D /* MGLSDKUpdateChecker.h */; };
9620BB3A1E69FE1700705A1D /* MGLSDKUpdateChecker.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9620BB371E69FE1700705A1D /* MGLSDKUpdateChecker.mm */; };
9620BB3B1E69FE1700705A1D /* MGLSDKUpdateChecker.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9620BB371E69FE1700705A1D /* MGLSDKUpdateChecker.mm */; };
+ 9654C1261FFC1AB900DB6A19 /* MGLPolyline_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 9654C1251FFC1AB900DB6A19 /* MGLPolyline_Private.h */; };
+ 9654C1291FFC1CCD00DB6A19 /* MGLPolygon_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 9654C1271FFC1CC000DB6A19 /* MGLPolygon_Private.h */; };
966FCF4C1F3A5C9200F2B6DE /* MGLUserLocationHeadingBeamLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 966FCF4A1F3A5C9200F2B6DE /* MGLUserLocationHeadingBeamLayer.h */; };
966FCF4E1F3A5C9200F2B6DE /* MGLUserLocationHeadingBeamLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 966FCF4B1F3A5C9200F2B6DE /* MGLUserLocationHeadingBeamLayer.m */; };
966FCF4F1F3A5C9200F2B6DE /* MGLUserLocationHeadingBeamLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 966FCF4B1F3A5C9200F2B6DE /* MGLUserLocationHeadingBeamLayer.m */; };
@@ -580,14 +578,18 @@
071BBAFC1EE75CD4001FB02A /* MGLImageSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLImageSource.h; sourceTree = "<group>"; };
071BBAFD1EE75CD4001FB02A /* MGLImageSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLImageSource.mm; sourceTree = "<group>"; };
071BBB051EE7761A001FB02A /* MGLImageSourceTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLImageSourceTests.m; path = ../../darwin/test/MGLImageSourceTests.m; sourceTree = "<group>"; };
+ 0778DD401F67555F00A73B34 /* MGLComputedShapeSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLComputedShapeSource.h; sourceTree = "<group>"; };
+ 0778DD411F67555F00A73B34 /* MGLComputedShapeSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLComputedShapeSource.mm; sourceTree = "<group>"; };
+ 07D8C6FD1F67562800381808 /* MGLComputedShapeSourceTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLComputedShapeSourceTests.m; path = ../../darwin/test/MGLComputedShapeSourceTests.m; sourceTree = "<group>"; };
+ 07D9474E1F67487E00E37934 /* MGLAbstractShapeSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAbstractShapeSource_Private.h; sourceTree = "<group>"; };
+ 07D9474F1F67487E00E37934 /* MGLAbstractShapeSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAbstractShapeSource.h; sourceTree = "<group>"; };
+ 07D947501F67487E00E37934 /* MGLAbstractShapeSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLAbstractShapeSource.mm; sourceTree = "<group>"; };
1753ED411E53CE6F00A9FD90 /* MGLConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLConversion.h; sourceTree = "<group>"; };
1F0666881EC64F8E001C16D7 /* MGLLight.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLLight.h; sourceTree = "<group>"; };
1F0666891EC64F8E001C16D7 /* MGLLight.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLLight.mm; sourceTree = "<group>"; };
1F7454941ECD450D00021D39 /* MGLLight_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLLight_Private.h; sourceTree = "<group>"; };
1F7454A61ED08AB400021D39 /* MGLLightTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLLightTest.mm; path = ../../darwin/test/MGLLightTest.mm; sourceTree = "<group>"; };
1F95931C1E6DE2E900D5B294 /* MGLNSDateAdditionsTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLNSDateAdditionsTests.mm; path = ../../darwin/test/MGLNSDateAdditionsTests.mm; sourceTree = "<group>"; };
- 1FDD9D6D1F26936400252B09 /* MGLVectorSource+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MGLVectorSource+MGLAdditions.h"; sourceTree = "<group>"; };
- 1FDD9D6E1F26936400252B09 /* MGLVectorSource+MGLAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MGLVectorSource+MGLAdditions.m"; sourceTree = "<group>"; };
20DABE861DF78148007AC5FF /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Foundation.strings"; sourceTree = "<group>"; };
20DABE881DF78148007AC5FF /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
20DABE8A1DF78149007AC5FF /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Root.strings"; sourceTree = "<group>"; };
@@ -673,7 +675,7 @@
4018B1C31CDC277F00F666AF /* MGLAnnotationView_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAnnotationView_Private.h; sourceTree = "<group>"; };
4018B1C41CDC277F00F666AF /* MGLAnnotationView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLAnnotationView.mm; sourceTree = "<group>"; };
4018B1C51CDC277F00F666AF /* MGLAnnotationView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAnnotationView.h; sourceTree = "<group>"; };
- 402E9DE01CD2C76200FD4519 /* Mapbox.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = Mapbox.playground; sourceTree = "<group>"; };
+ 402E9DE01CD2C76200FD4519 /* Mapbox.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = Mapbox.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
4031ACFE1E9FD29F00A3EA26 /* MGLSDKTestHelpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MGLSDKTestHelpers.swift; path = ../../darwin/test/MGLSDKTestHelpers.swift; sourceTree = "<group>"; };
404326881D5B9B1A007111BD /* MGLAnnotationContainerView_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLAnnotationContainerView_Private.h; sourceTree = "<group>"; };
4049C29B1DB6CD6C00B3F799 /* MGLPointCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLPointCollection.h; sourceTree = "<group>"; };
@@ -715,10 +717,6 @@
632281DD1E6F855900D75A5D /* MBXEmbeddedMapViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MBXEmbeddedMapViewController.h; sourceTree = "<group>"; };
632281DE1E6F855900D75A5D /* MBXEmbeddedMapViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MBXEmbeddedMapViewController.m; sourceTree = "<group>"; };
6407D66F1E0085FD00F6A9C3 /* MGLDocumentationExampleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MGLDocumentationExampleTests.swift; path = ../../darwin/test/MGLDocumentationExampleTests.swift; sourceTree = "<group>"; };
- 7E016D7C1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MGLPolyline+MGLAdditions.h"; sourceTree = "<group>"; };
- 7E016D7D1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MGLPolyline+MGLAdditions.m"; sourceTree = "<group>"; };
- 7E016D821D9E890300A29A21 /* MGLPolygon+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MGLPolygon+MGLAdditions.h"; sourceTree = "<group>"; };
- 7E016D831D9E890300A29A21 /* MGLPolygon+MGLAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MGLPolygon+MGLAdditions.m"; sourceTree = "<group>"; };
920A3E5C1E6F995200C16EFC /* MGLSourceQueryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLSourceQueryTests.m; path = ../../darwin/test/MGLSourceQueryTests.m; sourceTree = "<group>"; };
927FBCFA1F4DAA8300F8BF1F /* MBXSnapshotsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MBXSnapshotsViewController.h; sourceTree = "<group>"; };
927FBCFB1F4DAA8300F8BF1F /* MBXSnapshotsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MBXSnapshotsViewController.m; sourceTree = "<group>"; };
@@ -728,6 +726,8 @@
960D0C351ECF5AAF008E151F /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
9620BB361E69FE1700705A1D /* MGLSDKUpdateChecker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLSDKUpdateChecker.h; sourceTree = "<group>"; };
9620BB371E69FE1700705A1D /* MGLSDKUpdateChecker.mm */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; path = MGLSDKUpdateChecker.mm; sourceTree = "<group>"; };
+ 9654C1251FFC1AB900DB6A19 /* MGLPolyline_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLPolyline_Private.h; sourceTree = "<group>"; };
+ 9654C1271FFC1CC000DB6A19 /* MGLPolygon_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLPolygon_Private.h; sourceTree = "<group>"; };
9660916B1E5BBFD700A9A03B /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = "<group>"; };
9660916C1E5BBFD900A9A03B /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Localizable.strings; sourceTree = "<group>"; };
9660916D1E5BBFDB00A9A03B /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = "<group>"; };
@@ -1064,6 +1064,11 @@
35136D491D4277EA00C20EFD /* Sources */ = {
isa = PBXGroup;
children = (
+ 07D9474F1F67487E00E37934 /* MGLAbstractShapeSource.h */,
+ 07D9474E1F67487E00E37934 /* MGLAbstractShapeSource_Private.h */,
+ 07D947501F67487E00E37934 /* MGLAbstractShapeSource.mm */,
+ 0778DD401F67555F00A73B34 /* MGLComputedShapeSource.h */,
+ 0778DD411F67555F00A73B34 /* MGLComputedShapeSource.mm */,
071BBAFC1EE75CD4001FB02A /* MGLImageSource.h */,
071BBAFD1EE75CD4001FB02A /* MGLImageSource.mm */,
3566C76A1D4A8DFA008152BC /* MGLRasterSource.h */,
@@ -1135,8 +1140,6 @@
35599DB81D46AD7F0048254D /* Categories */ = {
isa = PBXGroup;
children = (
- 1FDD9D6D1F26936400252B09 /* MGLVectorSource+MGLAdditions.h */,
- 1FDD9D6E1F26936400252B09 /* MGLVectorSource+MGLAdditions.m */,
350098DA1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.h */,
350098DB1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.mm */,
);
@@ -1225,6 +1228,7 @@
40CFA64E1D78754A008103BD /* Sources */ = {
isa = PBXGroup;
children = (
+ 07D8C6FD1F67562800381808 /* MGLComputedShapeSourceTests.m */,
071BBB051EE7761A001FB02A /* MGLImageSourceTests.m */,
40CFA6501D787579008103BD /* MGLShapeSourceTests.mm */,
920A3E5C1E6F995200C16EFC /* MGLSourceQueryTests.m */,
@@ -1611,8 +1615,10 @@
4049C2AB1DB6E05500B3F799 /* MGLPointCollection_Private.h */,
4049C29C1DB6CD6C00B3F799 /* MGLPointCollection.mm */,
DA8847E91CBAFA5100AB86E3 /* MGLPolygon.h */,
+ 9654C1271FFC1CC000DB6A19 /* MGLPolygon_Private.h */,
DA88480C1CBAFA6200AB86E3 /* MGLPolygon.mm */,
DA8847EA1CBAFA5100AB86E3 /* MGLPolyline.h */,
+ 9654C1251FFC1AB900DB6A19 /* MGLPolyline_Private.h */,
DA88480D1CBAFA6200AB86E3 /* MGLPolyline.mm */,
DA8847EB1CBAFA5100AB86E3 /* MGLShape.h */,
40CF6DBA1DAC3C1800A4D18B /* MGLShape_Private.h */,
@@ -1643,10 +1649,6 @@
DAD165831CF4CFED001FF4B9 /* Categories */ = {
isa = PBXGroup;
children = (
- 7E016D821D9E890300A29A21 /* MGLPolygon+MGLAdditions.h */,
- 7E016D831D9E890300A29A21 /* MGLPolygon+MGLAdditions.m */,
- 7E016D7C1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.h */,
- 7E016D7D1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.m */,
400532FF1DB0862B0069F638 /* NSArray+MGLAdditions.h */,
400533001DB0862B0069F638 /* NSArray+MGLAdditions.mm */,
DA8848121CBAFA6200AB86E3 /* NSBundle+MGLAdditions.h */,
@@ -1746,14 +1748,14 @@
35E1A4D81D74336F007AA97F /* MGLValueEvaluator.h in Headers */,
DA88482C1CBAFA6200AB86E3 /* NSBundle+MGLAdditions.h in Headers */,
357FE2DD1E02D2B20068B753 /* NSCoder+MGLAdditions.h in Headers */,
- 7E016D7E1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.h in Headers */,
35D13AB71D3D15E300AFB4E0 /* MGLStyleLayer.h in Headers */,
+ 07D947531F67488E00E37934 /* MGLAbstractShapeSource_Private.h in Headers */,
+ 9654C1261FFC1AB900DB6A19 /* MGLPolyline_Private.h in Headers */,
DA88488E1CBB047F00AB86E3 /* reachability.h in Headers */,
40F887701D7A1E58008ECB67 /* MGLShapeSource_Private.h in Headers */,
350098DC1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.h in Headers */,
DA8848231CBAFA6200AB86E3 /* MGLOfflineStorage_Private.h in Headers */,
404326891D5B9B27007111BD /* MGLAnnotationContainerView_Private.h in Headers */,
- 1FB7DAAF1F2A4DBD00410606 /* MGLVectorSource+MGLAdditions.h in Headers */,
DA88483B1CBAFB8500AB86E3 /* MGLCalloutView.h in Headers */,
35E0CFE61D3E501500188327 /* MGLStyle_Private.h in Headers */,
3510FFF01D6D9D8C00F413B2 /* NSExpression+MGLAdditions.h in Headers */,
@@ -1764,17 +1766,18 @@
DA88485A1CBAFB9800AB86E3 /* MGLUserLocation_Private.h in Headers */,
966FCF531F3C322400F2B6DE /* MGLUserLocationHeadingArrowLayer.h in Headers */,
DA27C24F1CBB4C11000B0ECD /* MGLAccountManager_Private.h in Headers */,
+ 07D947521F67488800E37934 /* MGLAbstractShapeSource.h in Headers */,
DA8847FC1CBAFA5100AB86E3 /* MGLStyle.h in Headers */,
DD9BE4F71EB263C50079A3AF /* UIViewController+MGLAdditions.h in Headers */,
DAF0D8131DFE0EC500B28378 /* MGLVectorSource_Private.h in Headers */,
354B83961D2E873E005D9406 /* MGLUserLocationAnnotationView.h in Headers */,
DA8847F01CBAFA5100AB86E3 /* MGLAnnotation.h in Headers */,
- 7E016D841D9E890300A29A21 /* MGLPolygon+MGLAdditions.h in Headers */,
400533011DB0862B0069F638 /* NSArray+MGLAdditions.h in Headers */,
1F06668A1EC64F8E001C16D7 /* MGLLight.h in Headers */,
4049C29D1DB6CD6C00B3F799 /* MGLPointCollection.h in Headers */,
40CF6DBB1DAC3C6600A4D18B /* MGLShape_Private.h in Headers */,
4018B1CA1CDC288E00F666AF /* MGLAnnotationView.h in Headers */,
+ 9654C1291FFC1CCD00DB6A19 /* MGLPolygon_Private.h in Headers */,
35E79F201D41266300957B9E /* MGLStyleLayer_Private.h in Headers */,
FA68F14A1E9D656600F9F6C2 /* MGLFillExtrusionStyleLayer.h in Headers */,
353933FB1D3FB7C0003F57D7 /* MGLRasterStyleLayer.h in Headers */,
@@ -1787,6 +1790,7 @@
DD0902AB1DB192A800C5BDCE /* MGLNetworkConfiguration.h in Headers */,
DA8848571CBAFB9800AB86E3 /* MGLMapboxEvents.h in Headers */,
35D3A1E61E9BE7EB002B38EE /* MGLScaleBar.h in Headers */,
+ 0778DD431F67556700A73B34 /* MGLComputedShapeSource.h in Headers */,
DA8848311CBAFA6200AB86E3 /* NSString+MGLAdditions.h in Headers */,
353933F81D3FB79F003F57D7 /* MGLLineStyleLayer.h in Headers */,
92F2C3ED1F0E3C3A00268EC0 /* MGLRendererFrontend.h in Headers */,
@@ -1900,7 +1904,6 @@
9620BB391E69FE1700705A1D /* MGLSDKUpdateChecker.h in Headers */,
3510FFEB1D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.h in Headers */,
35E1A4D91D74336F007AA97F /* MGLValueEvaluator.h in Headers */,
- 7E016D7F1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.h in Headers */,
DABFB8701CBE9A0F00D62B32 /* MGLMapView+IBAdditions.h in Headers */,
353AFA151D65AB17005A69F4 /* NSDate+MGLAdditions.h in Headers */,
3510FFFA1D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.h in Headers */,
@@ -1934,7 +1937,6 @@
968F36B51E4D128D003A5522 /* MGLDistanceFormatter.h in Headers */,
4018B1CB1CDC288E00F666AF /* MGLAnnotationView.h in Headers */,
DABFB85F1CBE99E500D62B32 /* MGLGeometry.h in Headers */,
- 7E016D851D9E890300A29A21 /* MGLPolygon+MGLAdditions.h in Headers */,
353933F61D3FB785003F57D7 /* MGLBackgroundStyleLayer.h in Headers */,
DABFB85D1CBE99E500D62B32 /* MGLAccountManager.h in Headers */,
353933F91D3FB79F003F57D7 /* MGLLineStyleLayer.h in Headers */,
@@ -1942,7 +1944,6 @@
35136D4D1D4277FC00C20EFD /* MGLSource.h in Headers */,
DA35A2BC1CCA9A6900E826B2 /* MGLClockDirectionFormatter.h in Headers */,
35D13AC41D3D19DD00AFB4E0 /* MGLFillStyleLayer.h in Headers */,
- 1FB7DAB01F2A4DC200410606 /* MGLVectorSource+MGLAdditions.h in Headers */,
DABFB86E1CBE9A0F00D62B32 /* MGLCalloutView.h in Headers */,
1F7454971ECD450D00021D39 /* MGLLight_Private.h in Headers */,
DABFB8601CBE99E500D62B32 /* MGLMapCamera.h in Headers */,
@@ -2089,7 +2090,7 @@
isa = PBXProject;
attributes = {
CLASSPREFIX = MBX;
- LastUpgradeCheck = 0800;
+ LastUpgradeCheck = 0910;
ORGANIZATIONNAME = Mapbox;
TargetAttributes = {
DA1DC9491CB6C1C2006E619F = {
@@ -2301,6 +2302,7 @@
409D0A0D1ED614CE00C95D0C /* MGLAnnotationViewIntegrationTests.swift in Sources */,
DA2E88621CC0382C00F24E7B /* MGLOfflinePackTests.m in Sources */,
55E2AD131E5B125400E8C587 /* MGLOfflineStorageTests.mm in Sources */,
+ 07D8C6FF1F67562C00381808 /* MGLComputedShapeSourceTests.m in Sources */,
920A3E5D1E6F995200C16EFC /* MGLSourceQueryTests.m in Sources */,
DA5DB12A1FABF1EE001C2326 /* MGLMapAccessibilityElementTests.m in Sources */,
FAE1CDCB1E9D79CB00C40B5B /* MGLFillExtrusionStyleLayerTests.mm in Sources */,
@@ -2320,12 +2322,10 @@
files = (
35136D391D42271A00C20EFD /* MGLBackgroundStyleLayer.mm in Sources */,
3510FFEC1D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.mm in Sources */,
- 7E016D801D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.m in Sources */,
DAED38651D62D0FC00D7640F /* NSURL+MGLAdditions.m in Sources */,
9620BB3A1E69FE1700705A1D /* MGLSDKUpdateChecker.mm in Sources */,
354B83981D2E873E005D9406 /* MGLUserLocationAnnotationView.m in Sources */,
DA88485D1CBAFB9800AB86E3 /* MGLFaux3DUserLocationAnnotationView.m in Sources */,
- 1FB7DAB11F2A4DC800410606 /* MGLVectorSource+MGLAdditions.m in Sources */,
DAD165701CF41981001FF4B9 /* MGLFeature.mm in Sources */,
30E578191DAA855E0050F07E /* UIImage+MGLAdditions.mm in Sources */,
40EDA1C11CFE0E0500D9EA68 /* MGLAnnotationContainerView.m in Sources */,
@@ -2355,6 +2355,7 @@
35136D451D42275100C20EFD /* MGLSymbolStyleLayer.mm in Sources */,
35599DED1D46F14E0048254D /* MGLStyleValue.mm in Sources */,
DA8848211CBAFA6200AB86E3 /* MGLOfflinePack.mm in Sources */,
+ 0778DD441F67556C00A73B34 /* MGLComputedShapeSource.mm in Sources */,
3557F7B21E1D27D300CCA5E6 /* MGLDistanceFormatter.m in Sources */,
DA8848591CBAFB9800AB86E3 /* MGLMapView.mm in Sources */,
DA8848501CBAFB9800AB86E3 /* MGLAnnotationImage.m in Sources */,
@@ -2377,11 +2378,11 @@
DA88482B1CBAFA6200AB86E3 /* MGLTypes.m in Sources */,
FA68F14D1E9D656600F9F6C2 /* MGLFillExtrusionStyleLayer.mm in Sources */,
404C26E41D89B877000AA13D /* MGLTileSource.mm in Sources */,
+ 07D947541F67489200E37934 /* MGLAbstractShapeSource.mm in Sources */,
355AE0011E9281DA00F3939D /* MGLScaleBar.mm in Sources */,
DA88481D1CBAFA6200AB86E3 /* MGLMapCamera.mm in Sources */,
DA8848261CBAFA6200AB86E3 /* MGLPolygon.mm in Sources */,
35B82BFA1D6C5F8400B1B721 /* NSPredicate+MGLAdditions.mm in Sources */,
- 7E016D861D9E890300A29A21 /* MGLPolygon+MGLAdditions.m in Sources */,
DA8848521CBAFB9800AB86E3 /* MGLAPIClient.m in Sources */,
966FCF4E1F3A5C9200F2B6DE /* MGLUserLocationHeadingBeamLayer.m in Sources */,
DA8848301CBAFA6200AB86E3 /* NSProcessInfo+MGLAdditions.m in Sources */,
@@ -2409,12 +2410,10 @@
files = (
35136D3A1D42271A00C20EFD /* MGLBackgroundStyleLayer.mm in Sources */,
3510FFED1D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.mm in Sources */,
- 7E016D811D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.m in Sources */,
354B83991D2E873E005D9406 /* MGLUserLocationAnnotationView.m in Sources */,
9620BB3B1E69FE1700705A1D /* MGLSDKUpdateChecker.mm in Sources */,
DAA4E4221CBB730400178DFB /* MGLPointAnnotation.mm in Sources */,
DAED38661D62D0FC00D7640F /* NSURL+MGLAdditions.m in Sources */,
- 1FB7DAB21F2A4DC900410606 /* MGLVectorSource+MGLAdditions.m in Sources */,
DAD165711CF41981001FF4B9 /* MGLFeature.mm in Sources */,
30E5781A1DAA855E0050F07E /* UIImage+MGLAdditions.mm in Sources */,
40EDA1C21CFE0E0500D9EA68 /* MGLAnnotationContainerView.m in Sources */,
@@ -2468,9 +2467,9 @@
404C26E51D89B877000AA13D /* MGLTileSource.mm in Sources */,
355AE0021E9281DA00F3939D /* MGLScaleBar.mm in Sources */,
4018B1C81CDC287F00F666AF /* MGLAnnotationView.mm in Sources */,
+ 07D8C6FB1F67560100381808 /* MGLComputedShapeSource.mm in Sources */,
DAA4E4341CBB730400178DFB /* MGLFaux3DUserLocationAnnotationView.m in Sources */,
35B82BFB1D6C5F8400B1B721 /* NSPredicate+MGLAdditions.mm in Sources */,
- 7E016D871D9E890300A29A21 /* MGLPolygon+MGLAdditions.m in Sources */,
DAA4E4311CBB730400178DFB /* MGLMapboxEvents.m in Sources */,
966FCF4F1F3A5C9200F2B6DE /* MGLUserLocationHeadingBeamLayer.m in Sources */,
DAA4E4231CBB730400178DFB /* MGLPolygon.mm in Sources */,
@@ -2479,6 +2478,7 @@
DAA4E42A1CBB730400178DFB /* NSProcessInfo+MGLAdditions.m in Sources */,
DAA4E4211CBB730400178DFB /* MGLOfflineStorage.mm in Sources */,
4049C2A01DB6CD6C00B3F799 /* MGLPointCollection.mm in Sources */,
+ 07D8C6FC1F67560400381808 /* MGLAbstractShapeSource.mm in Sources */,
35136D401D42273000C20EFD /* MGLLineStyleLayer.mm in Sources */,
DA704CC51F65A475004B3F28 /* MGLMapAccessibilityElement.mm in Sources */,
DA72620E1DEEE3480043BB89 /* MGLOpenGLStyleLayer.mm in Sources */,
@@ -2698,7 +2698,9 @@
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
@@ -2706,7 +2708,11 @@
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
@@ -2751,7 +2757,9 @@
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
@@ -2759,7 +2767,11 @@
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
@@ -2782,6 +2794,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
+ SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SYMROOT = ../../build/ios;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
@@ -2845,6 +2858,7 @@
INFOPLIST_FILE = test/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ OTHER_CFLAGS = "-fvisibility=hidden";
OTHER_CPLUSPLUSFLAGS = (
"$(OTHER_CFLAGS)",
"$(variant_cflags)",
@@ -2869,6 +2883,7 @@
INFOPLIST_FILE = test/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ OTHER_CFLAGS = "-fvisibility=hidden";
OTHER_CPLUSPLUSFLAGS = (
"$(OTHER_CFLAGS)",
"$(variant_cflags)",
@@ -2888,6 +2903,7 @@
baseConfigurationReference = 55D8C9941D0F133500F42F10 /* config.xcconfig */;
buildSettings = {
BITCODE_GENERATION_MODE = bitcode;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -2929,6 +2945,7 @@
baseConfigurationReference = 55D8C9941D0F133500F42F10 /* config.xcconfig */;
buildSettings = {
BITCODE_GENERATION_MODE = bitcode;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
diff --git a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/CI.xcscheme b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/CI.xcscheme
index 40249b8024..4679378126 100644
--- a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/CI.xcscheme
+++ b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/CI.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "0820"
+ LastUpgradeVersion = "0910"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -54,6 +54,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
@@ -83,6 +84,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
diff --git a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/bench.xcscheme b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/bench.xcscheme
index f5aff5b3b4..d1a152bce7 100644
--- a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/bench.xcscheme
+++ b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/bench.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "0820"
+ LastUpgradeVersion = "0910"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -26,6 +26,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
@@ -45,6 +46,7 @@
buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
diff --git a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/dynamic+static.xcscheme b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/dynamic+static.xcscheme
index 8e1c176bba..e5f17124f2 100644
--- a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/dynamic+static.xcscheme
+++ b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/dynamic+static.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "0820"
+ LastUpgradeVersion = "0910"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -54,6 +54,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
@@ -83,6 +84,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
diff --git a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/dynamic.xcscheme b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/dynamic.xcscheme
index 7dfffccef5..3816aa5c91 100644
--- a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/dynamic.xcscheme
+++ b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/dynamic.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "0820"
+ LastUpgradeVersion = "0910"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -40,6 +40,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
@@ -69,6 +70,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
diff --git a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/iosapp.xcscheme b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/iosapp.xcscheme
index 035c7818ae..7d5f2cd6d2 100644
--- a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/iosapp.xcscheme
+++ b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/iosapp.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "0820"
+ LastUpgradeVersion = "0910"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -26,6 +26,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
@@ -45,6 +46,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
diff --git a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/static.xcscheme b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/static.xcscheme
index 156651a4a6..fc385d3763 100644
--- a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/static.xcscheme
+++ b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/static.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "0820"
+ LastUpgradeVersion = "0910"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -26,6 +26,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
@@ -45,6 +46,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
diff --git a/platform/ios/jazzy.yml b/platform/ios/jazzy.yml
index 2a7a2b667c..f7e1049c9c 100644
--- a/platform/ios/jazzy.yml
+++ b/platform/ios/jazzy.yml
@@ -3,7 +3,7 @@ author: Mapbox
author_url: https://www.mapbox.com/
github_url: https://github.com/mapbox/mapbox-gl-native
dash_url: https://www.mapbox.com/ios-sdk/docsets/Mapbox.xml
-copyright: '© 2014–2017 [Mapbox](https://www.mapbox.com/). See [license](https://github.com/mapbox/mapbox-gl-native/blob/master/LICENSE.md) for more details.'
+copyright: '© 2014–2018 [Mapbox](https://www.mapbox.com/). See [license](https://github.com/mapbox/mapbox-gl-native/blob/master/LICENSE.md) for more details.'
head: |
<link rel='shortcut icon' href='https://www.mapbox.com/img/favicon.ico' type='image/x-icon' />
@@ -79,7 +79,9 @@ custom_categories:
- MGLSource
- MGLTileSource
- MGLImageSource
+ - MGLAbstractShapeSource
- MGLShapeSource
+ - MGLComputedShapeSource
- MGLRasterSource
- MGLVectorSource
- name: Style Layers
diff --git a/platform/ios/src/MGLMapAccessibilityElement.mm b/platform/ios/src/MGLMapAccessibilityElement.mm
index 4e5f165fbf..1a2953b0bb 100644
--- a/platform/ios/src/MGLMapAccessibilityElement.mm
+++ b/platform/ios/src/MGLMapAccessibilityElement.mm
@@ -2,10 +2,11 @@
#import "MGLDistanceFormatter.h"
#import "MGLCompassDirectionFormatter.h"
#import "MGLFeature.h"
-#import "MGLVectorSource+MGLAdditions.h"
-#import "NSBundle+MGLAdditions.h"
#import "MGLGeometry_Private.h"
+#import "MGLVectorSource_Private.h"
+
+#import "NSBundle+MGLAdditions.h"
@implementation MGLMapAccessibilityElement
diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm
index c02446609a..33bbefc9db 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -18,6 +18,7 @@
#include <mbgl/style/image.hpp>
#include <mbgl/style/transition_options.hpp>
#include <mbgl/style/layers/custom_layer.hpp>
+#include <mbgl/renderer/mode.hpp>
#include <mbgl/renderer/renderer.hpp>
#include <mbgl/renderer/renderer_backend.hpp>
#include <mbgl/renderer/backend_scope.hpp>
@@ -40,11 +41,11 @@
#import "MGLGeometry_Private.h"
#import "MGLMultiPoint_Private.h"
#import "MGLOfflineStorage_Private.h"
+#import "MGLVectorSource_Private.h"
#import "MGLFoundation_Private.h"
#import "MGLRendererFrontend.h"
#import "MGLRendererConfiguration.h"
-#import "MGLVectorSource+MGLAdditions.h"
#import "NSBundle+MGLAdditions.h"
#import "NSDate+MGLAdditions.h"
#import "NSException+MGLAdditions.h"
@@ -460,6 +461,9 @@ public:
_attributionButtonConstraints = [NSMutableArray array];
[_attributionButton addObserver:self forKeyPath:@"hidden" options:NSKeyValueObservingOptionNew context:NULL];
+ UILongPressGestureRecognizer *attributionLongPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(showAttribution:)];
+ [_attributionButton addGestureRecognizer:attributionLongPress];
+
// setup compass
//
_compassView = [[UIImageView alloc] initWithImage:self.compassImage];
@@ -1982,13 +1986,28 @@ public:
#pragma mark - Attribution -
-- (void)showAttribution:(__unused id)sender
+- (void)showAttribution:(id)sender
{
+ BOOL shouldShowVersion = [sender isKindOfClass:[UILongPressGestureRecognizer class]];
+ if (shouldShowVersion)
+ {
+ UILongPressGestureRecognizer *longPress = (UILongPressGestureRecognizer *)sender;
+ if (longPress.state != UIGestureRecognizerStateBegan)
+ {
+ return;
+ }
+ }
+
NSString *title = NSLocalizedStringWithDefaultValue(@"SDK_NAME", nil, nil, @"Mapbox Maps SDK for iOS", @"Action sheet title");
UIAlertController *attributionController = [UIAlertController alertControllerWithTitle:title
message:nil
preferredStyle:UIAlertControllerStyleActionSheet];
-
+
+ if (shouldShowVersion)
+ {
+ attributionController.title = [title stringByAppendingFormat:@" %@", [NSBundle mgl_frameworkInfoDictionary][@"MGLSemanticVersionString"]];
+ }
+
NSArray *attributionInfos = [self.style attributionInfosWithFontSize:[UIFont buttonFontSize]
linkColor:nil];
for (MGLAttributionInfo *info in attributionInfos)
@@ -6041,7 +6060,7 @@ public:
[nativeView didFinishLoadingStyle];
}
- mbgl::gl::ProcAddress initializeExtension(const char* name) override {
+ mbgl::gl::ProcAddress getExtensionFunctionPointer(const char* name) override {
static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengles"));
if (!framework) {
throw std::runtime_error("Failed to load OpenGL framework.");
diff --git a/platform/ios/src/Mapbox.h b/platform/ios/src/Mapbox.h
index 9b2c472cf6..ce9c4965d7 100644
--- a/platform/ios/src/Mapbox.h
+++ b/platform/ios/src/Mapbox.h
@@ -51,6 +51,8 @@ FOUNDATION_EXPORT MGL_EXPORT const unsigned char MapboxVersionString[];
#import "MGLTileSource.h"
#import "MGLVectorSource.h"
#import "MGLShapeSource.h"
+#import "MGLAbstractShapeSource.h"
+#import "MGLComputedShapeSource.h"
#import "MGLRasterSource.h"
#import "MGLImageSource.h"
#import "MGLTilePyramidOfflineRegion.h"
diff --git a/platform/ios/src/UIImage+MGLAdditions.mm b/platform/ios/src/UIImage+MGLAdditions.mm
index 8ab1d5c259..884f92e003 100644
--- a/platform/ios/src/UIImage+MGLAdditions.mm
+++ b/platform/ios/src/UIImage+MGLAdditions.mm
@@ -6,7 +6,7 @@
- (nullable instancetype)initWithMGLStyleImage:(const mbgl::style::Image *)styleImage
{
- CGImageRef image = CGImageFromMGLPremultipliedImage(styleImage->getImage().clone());
+ CGImageRef image = CGImageCreateWithMGLPremultipliedImage(styleImage->getImage().clone());
if (!image) {
return nil;
}
@@ -24,7 +24,7 @@
- (nullable instancetype)initWithMGLPremultipliedImage:(const mbgl::PremultipliedImage&&)mbglImage scale:(CGFloat)scale
{
- CGImageRef image = CGImageFromMGLPremultipliedImage(mbglImage.clone());
+ CGImageRef image = CGImageCreateWithMGLPremultipliedImage(mbglImage.clone());
if (!image) {
return nil;
}
diff --git a/platform/ios/uitest/LaunchScreen.xib b/platform/ios/uitest/LaunchScreen.xib
index c0a15ddb13..dd23975342 100644
--- a/platform/ios/uitest/LaunchScreen.xib
+++ b/platform/ios/uitest/LaunchScreen.xib
@@ -12,7 +12,7 @@
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
- <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="© 2015–2017 Mapbox. All rights reserved." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
+ <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="© 2015–2018 Mapbox. All rights reserved." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
<rect key="frame" x="20" y="439" width="441" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
diff --git a/platform/ios/uitest/ios-tests.xcodeproj/xcshareddata/xcschemes/Mapbox GL Tests.xcscheme b/platform/ios/uitest/ios-tests.xcodeproj/xcshareddata/xcschemes/Mapbox GL Tests.xcscheme
index e941b6daf9..b1a1db6ba1 100644
--- a/platform/ios/uitest/ios-tests.xcodeproj/xcshareddata/xcschemes/Mapbox GL Tests.xcscheme
+++ b/platform/ios/uitest/ios-tests.xcodeproj/xcshareddata/xcschemes/Mapbox GL Tests.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "0820"
+ LastUpgradeVersion = "0910"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
@@ -40,6 +40,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
@@ -90,6 +91,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
diff --git a/platform/linux/config.cmake b/platform/linux/config.cmake
index fddcf90278..dd5f0af112 100644
--- a/platform/linux/config.cmake
+++ b/platform/linux/config.cmake
@@ -1,6 +1,5 @@
mason_use(glfw VERSION 2017-07-13-67c9155)
mason_use(mesa VERSION 13.0.4)
-mason_use(boost_libprogram_options VERSION 1.62.0${MASON_CXXABI_SUFFIX})
mason_use(sqlite VERSION 3.14.2)
mason_use(libuv VERSION 1.9.1)
mason_use(nunicode VERSION 1.7.1)
@@ -10,6 +9,7 @@ mason_use(webp VERSION 0.5.1)
mason_use(gtest VERSION 1.8.0${MASON_CXXABI_SUFFIX})
mason_use(benchmark VERSION 1.2.0)
mason_use(icu VERSION 58.1-min-size)
+mason_use(args VERSION 6.2.0 HEADER_ONLY)
include(cmake/loop-uv.cmake)
@@ -19,7 +19,6 @@ macro(mbgl_platform_core)
if(WITH_OSMESA)
target_sources(mbgl-core
PRIVATE platform/default/headless_backend_osmesa.cpp
- PRIVATE platform/default/mbgl/gl/headless_display.cpp
)
target_link_libraries(mbgl-core
PUBLIC -lOSMesa
@@ -27,17 +26,14 @@ macro(mbgl_platform_core)
elseif(WITH_EGL)
target_sources(mbgl-core
PRIVATE platform/linux/src/headless_backend_egl.cpp
- PRIVATE platform/linux/src/headless_display_egl.cpp
)
target_link_libraries(mbgl-core
PUBLIC -lGLESv2
PUBLIC -lEGL
- PUBLIC -lgbm
)
else()
target_sources(mbgl-core
PRIVATE platform/linux/src/headless_backend_glx.cpp
- PRIVATE platform/linux/src/headless_display_glx.cpp
)
target_link_libraries(mbgl-core
PUBLIC -lGL
@@ -67,7 +63,6 @@ macro(mbgl_platform_core)
PRIVATE platform/default/mbgl/gl/headless_frontend.hpp
PRIVATE platform/default/mbgl/gl/headless_backend.cpp
PRIVATE platform/default/mbgl/gl/headless_backend.hpp
- PRIVATE platform/default/mbgl/gl/headless_display.hpp
# Thread pool
PRIVATE platform/default/mbgl/util/default_thread_pool.cpp
@@ -77,6 +72,7 @@ macro(mbgl_platform_core)
target_include_directories(mbgl-core
PRIVATE platform/default
+ PRIVATE platform/linux
)
target_add_mason_package(mbgl-core PUBLIC nunicode)
@@ -119,7 +115,7 @@ macro(mbgl_platform_glfw)
add_custom_command(
TARGET mbgl-glfw POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
- ${CMAKE_SOURCE_DIR}/common/ca-bundle.crt
+ ${CMAKE_SOURCE_DIR}/misc/ca-bundle.crt
${CMAKE_CURRENT_BINARY_DIR}/ca-bundle.crt
)
endmacro()
@@ -150,6 +146,10 @@ macro(mbgl_platform_test)
PRIVATE platform/default/mbgl/test/main.cpp
)
+ target_include_directories(mbgl-test
+ PRIVATE platform/linux
+ )
+
set_source_files_properties(
platform/default/mbgl/test/main.cpp
PROPERTIES
diff --git a/platform/linux/mbgl/gl/gl_impl.hpp b/platform/linux/mbgl/gl/gl_impl.hpp
new file mode 100644
index 0000000000..ae829f3f7e
--- /dev/null
+++ b/platform/linux/mbgl/gl/gl_impl.hpp
@@ -0,0 +1,11 @@
+#pragma once
+
+#if MBGL_USE_GLES2
+ #define GL_GLEXT_PROTOTYPES
+ #include <GLES2/gl2.h>
+ #include <GLES2/gl2ext.h>
+#else
+ #define GL_GLEXT_PROTOTYPES
+ #include <GL/gl.h>
+ #include <GL/glext.h>
+#endif
diff --git a/platform/linux/src/headless_backend_egl.cpp b/platform/linux/src/headless_backend_egl.cpp
index 0784173af7..089e344987 100644
--- a/platform/linux/src/headless_backend_egl.cpp
+++ b/platform/linux/src/headless_backend_egl.cpp
@@ -1,5 +1,4 @@
#include <mbgl/gl/headless_backend.hpp>
-#include <mbgl/gl/headless_display.hpp>
#include <mbgl/util/logging.hpp>
@@ -9,11 +8,83 @@
namespace mbgl {
-struct EGLImpl : public HeadlessBackend::Impl {
- EGLImpl(EGLContext glContext_, EGLDisplay display_, EGLConfig config_)
- : glContext(glContext_),
- display(display_),
- config(config_) {
+// This class provides a singleton that contains information about the configuration used for
+// instantiating new headless rendering contexts.
+class EGLDisplayConfig {
+private:
+ // Key for singleton construction.
+ struct Key { explicit Key() = default; };
+
+public:
+ EGLDisplayConfig(Key) {
+ display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (display == EGL_NO_DISPLAY) {
+ throw std::runtime_error("Failed to obtain a valid EGL display.\n");
+ }
+
+ EGLint major, minor, numConfigs;
+ if (!eglInitialize(display, &major, &minor)) {
+ throw std::runtime_error("eglInitialize() failed.\n");
+ }
+
+ if (!eglBindAPI(EGL_OPENGL_ES_API)) {
+ mbgl::Log::Error(mbgl::Event::OpenGL, "eglBindAPI(EGL_OPENGL_ES_API) returned error %d",
+ eglGetError());
+ throw std::runtime_error("eglBindAPI() failed");
+ }
+
+ const EGLint attribs[] = {
+#if MBGL_USE_GLES2
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+#endif
+ EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
+ EGL_NONE
+ };
+
+ // Note: we're choosing an arbitrary pixel format, since we're not using the default surface
+ // anyway; all rendering will be directed to framebuffers which have their own configuration.
+ if (!eglChooseConfig(display, attribs, &config, 1, &numConfigs) || numConfigs != 1) {
+ throw std::runtime_error("Failed to choose ARGB config.\n");
+ }
+ }
+
+ ~EGLDisplayConfig() {
+ eglTerminate(display);
+ }
+
+ static std::shared_ptr<const EGLDisplayConfig> create() {
+ static std::weak_ptr<const EGLDisplayConfig> instance;
+ auto shared = instance.lock();
+ if (!shared) {
+ instance = shared = std::make_shared<EGLDisplayConfig>(Key{});
+ }
+ return shared;
+ }
+
+public:
+ EGLDisplay display = EGL_NO_DISPLAY;
+ EGLConfig config = 0;
+};
+
+class EGLBackendImpl : public HeadlessBackend::Impl {
+public:
+ EGLBackendImpl() {
+ // EGL initializes the context client version to 1 by default. We want to
+ // use OpenGL ES 2.0 which has the ability to create shader and program
+ // objects and also to write vertex and fragment shaders in the OpenGL ES
+ // Shading Language.
+ const EGLint attribs[] = {
+ EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_NONE
+ };
+
+ eglContext = eglCreateContext(eglDisplay->display, eglDisplay->config, EGL_NO_CONTEXT, attribs);
+ if (eglContext == EGL_NO_CONTEXT) {
+ mbgl::Log::Error(mbgl::Event::OpenGL, "eglCreateContext() returned error 0x%04x",
+ eglGetError());
+ throw std::runtime_error("Error creating the EGL context object.\n");
+ }
+
// Create a dummy pbuffer. We will render to framebuffers anyway, but we need a pbuffer to
// activate the context.
// Note that to be able to create pbuffer surfaces, we need to choose a config that
@@ -25,77 +96,49 @@ struct EGLImpl : public HeadlessBackend::Impl {
EGL_NONE
};
- glSurface = eglCreatePbufferSurface(display, config, surfAttribs);
- if (glSurface == EGL_NO_SURFACE) {
+ eglSurface = eglCreatePbufferSurface(eglDisplay->display, eglDisplay->config, surfAttribs);
+ if (eglSurface == EGL_NO_SURFACE) {
throw std::runtime_error("Could not create surface: " + std::to_string(eglGetError()));
}
}
- ~EGLImpl() {
- if (glSurface != EGL_NO_SURFACE) {
- if (!eglDestroySurface(display, glSurface)) {
- throw std::runtime_error("Failed to destroy EGL surface.\n");
+ ~EGLBackendImpl() final {
+ if (eglSurface != EGL_NO_SURFACE) {
+ if (!eglDestroySurface(eglDisplay->display, eglSurface)) {
+ Log::Error(Event::OpenGL, "Failed to destroy EGL surface.");
}
- glSurface = EGL_NO_SURFACE;
+ eglSurface = EGL_NO_SURFACE;
}
- if (!eglDestroyContext(display, glContext)) {
- throw std::runtime_error("Failed to destroy EGL context.\n");
+ if (!eglDestroyContext(eglDisplay->display, eglContext)) {
+ Log::Error(Event::OpenGL, "Failed to destroy EGL context.");
}
}
+ gl::ProcAddress getExtensionFunctionPointer(const char* name) final {
+ return eglGetProcAddress(name);
+ }
+
void activateContext() final {
- if (!eglMakeCurrent(display, glSurface, glSurface, glContext)) {
+ if (!eglMakeCurrent(eglDisplay->display, eglSurface, eglSurface, eglContext)) {
throw std::runtime_error("Switching OpenGL context failed.\n");
}
}
void deactivateContext() final {
- if (!eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) {
+ if (!eglMakeCurrent(eglDisplay->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) {
throw std::runtime_error("Removing OpenGL context failed.\n");
}
}
- EGLContext glContext = EGL_NO_CONTEXT;
- EGLDisplay display = EGL_NO_DISPLAY;
- EGLConfig config = 0;
- EGLSurface glSurface = EGL_NO_SURFACE;
+private:
+ const std::shared_ptr<const EGLDisplayConfig> eglDisplay = EGLDisplayConfig::create();
+ EGLContext eglContext = EGL_NO_CONTEXT;
+ EGLSurface eglSurface = EGL_NO_SURFACE;
};
-gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) {
- return eglGetProcAddress(name);
-}
-
-bool HeadlessBackend::hasDisplay() {
- if (!display) {
- display = HeadlessDisplay::create();
- }
- return bool(display);
-};
-
-void HeadlessBackend::createContext() {
- assert(!hasContext());
- assert(hasDisplay());
-
- EGLDisplay display_ = display->attribute<EGLDisplay>();
- EGLConfig& config = display->attribute<EGLConfig&>();
-
- // EGL initializes the context client version to 1 by default. We want to
- // use OpenGL ES 2.0 which has the ability to create shader and program
- // objects and also to write vertex and fragment shaders in the OpenGL ES
- // Shading Language.
- const EGLint attribs[] = {
- EGL_CONTEXT_CLIENT_VERSION, 2,
- EGL_NONE
- };
-
- EGLContext glContext = eglCreateContext(display_, config, EGL_NO_CONTEXT, attribs);
- if (glContext == EGL_NO_CONTEXT) {
- mbgl::Log::Error(mbgl::Event::OpenGL, "eglCreateContext() returned error 0x%04x",
- eglGetError());
- throw std::runtime_error("Error creating the EGL context object.\n");
- }
-
- impl.reset(new EGLImpl(glContext, display_, config));
+void HeadlessBackend::createImpl() {
+ assert(!impl);
+ impl = std::make_unique<EGLBackendImpl>();
}
} // namespace mbgl
diff --git a/platform/linux/src/headless_backend_glx.cpp b/platform/linux/src/headless_backend_glx.cpp
index 0ba7f08630..27af98e70a 100644
--- a/platform/linux/src/headless_backend_glx.cpp
+++ b/platform/linux/src/headless_backend_glx.cpp
@@ -1,5 +1,4 @@
#include <mbgl/gl/headless_backend.hpp>
-#include <mbgl/gl/headless_display.hpp>
#include <mbgl/util/logging.hpp>
@@ -9,79 +8,123 @@
namespace mbgl {
-struct GLXImpl : public HeadlessBackend::Impl {
- GLXImpl(GLXContext glContext_, GLXPbuffer glxPbuffer_, Display* xDisplay_, GLXFBConfig* fbConfigs_)
- : glContext(glContext_),
- glxPbuffer(glxPbuffer_),
- xDisplay(xDisplay_),
- fbConfigs(fbConfigs_) {
- }
+// This class provides a singleton that contains information about the configuration used for
+// instantiating new headless rendering contexts.
+class GLXDisplayConfig {
+private:
+ // Key for singleton construction.
+ struct Key { explicit Key() = default; };
+
+public:
+ GLXDisplayConfig(Key) {
+ if (!XInitThreads()) {
+ throw std::runtime_error("Failed to XInitThreads.");
+ }
- ~GLXImpl() override {
- if (glxPbuffer) {
- glXDestroyPbuffer(xDisplay, glxPbuffer);
+ xDisplay = XOpenDisplay(nullptr);
+ if (xDisplay == nullptr) {
+ throw std::runtime_error("Failed to open X display.");
}
- glXDestroyContext(xDisplay, glContext);
- }
- void activateContext() final {
- if (!glXMakeContextCurrent(xDisplay, glxPbuffer, glxPbuffer, glContext)) {
- throw std::runtime_error("Switching OpenGL context failed.\n");
+ const auto* extensions = reinterpret_cast<const char*>(
+ glXQueryServerString(xDisplay, DefaultScreen(xDisplay), GLX_EXTENSIONS));
+ if (!extensions) {
+ throw std::runtime_error("Cannot read GLX extensions.");
+ }
+ if (!strstr(extensions, "GLX_SGIX_fbconfig")) {
+ throw std::runtime_error("Extension GLX_SGIX_fbconfig was not found.");
+ }
+ if (!strstr(extensions, "GLX_SGIX_pbuffer")) {
+ throw std::runtime_error("Cannot find glXCreateContextAttribsARB.");
}
- }
- void deactivateContext() final {
- if (!glXMakeContextCurrent(xDisplay, 0, 0, nullptr)) {
- throw std::runtime_error("Removing OpenGL context failed.\n");
+ // We're creating a dummy pbuffer anyway that we're not using.
+ static int pixelFormat[] = { GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT, None };
+
+ int configs = 0;
+ fbConfigs = glXChooseFBConfig(xDisplay, DefaultScreen(xDisplay), pixelFormat, &configs);
+ if (fbConfigs == nullptr) {
+ throw std::runtime_error("Failed to glXChooseFBConfig.");
+ }
+ if (configs <= 0) {
+ throw std::runtime_error("No Framebuffer configurations.");
}
}
- GLXContext glContext = nullptr;
- GLXPbuffer glxPbuffer = 0;
+ ~GLXDisplayConfig() {
+ XFree(fbConfigs);
+ XCloseDisplay(xDisplay);
+ }
+
+ static std::shared_ptr<const GLXDisplayConfig> create() {
+ static std::weak_ptr<const GLXDisplayConfig> instance;
+ auto shared = instance.lock();
+ if (!shared) {
+ instance = shared = std::make_shared<GLXDisplayConfig>(Key{});
+ }
+ return shared;
+ }
- // Needed for ImplDeleter.
+public:
Display* xDisplay = nullptr;
GLXFBConfig* fbConfigs = nullptr;
};
-gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) {
- return glXGetProcAddress(reinterpret_cast<const GLubyte*>(name));
-}
+class GLXBackendImpl : public HeadlessBackend::Impl {
+public:
+ GLXBackendImpl() {
+ // Try to create a legacy context.
+ glContext = glXCreateNewContext(glxDisplay->xDisplay, glxDisplay->fbConfigs[0],
+ GLX_RGBA_TYPE, None, True);
+ if (glContext && !glXIsDirect(glxDisplay->xDisplay, glContext)) {
+ Log::Error(Event::OpenGL, "failed to create direct OpenGL Legacy context");
+ glXDestroyContext(glxDisplay->xDisplay, glContext);
+ glContext = nullptr;
+ }
+ if (glContext == nullptr) {
+ throw std::runtime_error("Error creating GL context object.");
+ }
-bool HeadlessBackend::hasDisplay() {
- if (!display) {
- display = HeadlessDisplay::create();
+ // Create a dummy pbuffer. We will render to framebuffers anyway, but we need a pbuffer to
+ // activate the context.
+ int pbufferAttributes[] = { GLX_PBUFFER_WIDTH, 8, GLX_PBUFFER_HEIGHT, 8, None };
+ glxPbuffer =
+ glXCreatePbuffer(glxDisplay->xDisplay, glxDisplay->fbConfigs[0], pbufferAttributes);
}
- return bool(display);
-};
-void HeadlessBackend::createContext() {
- assert(!hasContext());
+ ~GLXBackendImpl() final {
+ if (glxPbuffer) {
+ glXDestroyPbuffer(glxDisplay->xDisplay, glxPbuffer);
+ }
+ glXDestroyContext(glxDisplay->xDisplay, glContext);
+ }
- auto* xDisplay = display->attribute<Display*>();
- auto* fbConfigs = display->attribute<GLXFBConfig*>();
+ gl::ProcAddress getExtensionFunctionPointer(const char* name) final {
+ return glXGetProcAddress(reinterpret_cast<const GLubyte*>(name));
+ }
- // Try to create a legacy context.
- GLXContext glContext = glXCreateNewContext(xDisplay, fbConfigs[0], GLX_RGBA_TYPE, None, True);
- if (glContext && !glXIsDirect(xDisplay, glContext)) {
- Log::Error(Event::OpenGL, "failed to create direct OpenGL Legacy context");
- glXDestroyContext(xDisplay, glContext);
- glContext = nullptr;
+ void activateContext() final {
+ if (!glXMakeContextCurrent(glxDisplay->xDisplay, glxPbuffer, glxPbuffer, glContext)) {
+ throw std::runtime_error("Switching OpenGL context failed.\n");
+ }
}
- if (glContext == nullptr) {
- throw std::runtime_error("Error creating GL context object.");
+
+ void deactivateContext() final {
+ if (!glXMakeContextCurrent(glxDisplay->xDisplay, 0, 0, nullptr)) {
+ throw std::runtime_error("Removing OpenGL context failed.\n");
+ }
}
- // Create a dummy pbuffer. We will render to framebuffers anyway, but we need a pbuffer to
- // activate the context.
- int pbufferAttributes[] = {
- GLX_PBUFFER_WIDTH, 8,
- GLX_PBUFFER_HEIGHT, 8,
- None
- };
- GLXPbuffer glxPbuffer = glXCreatePbuffer(xDisplay, fbConfigs[0], pbufferAttributes);
+private:
+ const std::shared_ptr<const GLXDisplayConfig> glxDisplay = GLXDisplayConfig::create();
+
+ GLXContext glContext = nullptr;
+ GLXPbuffer glxPbuffer = 0;
+};
- impl = std::make_unique<mbgl::GLXImpl>(glContext, glxPbuffer, xDisplay, fbConfigs);
+void HeadlessBackend::createImpl() {
+ assert(!impl);
+ impl = std::make_unique<GLXBackendImpl>();
}
} // namespace mbgl
diff --git a/platform/linux/src/headless_display_egl.cpp b/platform/linux/src/headless_display_egl.cpp
deleted file mode 100644
index b746211924..0000000000
--- a/platform/linux/src/headless_display_egl.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-#include <mbgl/gl/headless_display.hpp>
-#include <mbgl/util/logging.hpp>
-#include <mbgl/util/string.hpp>
-
-#include <EGL/egl.h>
-
-namespace mbgl {
-
-class HeadlessDisplay::Impl {
-public:
- Impl();
- ~Impl();
-
- EGLDisplay display = EGL_NO_DISPLAY;
- EGLConfig config = 0;
-};
-
-HeadlessDisplay::Impl::Impl() {
- display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- if (display == EGL_NO_DISPLAY) {
- throw std::runtime_error("Failed to obtain a valid EGL display.\n");
- }
-
- EGLint major, minor, numConfigs;
- if (!eglInitialize(display, &major, &minor)) {
- throw std::runtime_error("eglInitialize() failed.\n");
- }
-
- if (!eglBindAPI(EGL_OPENGL_ES_API)) {
- mbgl::Log::Error(mbgl::Event::OpenGL, "eglBindAPI(EGL_OPENGL_ES_API) returned error %d", eglGetError());
- throw std::runtime_error("eglBindAPI() failed");
- }
-
- const EGLint attribs[] = {
-#if MBGL_USE_GLES2
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
-#endif
- EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
- EGL_NONE
- };
-
- if (!eglChooseConfig(display, attribs, &config, 1, &numConfigs) || numConfigs != 1) {
- throw std::runtime_error("Failed to choose ARGB config.\n");
- }
-}
-
-HeadlessDisplay::Impl::~Impl() {
- eglTerminate(display);
-}
-
-template <>
-EGLDisplay HeadlessDisplay::attribute() const {
- return impl->display;
-}
-
-template <>
-EGLConfig& HeadlessDisplay::attribute() const {
- return impl->config;
-}
-
-HeadlessDisplay::HeadlessDisplay()
- : impl(std::make_unique<Impl>()) {
-}
-
-HeadlessDisplay::~HeadlessDisplay() {
-}
-
-} // namespace mbgl
diff --git a/platform/linux/src/headless_display_glx.cpp b/platform/linux/src/headless_display_glx.cpp
deleted file mode 100644
index 5dc342154d..0000000000
--- a/platform/linux/src/headless_display_glx.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-#include <mbgl/gl/headless_display.hpp>
-
-#include <GL/glx.h>
-
-#include <cstring>
-#include <stdexcept>
-#include <string>
-
-namespace mbgl {
-
-class HeadlessDisplay::Impl {
-public:
- Impl();
- ~Impl();
-
- Display* xDisplay = nullptr;
- GLXFBConfig* fbConfigs = nullptr;
-};
-
-HeadlessDisplay::Impl::Impl() {
- if (!XInitThreads()) {
- throw std::runtime_error("Failed to XInitThreads.");
- }
-
- xDisplay = XOpenDisplay(nullptr);
- if (xDisplay == nullptr) {
- throw std::runtime_error("Failed to open X display.");
- }
-
- const auto *extensions = reinterpret_cast<const char *>(glXQueryServerString(xDisplay, DefaultScreen(xDisplay), GLX_EXTENSIONS));
- if (!extensions) {
- throw std::runtime_error("Cannot read GLX extensions.");
- }
- if (!strstr(extensions,"GLX_SGIX_fbconfig")) {
- throw std::runtime_error("Extension GLX_SGIX_fbconfig was not found.");
- }
- if (!strstr(extensions, "GLX_SGIX_pbuffer")) {
- throw std::runtime_error("Cannot find glXCreateContextAttribsARB.");
- }
-
- // We're creating a dummy pbuffer anyway that we're not using.
- static int pixelFormat[] = {
- GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
- None
- };
-
- int configs = 0;
- fbConfigs = glXChooseFBConfig(xDisplay, DefaultScreen(xDisplay), pixelFormat, &configs);
- if (fbConfigs == nullptr) {
- throw std::runtime_error("Failed to glXChooseFBConfig.");
- }
- if (configs <= 0) {
- throw std::runtime_error("No Framebuffer configurations.");
- }
-}
-
-HeadlessDisplay::Impl::~Impl() {
- XFree(fbConfigs);
- XCloseDisplay(xDisplay);
-}
-
-template <>
-Display* HeadlessDisplay::attribute() const {
- return impl->xDisplay;
-}
-
-template <>
-GLXFBConfig* HeadlessDisplay::attribute() const {
- return impl->fbConfigs;
-}
-
-HeadlessDisplay::HeadlessDisplay()
- : impl(std::make_unique<Impl>()) {
-}
-
-HeadlessDisplay::~HeadlessDisplay() = default;
-
-} // namespace mbgl
diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md
index b86ebae586..b919cba11c 100644
--- a/platform/macos/CHANGELOG.md
+++ b/platform/macos/CHANGELOG.md
@@ -1,5 +1,18 @@
# Changelog for Mapbox Maps SDK for macOS
+## master
+
+* Renamed this SDK from Mapbox macOS SDK to Mapbox Maps SDK for macOS. ([#10610](https://github.com/mapbox/mapbox-gl-native/pull/10610))
+
+### Annotations and user interaction
+
+* Increased the default maximum zoom level from 20 to 22. ([#9835](https://github.com/mapbox/mapbox-gl-native/pull/9835))
+
+### Styles
+
+* Fixed an issue preventing a dynamically-added `MGLRasterStyleLayer` from drawing until the map pans. ([#10270](https://github.com/mapbox/mapbox-gl-native/pull/10270))
+* Added `MGLComputedShapeSource` source class that allows applications to supply vector data on a per-tile basis.
+
## v0.6.0
### Packaging
diff --git a/platform/macos/app/Base.lproj/MainMenu.xib b/platform/macos/app/Base.lproj/MainMenu.xib
index 3243838848..d014676caa 100644
--- a/platform/macos/app/Base.lproj/MainMenu.xib
+++ b/platform/macos/app/Base.lproj/MainMenu.xib
@@ -565,6 +565,12 @@
<connections>
<action selector="addAnimatedImageSource:" target="-1" id="TuN-Pa-hTG"/>
</connections>
+ </menuItem>
+ <menuItem title="Add Graticule" id="Msk-p2-Lwt">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="insertGraticuleLayer:" target="-1" id="LE5-lz-kx4"/>
+ </connections>
</menuItem>
<menuItem title="Show All Annnotations" keyEquivalent="A" id="yMj-uM-8SN">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
@@ -574,8 +580,8 @@
</menuItem>
<menuItem title="Remove All Annotations" id="6rC-68-vk0">
<string key="keyEquivalent" base64-UTF8="YES">
-CA
-</string>
+ CA
+ </string>
<connections>
<action selector="removeAllAnnotations:" target="-1" id="6v3-0E-LsR"/>
</connections>
diff --git a/platform/macos/app/MapDocument.m b/platform/macos/app/MapDocument.m
index 0df6b10518..eb20063996 100644
--- a/platform/macos/app/MapDocument.m
+++ b/platform/macos/app/MapDocument.m
@@ -6,7 +6,7 @@
#import "MGLMapsnapshotter.h"
#import "MGLStyle+MBXAdditions.h"
-#import "MGLVectorSource+MGLAdditions.h"
+#import "MGLVectorSource_Private.h"
#import <Mapbox/Mapbox.h>
@@ -50,7 +50,7 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
return flattenedShapes;
}
-@interface MapDocument () <NSWindowDelegate, NSSharingServicePickerDelegate, NSMenuDelegate, NSSplitViewDelegate, MGLMapViewDelegate>
+@interface MapDocument () <NSWindowDelegate, NSSharingServicePickerDelegate, NSMenuDelegate, NSSplitViewDelegate, MGLMapViewDelegate, MGLComputedShapeSourceDataSource>
@property (weak) IBOutlet NSArrayController *styleLayersArrayController;
@property (weak) IBOutlet NSTableView *styleLayersTableView;
@@ -698,6 +698,47 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
[self.mapView.style removeLayer:layer];
}
+- (IBAction)insertGraticuleLayer:(id)sender {
+ [self.undoManager registerUndoWithTarget:self handler:^(id _Nonnull target) {
+ [self removeGraticuleLayer:sender];
+ }];
+
+ if (!self.undoManager.isUndoing) {
+ [self.undoManager setActionName:@"Add Graticule"];
+ }
+
+ MGLComputedShapeSource *source = [[MGLComputedShapeSource alloc] initWithIdentifier:@"graticule"
+ options:@{MGLShapeSourceOptionMaximumZoomLevel:@14}];
+ source.dataSource = self;
+ [self.mapView.style addSource:source];
+ MGLLineStyleLayer *lineLayer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"graticule.lines"
+ source:source];
+ [self.mapView.style addLayer:lineLayer];
+ MGLSymbolStyleLayer *labelLayer = [[MGLSymbolStyleLayer alloc] initWithIdentifier:@"graticule.labels"
+ source:source];
+ labelLayer.text = [MGLStyleValue valueWithRawValue:@"{value}"];
+ [self.mapView.style addLayer:labelLayer];
+}
+
+- (IBAction)removeGraticuleLayer:(id)sender {
+ [self.undoManager registerUndoWithTarget:self handler:^(id _Nonnull target) {
+ [self insertGraticuleLayer:sender];
+ }];
+
+ if (!self.undoManager.isUndoing) {
+ [self.undoManager setActionName:@"Delete Graticule"];
+ }
+
+ MGLStyleLayer *layer = [self.mapView.style layerWithIdentifier:@"graticule.lines"];
+ [self.mapView.style removeLayer:layer];
+
+ layer = [self.mapView.style layerWithIdentifier:@"graticule.labels"];
+ [self.mapView.style removeLayer:layer];
+
+ MGLSource *source = [self.mapView.style sourceWithIdentifier:@"graticule"];
+ [self.mapView.style removeSource:source];
+}
+
#pragma mark Offline packs
- (IBAction)addOfflinePack:(id)sender {
@@ -1011,6 +1052,9 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
if (menuItem.action == @selector(insertCustomStyleLayer:)) {
return ![self.mapView.style layerWithIdentifier:@"mbx-custom"];
}
+ if (menuItem.action == @selector(insertGraticuleLayer:)) {
+ return ![self.mapView.style sourceWithIdentifier:@"graticule"];
+ }
if (menuItem.action == @selector(showAllAnnotations:) || menuItem.action == @selector(removeAllAnnotations:)) {
return self.mapView.annotations.count > 0;
}
@@ -1185,6 +1229,53 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
return 0.8;
}
+#pragma mark - MGLComputedShapeSourceDataSource
+- (NSArray<id <MGLFeature>>*)featuresInCoordinateBounds:(MGLCoordinateBounds)bounds zoomLevel:(NSUInteger)zoom {
+ double gridSpacing;
+ if(zoom >= 13) {
+ gridSpacing = 0.01;
+ } else if(zoom >= 11) {
+ gridSpacing = 0.05;
+ } else if(zoom == 10) {
+ gridSpacing = .1;
+ } else if(zoom == 9) {
+ gridSpacing = 0.25;
+ } else if(zoom == 8) {
+ gridSpacing = 0.5;
+ } else if (zoom >= 6) {
+ gridSpacing = 1;
+ } else if(zoom == 5) {
+ gridSpacing = 2;
+ } else if(zoom >= 4) {
+ gridSpacing = 5;
+ } else if(zoom == 2) {
+ gridSpacing = 10;
+ } else {
+ gridSpacing = 20;
+ }
+
+ NSMutableArray <id <MGLFeature>> * features = [NSMutableArray array];
+ CLLocationCoordinate2D coords[2];
+
+ for (double y = ceil(bounds.ne.latitude / gridSpacing) * gridSpacing; y >= floor(bounds.sw.latitude / gridSpacing) * gridSpacing; y -= gridSpacing) {
+ coords[0] = CLLocationCoordinate2DMake(y, bounds.sw.longitude);
+ coords[1] = CLLocationCoordinate2DMake(y, bounds.ne.longitude);
+ MGLPolylineFeature *feature = [MGLPolylineFeature polylineWithCoordinates:coords count:2];
+ feature.attributes = @{@"value": @(y)};
+ [features addObject:feature];
+ }
+
+ for (double x = floor(bounds.sw.longitude / gridSpacing) * gridSpacing; x <= ceil(bounds.ne.longitude / gridSpacing) * gridSpacing; x += gridSpacing) {
+ coords[0] = CLLocationCoordinate2DMake(bounds.sw.latitude, x);
+ coords[1] = CLLocationCoordinate2DMake(bounds.ne.latitude, x);
+ MGLPolylineFeature *feature = [MGLPolylineFeature polylineWithCoordinates:coords count:2];
+ feature.attributes = @{@"value": @(x)};
+ [features addObject:feature];
+ }
+
+ return features;
+}
+
@end
@interface ValidatedToolbarItem : NSToolbarItem
diff --git a/platform/macos/config.cmake b/platform/macos/config.cmake
index 33eaa82518..e929bb55c6 100644
--- a/platform/macos/config.cmake
+++ b/platform/macos/config.cmake
@@ -1,10 +1,10 @@
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.10)
mason_use(glfw VERSION 2017-07-13-67c9155)
-mason_use(boost_libprogram_options VERSION 1.62.0)
mason_use(gtest VERSION 1.8.0)
mason_use(benchmark VERSION 1.2.0)
mason_use(icu VERSION 58.1-min-size)
+mason_use(args VERSION 6.2.0 HEADER_ONLY)
include(cmake/loop-uv.cmake)
include(cmake/loop-darwin.cmake)
@@ -34,8 +34,6 @@ macro(mbgl_platform_core)
PRIVATE platform/default/mbgl/gl/headless_backend.cpp
PRIVATE platform/default/mbgl/gl/headless_backend.hpp
PRIVATE platform/darwin/src/headless_backend_cgl.cpp
- PRIVATE platform/default/mbgl/gl/headless_display.hpp
- PRIVATE platform/darwin/src/headless_display_cgl.cpp
# Snapshotting
PRIVATE platform/default/mbgl/map/map_snapshotter.cpp
@@ -54,7 +52,6 @@ macro(mbgl_platform_core)
target_compile_options(mbgl-core
PRIVATE -fobjc-arc
- PRIVATE -fvisibility=hidden
)
target_include_directories(mbgl-core
@@ -86,7 +83,6 @@ macro(mbgl_filesource)
target_compile_options(mbgl-filesource
PRIVATE -fobjc-arc
- PRIVATE -fvisibility=hidden
)
target_link_libraries(mbgl-filesource
@@ -101,11 +97,6 @@ macro(mbgl_platform_glfw)
PRIVATE mbgl-filesource
PRIVATE mbgl-loop-darwin
)
-
- target_compile_options(mbgl-glfw
- PRIVATE -fvisibility=hidden
- )
-
endmacro()
@@ -114,9 +105,6 @@ macro(mbgl_platform_render)
PRIVATE mbgl-filesource
PRIVATE mbgl-loop-darwin
)
- target_compile_options(mbgl-render
- PRIVATE -fvisibility=hidden
- )
endmacro()
@@ -125,9 +113,6 @@ macro(mbgl_platform_offline)
PRIVATE mbgl-filesource
PRIVATE mbgl-loop-darwin
)
- target_compile_options(mbgl-offline
- PRIVATE -fvisibility=hidden
- )
endmacro()
@@ -136,16 +121,16 @@ macro(mbgl_platform_test)
PRIVATE platform/default/mbgl/test/main.cpp
)
+ target_include_directories(mbgl-test
+ PRIVATE platform/macos
+ )
+
set_source_files_properties(
platform/default/mbgl/test/main.cpp
PROPERTIES
COMPILE_FLAGS -DWORK_DIRECTORY="${CMAKE_SOURCE_DIR}"
)
- target_compile_options(mbgl-test
- PRIVATE -fvisibility=hidden
- )
-
target_link_libraries(mbgl-test
PRIVATE mbgl-filesource
PRIVATE mbgl-loop-darwin
@@ -153,10 +138,6 @@ macro(mbgl_platform_test)
endmacro()
macro(mbgl_platform_benchmark)
- target_compile_options(mbgl-benchmark
- PRIVATE -fvisibility=hidden
- )
-
target_sources(mbgl-benchmark
PRIVATE benchmark/src/main.cpp
)
@@ -174,10 +155,6 @@ macro(mbgl_platform_benchmark)
endmacro()
macro(mbgl_platform_node)
- target_compile_options(mbgl-node
- PRIVATE -fvisibility=hidden
- )
-
target_link_libraries(mbgl-node
PRIVATE "-Wl,-bind_at_load"
)
diff --git a/platform/macos/jazzy.yml b/platform/macos/jazzy.yml
index ab4643fa65..bdb29a890c 100644
--- a/platform/macos/jazzy.yml
+++ b/platform/macos/jazzy.yml
@@ -3,7 +3,7 @@ author: Mapbox
author_url: https://www.mapbox.com/
github_url: https://github.com/mapbox/mapbox-gl-native
dash_url: https://mapbox.github.io/mapbox-gl-native/macos/docsets/Mapbox.xml
-copyright: '© 2014–2017 [Mapbox](https://www.mapbox.com/). See [license](https://github.com/mapbox/mapbox-gl-native/blob/master/LICENSE.md) for more details.'
+copyright: '© 2014–2018 [Mapbox](https://www.mapbox.com/). See [license](https://github.com/mapbox/mapbox-gl-native/blob/master/LICENSE.md) for more details.'
head: |
<link rel='shortcut icon' href='https://www.mapbox.com/img/favicon.ico' type='image/x-icon' />
@@ -64,7 +64,9 @@ custom_categories:
children:
- MGLSource
- MGLTileSource
+ - MGLAbstractShapeSource
- MGLShapeSource
+ - MGLComputedShapeSource
- MGLRasterSource
- MGLVectorSource
- name: Style Layers
diff --git a/platform/macos/macos.xcodeproj/project.pbxproj b/platform/macos/macos.xcodeproj/project.pbxproj
index 25ee7516be..d21729341d 100644
--- a/platform/macos/macos.xcodeproj/project.pbxproj
+++ b/platform/macos/macos.xcodeproj/project.pbxproj
@@ -9,7 +9,13 @@
/* Begin PBXBuildFile section */
0721493F1EE200E900085505 /* MGLImageSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 07A019EB1ED662D800ACD43E /* MGLImageSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
07A019EF1ED665CD00ACD43E /* MGLImageSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 07A019EC1ED662D800ACD43E /* MGLImageSource.mm */; };
+ 07A240941F675674002C8210 /* MGLComputedShapeSourceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 07A240921F67566F002C8210 /* MGLComputedShapeSourceTests.m */; };
07BA4CAC1EE21887004528F5 /* MGLImageSourceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 07BA4CAB1EE21887004528F5 /* MGLImageSourceTests.m */; };
+ 07D9474B1F6743F000E37934 /* MGLAbstractShapeSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 07D947491F6741F500E37934 /* MGLAbstractShapeSource.mm */; };
+ 07D9474C1F67441500E37934 /* MGLAbstractShapeSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 07D947481F6741F500E37934 /* MGLAbstractShapeSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 07D9474D1F67441B00E37934 /* MGLAbstractShapeSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 07D947471F6741F500E37934 /* MGLAbstractShapeSource_Private.h */; };
+ 07F8E2F71F674C8800F794BB /* MGLComputedShapeSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 07F8E2F41F674C8000F794BB /* MGLComputedShapeSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 07F8E2F81F674C9000F794BB /* MGLComputedShapeSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 07F8E2F51F674C8000F794BB /* MGLComputedShapeSource.mm */; };
1753ED401E53CE6100A9FD90 /* MGLConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 1753ED3F1E53CE5200A9FD90 /* MGLConversion.h */; };
1F7454A31ECFB00300021D39 /* MGLLight_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F7454A01ECFB00300021D39 /* MGLLight_Private.h */; };
1F7454A41ECFB00300021D39 /* MGLLight.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F7454A11ECFB00300021D39 /* MGLLight.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -66,11 +72,7 @@
4049C2A51DB6CE7F00B3F799 /* MGLPointCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 4049C2A11DB6CE7800B3F799 /* MGLPointCollection.h */; settings = {ATTRIBUTES = (Public, ); }; };
4049C2AD1DB8020600B3F799 /* MGLPointCollection.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4049C2A71DB6D09B00B3F799 /* MGLPointCollection.mm */; };
408AA85B1DAEECFE00022900 /* MGLShape_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 408AA85A1DAEECF100022900 /* MGLShape_Private.h */; };
- 408AA8651DAEEE3400022900 /* MGLPolygon+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 408AA8601DAEED3300022900 /* MGLPolygon+MGLAdditions.h */; };
- 408AA8661DAEEE3600022900 /* MGLPolyline+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 408AA8611DAEED3300022900 /* MGLPolyline+MGLAdditions.h */; };
408AA8671DAEEE3900022900 /* NSDictionary+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 408AA85F1DAEED3300022900 /* NSDictionary+MGLAdditions.h */; };
- 408AA8681DAEEE5200022900 /* MGLPolygon+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 408AA85C1DAEED3300022900 /* MGLPolygon+MGLAdditions.m */; };
- 408AA8691DAEEE5500022900 /* MGLPolyline+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 408AA85D1DAEED3300022900 /* MGLPolyline+MGLAdditions.m */; };
408AA86A1DAEEE5D00022900 /* NSDictionary+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 408AA85E1DAEED3300022900 /* NSDictionary+MGLAdditions.mm */; };
40ABDB561DB0022100372083 /* NSImage+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 405C03971DB0004E001AC280 /* NSImage+MGLAdditions.mm */; };
40B77E451DB11BC9003DA2FE /* NSArray+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 40B77E431DB11BB0003DA2FE /* NSArray+MGLAdditions.h */; };
@@ -90,6 +92,8 @@
92092EF11F5EB10E00AF5130 /* MGLMapSnapshotter.mm in Sources */ = {isa = PBXBuildFile; fileRef = 92092EEF1F5EB10E00AF5130 /* MGLMapSnapshotter.mm */; };
920A3E591E6F859D00C16EFC /* MGLSourceQueryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 920A3E581E6F859D00C16EFC /* MGLSourceQueryTests.m */; };
92F2C3EB1F0E3A1900268EC0 /* MGLRendererFrontend.h in Headers */ = {isa = PBXBuildFile; fileRef = 92F2C3EA1F0E3A1900268EC0 /* MGLRendererFrontend.h */; };
+ 9654C12B1FFC38E000DB6A19 /* MGLPolyline_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 9654C12A1FFC38E000DB6A19 /* MGLPolyline_Private.h */; };
+ 9654C12D1FFC394700DB6A19 /* MGLPolygon_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 9654C12C1FFC394700DB6A19 /* MGLPolygon_Private.h */; };
96E027311E57C9A7004B8E66 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 96E027331E57C9A7004B8E66 /* Localizable.strings */; };
DA00FC8A1D5EEAC3009AABC8 /* MGLAttributionInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DA00FC881D5EEAC3009AABC8 /* MGLAttributionInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
DA00FC8B1D5EEAC3009AABC8 /* MGLAttributionInfo.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA00FC891D5EEAC3009AABC8 /* MGLAttributionInfo.mm */; };
@@ -285,7 +289,13 @@
/* Begin PBXFileReference section */
07A019EB1ED662D800ACD43E /* MGLImageSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLImageSource.h; sourceTree = "<group>"; };
07A019EC1ED662D800ACD43E /* MGLImageSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLImageSource.mm; sourceTree = "<group>"; };
+ 07A240921F67566F002C8210 /* MGLComputedShapeSourceTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLComputedShapeSourceTests.m; sourceTree = "<group>"; };
07BA4CAB1EE21887004528F5 /* MGLImageSourceTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLImageSourceTests.m; sourceTree = "<group>"; };
+ 07D947471F6741F500E37934 /* MGLAbstractShapeSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAbstractShapeSource_Private.h; sourceTree = "<group>"; };
+ 07D947481F6741F500E37934 /* MGLAbstractShapeSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAbstractShapeSource.h; sourceTree = "<group>"; };
+ 07D947491F6741F500E37934 /* MGLAbstractShapeSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLAbstractShapeSource.mm; sourceTree = "<group>"; };
+ 07F8E2F41F674C8000F794BB /* MGLComputedShapeSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLComputedShapeSource.h; sourceTree = "<group>"; };
+ 07F8E2F51F674C8000F794BB /* MGLComputedShapeSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLComputedShapeSource.mm; sourceTree = "<group>"; };
1753ED3F1E53CE5200A9FD90 /* MGLConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLConversion.h; sourceTree = "<group>"; };
1F7454A01ECFB00300021D39 /* MGLLight_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLLight_Private.h; sourceTree = "<group>"; };
1F7454A11ECFB00300021D39 /* MGLLight.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLLight.h; sourceTree = "<group>"; };
@@ -345,12 +355,8 @@
405C03961DB0004E001AC280 /* NSImage+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSImage+MGLAdditions.h"; sourceTree = "<group>"; };
405C03971DB0004E001AC280 /* NSImage+MGLAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSImage+MGLAdditions.mm"; sourceTree = "<group>"; };
408AA85A1DAEECF100022900 /* MGLShape_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLShape_Private.h; sourceTree = "<group>"; };
- 408AA85C1DAEED3300022900 /* MGLPolygon+MGLAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MGLPolygon+MGLAdditions.m"; sourceTree = "<group>"; };
- 408AA85D1DAEED3300022900 /* MGLPolyline+MGLAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MGLPolyline+MGLAdditions.m"; sourceTree = "<group>"; };
408AA85E1DAEED3300022900 /* NSDictionary+MGLAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSDictionary+MGLAdditions.mm"; sourceTree = "<group>"; };
408AA85F1DAEED3300022900 /* NSDictionary+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+MGLAdditions.h"; sourceTree = "<group>"; };
- 408AA8601DAEED3300022900 /* MGLPolygon+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MGLPolygon+MGLAdditions.h"; sourceTree = "<group>"; };
- 408AA8611DAEED3300022900 /* MGLPolyline+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MGLPolyline+MGLAdditions.h"; sourceTree = "<group>"; };
40B77E421DB11BB0003DA2FE /* NSArray+MGLAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSArray+MGLAdditions.mm"; sourceTree = "<group>"; };
40B77E431DB11BB0003DA2FE /* NSArray+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+MGLAdditions.h"; sourceTree = "<group>"; };
40E1601A1DF216E6005EA6D9 /* MGLStyleLayerTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLStyleLayerTests.h; sourceTree = "<group>"; };
@@ -369,6 +375,8 @@
92092EEF1F5EB10E00AF5130 /* MGLMapSnapshotter.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLMapSnapshotter.mm; sourceTree = "<group>"; };
920A3E581E6F859D00C16EFC /* MGLSourceQueryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLSourceQueryTests.m; sourceTree = "<group>"; };
92F2C3EA1F0E3A1900268EC0 /* MGLRendererFrontend.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLRendererFrontend.h; sourceTree = "<group>"; };
+ 9654C12A1FFC38E000DB6A19 /* MGLPolyline_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLPolyline_Private.h; sourceTree = "<group>"; };
+ 9654C12C1FFC394700DB6A19 /* MGLPolygon_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLPolygon_Private.h; sourceTree = "<group>"; };
966091701E5BBFF700A9A03B /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = "<group>"; };
966091711E5BBFF900A9A03B /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Localizable.strings; sourceTree = "<group>"; };
966091721E5BBFFA00A9A03B /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/Localizable.strings; sourceTree = "<group>"; };
@@ -678,8 +686,6 @@
352742791D4C235C00A1ECE6 /* Categories */ = {
isa = PBXGroup;
children = (
- 1FCDF1401F2A4F3600A46694 /* MGLVectorSource+MGLAdditions.h */,
- 1FCDF1411F2A4F3600A46694 /* MGLVectorSource+MGLAdditions.m */,
DA8F25A61D51CB270010E6B5 /* NSValue+MGLStyleAttributeAdditions.h */,
DA8F25A71D51CB270010E6B5 /* NSValue+MGLStyleAttributeAdditions.mm */,
);
@@ -689,6 +695,11 @@
3527427E1D4C242B00A1ECE6 /* Sources */ = {
isa = PBXGroup;
children = (
+ 07D947481F6741F500E37934 /* MGLAbstractShapeSource.h */,
+ 07D947471F6741F500E37934 /* MGLAbstractShapeSource_Private.h */,
+ 07D947491F6741F500E37934 /* MGLAbstractShapeSource.mm */,
+ 07F8E2F41F674C8000F794BB /* MGLComputedShapeSource.h */,
+ 07F8E2F51F674C8000F794BB /* MGLComputedShapeSource.mm */,
352742831D4C244700A1ECE6 /* MGLRasterSource.h */,
DA7DC9821DED647F0027472F /* MGLRasterSource_Private.h */,
352742841D4C244700A1ECE6 /* MGLRasterSource.mm */,
@@ -820,6 +831,7 @@
DA87A99A1DC9D88800810D09 /* Sources */ = {
isa = PBXGroup;
children = (
+ 07A240921F67566F002C8210 /* MGLComputedShapeSourceTests.m */,
DA87A9961DC9D88400810D09 /* MGLShapeSourceTests.mm */,
DA87A9971DC9D88400810D09 /* MGLTileSetTests.mm */,
920A3E581E6F859D00C16EFC /* MGLSourceQueryTests.m */,
@@ -938,8 +950,10 @@
DAF0D80D1DFE0E5D00B28378 /* MGLPointCollection_Private.h */,
4049C2A71DB6D09B00B3F799 /* MGLPointCollection.mm */,
DAE6C3541CC31E0400DB3429 /* MGLPolygon.h */,
+ 9654C12C1FFC394700DB6A19 /* MGLPolygon_Private.h */,
DAE6C3771CC31E2A00DB3429 /* MGLPolygon.mm */,
DAE6C3551CC31E0400DB3429 /* MGLPolyline.h */,
+ 9654C12A1FFC38E000DB6A19 /* MGLPolyline_Private.h */,
DAE6C3781CC31E2A00DB3429 /* MGLPolyline.mm */,
DAE6C3561CC31E0400DB3429 /* MGLShape.h */,
408AA85A1DAEECF100022900 /* MGLShape_Private.h */,
@@ -970,10 +984,6 @@
DAD1657F1CF4CF50001FF4B9 /* Categories */ = {
isa = PBXGroup;
children = (
- 408AA8601DAEED3300022900 /* MGLPolygon+MGLAdditions.h */,
- 408AA85C1DAEED3300022900 /* MGLPolygon+MGLAdditions.m */,
- 408AA8611DAEED3300022900 /* MGLPolyline+MGLAdditions.h */,
- 408AA85D1DAEED3300022900 /* MGLPolyline+MGLAdditions.m */,
40B77E431DB11BB0003DA2FE /* NSArray+MGLAdditions.h */,
40B77E421DB11BB0003DA2FE /* NSArray+MGLAdditions.mm */,
DAE6C37D1CC31E2A00DB3429 /* NSBundle+MGLAdditions.h */,
@@ -1145,12 +1155,12 @@
buildActionMask = 2147483647;
files = (
556660C61E1BEA0100E2C41B /* MGLFoundation.h in Headers */,
+ 07F8E2F71F674C8800F794BB /* MGLComputedShapeSource.h in Headers */,
DA8F258F1D51CA600010E6B5 /* MGLRasterStyleLayer.h in Headers */,
3508EC641D749D39009B0EE4 /* NSExpression+MGLAdditions.h in Headers */,
DAE6C38D1CC31E2A00DB3429 /* MGLOfflineRegion_Private.h in Headers */,
DA7DC9831DED647F0027472F /* MGLRasterSource_Private.h in Headers */,
1753ED401E53CE6100A9FD90 /* MGLConversion.h in Headers */,
- 408AA8651DAEEE3400022900 /* MGLPolygon+MGLAdditions.h in Headers */,
DA8F259C1D51CB000010E6B5 /* MGLStyleValue_Private.h in Headers */,
DAE6C35B1CC31E0400DB3429 /* MGLAnnotation.h in Headers */,
DAE6C3B61CC31EF300DB3429 /* MGLMapView_Private.h in Headers */,
@@ -1182,6 +1192,7 @@
DAE6C3861CC31E2A00DB3429 /* MGLGeometry_Private.h in Headers */,
DAE6C3841CC31E2A00DB3429 /* MGLAccountManager_Private.h in Headers */,
DAE6C3691CC31E0400DB3429 /* MGLTypes.h in Headers */,
+ 07D9474D1F67441B00E37934 /* MGLAbstractShapeSource_Private.h in Headers */,
DAE6C3991CC31E2A00DB3429 /* NSException+MGLAdditions.h in Headers */,
DA8F25871D51C9E10010E6B5 /* MGLBackgroundStyleLayer.h in Headers */,
4049C2A51DB6CE7F00B3F799 /* MGLPointCollection.h in Headers */,
@@ -1196,6 +1207,7 @@
35602BFA1D3EA99F0050646F /* MGLFillStyleLayer.h in Headers */,
DA35A2A41CC9EB1A00E826B2 /* MGLCoordinateFormatter.h in Headers */,
35C5D8491D6DD66D00E95907 /* NSCompoundPredicate+MGLAdditions.h in Headers */,
+ 07D9474C1F67441500E37934 /* MGLAbstractShapeSource.h in Headers */,
DD0902B31DB1AC6400C5BDCE /* MGLNetworkConfiguration.h in Headers */,
DAE6C3621CC31E0400DB3429 /* MGLOverlay.h in Headers */,
DAE6C3651CC31E0400DB3429 /* MGLPolyline.h in Headers */,
@@ -1207,12 +1219,10 @@
1F7454A31ECFB00300021D39 /* MGLLight_Private.h in Headers */,
359819591E02F611008FC139 /* NSCoder+MGLAdditions.h in Headers */,
DAE6C38E1CC31E2A00DB3429 /* MGLOfflineStorage_Private.h in Headers */,
- 408AA8661DAEEE3600022900 /* MGLPolyline+MGLAdditions.h in Headers */,
DA87A9A01DC9DC6200810D09 /* MGLValueEvaluator.h in Headers */,
DAE6C3601CC31E0400DB3429 /* MGLOfflineRegion.h in Headers */,
DAE6C3681CC31E0400DB3429 /* MGLTilePyramidOfflineRegion.h in Headers */,
DA35A2CF1CCAAED300E826B2 /* NSValue+MGLAdditions.h in Headers */,
- 1FCDF1421F2A4F3600A46694 /* MGLVectorSource+MGLAdditions.h in Headers */,
DAE6C3A61CC31E9400DB3429 /* MGLMapViewDelegate.h in Headers */,
DAE6C38B1CC31E2A00DB3429 /* MGLOfflinePack_Private.h in Headers */,
558DE7A61E56161C00C7916D /* MGLFoundation_Private.h in Headers */,
@@ -1236,8 +1246,10 @@
DAE6C3A51CC31E9400DB3429 /* MGLMapView+IBAdditions.h in Headers */,
DA35A2AD1CCA091800E826B2 /* MGLCompassDirectionFormatter.h in Headers */,
352742851D4C244700A1ECE6 /* MGLRasterSource.h in Headers */,
+ 9654C12D1FFC394700DB6A19 /* MGLPolygon_Private.h in Headers */,
408AA85B1DAEECFE00022900 /* MGLShape_Private.h in Headers */,
DACC22181CF3D4F700D220D9 /* MGLFeature_Private.h in Headers */,
+ 9654C12B1FFC38E000DB6A19 /* MGLPolyline_Private.h in Headers */,
DA6408D71DA4E5DA00908C90 /* MGLVectorStyleLayer.h in Headers */,
352742891D4C245800A1ECE6 /* MGLShapeSource.h in Headers */,
1F7454A41ECFB00300021D39 /* MGLLight.h in Headers */,
@@ -1329,7 +1341,7 @@
isa = PBXProject;
attributes = {
CLASSPREFIX = MBX;
- LastUpgradeCheck = 0800;
+ LastUpgradeCheck = 0920;
ORGANIZATIONNAME = Mapbox;
TargetAttributes = {
DA839E911CC2E3400062CAFB = {
@@ -1460,7 +1472,6 @@
40B77E461DB11BCD003DA2FE /* NSArray+MGLAdditions.mm in Sources */,
DAE6C38C1CC31E2A00DB3429 /* MGLOfflinePack.mm in Sources */,
35D65C5B1D65AD5500722C23 /* NSDate+MGLAdditions.mm in Sources */,
- 1FCDF1431F2A4F3600A46694 /* MGLVectorSource+MGLAdditions.m in Sources */,
DD0902B21DB1AC6400C5BDCE /* MGLNetworkConfiguration.m in Sources */,
1F7454A51ECFB00300021D39 /* MGLLight.mm in Sources */,
DAE6C3B11CC31EF300DB3429 /* MGLAnnotationImage.m in Sources */,
@@ -1475,6 +1486,7 @@
558DE7A71E56161C00C7916D /* MGLFoundation.mm in Sources */,
DAE6C39D1CC31E2A00DB3429 /* NSString+MGLAdditions.m in Sources */,
3598195A1E02F611008FC139 /* NSCoder+MGLAdditions.mm in Sources */,
+ 07D9474B1F6743F000E37934 /* MGLAbstractShapeSource.mm in Sources */,
DAE6C3941CC31E2A00DB3429 /* MGLStyle.mm in Sources */,
DAE6C3871CC31E2A00DB3429 /* MGLGeometry.mm in Sources */,
3527428E1D4C24AB00A1ECE6 /* MGLCircleStyleLayer.mm in Sources */,
@@ -1486,6 +1498,7 @@
DA35A2D01CCAAED300E826B2 /* NSValue+MGLAdditions.m in Sources */,
3538AA241D542685008EC33D /* MGLStyleLayer.mm in Sources */,
DA35A2C01CCA9B1A00E826B2 /* MGLClockDirectionFormatter.m in Sources */,
+ 07F8E2F81F674C9000F794BB /* MGLComputedShapeSource.mm in Sources */,
DAE6C3BA1CC31EF300DB3429 /* MGLOpenGLLayer.mm in Sources */,
DAE6C38A1CC31E2A00DB3429 /* MGLMultiPoint.mm in Sources */,
DAE6C3961CC31E2A00DB3429 /* MGLTypes.m in Sources */,
@@ -1502,7 +1515,6 @@
DAE6C38F1CC31E2A00DB3429 /* MGLOfflineStorage.mm in Sources */,
DAED38601D62CED700D7640F /* NSURL+MGLAdditions.m in Sources */,
35C5D84A1D6DD66D00E95907 /* NSCompoundPredicate+MGLAdditions.mm in Sources */,
- 408AA8681DAEEE5200022900 /* MGLPolygon+MGLAdditions.m in Sources */,
DAE6C3951CC31E2A00DB3429 /* MGLTilePyramidOfflineRegion.mm in Sources */,
DAE6C3851CC31E2A00DB3429 /* MGLAccountManager.m in Sources */,
DA00FC8B1D5EEAC3009AABC8 /* MGLAttributionInfo.mm in Sources */,
@@ -1514,7 +1526,6 @@
35C5D8481D6DD66D00E95907 /* NSComparisonPredicate+MGLAdditions.mm in Sources */,
DA35A2AE1CCA091800E826B2 /* MGLCompassDirectionFormatter.m in Sources */,
DA8F258C1D51CA540010E6B5 /* MGLLineStyleLayer.mm in Sources */,
- 408AA8691DAEEE5500022900 /* MGLPolyline+MGLAdditions.m in Sources */,
DA8F25941D51CA750010E6B5 /* MGLSymbolStyleLayer.mm in Sources */,
3529039C1D6C63B80002C7DF /* NSPredicate+MGLAdditions.mm in Sources */,
DA8F25981D51CAC70010E6B5 /* MGLVectorSource.mm in Sources */,
@@ -1531,6 +1542,7 @@
DAE6C3D41CC34C9900DB3429 /* MGLOfflineRegionTests.m in Sources */,
DAE6C3D61CC34C9900DB3429 /* MGLStyleTests.mm in Sources */,
1F7454AB1ED1DDBD00021D39 /* MGLLightTest.mm in Sources */,
+ 07A240941F675674002C8210 /* MGLComputedShapeSourceTests.m in Sources */,
DAEDC4371D606291000224FF /* MGLAttributionButtonTests.m in Sources */,
920A3E591E6F859D00C16EFC /* MGLSourceQueryTests.m in Sources */,
DA35A2B61CCA14D700E826B2 /* MGLCompassDirectionFormatterTests.m in Sources */,
@@ -1717,7 +1729,9 @@
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
@@ -1725,12 +1739,19 @@
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
+ CURRENT_COMMIT_HASH = deadbeef;
+ CURRENT_SEMANTIC_VERSION = 1.0.0;
+ CURRENT_SHORT_VERSION = 1.0;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
@@ -1765,7 +1786,9 @@
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
@@ -1773,12 +1796,19 @@
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
+ CURRENT_COMMIT_HASH = deadbeef;
+ CURRENT_SEMANTIC_VERSION = 1.0.0;
+ CURRENT_SHORT_VERSION = 1.0;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -1792,6 +1822,7 @@
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = NO;
+ SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SYMROOT = "$(PROJECT_DIR)/cmake";
};
name = Release;
diff --git a/platform/macos/macos.xcodeproj/xcshareddata/xcschemes/CI.xcscheme b/platform/macos/macos.xcodeproj/xcshareddata/xcschemes/CI.xcscheme
index a049928fdd..335441cc23 100644
--- a/platform/macos/macos.xcodeproj/xcshareddata/xcschemes/CI.xcscheme
+++ b/platform/macos/macos.xcodeproj/xcshareddata/xcschemes/CI.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "0810"
+ LastUpgradeVersion = "0920"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -56,7 +56,7 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
- BlueprintIdentifier = "8E8A234D3E364CDFA2918983"
+ BlueprintIdentifier = "E933DEF922EF4BC1AD735333"
BuildableName = "mbgl-test"
BlueprintName = "mbgl-test"
ReferencedContainer = "container:../../build/macos/mbgl.xcodeproj">
@@ -70,7 +70,7 @@
buildForAnalyzing = "NO">
<BuildableReference
BuildableIdentifier = "primary"
- BlueprintIdentifier = "11FCEF1E29744645907C1E4B"
+ BlueprintIdentifier = "1D3EE78DAFFA4A42AFD7160D"
BuildableName = "mbgl-benchmark"
BlueprintName = "mbgl-benchmark"
ReferencedContainer = "container:../../build/macos/mbgl.xcodeproj">
@@ -82,6 +82,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
@@ -111,6 +112,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
diff --git a/platform/macos/macos.xcodeproj/xcshareddata/xcschemes/dynamic.xcscheme b/platform/macos/macos.xcodeproj/xcshareddata/xcschemes/dynamic.xcscheme
index 95351f7f04..4dadaee743 100644
--- a/platform/macos/macos.xcodeproj/xcshareddata/xcschemes/dynamic.xcscheme
+++ b/platform/macos/macos.xcodeproj/xcshareddata/xcschemes/dynamic.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "0810"
+ LastUpgradeVersion = "0920"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -40,6 +40,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
@@ -69,6 +70,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
diff --git a/platform/macos/macos.xcodeproj/xcshareddata/xcschemes/macosapp.xcscheme b/platform/macos/macos.xcodeproj/xcshareddata/xcschemes/macosapp.xcscheme
index a58ef5c9cf..b0ce01fbf0 100644
--- a/platform/macos/macos.xcodeproj/xcshareddata/xcschemes/macosapp.xcscheme
+++ b/platform/macos/macos.xcodeproj/xcshareddata/xcschemes/macosapp.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "0810"
+ LastUpgradeVersion = "0920"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -26,6 +26,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
@@ -55,6 +56,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
diff --git a/platform/macos/sdk/Info.plist b/platform/macos/sdk/Info.plist
index 3b2b38a58a..a3a7d6b902 100644
--- a/platform/macos/sdk/Info.plist
+++ b/platform/macos/sdk/Info.plist
@@ -3,7 +3,7 @@
<plist version="1.0">
<dict>
<key>CFBundleShortVersionString</key>
- <string>1.0</string>
+ <string>$(CURRENT_SHORT_VERSION)</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
@@ -20,5 +20,9 @@
<string>????</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
+ <key>MGLCommitHash</key>
+ <string>$(CURRENT_COMMIT_HASH)</string>
+ <key>MGLSemanticVersionString</key>
+ <string>$(CURRENT_SEMANTIC_VERSION)</string>
</dict>
</plist>
diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm
index f2c6afb2f7..9ec9012198 100644
--- a/platform/macos/src/MGLMapView.mm
+++ b/platform/macos/src/MGLMapView.mm
@@ -2887,7 +2887,7 @@ public:
[nativeView sourceDidChange:nativeSource];
}
- mbgl::gl::ProcAddress initializeExtension(const char* name) override {
+ mbgl::gl::ProcAddress getExtensionFunctionPointer(const char* name) override {
static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
if (!framework) {
throw std::runtime_error("Failed to load OpenGL framework.");
diff --git a/platform/macos/src/Mapbox.h b/platform/macos/src/Mapbox.h
index a082a4771e..26c67d5550 100644
--- a/platform/macos/src/Mapbox.h
+++ b/platform/macos/src/Mapbox.h
@@ -49,6 +49,8 @@ FOUNDATION_EXPORT MGL_EXPORT const unsigned char MapboxVersionString[];
#import "MGLTileSource.h"
#import "MGLVectorSource.h"
#import "MGLShapeSource.h"
+#import "MGLAbstractShapeSource.h"
+#import "MGLComputedShapeSource.h"
#import "MGLRasterSource.h"
#import "MGLImageSource.h"
#import "MGLTilePyramidOfflineRegion.h"
diff --git a/platform/macos/src/NSImage+MGLAdditions.mm b/platform/macos/src/NSImage+MGLAdditions.mm
index 7500a8a207..2666dfe790 100644
--- a/platform/macos/src/NSImage+MGLAdditions.mm
+++ b/platform/macos/src/NSImage+MGLAdditions.mm
@@ -5,7 +5,7 @@
@implementation NSImage (MGLAdditions)
- (nullable instancetype)initWithMGLPremultipliedImage:(mbgl::PremultipliedImage&&)src {
- CGImageRef image = CGImageFromMGLPremultipliedImage(std::move(src));
+ CGImageRef image = CGImageCreateWithMGLPremultipliedImage(std::move(src));
if (!image) {
return nil;
}
@@ -16,7 +16,7 @@
}
- (nullable instancetype)initWithMGLStyleImage:(const mbgl::style::Image *)styleImage {
- CGImageRef image = CGImageFromMGLPremultipliedImage(styleImage->getImage().clone());
+ CGImageRef image = CGImageCreateWithMGLPremultipliedImage(styleImage->getImage().clone());
if (!image) {
return nil;
}
diff --git a/platform/node/CHANGELOG.md b/platform/node/CHANGELOG.md
index 1d166a9a79..feb2b4185d 100644
--- a/platform/node/CHANGELOG.md
+++ b/platform/node/CHANGELOG.md
@@ -1,3 +1,14 @@
+# master
+- 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.
+
+# 3.5.8 - October 19, 2017
+- Fixes an issue that causes memory leaks when not deleting the frontend object
+ in NodeMap::release()
+- Fixes a crash in Earcut: [#10245](https://github.com/mapbox/mapbox-gl-native/pull/10245)
+
+# 3.5.7 - October 9, 2017
+- Fixed an issue causing synchronous resource requests to stall [#10153](https://github.com/mapbox/mapbox-gl-native/pull/10153)
+
# 3.5.6 - September 29, 2017
- Protects against requests which throw [#9554](https://github.com/mapbox/mapbox-gl-native/pull/9554)
- Fixed an issue around reusing a map object [#9554](https://github.com/mapbox/mapbox-gl-native/pull/9554)
diff --git a/platform/node/DEVELOPING.md b/platform/node/DEVELOPING.md
index 4e8da881a8..b313d75c13 100644
--- a/platform/node/DEVELOPING.md
+++ b/platform/node/DEVELOPING.md
@@ -1,6 +1,6 @@
# Developing the Mapbox GL Native Node.js module
-This document explains how to build the [Node.js](https://nodejs.org/) bindings for [../../README.md](Mapbox GL Native) for contributing to the development of the bindings themselves. If you just want to use the module, you can simply install it via `npm`; see [README.md](README.md) for installation and usage instructions.
+This document explains how to build the [Node.js](https://nodejs.org/) bindings for [Mapbox GL Native](../../README.md) for contributing to the development of the bindings themselves. If you just want to use the module, you can simply install it via `npm`; see [README.md](README.md) for installation and usage instructions.
## Building
diff --git a/platform/node/src/node_conversion.hpp b/platform/node/src/node_conversion.hpp
index d266745548..7c5bbf4386 100644
--- a/platform/node/src/node_conversion.hpp
+++ b/platform/node/src/node_conversion.hpp
@@ -9,111 +9,136 @@
#include <mbgl/util/optional.hpp>
#include <mbgl/util/feature.hpp>
#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/conversion/geojson.hpp>
namespace mbgl {
namespace style {
namespace conversion {
-inline bool isUndefined(v8::Local<v8::Value> value) {
- Nan::HandleScope scope;
- return value->IsUndefined() || value->IsNull();
-}
+template <>
+class ConversionTraits<v8::Local<v8::Value>> {
+public:
+ static bool isUndefined(const v8::Local<v8::Value>& value) {
+ Nan::HandleScope scope;
+ return value->IsUndefined() || value->IsNull();
+ }
-inline bool isArray(v8::Local<v8::Value> value) {
- Nan::HandleScope scope;
- return value->IsArray();
-}
+ static bool isArray(const v8::Local<v8::Value>& value) {
+ Nan::HandleScope scope;
+ return value->IsArray();
+ }
-inline std::size_t arrayLength(v8::Local<v8::Value> value) {
- Nan::HandleScope scope;
- return value.As<v8::Array>()->Length();
-}
+ static std::size_t arrayLength(const v8::Local<v8::Value>& value) {
+ Nan::HandleScope scope;
+ // const_cast because v8::Local<T>::As is not marked const until node v8.0
+ v8::Local<v8::Array> array = const_cast<v8::Local<v8::Value>&>(value).As<v8::Array>();
+ return array->Length();
+ }
-inline v8::Local<v8::Value> arrayMember(v8::Local<v8::Value> value, std::size_t i) {
- Nan::EscapableHandleScope scope;
- return scope.Escape(Nan::Get(value.As<v8::Array>(), i).ToLocalChecked());
-}
+ static v8::Local<v8::Value> arrayMember(const v8::Local<v8::Value>& value, std::size_t i) {
+ Nan::EscapableHandleScope scope;
+ // const_cast because v8::Local<T>::As is not marked const until node v8.0
+ v8::Local<v8::Array> array = const_cast<v8::Local<v8::Value>&>(value).As<v8::Array>();
+ return scope.Escape(Nan::Get(array, i).ToLocalChecked());
+ }
-inline bool isObject(v8::Local<v8::Value> value) {
- Nan::HandleScope scope;
- return value->IsObject() && !value->IsArray();
-}
+ static bool isObject(const v8::Local<v8::Value>& value) {
+ Nan::HandleScope scope;
+ return value->IsObject() && !value->IsArray();
+ }
-inline optional<v8::Local<v8::Value>> objectMember(v8::Local<v8::Value> value, const char * name) {
- Nan::EscapableHandleScope scope;
- if (!Nan::Has(Nan::To<v8::Object>(value).ToLocalChecked(), Nan::New(name).ToLocalChecked()).FromJust()) {
- return {};
+ static optional<v8::Local<v8::Value>> objectMember(const v8::Local<v8::Value>& value, const char * name) {
+ Nan::EscapableHandleScope scope;
+ if (!Nan::Has(Nan::To<v8::Object>(value).ToLocalChecked(), Nan::New(name).ToLocalChecked()).FromJust()) {
+ return {};
+ }
+ Nan::MaybeLocal<v8::Value> result = Nan::Get(Nan::To<v8::Object>(value).ToLocalChecked(), Nan::New(name).ToLocalChecked());
+ if (result.IsEmpty()) {
+ return {};
+ }
+ return {scope.Escape(result.ToLocalChecked())};
}
- Nan::MaybeLocal<v8::Value> result = Nan::Get(Nan::To<v8::Object>(value).ToLocalChecked(), Nan::New(name).ToLocalChecked());
- if (result.IsEmpty()) {
+
+ template <class Fn>
+ static optional<Error> eachMember(const v8::Local<v8::Value>& value, Fn&& fn) {
+ Nan::HandleScope scope;
+ v8::Local<v8::Array> names = Nan::GetOwnPropertyNames(Nan::To<v8::Object>(value).ToLocalChecked()).ToLocalChecked();
+ for (uint32_t i = 0; i < names->Length(); ++i) {
+ v8::Local<v8::Value> k = Nan::Get(names, i).ToLocalChecked();
+ v8::Local<v8::Value> v = Nan::Get(Nan::To<v8::Object>(value).ToLocalChecked(), k).ToLocalChecked();
+ optional<Error> result = fn(*Nan::Utf8String(k), std::move(v));
+ if (result) {
+ return result;
+ }
+ }
return {};
}
- return scope.Escape(result.ToLocalChecked());
-}
-template <class Fn>
-optional<Error> eachMember(v8::Local<v8::Value> value, Fn&& fn) {
- Nan::HandleScope scope;
- v8::Local<v8::Array> names = Nan::GetOwnPropertyNames(Nan::To<v8::Object>(value).ToLocalChecked()).ToLocalChecked();
- for (uint32_t i = 0; i < names->Length(); ++i) {
- v8::Local<v8::Value> k = Nan::Get(names, i).ToLocalChecked();
- v8::Local<v8::Value> v = Nan::Get(Nan::To<v8::Object>(value).ToLocalChecked(), k).ToLocalChecked();
- optional<Error> result = fn(*Nan::Utf8String(k), v);
- if (result) {
- return result;
+ static optional<bool> toBool(const v8::Local<v8::Value>& value) {
+ Nan::HandleScope scope;
+ if (!value->IsBoolean()) {
+ return {};
}
+ return value->BooleanValue();
}
- return {};
-}
-inline optional<bool> toBool(v8::Local<v8::Value> value) {
- Nan::HandleScope scope;
- if (!value->IsBoolean()) {
- return {};
+ static optional<float> toNumber(const v8::Local<v8::Value>& value) {
+ Nan::HandleScope scope;
+ if (!value->IsNumber()) {
+ return {};
+ }
+ return value->NumberValue();
}
- return value->BooleanValue();
-}
-inline optional<float> toNumber(v8::Local<v8::Value> value) {
- Nan::HandleScope scope;
- if (!value->IsNumber()) {
- return {};
+ static optional<double> toDouble(const v8::Local<v8::Value>& value) {
+ Nan::HandleScope scope;
+ if (!value->IsNumber()) {
+ return {};
+ }
+ return value->NumberValue();
}
- return value->NumberValue();
-}
-inline optional<double> toDouble(v8::Local<v8::Value> value) {
- Nan::HandleScope scope;
- if (!value->IsNumber()) {
- return {};
+ static optional<std::string> toString(const v8::Local<v8::Value>& value) {
+ Nan::HandleScope scope;
+ if (!value->IsString()) {
+ return {};
+ }
+ return std::string(*Nan::Utf8String(value));
}
- return value->NumberValue();
-}
-inline optional<std::string> toString(v8::Local<v8::Value> value) {
- Nan::HandleScope scope;
- if (!value->IsString()) {
- return {};
+ static optional<Value> toValue(const v8::Local<v8::Value>& value) {
+ if (value->IsFalse()) {
+ return { false };
+ } else if (value->IsTrue()) {
+ return { true };
+ } else if (value->IsString()) {
+ return { std::string(*Nan::Utf8String(value)) };
+ } else if (value->IsUint32()) {
+ return { std::uint64_t(value->Uint32Value()) };
+ } else if (value->IsInt32()) {
+ return { std::int64_t(value->Int32Value()) };
+ } else if (value->IsNumber()) {
+ return { value->NumberValue() };
+ } else {
+ return {};
+ }
}
- return std::string(*Nan::Utf8String(value));
-}
-inline optional<Value> toValue(v8::Local<v8::Value> value) {
- if (value->IsFalse()) {
- return { false };
- } else if (value->IsTrue()) {
- return { true };
- } else if (value->IsString()) {
- return { std::string(*Nan::Utf8String(value)) };
- } else if (value->IsUint32()) {
- return { std::uint64_t(value->Uint32Value()) };
- } else if (value->IsInt32()) {
- return { std::int64_t(value->Int32Value()) };
- } else if (value->IsNumber()) {
- return { value->NumberValue() };
- } else {
- return {};
+ static optional<GeoJSON> toGeoJSON(const v8::Local<v8::Value>& value, Error& error) {
+ try {
+ Nan::JSON JSON;
+ std::string string = *Nan::Utf8String(JSON.Stringify(value->ToObject()).ToLocalChecked());
+ return parseGeoJSON(string, error);
+ } catch (const std::exception& ex) {
+ error = { ex.what() };
+ return {};
+ }
}
+};
+
+template <class T, class...Args>
+optional<T> convert(const v8::Local<v8::Value>& value, Error& error, Args&&...args) {
+ return convert<T>(Convertible(value), error, std::forward<Args>(args)...);
}
} // namespace conversion
diff --git a/platform/node/src/node_expression.cpp b/platform/node/src/node_expression.cpp
new file mode 100644
index 0000000000..8958d5c6c7
--- /dev/null
+++ b/platform/node/src/node_expression.cpp
@@ -0,0 +1,230 @@
+#include "node_conversion.hpp"
+#include "node_expression.hpp"
+
+#include <mbgl/style/expression/parsing_context.hpp>
+#include <mbgl/style/expression/is_constant.hpp>
+#include <mbgl/style/conversion/geojson.hpp>
+#include <mbgl/util/geojson.hpp>
+#include <nan.h>
+
+using namespace mbgl::style;
+using namespace mbgl::style::expression;
+
+namespace node_mbgl {
+
+Nan::Persistent<v8::Function> NodeExpression::constructor;
+
+void NodeExpression::Init(v8::Local<v8::Object> target) {
+ v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
+ tpl->SetClassName(Nan::New("Expression").ToLocalChecked());
+ tpl->InstanceTemplate()->SetInternalFieldCount(1); // what is this doing?
+
+ Nan::SetPrototypeMethod(tpl, "evaluate", Evaluate);
+ Nan::SetPrototypeMethod(tpl, "getType", GetType);
+ Nan::SetPrototypeMethod(tpl, "isFeatureConstant", IsFeatureConstant);
+ Nan::SetPrototypeMethod(tpl, "isZoomConstant", IsZoomConstant);
+
+ Nan::SetMethod(tpl, "parse", Parse);
+
+ constructor.Reset(tpl->GetFunction()); // what is this doing?
+ Nan::Set(target, Nan::New("Expression").ToLocalChecked(), tpl->GetFunction());
+}
+
+type::Type parseType(v8::Local<v8::Object> type) {
+ static std::unordered_map<std::string, type::Type> types = {
+ {"string", type::String},
+ {"number", type::Number},
+ {"noolean", type::Boolean},
+ {"object", type::Object},
+ {"color", type::Color},
+ {"value", type::Value}
+ };
+
+ v8::Local<v8::Value> v8kind = Nan::Get(type, Nan::New("kind").ToLocalChecked()).ToLocalChecked();
+ std::string kind(*v8::String::Utf8Value(v8kind));
+
+ if (kind == "array") {
+ type::Type itemType = parseType(Nan::Get(type, Nan::New("itemType").ToLocalChecked()).ToLocalChecked()->ToObject());
+ mbgl::optional<std::size_t> N;
+
+ v8::Local<v8::String> Nkey = Nan::New("N").ToLocalChecked();
+ if (Nan::Has(type, Nkey).FromMaybe(false)) {
+ N = Nan::Get(type, Nkey).ToLocalChecked()->ToInt32()->Value();
+ }
+ return type::Array(itemType, N);
+ }
+
+ return types[kind];
+}
+
+void NodeExpression::Parse(const Nan::FunctionCallbackInfo<v8::Value>& info) {
+ v8::Local<v8::Function> cons = Nan::New(constructor);
+
+ if (info.Length() < 1 || info[0]->IsUndefined()) {
+ return Nan::ThrowTypeError("Requires a JSON style expression argument.");
+ }
+
+ mbgl::optional<type::Type> expected;
+ if (info.Length() > 1 && info[1]->IsObject()) {
+ expected = parseType(info[1]->ToObject());
+ }
+
+ auto expr = info[0];
+
+ try {
+ ParsingContext ctx(expected);
+ ParseResult parsed = ctx.parse(mbgl::style::conversion::Convertible(expr));
+ if (parsed) {
+ assert(ctx.getErrors().size() == 0);
+ auto nodeExpr = new NodeExpression(std::move(*parsed));
+ const int argc = 0;
+ v8::Local<v8::Value> argv[0] = {};
+ auto wrapped = Nan::NewInstance(cons, argc, argv).ToLocalChecked();
+ nodeExpr->Wrap(wrapped);
+ info.GetReturnValue().Set(wrapped);
+ return;
+ }
+
+ v8::Local<v8::Array> result = Nan::New<v8::Array>();
+ for (std::size_t i = 0; i < ctx.getErrors().size(); i++) {
+ const auto& error = ctx.getErrors()[i];
+ v8::Local<v8::Object> err = Nan::New<v8::Object>();
+ Nan::Set(err,
+ Nan::New("key").ToLocalChecked(),
+ Nan::New(error.key.c_str()).ToLocalChecked());
+ Nan::Set(err,
+ Nan::New("error").ToLocalChecked(),
+ Nan::New(error.message.c_str()).ToLocalChecked());
+ Nan::Set(result, Nan::New((uint32_t)i), err);
+ }
+ info.GetReturnValue().Set(result);
+ } catch(std::exception &ex) {
+ return Nan::ThrowError(ex.what());
+ }
+}
+
+void NodeExpression::New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
+ if (!info.IsConstructCall()) {
+ return Nan::ThrowTypeError("Use the new operator to create new Expression objects");
+ }
+
+ info.GetReturnValue().Set(info.This());
+}
+
+struct ToValue {
+ v8::Local<v8::Value> operator()(mbgl::NullValue) {
+ Nan::EscapableHandleScope scope;
+ return scope.Escape(Nan::Null());
+ }
+
+ v8::Local<v8::Value> operator()(bool t) {
+ Nan::EscapableHandleScope scope;
+ return scope.Escape(Nan::New(t));
+ }
+
+ v8::Local<v8::Value> operator()(double t) {
+ Nan::EscapableHandleScope scope;
+ return scope.Escape(Nan::New(t));
+ }
+
+ v8::Local<v8::Value> operator()(const std::string& t) {
+ Nan::EscapableHandleScope scope;
+ return scope.Escape(Nan::New(t).ToLocalChecked());
+ }
+
+ v8::Local<v8::Value> operator()(const std::vector<Value>& array) {
+ Nan::EscapableHandleScope scope;
+ v8::Local<v8::Array> result = Nan::New<v8::Array>();
+ for (unsigned int i = 0; i < array.size(); i++) {
+ result->Set(i, toJS(array[i]));
+ }
+ return scope.Escape(result);
+ }
+
+ v8::Local<v8::Value> operator()(const mbgl::Color& color) {
+ return operator()(std::vector<Value> {
+ static_cast<double>(color.r),
+ static_cast<double>(color.g),
+ static_cast<double>(color.b),
+ static_cast<double>(color.a)
+ });
+ }
+
+ v8::Local<v8::Value> operator()(const std::unordered_map<std::string, Value>& map) {
+ Nan::EscapableHandleScope scope;
+ v8::Local<v8::Object> result = Nan::New<v8::Object>();
+ for (const auto& entry : map) {
+ Nan::Set(result, Nan::New(entry.first).ToLocalChecked(), toJS(entry.second));
+ }
+
+ return scope.Escape(result);
+ }
+};
+
+v8::Local<v8::Value> toJS(const Value& value) {
+ return Value::visit(value, ToValue());
+}
+
+void NodeExpression::Evaluate(const Nan::FunctionCallbackInfo<v8::Value>& info) {
+ NodeExpression* nodeExpr = ObjectWrap::Unwrap<NodeExpression>(info.Holder());
+ const std::unique_ptr<Expression>& expression = nodeExpr->expression;
+
+ if (info.Length() < 2 || !info[0]->IsObject()) {
+ return Nan::ThrowTypeError("Requires globals and feature arguments.");
+ }
+
+ mbgl::optional<float> zoom;
+ v8::Local<v8::Value> v8zoom = Nan::Get(info[0]->ToObject(), Nan::New("zoom").ToLocalChecked()).ToLocalChecked();
+ if (v8zoom->IsNumber()) zoom = v8zoom->NumberValue();
+
+ mbgl::optional<double> heatmapDensity;
+ v8::Local<v8::Value> v8heatmapDensity = Nan::Get(info[0]->ToObject(), Nan::New("heatmapDensity").ToLocalChecked()).ToLocalChecked();
+ if (v8heatmapDensity->IsNumber()) heatmapDensity = v8heatmapDensity->NumberValue();
+
+ Nan::JSON NanJSON;
+ conversion::Error conversionError;
+ mbgl::optional<mbgl::GeoJSON> geoJSON = conversion::convert<mbgl::GeoJSON>(info[1], conversionError);
+ if (!geoJSON) {
+ Nan::ThrowTypeError(conversionError.message.c_str());
+ return;
+ }
+
+ try {
+ mapbox::geojson::feature feature = geoJSON->get<mapbox::geojson::feature>();
+ auto result = expression->evaluate(zoom, feature, heatmapDensity);
+ if (result) {
+ info.GetReturnValue().Set(toJS(*result));
+ } else {
+ v8::Local<v8::Object> res = Nan::New<v8::Object>();
+ Nan::Set(res,
+ Nan::New("error").ToLocalChecked(),
+ Nan::New(result.error().message.c_str()).ToLocalChecked());
+ info.GetReturnValue().Set(res);
+ }
+ } catch(std::exception &ex) {
+ return Nan::ThrowTypeError(ex.what());
+ }
+}
+
+void NodeExpression::GetType(const Nan::FunctionCallbackInfo<v8::Value>& info) {
+ NodeExpression* nodeExpr = ObjectWrap::Unwrap<NodeExpression>(info.Holder());
+ const std::unique_ptr<Expression>& expression = nodeExpr->expression;
+
+ const type::Type type = expression->getType();
+ const std::string name = type.match([&] (const auto& t) { return t.getName(); });
+ info.GetReturnValue().Set(Nan::New(name.c_str()).ToLocalChecked());
+}
+
+void NodeExpression::IsFeatureConstant(const Nan::FunctionCallbackInfo<v8::Value>& info) {
+ NodeExpression* nodeExpr = ObjectWrap::Unwrap<NodeExpression>(info.Holder());
+ const std::unique_ptr<Expression>& expression = nodeExpr->expression;
+ info.GetReturnValue().Set(Nan::New(isFeatureConstant(*expression)));
+}
+
+void NodeExpression::IsZoomConstant(const Nan::FunctionCallbackInfo<v8::Value>& info) {
+ NodeExpression* nodeExpr = ObjectWrap::Unwrap<NodeExpression>(info.Holder());
+ const std::unique_ptr<Expression>& expression = nodeExpr->expression;
+ info.GetReturnValue().Set(Nan::New(isZoomConstant(*expression)));
+}
+
+} // namespace node_mbgl
diff --git a/platform/node/src/node_expression.hpp b/platform/node/src/node_expression.hpp
new file mode 100644
index 0000000000..7af5b7ab51
--- /dev/null
+++ b/platform/node/src/node_expression.hpp
@@ -0,0 +1,40 @@
+#pragma once
+
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/expression/expression.hpp>
+#include <exception>
+#include <memory>
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#pragma GCC diagnostic ignored "-Wshadow"
+#include <nan.h>
+#pragma GCC diagnostic pop
+
+using namespace mbgl::style::expression;
+
+namespace node_mbgl {
+
+v8::Local<v8::Value> toJS(const Value&);
+
+class NodeExpression : public Nan::ObjectWrap {
+public:
+ static void Init(v8::Local<v8::Object>);
+
+private:
+ NodeExpression(std::unique_ptr<Expression> expression_) :
+ expression(std::move(expression_))
+ {};
+
+ static void New(const Nan::FunctionCallbackInfo<v8::Value>&);
+ static void Parse(const Nan::FunctionCallbackInfo<v8::Value>&);
+ static void Evaluate(const Nan::FunctionCallbackInfo<v8::Value>&);
+ static void GetType(const Nan::FunctionCallbackInfo<v8::Value>&);
+ static void IsFeatureConstant(const Nan::FunctionCallbackInfo<v8::Value>&);
+ static void IsZoomConstant(const Nan::FunctionCallbackInfo<v8::Value>&);
+ static Nan::Persistent<v8::Function> constructor;
+
+ std::unique_ptr<Expression> expression;
+};
+
+} // namespace node_mbgl
diff --git a/platform/node/src/node_geojson.hpp b/platform/node/src/node_geojson.hpp
deleted file mode 100644
index 8a3927e2cf..0000000000
--- a/platform/node/src/node_geojson.hpp
+++ /dev/null
@@ -1,17 +0,0 @@
-#include <mbgl/style/conversion/geojson.hpp>
-
-#include <string>
-namespace mbgl {
-namespace style {
-namespace conversion {
-
-template <>
-optional<GeoJSON> Converter<GeoJSON>::operator()(const v8::Local<v8::Value>& value, Error& error) const {
- Nan::JSON JSON;
- std::string string = *Nan::Utf8String(JSON.Stringify(value->ToObject()).ToLocalChecked());
- return convert<GeoJSON>(string, error);
-}
-
-} // namespace conversion
-} // namespace style
-} // namespace mbgl
diff --git a/platform/node/src/node_map.cpp b/platform/node/src/node_map.cpp
index 9a7ebce445..b8c5e9cc88 100644
--- a/platform/node/src/node_map.cpp
+++ b/platform/node/src/node_map.cpp
@@ -2,7 +2,6 @@
#include "node_request.hpp"
#include "node_feature.hpp"
#include "node_conversion.hpp"
-#include "node_geojson.hpp"
#include <mbgl/util/exception.hpp>
#include <mbgl/renderer/renderer.hpp>
@@ -10,6 +9,15 @@
#include <mbgl/style/conversion/source.hpp>
#include <mbgl/style/conversion/layer.hpp>
#include <mbgl/style/conversion/filter.hpp>
+
+#include <mbgl/style/layers/background_layer.hpp>
+#include <mbgl/style/layers/circle_layer.hpp>
+#include <mbgl/style/layers/fill_layer.hpp>
+#include <mbgl/style/layers/fill_extrusion_layer.hpp>
+#include <mbgl/style/layers/line_layer.hpp>
+#include <mbgl/style/layers/raster_layer.hpp>
+#include <mbgl/style/layers/symbol_layer.hpp>
+
#include <mbgl/style/style.hpp>
#include <mbgl/style/image.hpp>
#include <mbgl/map/map_observer.hpp>
@@ -26,6 +34,9 @@ struct NodeMap::RenderOptions {
double latitude = 0;
double longitude = 0;
mbgl::Size size = { 512, 512 };
+ bool axonometric = false;
+ double xSkew = 0;
+ double ySkew = 1;
std::vector<std::string> classes;
mbgl::MapDebugOptions debugOptions = mbgl::MapDebugOptions::NoDebug;
};
@@ -65,6 +76,9 @@ void NodeMap::Init(v8::Local<v8::Object> target) {
Nan::SetPrototypeMethod(tpl, "setZoom", SetZoom);
Nan::SetPrototypeMethod(tpl, "setBearing", SetBearing);
Nan::SetPrototypeMethod(tpl, "setPitch", SetPitch);
+ Nan::SetPrototypeMethod(tpl, "setAxonometric", SetAxonometric);
+ Nan::SetPrototypeMethod(tpl, "setXSkew", SetXSkew);
+ Nan::SetPrototypeMethod(tpl, "setYSkew", SetYSkew);
Nan::SetPrototypeMethod(tpl, "dumpDebugLogs", DumpDebugLogs);
Nan::SetPrototypeMethod(tpl, "queryRenderedFeatures", QueryRenderedFeatures);
@@ -251,6 +265,19 @@ NodeMap::RenderOptions NodeMap::ParseOptions(v8::Local<v8::Object> obj) {
options.pitch = Nan::Get(obj, Nan::New("pitch").ToLocalChecked()).ToLocalChecked()->NumberValue();
}
+ if (Nan::Has(obj, Nan::New("axonometric").ToLocalChecked()).FromJust()) {
+ options.axonometric = Nan::Get(obj, Nan::New("axonometric").ToLocalChecked()).ToLocalChecked()->BooleanValue();
+ }
+
+ if (Nan::Has(obj, Nan::New("skew").ToLocalChecked()).FromJust()) {
+ auto skewObj = Nan::Get(obj, Nan::New("skew").ToLocalChecked()).ToLocalChecked();
+ if (skewObj->IsArray()) {
+ auto skew = skewObj.As<v8::Array>();
+ if (skew->Length() > 0) { options.xSkew = Nan::Get(skew, 0).ToLocalChecked()->NumberValue(); }
+ if (skew->Length() > 1) { options.ySkew = Nan::Get(skew, 1).ToLocalChecked()->NumberValue(); }
+ }
+ }
+
if (Nan::Has(obj, Nan::New("center").ToLocalChecked()).FromJust()) {
auto centerObj = Nan::Get(obj, Nan::New("center").ToLocalChecked()).ToLocalChecked();
if (centerObj->IsArray()) {
@@ -370,6 +397,18 @@ void NodeMap::startRender(NodeMap::RenderOptions options) {
camera.angle = -options.bearing * mbgl::util::DEG2RAD;
camera.pitch = options.pitch * mbgl::util::DEG2RAD;
+ if (map->getAxonometric() != options.axonometric) {
+ map->setAxonometric(options.axonometric);
+ }
+
+ if (map->getXSkew() != options.xSkew) {
+ map->setXSkew(options.xSkew);
+ }
+
+ if (map->getYSkew() != options.ySkew) {
+ map->setYSkew(options.ySkew);
+ }
+
map->renderStill(camera, options.debugOptions, [this](const std::exception_ptr eptr) {
if (eptr) {
error = std::move(eptr);
@@ -477,6 +516,7 @@ void NodeMap::release() {
});
map.reset();
+ frontend.reset();
}
/**
@@ -508,7 +548,7 @@ void NodeMap::cancel() {
frontend = std::make_unique<mbgl::HeadlessFrontend>(mbgl::Size{ 256, 256 }, pixelRatio, *this, threadpool);
map = std::make_unique<mbgl::Map>(*frontend, mapObserver, frontend->getSize(), pixelRatio,
- *this, threadpool, mbgl::MapMode::Still);
+ *this, threadpool, mode);
// FIXME: Reload the style after recreating the map. We need to find
// a better way of canceling an ongoing rendering on the core level
@@ -709,7 +749,7 @@ void NodeMap::SetLayoutProperty(const Nan::FunctionCallbackInfo<v8::Value>& info
return Nan::ThrowTypeError("Second argument must be a string");
}
- mbgl::optional<Error> error = setLayoutProperty(*layer, *Nan::Utf8String(info[1]), info[2]);
+ mbgl::optional<Error> error = setLayoutProperty(*layer, *Nan::Utf8String(info[1]), Convertible(info[2]));
if (error) {
return Nan::ThrowTypeError(error->message.c_str());
}
@@ -741,7 +781,7 @@ void NodeMap::SetPaintProperty(const Nan::FunctionCallbackInfo<v8::Value>& info)
return Nan::ThrowTypeError("Second argument must be a string");
}
- mbgl::optional<Error> error = setPaintProperty(*layer, *Nan::Utf8String(info[1]), info[2]);
+ mbgl::optional<Error> error = setPaintProperty(*layer, *Nan::Utf8String(info[1]), Convertible(info[2]));
if (error) {
return Nan::ThrowTypeError(error->message.c_str());
}
@@ -879,6 +919,57 @@ void NodeMap::SetPitch(const Nan::FunctionCallbackInfo<v8::Value>& info) {
info.GetReturnValue().SetUndefined();
}
+void NodeMap::SetAxonometric(const Nan::FunctionCallbackInfo<v8::Value>& info) {
+ auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(info.Holder());
+ if (!nodeMap->map) return Nan::ThrowError(releasedMessage());
+
+ if (info.Length() <= 0 || !info[0]->IsBoolean()) {
+ return Nan::ThrowTypeError("First argument must be a boolean");
+ }
+
+ try {
+ nodeMap->map->setAxonometric(info[0]->BooleanValue());
+ } catch (const std::exception &ex) {
+ return Nan::ThrowError(ex.what());
+ }
+
+ info.GetReturnValue().SetUndefined();
+}
+
+void NodeMap::SetXSkew(const Nan::FunctionCallbackInfo<v8::Value>& info) {
+ auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(info.Holder());
+ if (!nodeMap->map) return Nan::ThrowError(releasedMessage());
+
+ if (info.Length() <= 0 || !info[0]->IsNumber()) {
+ return Nan::ThrowTypeError("First argument must be a number");
+ }
+
+ try {
+ nodeMap->map->setXSkew(info[0]->NumberValue());
+ } catch (const std::exception &ex) {
+ return Nan::ThrowError(ex.what());
+ }
+
+ info.GetReturnValue().SetUndefined();
+}
+
+void NodeMap::SetYSkew(const Nan::FunctionCallbackInfo<v8::Value>& info) {
+ auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(info.Holder());
+ if (!nodeMap->map) return Nan::ThrowError(releasedMessage());
+
+ if (info.Length() <= 0 || !info[0]->IsNumber()) {
+ return Nan::ThrowTypeError("First argument must be a number");
+ }
+
+ try {
+ nodeMap->map->setYSkew(info[0]->NumberValue());
+ } catch (const std::exception &ex) {
+ return Nan::ThrowError(ex.what());
+ }
+
+ info.GetReturnValue().SetUndefined();
+}
+
void NodeMap::DumpDebugLogs(const Nan::FunctionCallbackInfo<v8::Value>& info) {
auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(info.Holder());
if (!nodeMap->map) return Nan::ThrowError(releasedMessage());
@@ -983,6 +1074,15 @@ NodeMap::NodeMap(v8::Local<v8::Object> options)
->NumberValue()
: 1.0;
}())
+ , mode([&] {
+ Nan::HandleScope scope;
+ if (Nan::Has(options, Nan::New("mode").ToLocalChecked()).FromJust() &&
+ std::string(*v8::String::Utf8Value(Nan::Get(options, Nan::New("mode").ToLocalChecked()).ToLocalChecked()->ToString())) == "tile") {
+ return mbgl::MapMode::Tile;
+ } else {
+ return mbgl::MapMode::Static;
+ }
+ }())
, mapObserver(NodeMapObserver())
, frontend(std::make_unique<mbgl::HeadlessFrontend>(mbgl::Size { 256, 256 }, pixelRatio, *this, threadpool))
, map(std::make_unique<mbgl::Map>(*frontend,
@@ -991,7 +1091,7 @@ NodeMap::NodeMap(v8::Local<v8::Object> options)
pixelRatio,
*this,
threadpool,
- mbgl::MapMode::Still)),
+ mode)),
async(new uv_async_t) {
async->data = this;
diff --git a/platform/node/src/node_map.hpp b/platform/node/src/node_map.hpp
index c8e33bb347..b84f4d576f 100644
--- a/platform/node/src/node_map.hpp
+++ b/platform/node/src/node_map.hpp
@@ -57,6 +57,9 @@ public:
static void SetZoom(const Nan::FunctionCallbackInfo<v8::Value>&);
static void SetBearing(const Nan::FunctionCallbackInfo<v8::Value>&);
static void SetPitch(const Nan::FunctionCallbackInfo<v8::Value>&);
+ static void SetAxonometric(const Nan::FunctionCallbackInfo<v8::Value>&);
+ static void SetXSkew(const Nan::FunctionCallbackInfo<v8::Value>&);
+ static void SetYSkew(const Nan::FunctionCallbackInfo<v8::Value>&);
static void DumpDebugLogs(const Nan::FunctionCallbackInfo<v8::Value>&);
static void QueryRenderedFeatures(const Nan::FunctionCallbackInfo<v8::Value>&);
@@ -71,6 +74,7 @@ public:
std::unique_ptr<mbgl::AsyncRequest> request(const mbgl::Resource&, mbgl::FileSource::Callback);
const float pixelRatio;
+ mbgl::MapMode mode;
NodeThreadPool threadpool;
NodeMapObserver mapObserver;
std::unique_ptr<mbgl::HeadlessFrontend> frontend;
diff --git a/platform/node/src/node_mapbox_gl_native.cpp b/platform/node/src/node_mapbox_gl_native.cpp
index cdcc982220..96e96e4298 100644
--- a/platform/node/src/node_mapbox_gl_native.cpp
+++ b/platform/node/src/node_mapbox_gl_native.cpp
@@ -10,6 +10,7 @@
#include "node_map.hpp"
#include "node_logging.hpp"
#include "node_request.hpp"
+#include "node_expression.hpp"
void RegisterModule(v8::Local<v8::Object> target, v8::Local<v8::Object> module) {
// This has the effect of:
@@ -20,6 +21,7 @@ void RegisterModule(v8::Local<v8::Object> target, v8::Local<v8::Object> module)
node_mbgl::NodeMap::Init(target);
node_mbgl::NodeRequest::Init();
+ node_mbgl::NodeExpression::Init(target);
// Exports Resource constants.
v8::Local<v8::Object> resource = Nan::New<v8::Object>();
diff --git a/platform/node/test/expression.test.js b/platform/node/test/expression.test.js
new file mode 100644
index 0000000000..aac039ce18
--- /dev/null
+++ b/platform/node/test/expression.test.js
@@ -0,0 +1,71 @@
+'use strict';
+
+var suite = require('../../../mapbox-gl-js/test/integration').expression;
+var mbgl = require('../index');
+var ignores = require('./ignores.json');
+
+var tests;
+
+if (process.argv[1] === __filename && process.argv.length > 2) {
+ tests = process.argv.slice(2);
+}
+
+function getExpectedType(spec) {
+ if (spec.type === 'array') {
+ const itemType = getExpectedType({ type: spec.value });
+ const array = {
+ kind: 'array',
+ itemType: itemType || { kind: 'value' },
+ };
+ if (typeof spec.length === 'number') {
+ array.N = spec.length;
+ }
+ return array;
+ }
+
+ if (spec.type === 'enum') {
+ return { kind: 'string' };
+ }
+
+ return typeof spec.type === 'string' ? {kind: spec.type} : null;
+}
+
+suite.run('native', {ignores: ignores, tests: tests}, (fixture) => {
+ const compiled = {};
+ const result = {
+ compiled
+ };
+
+ const spec = fixture.propertySpec || {};
+ const expression = mbgl.Expression.parse(fixture.expression, getExpectedType(spec));
+
+ if (expression instanceof mbgl.Expression) {
+ compiled.result = 'success';
+ compiled.isFeatureConstant = expression.isFeatureConstant();
+ compiled.isZoomConstant = expression.isZoomConstant();
+ compiled.type = expression.getType();
+
+ const evaluate = fixture.inputs || [];
+ const evaluateResults = [];
+ for (const input of evaluate) {
+ const feature = Object.assign({
+ type: 'Feature',
+ properties: {},
+ geometry: { type: 'Point', coordinates: [0, 0] }
+ }, input[1])
+
+ const output = expression.evaluate(input[0], feature);
+ evaluateResults.push(output);
+ }
+
+ if (fixture.inputs) {
+ result.outputs = evaluateResults;
+ }
+ } else {
+ compiled.result = 'error';
+ compiled.errors = expression;
+ }
+
+ return result;
+});
+
diff --git a/platform/node/test/ignores.json b/platform/node/test/ignores.json
index 1084a5c923..62e042cd4d 100644
--- a/platform/node/test/ignores.json
+++ b/platform/node/test/ignores.json
@@ -1,59 +1,153 @@
{
+ "expression-tests/array/implicit-1": "https://github.com/mapbox/mapbox-gl-native/issues/10533",
+ "expression-tests/array/implicit-2": "https://github.com/mapbox/mapbox-gl-native/issues/10533",
+ "expression-tests/array/implicit-3": "https://github.com/mapbox/mapbox-gl-native/issues/10533",
+ "expression-tests/coalesce/inference": "https://github.com/mapbox/mapbox-gl-native/issues/10588",
+ "expression-tests/equal/array": "https://github.com/mapbox/mapbox-gl-native/issues/10678",
+ "expression-tests/equal/color": "https://github.com/mapbox/mapbox-gl-native/issues/10678",
+ "expression-tests/equal/mismatch": "https://github.com/mapbox/mapbox-gl-native/issues/10678",
+ "expression-tests/equal/null-lhs": "https://github.com/mapbox/mapbox-gl-native/issues/10678",
+ "expression-tests/equal/null-rhs": "https://github.com/mapbox/mapbox-gl-native/issues/10678",
+ "expression-tests/equal/number": "https://github.com/mapbox/mapbox-gl-native/issues/10678",
+ "expression-tests/equal/object": "https://github.com/mapbox/mapbox-gl-native/issues/10678",
+ "expression-tests/equal/string": "https://github.com/mapbox/mapbox-gl-native/issues/10678",
+ "expression-tests/equal/value": "https://github.com/mapbox/mapbox-gl-native/issues/10678",
+ "expression-tests/not_equal/mismatch": "https://github.com/mapbox/mapbox-gl-native/issues/10678",
+ "expression-tests/not_equal/number": "https://github.com/mapbox/mapbox-gl-native/issues/10678",
+ "expression-tests/not_equal/string": "https://github.com/mapbox/mapbox-gl-native/issues/10678",
+ "expression-tests/not_equal/value": "https://github.com/mapbox/mapbox-gl-native/issues/10678",
+ "expression-tests/interpolate/linear-color": "https://github.com/mapbox/mapbox-gl-native/issues/10604",
+ "expression-tests/to-rgba/alpha": "https://github.com/mapbox/mapbox-gl-native/issues/10604",
+ "expression-tests/to-rgba/basic": "https://github.com/mapbox/mapbox-gl-native/issues/10604",
+ "query-tests/circle-stroke-width/inside": "https://github.com/mapbox/mapbox-gl-native/issues/10307",
"query-tests/geometry/multilinestring": "needs investigation",
"query-tests/geometry/multipolygon": "needs investigation",
"query-tests/geometry/polygon": "needs investigation",
- "query-tests/regressions/mapbox-gl-js#3534": "https://github.com/mapbox/mapbox-gl-native/issues/8193",
- "query-tests/regressions/mapbox-gl-js#4417": "https://github.com/mapbox/mapbox-gl-native/issues/8007",
- "query-tests/symbol-features-in/pitched-screen": "https://github.com/mapbox/mapbox-gl-native/issues/6817",
- "query-tests/symbol-features-in/tilted-inside": "https://github.com/mapbox/mapbox-gl-native/issues/5056",
- "query-tests/symbol-features-in/tilted-outside": "https://github.com/mapbox/mapbox-gl-native/issues/9435",
+ "query-tests/symbol/panned-after-insert": "https://github.com/mapbox/mapbox-gl-native/issues/10408",
+ "query-tests/symbol/rotated-after-insert": "https://github.com/mapbox/mapbox-gl-native/issues/10408",
"query-tests/world-wrapping/box": "skip - needs issue",
"query-tests/world-wrapping/point": "skip - needs issue",
- "render-tests/debug/collision-overscaled": "https://github.com/mapbox/mapbox-gl-native/issues/3841",
- "render-tests/debug/collision-pitched-wrapped": "https://github.com/mapbox/mapbox-gl-native/issues/3841",
- "render-tests/debug/collision-pitched": "https://github.com/mapbox/mapbox-gl-native/issues/3841",
+ "render-tests/background-color/transition": "https://github.com/mapbox/mapbox-gl-native/issues/10619",
"render-tests/debug/collision": "https://github.com/mapbox/mapbox-gl-native/issues/3841",
- "render-tests/debug/tile-overscaled": "https://github.com/mapbox/mapbox-gl-native/issues/3841",
+ "render-tests/debug/collision-lines": "https://github.com/mapbox/mapbox-gl-native/issues/10412",
+ "render-tests/debug/collision-lines-pitched": "https://github.com/mapbox/mapbox-gl-native/issues/10412",
+ "render-tests/debug/collision-pitched-wrapped": "https://github.com/mapbox/mapbox-gl-native/issues/10412",
"render-tests/debug/tile": "https://github.com/mapbox/mapbox-gl-native/issues/3841",
+ "render-tests/debug/tile-overscaled": "https://github.com/mapbox/mapbox-gl-native/issues/3841",
"render-tests/extent/1024-circle": "needs investigation",
- "render-tests/extent/1024-symbol": "needs investigation",
"render-tests/fill-extrusion-pattern/@2x": "https://github.com/mapbox/mapbox-gl-js/issues/3327",
- "render-tests/fill-extrusion-pattern/function-2": "https://github.com/mapbox/mapbox-gl-js/issues/3327",
"render-tests/fill-extrusion-pattern/function": "https://github.com/mapbox/mapbox-gl-js/issues/3327",
+ "render-tests/fill-extrusion-pattern/function-2": "https://github.com/mapbox/mapbox-gl-js/issues/3327",
"render-tests/fill-extrusion-pattern/literal": "https://github.com/mapbox/mapbox-gl-js/issues/3327",
"render-tests/fill-extrusion-pattern/missing": "https://github.com/mapbox/mapbox-gl-js/issues/3327",
"render-tests/fill-extrusion-pattern/opacity": "https://github.com/mapbox/mapbox-gl-js/issues/3327",
"render-tests/geojson/inline-linestring-fill": "current behavior is arbitrary",
"render-tests/geojson/inline-polygon-symbol": "behavior needs reconciliation with gl-js",
+ "render-tests/heatmap-color/default": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/heatmap-color/expression": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/heatmap-color/function": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/heatmap-intensity/default": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/heatmap-intensity/function": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/heatmap-intensity/literal": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/heatmap-opacity/default": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/heatmap-opacity/function": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/heatmap-opacity/literal": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/heatmap-radius/antimeridian": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/heatmap-radius/data-expression": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/heatmap-radius/default": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/heatmap-radius/function": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/heatmap-radius/literal": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/heatmap-radius/pitch30": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/heatmap-weight/default": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/heatmap-weight/identity-property-function": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/heatmap-weight/literal": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
"render-tests/icon-size/composite-function-high-base-plain": "https://github.com/mapbox/mapbox-gl-native/issues/8654",
"render-tests/icon-size/composite-function-high-base-sdf": "https://github.com/mapbox/mapbox-gl-native/issues/8654",
- "render-tests/icon-text-fit/both-padding": "https://github.com/mapbox/mapbox-gl-native/issues/5602",
- "render-tests/icon-text-fit/both": "https://github.com/mapbox/mapbox-gl-native/issues/5602",
- "render-tests/icon-text-fit/height": "https://github.com/mapbox/mapbox-gl-native/issues/5602",
- "render-tests/icon-text-fit/width-padding": "https://github.com/mapbox/mapbox-gl-native/issues/5602",
- "render-tests/icon-text-fit/width": "https://github.com/mapbox/mapbox-gl-native/issues/5602",
- "render-tests/line-width/property-function": "https://github.com/mapbox/mapbox-gl-js/issues/3682#issuecomment-264348200",
- "render-tests/line-join/property-function": "https://github.com/mapbox/mapbox-gl-js/pull/5020",
- "render-tests/line-join/property-function-dasharray": "https://github.com/mapbox/mapbox-gl-js/pull/5020",
- "render-tests/line-opacity/step-curve": "https://github.com/mapbox/mapbox-gl-native/pull/9439",
+ "render-tests/mixed-zoom/z10-z11": "https://github.com/mapbox/mapbox-gl-native/issues/10397",
+ "render-tests/raster-masking/overlapping-zoom": "https://github.com/mapbox/mapbox-gl-native/issues/10195",
"render-tests/regressions/mapbox-gl-js#2305": "https://github.com/mapbox/mapbox-gl-native/issues/6927",
+ "render-tests/regressions/mapbox-gl-js#2467": "https://github.com/mapbox/mapbox-gl-native/issues/10619",
+ "render-tests/regressions/mapbox-gl-js#2762": "https://github.com/mapbox/mapbox-gl-native/issues/10619",
+ "render-tests/regressions/mapbox-gl-js#2769": "https://github.com/mapbox/mapbox-gl-native/issues/10619",
"render-tests/regressions/mapbox-gl-js#3682": "https://github.com/mapbox/mapbox-gl-js/issues/3682",
+ "render-tests/regressions/mapbox-gl-js#4172": "https://github.com/mapbox/mapbox-gl-native/issues/10618",
+ "render-tests/regressions/mapbox-gl-js#5370": "skip - https://github.com/mapbox/mapbox-gl-native/pull/9439",
+ "render-tests/regressions/mapbox-gl-js#5599": "https://github.com/mapbox/mapbox-gl-native/issues/10399",
+ "render-tests/regressions/mapbox-gl-js#5740": "https://github.com/mapbox/mapbox-gl-native/issues/10619",
"render-tests/regressions/mapbox-gl-native#7357": "https://github.com/mapbox/mapbox-gl-native/issues/7357",
"render-tests/runtime-styling/image-add-sdf": "https://github.com/mapbox/mapbox-gl-native/issues/9847",
"render-tests/runtime-styling/paint-property-fill-flat-to-extrude": "https://github.com/mapbox/mapbox-gl-native/issues/6745",
"render-tests/runtime-styling/set-style-paint-property-fill-flat-to-extrude": "https://github.com/mapbox/mapbox-gl-native/issues/6745",
- "render-tests/symbol-placement/line": "needs issue",
- "render-tests/text-font/camera-function": "https://github.com/mapbox/mapbox-gl-native/pull/9439",
- "render-tests/text-keep-upright/line-placement-true-offset": "https://github.com/mapbox/mapbox-gl-native/issues/9271",
+ "render-tests/symbol-placement/line-overscaled": "https://github.com/mapbox/mapbox-gl-js/issues/5654",
+ "render-tests/symbol-visibility/visible": "https://github.com/mapbox/mapbox-gl-native/issues/10409",
+ "render-tests/text-font/data-expression": "https://github.com/mapbox/mapbox-gl-native/issues/10535",
"render-tests/text-pitch-alignment/auto-text-rotation-alignment-map": "https://github.com/mapbox/mapbox-gl-native/issues/9732",
- "render-tests/text-pitch-alignment/auto-text-rotation-alignment-viewport": "https://github.com/mapbox/mapbox-gl-native/issues/9732",
"render-tests/text-pitch-alignment/map-text-rotation-alignment-map": "https://github.com/mapbox/mapbox-gl-native/issues/9732",
- "render-tests/text-pitch-alignment/map-text-rotation-alignment-viewport": "https://github.com/mapbox/mapbox-gl-native/issues/9732",
- "render-tests/text-pitch-alignment/viewport-overzoomed": "https://github.com/mapbox/mapbox-gl-js/issues/5095",
- "render-tests/text-pitch-alignment/viewport-overzoomed-single-glyph": "https://github.com/mapbox/mapbox-gl-js/issues/5095",
"render-tests/text-pitch-alignment/viewport-text-rotation-alignment-map": "https://github.com/mapbox/mapbox-gl-native/issues/9732",
- "render-tests/text-pitch-alignment/viewport-text-rotation-alignment-viewport": "https://github.com/mapbox/mapbox-gl-native/issues/9732",
"render-tests/text-pitch-scaling/line-half": "https://github.com/mapbox/mapbox-gl-native/issues/9732",
- "render-tests/text-size/composite-expression": "https://github.com/mapbox/mapbox-gl-native/pull/9439",
- "render-tests/video/default": "skip - https://github.com/mapbox/mapbox-gl-native/issues/601"
+ "render-tests/video/default": "skip - https://github.com/mapbox/mapbox-gl-native/issues/601",
+ "render-tests/background-color/colorSpace-hcl": "needs issue",
+ "render-tests/hillshade-accent-color/default": "skip - https://github.com/mapbox/mapbox-gl-native/pull/10642",
+ "render-tests/hillshade-accent-color/literal": "skip - https://github.com/mapbox/mapbox-gl-native/pull/10642",
+ "render-tests/hillshade-accent-color/zoom-function": "skip - https://github.com/mapbox/mapbox-gl-native/pull/10642",
+ "render-tests/hillshade-highlight-color/default": "skip - https://github.com/mapbox/mapbox-gl-native/pull/10642",
+ "render-tests/hillshade-highlight-color/literal": "skip - https://github.com/mapbox/mapbox-gl-native/pull/10642",
+ "render-tests/hillshade-highlight-color/zoom-function": "skip - https://github.com/mapbox/mapbox-gl-native/pull/10642",
+ "render-tests/hillshade-shadow-color/default": "skip - https://github.com/mapbox/mapbox-gl-native/pull/10642",
+ "render-tests/hillshade-shadow-color/literal": "skip - https://github.com/mapbox/mapbox-gl-native/pull/10642",
+ "render-tests/hillshade-shadow-color/zoom-function": "skip - https://github.com/mapbox/mapbox-gl-native/pull/10642",
+ "render-tests/combinations/background-opaque--heatmap-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/combinations/background-translucent--heatmap-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/combinations/circle-translucent--heatmap-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/combinations/fill-extrusion-translucent--heatmap-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/combinations/fill-opaque--heatmap-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/combinations/fill-translucent--heatmap-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/combinations/heatmap-translucent--background-opaque": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/combinations/heatmap-translucent--background-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/combinations/heatmap-translucent--circle-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/combinations/heatmap-translucent--fill-extrusion-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/combinations/heatmap-translucent--fill-opaque": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/combinations/heatmap-translucent--fill-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/combinations/heatmap-translucent--heatmap-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/combinations/heatmap-translucent--hillshade-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/combinations/heatmap-translucent--line-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/combinations/heatmap-translucent--raster-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/combinations/heatmap-translucent--symbol-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/combinations/line-translucent--heatmap-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/combinations/raster-translucent--heatmap-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/combinations/symbol-translucent--heatmap-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146",
+ "render-tests/combinations/background-opaque--hillshade-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642",
+ "render-tests/combinations/background-translucent--hillshade-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642",
+ "render-tests/combinations/circle-translucent--hillshade-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642",
+ "render-tests/combinations/fill-extrusion-translucent--hillshade-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642",
+ "render-tests/combinations/fill-opaque--hillshade-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642",
+ "render-tests/combinations/fill-translucent--hillshade-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642",
+ "render-tests/combinations/hillshade-translucent--background-opaque": "https://github.com/mapbox/mapbox-gl-native/pull/10642",
+ "render-tests/combinations/hillshade-translucent--background-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642",
+ "render-tests/combinations/hillshade-translucent--circle-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642",
+ "render-tests/combinations/hillshade-translucent--fill-extrusion-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642",
+ "render-tests/combinations/hillshade-translucent--fill-opaque": "https://github.com/mapbox/mapbox-gl-native/pull/10642",
+ "render-tests/combinations/hillshade-translucent--fill-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642",
+ "render-tests/combinations/hillshade-translucent--heatmap-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642",
+ "render-tests/combinations/hillshade-translucent--hillshade-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642",
+ "render-tests/combinations/hillshade-translucent--line-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642",
+ "render-tests/combinations/hillshade-translucent--raster-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642",
+ "render-tests/combinations/hillshade-translucent--symbol-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642",
+ "render-tests/combinations/line-translucent--hillshade-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642",
+ "render-tests/combinations/raster-translucent--hillshade-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642",
+ "render-tests/combinations/symbol-translucent--hillshade-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642",
+ "render-tests/combinations/background-opaque--fill-extrusion-translucent": "needs investigation",
+ "render-tests/combinations/background-translucent--fill-extrusion-translucent": "needs investigation",
+ "render-tests/combinations/circle-translucent--fill-extrusion-translucent": "needs investigation",
+ "render-tests/combinations/fill-extrusion-translucent--background-translucent": "needs investigation",
+ "render-tests/combinations/fill-extrusion-translucent--circle-translucent": "needs investigation",
+ "render-tests/combinations/fill-extrusion-translucent--fill-extrusion-translucent": "needs investigation",
+ "render-tests/combinations/fill-extrusion-translucent--fill-translucent": "needs investigation",
+ "render-tests/combinations/fill-extrusion-translucent--line-translucent": "needs investigation",
+ "render-tests/combinations/fill-extrusion-translucent--symbol-translucent": "needs investigation",
+ "render-tests/combinations/fill-opaque--fill-extrusion-translucent": "needs investigation",
+ "render-tests/combinations/fill-translucent--fill-extrusion-translucent": "needs investigation",
+ "render-tests/combinations/line-translucent--fill-extrusion-translucent": "needs investigation",
+ "render-tests/combinations/raster-translucent--fill-extrusion-translucent": "needs investigation",
+ "render-tests/combinations/symbol-translucent--fill-extrusion-translucent": "needs investigation"
}
diff --git a/platform/node/test/js/map.test.js b/platform/node/test/js/map.test.js
index 39665e41ef..e3c8031908 100644
--- a/platform/node/test/js/map.test.js
+++ b/platform/node/test/js/map.test.js
@@ -121,6 +121,9 @@ test('Map', function(t) {
'setZoom',
'setBearing',
'setPitch',
+ 'setAxonometric',
+ 'setXSkew',
+ 'setYSkew',
'dumpDebugLogs',
'queryRenderedFeatures'
]);
diff --git a/platform/node/test/suite_implementation.js b/platform/node/test/suite_implementation.js
index 323f429bed..b0be2fa0eb 100644
--- a/platform/node/test/suite_implementation.js
+++ b/platform/node/test/suite_implementation.js
@@ -14,21 +14,25 @@ mbgl.on('message', function(msg) {
var maps = new Map();
module.exports = function (style, options, callback) {
+ var tileMode = options.mapMode === 'tile';
if (options.recycleMap) {
- if (maps.has(options.pixelRatio)) {
- var map = maps.get(options.pixelRatio);
+ var key = options.pixelRatio + '/' + tileMode;
+ if (maps.has(key)) {
+ var map = maps.get(key);
map.request = mapRequest;
} else {
- maps.set(options.pixelRatio, new mbgl.Map({
+ maps.set(key, new mbgl.Map({
ratio: options.pixelRatio,
- request: mapRequest
+ request: mapRequest,
+ mode: options.mapMode
}));
- var map = maps.get(options.pixelRatio);
+ var map = maps.get(key);
}
} else {
var map = new mbgl.Map({
ratio: options.pixelRatio,
- request: mapRequest
+ request: mapRequest,
+ mode: options.mapMode
});
}
@@ -90,6 +94,12 @@ module.exports = function (style, options, callback) {
applyOperations(operations.slice(1), callback);
});
+ } else if (operation[0] === 'sleep') {
+ // Prefer "wait", which renders until the map is loaded
+ // Use "sleep" when you need to test something that sidesteps the "loaded" logic
+ setTimeout(() => {
+ applyOperations(operations.slice(1), callback);
+ }, operation[1]);
} else if (operation[0] === 'addImage' || operation[0] === 'updateImage') {
var img = PNG.sync.read(fs.readFileSync(path.join(__dirname, '../../../mapbox-gl-js/test/integration', operation[2])));
const testOpts = (operation.length > 3) ? operation[3] : {};
diff --git a/platform/qt/config.cmake b/platform/qt/config.cmake
index 57e586d7c3..9417963767 100644
--- a/platform/qt/config.cmake
+++ b/platform/qt/config.cmake
@@ -20,6 +20,7 @@ macro(mbgl_platform_core)
target_include_directories(mbgl-core
PUBLIC platform/default
+ PRIVATE platform/qt
PRIVATE platform/qt/include
)
@@ -71,6 +72,10 @@ macro(mbgl_platform_test)
PRIVATE platform/qt/test/qmapboxgl.test.cpp
)
+ target_include_directories(mbgl-test
+ PRIVATE platform/qt
+ )
+
set_source_files_properties(
platform/qt/test/main.cpp
PROPERTIES COMPILE_FLAGS -DWORK_DIRECTORY="${CMAKE_SOURCE_DIR}"
diff --git a/platform/qt/include/qmapbox.hpp b/platform/qt/include/qmapbox.hpp
index d138f4057b..2bb5d8705c 100644
--- a/platform/qt/include/qmapbox.hpp
+++ b/platform/qt/include/qmapbox.hpp
@@ -27,6 +27,7 @@ struct Q_DECL_EXPORT Feature {
PolygonType
};
+ /*! Class constructor. */
Feature(Type type_ = PointType, const CoordinatesCollections& geometry_ = CoordinatesCollections(),
const QVariantMap& properties_ = QVariantMap(), const QVariant& id_ = QVariant())
: type(type_), geometry(geometry_), properties(properties_), id(id_) {}
@@ -45,6 +46,7 @@ struct Q_DECL_EXPORT ShapeAnnotationGeometry {
MultiPolygonType
};
+ /*! Class constructor. */
ShapeAnnotationGeometry(Type type_ = LineStringType, const CoordinatesCollections& geometry_ = CoordinatesCollections())
: type(type_), geometry(geometry_) {}
@@ -58,6 +60,7 @@ struct Q_DECL_EXPORT SymbolAnnotation {
};
struct Q_DECL_EXPORT LineAnnotation {
+ /*! Class constructor. */
LineAnnotation(const ShapeAnnotationGeometry& geometry_ = ShapeAnnotationGeometry(), float opacity_ = 1.0f,
float width_ = 1.0f, const QColor& color_ = Qt::black)
: geometry(geometry_), opacity(opacity_), width(width_), color(color_) {}
@@ -69,6 +72,7 @@ struct Q_DECL_EXPORT LineAnnotation {
};
struct Q_DECL_EXPORT FillAnnotation {
+ /*! Class constructor. */
FillAnnotation(const ShapeAnnotationGeometry& geometry_ = ShapeAnnotationGeometry(), float opacity_ = 1.0f,
const QColor& color_ = Qt::black, const QVariant& outlineColor_ = QVariant())
: geometry(geometry_), opacity(opacity_), color(color_), outlineColor(outlineColor_) {}
diff --git a/platform/qt/include/qmapboxgl.hpp b/platform/qt/include/qmapboxgl.hpp
index e2fb283989..ebbd949921 100644
--- a/platform/qt/include/qmapboxgl.hpp
+++ b/platform/qt/include/qmapboxgl.hpp
@@ -10,6 +10,8 @@
#include <QString>
#include <QStringList>
+#include <functional>
+
class QMapboxGLPrivate;
// This header follows the Qt coding style: https://wiki.qt.io/Qt_Coding_Style
@@ -59,6 +61,9 @@ public:
QString apiBaseUrl() const;
void setApiBaseUrl(const QString &);
+ std::function<std::string(const std::string &&)> resourceTransform() const;
+ void setResourceTransform(const std::function<std::string(const std::string &&)> &);
+
private:
GLContextMode m_contextMode;
ConstrainMode m_constrainMode;
@@ -69,6 +74,7 @@ private:
QString m_assetPath;
QString m_accessToken;
QString m_apiBaseUrl;
+ std::function<std::string(const std::string &&)> m_resourceTransform;
};
struct Q_DECL_EXPORT QMapboxGLCameraOptions {
diff --git a/platform/qt/mbgl/gl/gl_impl.hpp b/platform/qt/mbgl/gl/gl_impl.hpp
new file mode 100644
index 0000000000..b08efe1eec
--- /dev/null
+++ b/platform/qt/mbgl/gl/gl_impl.hpp
@@ -0,0 +1,178 @@
+#pragma once
+
+#include <QtGlobal>
+
+// Qt4
+#if QT_VERSION < 0x050000
+ #if __APPLE__
+ #include "TargetConditionals.h"
+ #include <OpenGL/OpenGL.h>
+ #include <OpenGL/gl.h>
+ #include <OpenGL/glext.h>
+ #elif MBGL_USE_GLES2
+ #define GL_GLEXT_PROTOTYPES
+ #include <GLES2/gl2.h>
+ #include <GLES2/gl2ext.h>
+ #else
+ #define GL_GLEXT_PROTOTYPES
+ #include <GL/gl.h>
+ #include <GL/glext.h>
+ #endif
+
+// Qt5
+#else
+ #include <QOpenGLContext>
+ #include <QOpenGLFunctions>
+
+ #ifndef GL_RGBA8_OES
+ #define GL_RGBA8_OES GL_RGBA8
+ #endif
+
+ #ifndef GL_DEPTH24_STENCIL8_OES
+ #define GL_DEPTH24_STENCIL8_OES GL_DEPTH24_STENCIL8
+ #endif
+
+ #define glActiveTexture(...) QOpenGLContext::currentContext()->functions()->glActiveTexture(__VA_ARGS__)
+ #define glAttachShader(...) QOpenGLContext::currentContext()->functions()->glAttachShader(__VA_ARGS__)
+ #define glBindAttribLocation(...) QOpenGLContext::currentContext()->functions()->glBindAttribLocation(__VA_ARGS__)
+ #define glBindBuffer(...) QOpenGLContext::currentContext()->functions()->glBindBuffer(__VA_ARGS__)
+ #define glBindFramebuffer(...) QOpenGLContext::currentContext()->functions()->glBindFramebuffer(__VA_ARGS__)
+ #define glBindRenderbuffer(...) QOpenGLContext::currentContext()->functions()->glBindRenderbuffer(__VA_ARGS__)
+ #define glBindTexture(...) QOpenGLContext::currentContext()->functions()->glBindTexture(__VA_ARGS__)
+ #define glBlendColor(...) QOpenGLContext::currentContext()->functions()->glBlendColor(__VA_ARGS__)
+ #define glBlendEquation(...) QOpenGLContext::currentContext()->functions()->glBlendEquation(__VA_ARGS__)
+ #define glBlendEquationSeparate(...) QOpenGLContext::currentContext()->functions()->glBlendEquationSeparate(__VA_ARGS__)
+ #define glBlendFunc(...) QOpenGLContext::currentContext()->functions()->glBlendFunc(__VA_ARGS__)
+ #define glBlendFuncSeparate(...) QOpenGLContext::currentContext()->functions()->glBlendFuncSeparate(__VA_ARGS__)
+ #define glBufferData(...) QOpenGLContext::currentContext()->functions()->glBufferData(__VA_ARGS__)
+ #define glBufferSubData(...) QOpenGLContext::currentContext()->functions()->glBufferSubData(__VA_ARGS__)
+ #define glCheckFramebufferStatus(...) QOpenGLContext::currentContext()->functions()->glCheckFramebufferStatus(__VA_ARGS__)
+ #define glClear(...) QOpenGLContext::currentContext()->functions()->glClear(__VA_ARGS__)
+ #define glClearColor(...) QOpenGLContext::currentContext()->functions()->glClearColor(__VA_ARGS__)
+ #define glClearDepthf(...) QOpenGLContext::currentContext()->functions()->glClearDepthf(__VA_ARGS__)
+ #define glClearStencil(...) QOpenGLContext::currentContext()->functions()->glClearStencil(__VA_ARGS__)
+ #define glColorMask(...) QOpenGLContext::currentContext()->functions()->glColorMask(__VA_ARGS__)
+ #define glCompileShader(...) QOpenGLContext::currentContext()->functions()->glCompileShader(__VA_ARGS__)
+ #define glCompressedTexImage2D(...) QOpenGLContext::currentContext()->functions()->glCompressedTexImage2D(__VA_ARGS__)
+ #define glCompressedTexSubImage2D(...) QOpenGLContext::currentContext()->functions()->glCompressedTexSubImage2D(__VA_ARGS__)
+ #define glCopyTexImage2D(...) QOpenGLContext::currentContext()->functions()->glCopyTexImage2D(__VA_ARGS__)
+ #define glCopyTexSubImage2D(...) QOpenGLContext::currentContext()->functions()->glCopyTexSubImage2D(__VA_ARGS__)
+ #define glCreateProgram(...) QOpenGLContext::currentContext()->functions()->glCreateProgram(__VA_ARGS__)
+ #define glCreateShader(...) QOpenGLContext::currentContext()->functions()->glCreateShader(__VA_ARGS__)
+ #define glCullFace(...) QOpenGLContext::currentContext()->functions()->glCullFace(__VA_ARGS__)
+ #define glDeleteBuffers(...) QOpenGLContext::currentContext()->functions()->glDeleteBuffers(__VA_ARGS__)
+ #define glDeleteFramebuffers(...) QOpenGLContext::currentContext()->functions()->glDeleteFramebuffers(__VA_ARGS__)
+ #define glDeleteProgram(...) QOpenGLContext::currentContext()->functions()->glDeleteProgram(__VA_ARGS__)
+ #define glDeleteRenderbuffers(...) QOpenGLContext::currentContext()->functions()->glDeleteRenderbuffers(__VA_ARGS__)
+ #define glDeleteShader(...) QOpenGLContext::currentContext()->functions()->glDeleteShader(__VA_ARGS__)
+ #define glDeleteTextures(...) QOpenGLContext::currentContext()->functions()->glDeleteTextures(__VA_ARGS__)
+ #define glDepthFunc(...) QOpenGLContext::currentContext()->functions()->glDepthFunc(__VA_ARGS__)
+ #define glDepthMask(...) QOpenGLContext::currentContext()->functions()->glDepthMask(__VA_ARGS__)
+ #define glDepthRangef(...) QOpenGLContext::currentContext()->functions()->glDepthRangef(__VA_ARGS__)
+ #define glDetachShader(...) QOpenGLContext::currentContext()->functions()->glDetachShader(__VA_ARGS__)
+ #define glDisable(...) QOpenGLContext::currentContext()->functions()->glDisable(__VA_ARGS__)
+ #define glDisableVertexAttribArray(...) QOpenGLContext::currentContext()->functions()->glDisableVertexAttribArray(__VA_ARGS__)
+ #define glDrawArrays(...) QOpenGLContext::currentContext()->functions()->glDrawArrays(__VA_ARGS__)
+ #define glDrawElements(...) QOpenGLContext::currentContext()->functions()->glDrawElements(__VA_ARGS__)
+ #define glEnable(...) QOpenGLContext::currentContext()->functions()->glEnable(__VA_ARGS__)
+ #define glEnableVertexAttribArray(...) QOpenGLContext::currentContext()->functions()->glEnableVertexAttribArray(__VA_ARGS__)
+ #define glFinish(...) QOpenGLContext::currentContext()->functions()->glFinish(__VA_ARGS__)
+ #define glFlush(...) QOpenGLContext::currentContext()->functions()->glFlush(__VA_ARGS__)
+ #define glFramebufferRenderbuffer(...) QOpenGLContext::currentContext()->functions()->glFramebufferRenderbuffer(__VA_ARGS__)
+ #define glFramebufferTexture2D(...) QOpenGLContext::currentContext()->functions()->glFramebufferTexture2D(__VA_ARGS__)
+ #define glFrontFace(...) QOpenGLContext::currentContext()->functions()->glFrontFace(__VA_ARGS__)
+ #define glGenBuffers(...) QOpenGLContext::currentContext()->functions()->glGenBuffers(__VA_ARGS__)
+ #define glGenerateMipmap(...) QOpenGLContext::currentContext()->functions()->glGenerateMipmap(__VA_ARGS__)
+ #define glGenFramebuffers(...) QOpenGLContext::currentContext()->functions()->glGenFramebuffers(__VA_ARGS__)
+ #define glGenRenderbuffers(...) QOpenGLContext::currentContext()->functions()->glGenRenderbuffers(__VA_ARGS__)
+ #define glGenTextures(...) QOpenGLContext::currentContext()->functions()->glGenTextures(__VA_ARGS__)
+ #define glGetActiveAttrib(...) QOpenGLContext::currentContext()->functions()->glGetActiveAttrib(__VA_ARGS__)
+ #define glGetActiveUniform(...) QOpenGLContext::currentContext()->functions()->glGetActiveUniform(__VA_ARGS__)
+ #define glGetAttachedShaders(...) QOpenGLContext::currentContext()->functions()->glGetAttachedShaders(__VA_ARGS__)
+ #define glGetAttribLocation(...) QOpenGLContext::currentContext()->functions()->glGetAttribLocation(__VA_ARGS__)
+ #define glGetBooleanv(...) QOpenGLContext::currentContext()->functions()->glGetBooleanv(__VA_ARGS__)
+ #define glGetBufferParameteriv(...) QOpenGLContext::currentContext()->functions()->glGetBufferParameteriv(__VA_ARGS__)
+ #define glGetError(...) QOpenGLContext::currentContext()->functions()->glGetError(__VA_ARGS__)
+ #define glGetFloatv(...) QOpenGLContext::currentContext()->functions()->glGetFloatv(__VA_ARGS__)
+ #define glGetFramebufferAttachmentParameteriv(...) QOpenGLContext::currentContext()->functions()->glGetFramebufferAttachmentParameteriv(__VA_ARGS__)
+ #define glGetIntegerv(...) QOpenGLContext::currentContext()->functions()->glGetIntegerv(__VA_ARGS__)
+ #define glGetProgramInfoLog(...) QOpenGLContext::currentContext()->functions()->glGetProgramInfoLog(__VA_ARGS__)
+ #define glGetProgramiv(...) QOpenGLContext::currentContext()->functions()->glGetProgramiv(__VA_ARGS__)
+ #define glGetRenderbufferParameteriv(...) QOpenGLContext::currentContext()->functions()->glGetRenderbufferParameteriv(__VA_ARGS__)
+ #define glGetShaderInfoLog(...) QOpenGLContext::currentContext()->functions()->glGetShaderInfoLog(__VA_ARGS__)
+ #define glGetShaderiv(...) QOpenGLContext::currentContext()->functions()->glGetShaderiv(__VA_ARGS__)
+ #define glGetShaderPrecisionFormat(...) QOpenGLContext::currentContext()->functions()->glGetShaderPrecisionFormat(__VA_ARGS__)
+ #define glGetShaderSource(...) QOpenGLContext::currentContext()->functions()->glGetShaderSource(__VA_ARGS__)
+ #define glGetString(...) QOpenGLContext::currentContext()->functions()->glGetString(__VA_ARGS__)
+ #define glGetTexParameterfv(...) QOpenGLContext::currentContext()->functions()->glGetTexParameterfv(__VA_ARGS__)
+ #define glGetTexParameteriv(...) QOpenGLContext::currentContext()->functions()->glGetTexParameteriv(__VA_ARGS__)
+ #define glGetUniformfv(...) QOpenGLContext::currentContext()->functions()->glGetUniformfv(__VA_ARGS__)
+ #define glGetUniformiv(...) QOpenGLContext::currentContext()->functions()->glGetUniformiv(__VA_ARGS__)
+ #define glGetUniformLocation(...) QOpenGLContext::currentContext()->functions()->glGetUniformLocation(__VA_ARGS__)
+ #define glGetVertexAttribfv(...) QOpenGLContext::currentContext()->functions()->glGetVertexAttribfv(__VA_ARGS__)
+ #define glGetVertexAttribiv(...) QOpenGLContext::currentContext()->functions()->glGetVertexAttribiv(__VA_ARGS__)
+ #define glGetVertexAttribPointerv(...) QOpenGLContext::currentContext()->functions()->glGetVertexAttribPointerv(__VA_ARGS__)
+ #define glHint(...) QOpenGLContext::currentContext()->functions()->glHint(__VA_ARGS__)
+ #define glIsBuffer(...) QOpenGLContext::currentContext()->functions()->glIsBuffer(__VA_ARGS__)
+ #define glIsEnabled(...) QOpenGLContext::currentContext()->functions()->glIsEnabled(__VA_ARGS__)
+ #define glIsFramebuffer(...) QOpenGLContext::currentContext()->functions()->glIsFramebuffer(__VA_ARGS__)
+ #define glIsProgram(...) QOpenGLContext::currentContext()->functions()->glIsProgram(__VA_ARGS__)
+ #define glIsRenderbuffer(...) QOpenGLContext::currentContext()->functions()->glIsRenderbuffer(__VA_ARGS__)
+ #define glIsShader(...) QOpenGLContext::currentContext()->functions()->glIsShader(__VA_ARGS__)
+ #define glIsTexture(...) QOpenGLContext::currentContext()->functions()->glIsTexture(__VA_ARGS__)
+ #define glLineWidth(...) QOpenGLContext::currentContext()->functions()->glLineWidth(__VA_ARGS__)
+ #define glLinkProgram(...) QOpenGLContext::currentContext()->functions()->glLinkProgram(__VA_ARGS__)
+ #define glPixelStorei(...) QOpenGLContext::currentContext()->functions()->glPixelStorei(__VA_ARGS__)
+ #define glPolygonOffset(...) QOpenGLContext::currentContext()->functions()->glPolygonOffset(__VA_ARGS__)
+ #define glReadPixels(...) QOpenGLContext::currentContext()->functions()->glReadPixels(__VA_ARGS__)
+ #define glReleaseShaderCompiler(...) QOpenGLContext::currentContext()->functions()->glReleaseShaderCompiler(__VA_ARGS__)
+ #define glRenderbufferStorage(...) QOpenGLContext::currentContext()->functions()->glRenderbufferStorage(__VA_ARGS__)
+ #define glSampleCoverage(...) QOpenGLContext::currentContext()->functions()->glSampleCoverage(__VA_ARGS__)
+ #define glScissor(...) QOpenGLContext::currentContext()->functions()->glScissor(__VA_ARGS__)
+ #define glShaderBinary(...) QOpenGLContext::currentContext()->functions()->glShaderBinary(__VA_ARGS__)
+ #define glShaderSource(...) QOpenGLContext::currentContext()->functions()->glShaderSource(__VA_ARGS__)
+ #define glStencilFunc(...) QOpenGLContext::currentContext()->functions()->glStencilFunc(__VA_ARGS__)
+ #define glStencilFuncSeparate(...) QOpenGLContext::currentContext()->functions()->glStencilFuncSeparate(__VA_ARGS__)
+ #define glStencilMask(...) QOpenGLContext::currentContext()->functions()->glStencilMask(__VA_ARGS__)
+ #define glStencilMaskSeparate(...) QOpenGLContext::currentContext()->functions()->glStencilMaskSeparate(__VA_ARGS__)
+ #define glStencilOp(...) QOpenGLContext::currentContext()->functions()->glStencilOp(__VA_ARGS__)
+ #define glStencilOpSeparate(...) QOpenGLContext::currentContext()->functions()->glStencilOpSeparate(__VA_ARGS__)
+ #define glTexImage2D(...) QOpenGLContext::currentContext()->functions()->glTexImage2D(__VA_ARGS__)
+ #define glTexLevelParameteriv(...) QOpenGLContext::currentContext()->functions()->glTexLevelParameteriv(__VA_ARGS__)
+ #define glTexParameterf(...) QOpenGLContext::currentContext()->functions()->glTexParameterf(__VA_ARGS__)
+ #define glTexParameterfv(...) QOpenGLContext::currentContext()->functions()->glTexParameterfv(__VA_ARGS__)
+ #define glTexParameteri(...) QOpenGLContext::currentContext()->functions()->glTexParameteri(__VA_ARGS__)
+ #define glTexParameteriv(...) QOpenGLContext::currentContext()->functions()->glTexParameteriv(__VA_ARGS__)
+ #define glTexSubImage2D(...) QOpenGLContext::currentContext()->functions()->glTexSubImage2D(__VA_ARGS__)
+ #define glUniform1f(...) QOpenGLContext::currentContext()->functions()->glUniform1f(__VA_ARGS__)
+ #define glUniform1fv(...) QOpenGLContext::currentContext()->functions()->glUniform1fv(__VA_ARGS__)
+ #define glUniform1i(...) QOpenGLContext::currentContext()->functions()->glUniform1i(__VA_ARGS__)
+ #define glUniform1iv(...) QOpenGLContext::currentContext()->functions()->glUniform1iv(__VA_ARGS__)
+ #define glUniform2f(...) QOpenGLContext::currentContext()->functions()->glUniform2f(__VA_ARGS__)
+ #define glUniform2fv(...) QOpenGLContext::currentContext()->functions()->glUniform2fv(__VA_ARGS__)
+ #define glUniform2i(...) QOpenGLContext::currentContext()->functions()->glUniform2i(__VA_ARGS__)
+ #define glUniform2iv(...) QOpenGLContext::currentContext()->functions()->glUniform2iv(__VA_ARGS__)
+ #define glUniform3f(...) QOpenGLContext::currentContext()->functions()->glUniform3f(__VA_ARGS__)
+ #define glUniform3fv(...) QOpenGLContext::currentContext()->functions()->glUniform3fv(__VA_ARGS__)
+ #define glUniform3i(...) QOpenGLContext::currentContext()->functions()->glUniform3i(__VA_ARGS__)
+ #define glUniform3iv(...) QOpenGLContext::currentContext()->functions()->glUniform3iv(__VA_ARGS__)
+ #define glUniform4f(...) QOpenGLContext::currentContext()->functions()->glUniform4f(__VA_ARGS__)
+ #define glUniform4fv(...) QOpenGLContext::currentContext()->functions()->glUniform4fv(__VA_ARGS__)
+ #define glUniform4i(...) QOpenGLContext::currentContext()->functions()->glUniform4i(__VA_ARGS__)
+ #define glUniform4iv(...) QOpenGLContext::currentContext()->functions()->glUniform4iv(__VA_ARGS__)
+ #define glUniformMatrix2fv(...) QOpenGLContext::currentContext()->functions()->glUniformMatrix2fv(__VA_ARGS__)
+ #define glUniformMatrix3fv(...) QOpenGLContext::currentContext()->functions()->glUniformMatrix3fv(__VA_ARGS__)
+ #define glUniformMatrix4fv(...) QOpenGLContext::currentContext()->functions()->glUniformMatrix4fv(__VA_ARGS__)
+ #define glUseProgram(...) QOpenGLContext::currentContext()->functions()->glUseProgram(__VA_ARGS__)
+ #define glValidateProgram(...) QOpenGLContext::currentContext()->functions()->glValidateProgram(__VA_ARGS__)
+ #define glVertexAttrib1f(...) QOpenGLContext::currentContext()->functions()->glVertexAttrib1f(__VA_ARGS__)
+ #define glVertexAttrib1fv(...) QOpenGLContext::currentContext()->functions()->glVertexAttrib1fv(__VA_ARGS__)
+ #define glVertexAttrib2f(...) QOpenGLContext::currentContext()->functions()->glVertexAttrib2f(__VA_ARGS__)
+ #define glVertexAttrib2fv(...) QOpenGLContext::currentContext()->functions()->glVertexAttrib2fv(__VA_ARGS__)
+ #define glVertexAttrib3f(...) QOpenGLContext::currentContext()->functions()->glVertexAttrib3f(__VA_ARGS__)
+ #define glVertexAttrib3fv(...) QOpenGLContext::currentContext()->functions()->glVertexAttrib3fv(__VA_ARGS__)
+ #define glVertexAttrib4f(...) QOpenGLContext::currentContext()->functions()->glVertexAttrib4f(__VA_ARGS__)
+ #define glVertexAttrib4fv(...) QOpenGLContext::currentContext()->functions()->glVertexAttrib4fv(__VA_ARGS__)
+ #define glVertexAttribPointer(...) QOpenGLContext::currentContext()->functions()->glVertexAttribPointer(__VA_ARGS__)
+ #define glViewport(...) QOpenGLContext::currentContext()->functions()->glViewport(__VA_ARGS__)
+#endif
diff --git a/platform/qt/qt.cmake b/platform/qt/qt.cmake
index 2346d7d820..ae8b4bac99 100644
--- a/platform/qt/qt.cmake
+++ b/platform/qt/qt.cmake
@@ -5,8 +5,7 @@ option(WITH_QT_DECODERS "Use builtin Qt image decoders" OFF)
option(WITH_QT_I18N "Use builtin Qt i18n support" OFF)
option(WITH_QT_4 "Use Qt4 instead of Qt5" OFF)
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -D__QT__")
-set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden -D__QT__")
+add_definitions("-D__QT__")
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
@@ -17,13 +16,8 @@ set(MBGL_QT_CORE_FILES
PRIVATE platform/default/mbgl/gl/headless_frontend.hpp
PRIVATE platform/default/mbgl/gl/headless_backend.cpp
PRIVATE platform/default/mbgl/gl/headless_backend.hpp
- PRIVATE platform/default/mbgl/gl/headless_display.cpp
- PRIVATE platform/default/mbgl/gl/headless_display.hpp
PRIVATE platform/qt/src/headless_backend_qt.cpp
- # Misc
- PRIVATE platform/default/logging_stderr.cpp
-
# Thread pool
PRIVATE platform/default/mbgl/util/shared_thread_pool.cpp
PRIVATE platform/default/mbgl/util/shared_thread_pool.hpp
@@ -36,6 +30,7 @@ set(MBGL_QT_CORE_FILES
# Platform integration
PRIVATE platform/qt/src/async_task.cpp
PRIVATE platform/qt/src/async_task_impl.hpp
+ PRIVATE platform/qt/src/qt_logging.cpp
PRIVATE platform/qt/src/qt_image.cpp
PRIVATE platform/qt/src/run_loop.cpp
PRIVATE platform/qt/src/run_loop_impl.hpp
@@ -60,6 +55,9 @@ set(MBGL_QT_FILESOURCE_FILES
add_library(qmapboxgl SHARED
platform/qt/include/qmapbox.hpp
platform/qt/include/qmapboxgl.hpp
+ platform/qt/src/qt_conversion.hpp
+ platform/qt/src/qt_geojson.cpp
+ platform/qt/src/qt_geojson.hpp
platform/qt/src/qmapbox.cpp
platform/qt/src/qmapboxgl.cpp
platform/qt/src/qmapboxgl_p.hpp
@@ -103,12 +101,6 @@ endif()
xcode_create_scheme(TARGET mbgl-qt)
-if(WITH_QT_4)
- include(platform/qt/qt4.cmake)
-else()
- include(platform/qt/qt5.cmake)
-endif()
-
# OS specific configurations
if (MASON_PLATFORM STREQUAL "osx" OR MASON_PLATFORM STREQUAL "ios")
list(APPEND MBGL_QT_CORE_FILES
@@ -116,15 +108,21 @@ if (MASON_PLATFORM STREQUAL "osx" OR MASON_PLATFORM STREQUAL "ios")
)
list(APPEND MBGL_QT_CORE_LIBRARIES
PRIVATE "-framework Foundation"
- PRIVATE "-framework OpenGL"
)
+ if(WITH_QT_4)
+ list(APPEND MBGL_QT_CORE_LIBRARIES
+ PRIVATE "-framework OpenGL"
+ )
+ endif()
elseif (CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
list(APPEND MBGL_QT_CORE_FILES
PRIVATE platform/default/thread.cpp
)
- list(APPEND MBGL_QT_CORE_LIBRARIES
- PRIVATE -lGL
- )
+ if(WITH_QT_4)
+ list(APPEND MBGL_QT_CORE_LIBRARIES
+ PRIVATE "-lGL"
+ )
+ endif()
elseif (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
list(APPEND MBGL_QT_CORE_FILES
PRIVATE platform/qt/src/thread.cpp
diff --git a/platform/qt/qt5.cmake b/platform/qt/qt5.cmake
index c4af774ba3..0c9a974b4b 100644
--- a/platform/qt/qt5.cmake
+++ b/platform/qt/qt5.cmake
@@ -5,6 +5,12 @@ find_package(Qt5OpenGL REQUIRED)
find_package(Qt5Widgets REQUIRED)
find_package(Qt5Sql REQUIRED)
+# Qt5 always build OpenGL ES2 which is the compatibility
+# mode. Qt5 will take care of translating the desktop
+# version of OpenGL to ES2.
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMBGL_USE_GLES2")
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMBGL_USE_GLES2")
+
set(MBGL_QT_CORE_LIBRARIES
PUBLIC Qt5::Core
PUBLIC Qt5::Gui
diff --git a/platform/qt/resources/common.qrc b/platform/qt/resources/common.qrc
index 598059d55e..24f663df77 100644
--- a/platform/qt/resources/common.qrc
+++ b/platform/qt/resources/common.qrc
@@ -1,6 +1,6 @@
<RCC>
<qresource prefix="/">
- <file alias="icon.png">../../../common/mb-icon-blue-square.png</file>
+ <file alias="icon.png">../../../misc/mb-icon-blue-square.png</file>
<file alias="default_marker.svg">../../../platform/default/resources/default_marker.svg</file>
<file>source1.geojson</file>
<file>source2.geojson</file>
diff --git a/platform/qt/src/headless_backend_qt.cpp b/platform/qt/src/headless_backend_qt.cpp
index 5f95b2f96a..ad3fa42290 100644
--- a/platform/qt/src/headless_backend_qt.cpp
+++ b/platform/qt/src/headless_backend_qt.cpp
@@ -12,19 +12,11 @@
namespace mbgl {
-struct QtImpl : public HeadlessBackend::Impl {
- void activateContext() final {
- widget.makeCurrent();
- }
+class QtBackendImpl : public HeadlessBackend::Impl {
+public:
+ ~QtBackendImpl() final = default;
- void deactivateContext() final {
- widget.doneCurrent();
- }
-
- QGLWidget widget;
-};
-
-gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) {
+ gl::ProcAddress getExtensionFunctionPointer(const char* name) final {
#if QT_VERSION >= 0x050000
QOpenGLContext* thisContext = QOpenGLContext::currentContext();
return thisContext->getProcAddress(name);
@@ -32,15 +24,23 @@ gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) {
const QGLContext* thisContext = QGLContext::currentContext();
return reinterpret_cast<gl::ProcAddress>(thisContext->getProcAddress(name));
#endif
-}
+ }
+
+ void activateContext() final {
+ widget.makeCurrent();
+ }
-bool HeadlessBackend::hasDisplay() {
- return true;
+ void deactivateContext() final {
+ widget.doneCurrent();
+ }
+
+private:
+ QGLWidget widget;
};
-void HeadlessBackend::createContext() {
- assert(!hasContext());
- impl.reset(new QtImpl);
+void HeadlessBackend::createImpl() {
+ assert(!impl);
+ impl = std::make_unique<QtBackendImpl>();
}
} // namespace mbgl
diff --git a/platform/qt/src/http_file_source.cpp b/platform/qt/src/http_file_source.cpp
index 573b707c27..6e70693241 100644
--- a/platform/qt/src/http_file_source.cpp
+++ b/platform/qt/src/http_file_source.cpp
@@ -80,9 +80,10 @@ void HTTPFileSource::Impl::onReplyFinished()
return;
}
+ QByteArray data = reply->readAll();
QVector<HTTPRequest*>& requestsVector = it.value().second;
for (auto req : requestsVector) {
- req->handleNetworkReply(reply);
+ req->handleNetworkReply(reply, data);
}
m_pending.erase(it);
diff --git a/platform/qt/src/http_request.cpp b/platform/qt/src/http_request.cpp
index 386a2d9ef4..ea3f388bd5 100644
--- a/platform/qt/src/http_request.cpp
+++ b/platform/qt/src/http_request.cpp
@@ -52,7 +52,7 @@ QNetworkRequest HTTPRequest::networkRequest() const
return req;
}
-void HTTPRequest::handleNetworkReply(QNetworkReply *reply)
+void HTTPRequest::handleNetworkReply(QNetworkReply *reply, const QByteArray& data)
{
m_handled = true;
@@ -98,11 +98,10 @@ void HTTPRequest::handleNetworkReply(QNetworkReply *reply)
switch(responseCode) {
case 200: {
- QByteArray bytes = reply->readAll();
- if (bytes.isEmpty()) {
+ if (data.isEmpty()) {
response.data = std::make_shared<std::string>();
} else {
- response.data = std::make_shared<std::string>(bytes.constData(), bytes.size());
+ response.data = std::make_shared<std::string>(data.constData(), data.size());
}
break;
}
diff --git a/platform/qt/src/http_request.hpp b/platform/qt/src/http_request.hpp
index 959f97759a..b4d476d586 100644
--- a/platform/qt/src/http_request.hpp
+++ b/platform/qt/src/http_request.hpp
@@ -20,7 +20,7 @@ public:
QUrl requestUrl() const;
QNetworkRequest networkRequest() const;
- void handleNetworkReply(QNetworkReply *);
+ void handleNetworkReply(QNetworkReply *, const QByteArray& data);
private:
HTTPFileSource::Impl* m_context;
diff --git a/platform/qt/src/qmapboxgl.cpp b/platform/qt/src/qmapboxgl.cpp
index e79c6af56a..2675d87862 100644
--- a/platform/qt/src/qmapboxgl.cpp
+++ b/platform/qt/src/qmapboxgl.cpp
@@ -14,7 +14,17 @@
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/layer.hpp>
#include <mbgl/style/conversion/source.hpp>
+#include <mbgl/style/conversion/filter.hpp>
+#include <mbgl/style/conversion/geojson.hpp>
+#include <mbgl/style/filter.hpp>
#include <mbgl/style/layers/custom_layer.hpp>
+#include <mbgl/style/layers/background_layer.hpp>
+#include <mbgl/style/layers/circle_layer.hpp>
+#include <mbgl/style/layers/fill_layer.hpp>
+#include <mbgl/style/layers/fill_extrusion_layer.hpp>
+#include <mbgl/style/layers/line_layer.hpp>
+#include <mbgl/style/layers/raster_layer.hpp>
+#include <mbgl/style/layers/symbol_layer.hpp>
#include <mbgl/style/sources/geojson_source.hpp>
#include <mbgl/style/transition_options.hpp>
#include <mbgl/style/image.hpp>
@@ -29,6 +39,7 @@
#include <mbgl/util/run_loop.hpp>
#include <mbgl/util/shared_thread_pool.hpp>
#include <mbgl/util/traits.hpp>
+#include <mbgl/actor/scheduler.hpp>
#if QT_VERSION >= 0x050000
#include <QGuiApplication>
@@ -100,8 +111,13 @@ std::unique_ptr<mbgl::style::Image> toStyleImage(const QString &id, const QImage
.rgbSwapped()
.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+#if QT_VERSION >= 0x051000
+ auto img = std::make_unique<uint8_t[]>(swapped.sizeInBytes());
+ memcpy(img.get(), swapped.constBits(), swapped.sizeInBytes());
+#else
auto img = std::make_unique<uint8_t[]>(swapped.byteCount());
memcpy(img.get(), swapped.constBits(), swapped.byteCount());
+#endif
return std::make_unique<mbgl::style::Image>(
id.toStdString(),
@@ -139,9 +155,11 @@ std::unique_ptr<mbgl::style::Image> toStyleImage(const QString &id, const QImage
reset before each rendering. Use this mode if the intention is to only draw a
fullscreen map.
- \value SharedGLContext The OpenGL context is shared and the state will be restored
- before rendering. This mode is safer when OpenGL calls are performed prior of after
- we call QMapboxGL::render for rendering a map.
+ \value SharedGLContext The OpenGL context is shared and the state will be
+ marked dirty - which invalidates any previously assumed GL state. The
+ embedder is responsible for clearing up the viewport prior to calling
+ QMapboxGL::render. The embedder is also responsible for resetting its own
+ GL state after QMapboxGL::render has finished, if needed.
\sa contextMode()
*/
@@ -362,6 +380,27 @@ void QMapboxGLSettings::setApiBaseUrl(const QString& url)
}
/*!
+ Returns resource transformation callback used to transform requested URLs.
+*/
+std::function<std::string(const std::string &&)> QMapboxGLSettings::resourceTransform() const
+{
+ return m_resourceTransform;
+}
+
+/*!
+ Sets the resource \a transform callback.
+
+ When given, resource transformation callback will be used to transform the
+ requested resource URLs before they are requested from internet. This can be
+ used add or remove custom parameters, or reroute certain requests to other
+ servers or endpoints.
+*/
+void QMapboxGLSettings::setResourceTransform(const std::function<std::string(const std::string &&)> &transform)
+{
+ m_resourceTransform = transform;
+}
+
+/*!
\class QMapboxGL
\brief The QMapboxGL class is a Qt wrapper for the Mapbox GL Native engine.
@@ -850,7 +889,7 @@ void QMapboxGL::removeAnnotation(QMapbox::AnnotationID id)
}
/*!
- Sets a layout \a property \a value to an existing \a layer. The \a property_ string can be any
+ Sets a layout \a property_ \a value to an existing \a layer. The \a property_ string can be any
as defined by the \l {https://www.mapbox.com/mapbox-gl-style-spec/} {Mapbox style specification}
for layout properties.
@@ -901,7 +940,7 @@ void QMapboxGL::setLayoutProperty(const QString& layer, const QString& property_
}
/*!
- Sets a paint \a property_ \a value to an existing \a layer. The \a property string can be any
+ Sets a paint \a property_ \a value to an existing \a layer. The \a property_ string can be any
as defined by the \l {https://www.mapbox.com/mapbox-gl-style-spec/} {Mapbox style specification}
for paint properties.
@@ -1499,6 +1538,18 @@ QMapboxGLPrivate::QMapboxGLPrivate(QMapboxGL *q, const QMapboxGLSettings &settin
settings.cacheDatabaseMaximumSize()))
, threadPool(mbgl::sharedThreadPool())
{
+ // Setup resource transform if needed
+ if (settings.resourceTransform()) {
+ m_resourceTransform =
+ std::make_unique< mbgl::Actor<mbgl::ResourceTransform> >( *mbgl::Scheduler::GetCurrent(),
+ [callback = settings.resourceTransform()]
+ (mbgl::Resource::Kind , const std::string&& url_) -> std::string {
+ return callback(std::move(url_));
+ }
+ );
+ fileSourceObj->setResourceTransform(m_resourceTransform->self());
+ }
+
// Setup and connect the renderer frontend
frontend = std::make_unique<QMapboxGLRendererFrontend>(
std::make_unique<mbgl::Renderer>(*this, pixelRatio, *fileSourceObj, *threadPool,
@@ -1534,7 +1585,9 @@ mbgl::Size QMapboxGLPrivate::getFramebufferSize() const {
void QMapboxGLPrivate::updateAssumedState() {
assumeFramebufferBinding(fbObject);
+#if QT_VERSION >= 0x050600
assumeViewport(0, 0, getFramebufferSize());
+#endif
}
void QMapboxGLPrivate::bind() {
@@ -1642,7 +1695,7 @@ void QMapboxGLPrivate::onSourceChanged(mbgl::style::Source&)
Initializes an OpenGL extension function such as Vertex Array Objects (VAOs),
required by Mapbox GL Native engine.
*/
-mbgl::gl::ProcAddress QMapboxGLPrivate::initializeExtension(const char* name) {
+mbgl::gl::ProcAddress QMapboxGLPrivate::getExtensionFunctionPointer(const char* name) {
#if QT_VERSION >= 0x050000
QOpenGLContext* thisContext = QOpenGLContext::currentContext();
return thisContext->getProcAddress(name);
diff --git a/platform/qt/src/qmapboxgl_p.hpp b/platform/qt/src/qmapboxgl_p.hpp
index eb86870c10..f947c09f48 100644
--- a/platform/qt/src/qmapboxgl_p.hpp
+++ b/platform/qt/src/qmapboxgl_p.hpp
@@ -3,15 +3,19 @@
#include "qmapboxgl.hpp"
#include "qmapboxgl_renderer_frontend_p.hpp"
+#include <mbgl/actor/actor.hpp>
#include <mbgl/map/map.hpp>
#include <mbgl/renderer/renderer_backend.hpp>
#include <mbgl/util/default_thread_pool.hpp>
#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/util/geo.hpp>
+#include <mbgl/storage/resource_transform.hpp>
#include <QObject>
#include <QSize>
+#include <memory>
+
class QMapboxGLPrivate : public QObject, public mbgl::RendererBackend, public mbgl::MapObserver
{
Q_OBJECT
@@ -57,7 +61,7 @@ public:
bool dirty { false };
private:
- mbgl::gl::ProcAddress initializeExtension(const char*) override;
+ mbgl::gl::ProcAddress getExtensionFunctionPointer(const char*) override;
public slots:
void connectionEstablished();
@@ -68,4 +72,7 @@ signals:
void needsRendering();
void mapChanged(QMapboxGL::MapChange);
void copyrightsChanged(const QString &copyrightsHtml);
+
+private:
+ std::unique_ptr< mbgl::Actor<mbgl::ResourceTransform> > m_resourceTransform;
};
diff --git a/platform/qt/src/qt_conversion.hpp b/platform/qt/src/qt_conversion.hpp
index 40d7e5b928..19b0cb54fc 100644
--- a/platform/qt/src/qt_conversion.hpp
+++ b/platform/qt/src/qt_conversion.hpp
@@ -1,120 +1,145 @@
#pragma once
#include <mbgl/style/conversion.hpp>
-#include <mbgl/util/feature.hpp>
+#include <mbgl/style/conversion/geojson.hpp>
#include <mbgl/util/optional.hpp>
-#include <QMapbox>
-
-#include <QColor>
#include <QVariant>
+#include <QColor>
+#include <QMapbox>
+#include "qt_geojson.hpp"
namespace mbgl {
namespace style {
namespace conversion {
-inline bool isUndefined(const QVariant& value) {
- return value.isNull() || !value.isValid();
-}
+template <>
+class ConversionTraits<QVariant> {
+public:
+ static bool isUndefined(const QVariant& value) {
+ return value.isNull() || !value.isValid();
+ }
-inline bool isArray(const QVariant& value) {
- return value.canConvert(QVariant::List);
-}
+ static bool isArray(const QVariant& value) {
+ return value.canConvert(QVariant::List);
+ }
-inline std::size_t arrayLength(const QVariant& value) {
- return value.toList().size();
-}
+ static std::size_t arrayLength(const QVariant& value) {
+ return value.toList().size();
+ }
-inline QVariant arrayMember(const QVariant& value, std::size_t i) {
- return value.toList()[i];
-}
+ static QVariant arrayMember(const QVariant& value, std::size_t i) {
+ return value.toList()[i];
+ }
-inline bool isObject(const QVariant& value) {
- return value.canConvert(QVariant::Map)
- || value.type() == QVariant::ByteArray
-#if QT_VERSION >= 0x050000
- || QString(value.typeName()) == QStringLiteral("QMapbox::Feature");
-#else
- || QString(value.typeName()) == QString("QMapbox::Feature");
-#endif
-}
+ static bool isObject(const QVariant& value) {
+ return value.canConvert(QVariant::Map)
+ || value.type() == QVariant::ByteArray
+ #if QT_VERSION >= 0x050000
+ || QString(value.typeName()) == QStringLiteral("QMapbox::Feature");
+ #else
+ || QString(value.typeName()) == QString("QMapbox::Feature");
+ #endif
+ }
-inline optional<QVariant> objectMember(const QVariant& value, const char* key) {
- auto map = value.toMap();
- auto iter = map.constFind(key);
+ static optional<QVariant> objectMember(const QVariant& value, const char* key) {
+ auto map = value.toMap();
+ auto iter = map.constFind(key);
- if (iter != map.constEnd()) {
- return iter.value();
- } else {
- return {};
+ if (iter != map.constEnd()) {
+ return iter.value();
+ } else {
+ return {};
+ }
}
-}
-using EachMemberFn = std::function<optional<Error>(const std::string&, const QVariant&)>;
+ template <class Fn>
+ static optional<Error> eachMember(const QVariant& value, Fn&& fn) {
+ auto map = value.toMap();
+ auto iter = map.constBegin();
-optional<Error> eachMember(const QVariant& value, EachMemberFn&& fn) {
- auto map = value.toMap();
- auto iter = map.constBegin();
+ while (iter != map.constEnd()) {
+ optional<Error> result = fn(iter.key().toStdString(), QVariant(iter.value()));
+ if (result) {
+ return result;
+ }
- while (iter != map.constEnd()) {
- optional<Error> result = fn(iter.key().toStdString(), iter.value());
- if (result) {
- return result;
+ ++iter;
}
- ++iter;
+ return {};
}
- return {};
-}
+ static optional<bool> toBool(const QVariant& value) {
+ if (value.type() == QVariant::Bool) {
+ return value.toBool();
+ } else {
+ return {};
+ }
+ }
-inline optional<bool> toBool(const QVariant& value) {
- if (value.type() == QVariant::Bool) {
- return value.toBool();
- } else {
- return {};
+ static optional<float> toNumber(const QVariant& value) {
+ if (value.type() == QVariant::Int || value.type() == QVariant::Double) {
+ return value.toFloat();
+ } else {
+ return {};
+ }
}
-}
-inline optional<float> toNumber(const QVariant& value) {
- if (value.type() == QVariant::Int || value.type() == QVariant::Double) {
- return value.toFloat();
- } else {
- return {};
+ static optional<double> toDouble(const QVariant& value) {
+ if (value.type() == QVariant::Int || value.type() == QVariant::Double) {
+ return value.toDouble();
+ } else {
+ return {};
+ }
}
-}
-inline optional<double> toDouble(const QVariant& value) {
- if (value.type() == QVariant::Int || value.type() == QVariant::Double) {
- return value.toDouble();
- } else {
- return {};
+
+ static optional<std::string> toString(const QVariant& value) {
+ if (value.type() == QVariant::String) {
+ return value.toString().toStdString();
+ } else if (value.type() == QVariant::Color) {
+ return value.value<QColor>().name().toStdString();
+ } else {
+ return {};
+ }
}
-}
-inline optional<std::string> toString(const QVariant& value) {
- if (value.type() == QVariant::String) {
- return value.toString().toStdString();
- } else if (value.type() == QVariant::Color) {
- return value.value<QColor>().name().toStdString();
- } else {
- return {};
+ static optional<Value> toValue(const QVariant& value) {
+ if (value.type() == QVariant::Bool) {
+ return { value.toBool() };
+ } else if (value.type() == QVariant::String) {
+ return { value.toString().toStdString() };
+ } else if (value.type() == QVariant::Color) {
+ return { value.value<QColor>().name().toStdString() };
+ } else if (value.type() == QVariant::Int) {
+ return { int64_t(value.toInt()) };
+ } else if (value.canConvert(QVariant::Double)) {
+ return { value.toDouble() };
+ } else {
+ return {};
+ }
}
-}
-inline optional<Value> toValue(const QVariant& value) {
- if (value.type() == QVariant::Bool) {
- return { value.toBool() };
- } else if (value.type() == QVariant::String) {
- return { value.toString().toStdString() };
- } else if (value.type() == QVariant::Color) {
- return { value.value<QColor>().name().toStdString() };
- } else if (value.type() == QVariant::Int) {
- return { int64_t(value.toInt()) };
- } else if (value.canConvert(QVariant::Double)) {
- return { value.toDouble() };
- } else {
- return {};
+ static optional<GeoJSON> toGeoJSON(const QVariant& value, Error& error) {
+ #if QT_VERSION >= 0x050000
+ if (value.typeName() == QStringLiteral("QMapbox::Feature")) {
+ #else
+ if (value.typeName() == QString("QMapbox::Feature")) {
+ #endif
+ return GeoJSON { asMapboxGLFeature(value.value<QMapbox::Feature>()) };
+ } else if (value.type() != QVariant::ByteArray) {
+ error = { "JSON data must be in QByteArray" };
+ return {};
+ }
+
+ QByteArray data = value.toByteArray();
+ return parseGeoJSON(std::string(data.constData(), data.size()), error);
}
+};
+
+template <class T, class...Args>
+optional<T> convert(const QVariant& value, Error& error, Args&&...args) {
+ return convert<T>(Convertible(value), error, std::forward<Args>(args)...);
}
} // namespace conversion
diff --git a/platform/qt/src/qt_geojson.cpp b/platform/qt/src/qt_geojson.cpp
new file mode 100644
index 0000000000..80377de64d
--- /dev/null
+++ b/platform/qt/src/qt_geojson.cpp
@@ -0,0 +1,166 @@
+#include "qt_geojson.hpp"
+#include <mapbox/geojson.hpp>
+#include <mbgl/util/geometry.hpp>
+#include <mbgl/util/feature.hpp>
+
+namespace QMapbox {
+
+mbgl::Point<double> asMapboxGLPoint(const QMapbox::Coordinate &coordinate) {
+ return mbgl::Point<double> { coordinate.second, coordinate.first };
+}
+
+mbgl::MultiPoint<double> asMapboxGLMultiPoint(const QMapbox::Coordinates &multiPoint) {
+ mbgl::MultiPoint<double> mbglMultiPoint;
+ mbglMultiPoint.reserve(multiPoint.size());
+ for (const auto &point: multiPoint) {
+ mbglMultiPoint.emplace_back(asMapboxGLPoint(point));
+ }
+ return mbglMultiPoint;
+};
+
+mbgl::LineString<double> asMapboxGLLineString(const QMapbox::Coordinates &lineString) {
+ mbgl::LineString<double> mbglLineString;
+ mbglLineString.reserve(lineString.size());
+ for (const auto &coordinate : lineString) {
+ mbglLineString.emplace_back(asMapboxGLPoint(coordinate));
+ }
+ return mbglLineString;
+};
+
+mbgl::MultiLineString<double> asMapboxGLMultiLineString(const QMapbox::CoordinatesCollection &multiLineString) {
+ mbgl::MultiLineString<double> mbglMultiLineString;
+ mbglMultiLineString.reserve(multiLineString.size());
+ for (const auto &lineString : multiLineString) {
+ mbglMultiLineString.emplace_back(std::forward<mbgl::LineString<double>>(asMapboxGLLineString(lineString)));
+ }
+ return mbglMultiLineString;
+};
+
+mbgl::Polygon<double> asMapboxGLPolygon(const QMapbox::CoordinatesCollection &polygon) {
+ mbgl::Polygon<double> mbglPolygon;
+ mbglPolygon.reserve(polygon.size());
+ for (const auto &linearRing : polygon) {
+ mbgl::LinearRing<double> mbglLinearRing;
+ mbglLinearRing.reserve(linearRing.size());
+ for (const auto &coordinate: linearRing) {
+ mbglLinearRing.emplace_back(asMapboxGLPoint(coordinate));
+ }
+ mbglPolygon.emplace_back(std::move(mbglLinearRing));
+ }
+ return mbglPolygon;
+};
+
+mbgl::MultiPolygon<double> asMapboxGLMultiPolygon(const QMapbox::CoordinatesCollections &multiPolygon) {
+ mbgl::MultiPolygon<double> mbglMultiPolygon;
+ mbglMultiPolygon.reserve(multiPolygon.size());
+ for (const auto &polygon : multiPolygon) {
+ mbglMultiPolygon.emplace_back(std::forward<mbgl::Polygon<double>>(asMapboxGLPolygon(polygon)));
+ }
+ return mbglMultiPolygon;
+};
+
+mbgl::Value asMapboxGLPropertyValue(const QVariant &value) {
+ auto valueList = [](const QVariantList &list) {
+ std::vector<mbgl::Value> mbglList;
+ mbglList.reserve(list.size());
+ for (const auto& listValue : list) {
+ mbglList.emplace_back(asMapboxGLPropertyValue(listValue));
+ }
+ return mbglList;
+ };
+
+ auto valueMap = [](const QVariantMap &map) {
+ std::unordered_map<std::string, mbgl::Value> mbglMap;
+ mbglMap.reserve(map.size());
+ auto it = map.constBegin();
+ while (it != map.constEnd()) {
+ mbglMap.emplace(std::make_pair(it.key().toStdString(), asMapboxGLPropertyValue(it.value())));
+ ++it;
+ }
+ return mbglMap;
+ };
+
+ switch (value.type()) {
+#if QT_VERSION >= 0x050000
+ case QMetaType::UnknownType:
+#else
+ case QVariant::Invalid:
+#endif
+ return mbgl::NullValue {};
+ case QMetaType::Bool:
+ return { value.toBool() };
+ case QMetaType::ULongLong:
+ return { uint64_t(value.toULongLong()) };
+ case QMetaType::LongLong:
+ return { int64_t(value.toLongLong()) };
+ case QMetaType::Double:
+ return { value.toDouble() };
+ case QMetaType::QString:
+ return { value.toString().toStdString() };
+ case QMetaType::QVariantList:
+ return valueList(value.toList());
+ case QMetaType::QVariantMap:
+ return valueMap(value.toMap());
+ default:
+ qWarning() << "Unsupported feature property value:" << value;
+ return {};
+ }
+}
+
+mbgl::FeatureIdentifier asMapboxGLFeatureIdentifier(const QVariant &id) {
+ switch (id.type()) {
+#if QT_VERSION >= 0x050000
+ case QMetaType::UnknownType:
+#else
+ case QVariant::Invalid:
+#endif
+ return {};
+ case QMetaType::ULongLong:
+ return { uint64_t(id.toULongLong()) };
+ case QMetaType::LongLong:
+ return { int64_t(id.toLongLong()) };
+ case QMetaType::Double:
+ return { id.toDouble() };
+ case QMetaType::QString:
+ return { id.toString().toStdString() };
+ default:
+ qWarning() << "Unsupported feature identifier:" << id;
+ return {};
+ }
+}
+
+mbgl::Feature asMapboxGLFeature(const QMapbox::Feature &feature) {
+ mbgl::PropertyMap properties;
+ properties.reserve(feature.properties.size());
+ auto it = feature.properties.constBegin();
+ while (it != feature.properties.constEnd()) {
+ properties.emplace(std::make_pair(it.key().toStdString(), asMapboxGLPropertyValue(it.value())));
+ }
+
+ mbgl::FeatureIdentifier id = asMapboxGLFeatureIdentifier(feature.id);
+
+ if (feature.type == QMapbox::Feature::PointType) {
+ const QMapbox::Coordinates &points = feature.geometry.first().first();
+ if (points.size() == 1) {
+ return { asMapboxGLPoint(points.first()), std::move(properties), std::move(id) };
+ } else {
+ return { asMapboxGLMultiPoint(points), std::move(properties), std::move(id) };
+ }
+ } else if (feature.type == QMapbox::Feature::LineStringType) {
+ const QMapbox::CoordinatesCollection &lineStrings = feature.geometry.first();
+ if (lineStrings.size() == 1) {
+ return { asMapboxGLLineString(lineStrings.first()), std::move(properties), std::move(id) };
+ } else {
+ return { asMapboxGLMultiLineString(lineStrings), std::move(properties), std::move(id) };
+ }
+ } else { // PolygonType
+ const QMapbox::CoordinatesCollections &polygons = feature.geometry;
+ if (polygons.size() == 1) {
+ return { asMapboxGLPolygon(polygons.first()), std::move(properties), std::move(id) };
+ } else {
+ return { asMapboxGLMultiPolygon(polygons), std::move(properties), std::move(id) };
+ }
+ }
+};
+
+} // namespace QMapbox
diff --git a/platform/qt/src/qt_geojson.hpp b/platform/qt/src/qt_geojson.hpp
index a6958b7edc..a9c10272ab 100644
--- a/platform/qt/src/qt_geojson.hpp
+++ b/platform/qt/src/qt_geojson.hpp
@@ -1,7 +1,8 @@
#pragma once
#include <mapbox/geojson.hpp>
-#include <mbgl/style/conversion/geojson.hpp>
+#include <mbgl/util/geometry.hpp>
+#include <mbgl/util/feature.hpp>
#include <QMapbox>
@@ -13,187 +14,14 @@
namespace QMapbox {
-mbgl::Point<double> asMapboxGLPoint(const QMapbox::Coordinate &coordinate) {
- return mbgl::Point<double> { coordinate.second, coordinate.first };
-}
-
-mbgl::MultiPoint<double> asMapboxGLMultiPoint(const QMapbox::Coordinates &multiPoint) {
- mbgl::MultiPoint<double> mbglMultiPoint;
- mbglMultiPoint.reserve(multiPoint.size());
- for (const auto &point: multiPoint) {
- mbglMultiPoint.emplace_back(asMapboxGLPoint(point));
- }
- return mbglMultiPoint;
-};
-
-mbgl::LineString<double> asMapboxGLLineString(const QMapbox::Coordinates &lineString) {
- mbgl::LineString<double> mbglLineString;
- mbglLineString.reserve(lineString.size());
- for (const auto &coordinate : lineString) {
- mbglLineString.emplace_back(asMapboxGLPoint(coordinate));
- }
- return mbglLineString;
-};
-
-mbgl::MultiLineString<double> asMapboxGLMultiLineString(const QMapbox::CoordinatesCollection &multiLineString) {
- mbgl::MultiLineString<double> mbglMultiLineString;
- mbglMultiLineString.reserve(multiLineString.size());
- for (const auto &lineString : multiLineString) {
- mbglMultiLineString.emplace_back(std::forward<mbgl::LineString<double>>(asMapboxGLLineString(lineString)));
- }
- return mbglMultiLineString;
-};
-
-mbgl::Polygon<double> asMapboxGLPolygon(const QMapbox::CoordinatesCollection &polygon) {
- mbgl::Polygon<double> mbglPolygon;
- mbglPolygon.reserve(polygon.size());
- for (const auto &linearRing : polygon) {
- mbgl::LinearRing<double> mbglLinearRing;
- mbglLinearRing.reserve(linearRing.size());
- for (const auto &coordinate: linearRing) {
- mbglLinearRing.emplace_back(asMapboxGLPoint(coordinate));
- }
- mbglPolygon.emplace_back(std::move(mbglLinearRing));
- }
- return mbglPolygon;
-};
-
-mbgl::MultiPolygon<double> asMapboxGLMultiPolygon(const QMapbox::CoordinatesCollections &multiPolygon) {
- mbgl::MultiPolygon<double> mbglMultiPolygon;
- mbglMultiPolygon.reserve(multiPolygon.size());
- for (const auto &polygon : multiPolygon) {
- mbglMultiPolygon.emplace_back(std::forward<mbgl::Polygon<double>>(asMapboxGLPolygon(polygon)));
- }
- return mbglMultiPolygon;
-};
-
-mbgl::Value asMapboxGLPropertyValue(const QVariant &value) {
- auto valueList = [](const QVariantList &list) {
- std::vector<mbgl::Value> mbglList;
- mbglList.reserve(list.size());
- for (const auto& listValue : list) {
- mbglList.emplace_back(asMapboxGLPropertyValue(listValue));
- }
- return mbglList;
- };
-
- auto valueMap = [](const QVariantMap &map) {
- std::unordered_map<std::string, mbgl::Value> mbglMap;
- mbglMap.reserve(map.size());
- auto it = map.constBegin();
- while (it != map.constEnd()) {
- mbglMap.emplace(std::make_pair(it.key().toStdString(), asMapboxGLPropertyValue(it.value())));
- ++it;
- }
- return mbglMap;
- };
-
- switch (value.type()) {
-#if QT_VERSION >= 0x050000
- case QMetaType::UnknownType:
-#else
- case QVariant::Invalid:
-#endif
- return mbgl::NullValue {};
- case QMetaType::Bool:
- return { value.toBool() };
- case QMetaType::ULongLong:
- return { uint64_t(value.toULongLong()) };
- case QMetaType::LongLong:
- return { int64_t(value.toLongLong()) };
- case QMetaType::Double:
- return { value.toDouble() };
- case QMetaType::QString:
- return { value.toString().toStdString() };
- case QMetaType::QVariantList:
- return valueList(value.toList());
- case QMetaType::QVariantMap:
- return valueMap(value.toMap());
- default:
- qWarning() << "Unsupported feature property value:" << value;
- return {};
- }
-}
-
-mbgl::FeatureIdentifier asMapboxGLFeatureIdentifier(const QVariant &id) {
- switch (id.type()) {
-#if QT_VERSION >= 0x050000
- case QMetaType::UnknownType:
-#else
- case QVariant::Invalid:
-#endif
- return {};
- case QMetaType::ULongLong:
- return { uint64_t(id.toULongLong()) };
- case QMetaType::LongLong:
- return { int64_t(id.toLongLong()) };
- case QMetaType::Double:
- return { id.toDouble() };
- case QMetaType::QString:
- return { id.toString().toStdString() };
- default:
- qWarning() << "Unsupported feature identifier:" << id;
- return {};
- }
-}
-
-mbgl::Feature asMapboxGLFeature(const QMapbox::Feature &feature) {
- mbgl::PropertyMap properties;
- properties.reserve(feature.properties.size());
- auto it = feature.properties.constBegin();
- while (it != feature.properties.constEnd()) {
- properties.emplace(std::make_pair(it.key().toStdString(), asMapboxGLPropertyValue(it.value())));
- }
-
- mbgl::FeatureIdentifier id = asMapboxGLFeatureIdentifier(feature.id);
-
- if (feature.type == QMapbox::Feature::PointType) {
- const QMapbox::Coordinates &points = feature.geometry.first().first();
- if (points.size() == 1) {
- return { asMapboxGLPoint(points.first()), std::move(properties), std::move(id) };
- } else {
- return { asMapboxGLMultiPoint(points), std::move(properties), std::move(id) };
- }
- } else if (feature.type == QMapbox::Feature::LineStringType) {
- const QMapbox::CoordinatesCollection &lineStrings = feature.geometry.first();
- if (lineStrings.size() == 1) {
- return { asMapboxGLLineString(lineStrings.first()), std::move(properties), std::move(id) };
- } else {
- return { asMapboxGLMultiLineString(lineStrings), std::move(properties), std::move(id) };
- }
- } else { // PolygonType
- const QMapbox::CoordinatesCollections &polygons = feature.geometry;
- if (polygons.size() == 1) {
- return { asMapboxGLPolygon(polygons.first()), std::move(properties), std::move(id) };
- } else {
- return { asMapboxGLMultiPolygon(polygons), std::move(properties), std::move(id) };
- }
- }
-};
+mbgl::Point<double> asMapboxGLPoint(const QMapbox::Coordinate &coordinate);
+mbgl::MultiPoint<double> asMapboxGLMultiPoint(const QMapbox::Coordinates &multiPoint);
+mbgl::LineString<double> asMapboxGLLineString(const QMapbox::Coordinates &lineString);
+mbgl::MultiLineString<double> asMapboxGLMultiLineString(const QMapbox::CoordinatesCollection &multiLineString);
+mbgl::Polygon<double> asMapboxGLPolygon(const QMapbox::CoordinatesCollection &polygon);
+mbgl::MultiPolygon<double> asMapboxGLMultiPolygon(const QMapbox::CoordinatesCollections &multiPolygon);
+mbgl::Value asMapboxGLPropertyValue(const QVariant &value);
+mbgl::FeatureIdentifier asMapboxGLFeatureIdentifier(const QVariant &id);
+mbgl::Feature asMapboxGLFeature(const QMapbox::Feature &feature);
} // namespace QMapbox
-
-namespace mbgl {
-namespace style {
-namespace conversion {
-
-template <>
-optional<GeoJSON> Converter<GeoJSON>::operator()(const QVariant& value, Error& error) const {
-#if QT_VERSION >= 0x050000
- if (value.typeName() == QStringLiteral("QMapbox::Feature")) {
-#else
- if (value.typeName() == QString("QMapbox::Feature")) {
-#endif
- return GeoJSON { asMapboxGLFeature(value.value<QMapbox::Feature>()) };
- } else if (value.type() != QVariant::ByteArray) {
- error = { "JSON data must be in QByteArray" };
- return {};
- }
-
- QByteArray data = value.toByteArray();
- return convert<GeoJSON>(std::string(data.constData(), data.size()), error);
-}
-
-} // namespace conversion
-} // namespace style
-} // namespace mbgl
diff --git a/platform/qt/src/qt_image.cpp b/platform/qt/src/qt_image.cpp
index 403ca9cbd3..a5c92514c1 100644
--- a/platform/qt/src/qt_image.cpp
+++ b/platform/qt/src/qt_image.cpp
@@ -54,8 +54,13 @@ PremultipliedImage decodeImage(const std::string& string) {
throw std::runtime_error("Unsupported image type");
}
+#if QT_VERSION >= 0x051000
+ auto img = std::make_unique<uint8_t[]>(image.sizeInBytes());
+ memcpy(img.get(), image.constBits(), image.sizeInBytes());
+#else
auto img = std::make_unique<uint8_t[]>(image.byteCount());
memcpy(img.get(), image.constBits(), image.byteCount());
+#endif
return { { static_cast<uint32_t>(image.width()), static_cast<uint32_t>(image.height()) },
std::move(img) };
diff --git a/platform/qt/src/qt_logging.cpp b/platform/qt/src/qt_logging.cpp
new file mode 100755
index 0000000000..acbe9562d0
--- /dev/null
+++ b/platform/qt/src/qt_logging.cpp
@@ -0,0 +1,12 @@
+#include <mbgl/util/logging.hpp>
+#include <mbgl/util/enum.hpp>
+
+#include <QDebug>
+
+namespace mbgl {
+
+void Log::platformRecord(EventSeverity severity, const std::string &msg) {
+ qWarning() << "[" << Enum<EventSeverity>::toString(severity) << "] " << QString::fromStdString(msg);
+}
+
+} // namespace mbgl
diff --git a/platform/qt/src/sqlite3.cpp b/platform/qt/src/sqlite3.cpp
index 7d47ae552b..2f3db12f33 100644
--- a/platform/qt/src/sqlite3.cpp
+++ b/platform/qt/src/sqlite3.cpp
@@ -6,6 +6,7 @@
#include <QStringList>
#include <QThread>
#include <QVariant>
+#include <QAtomicInt>
#include <cassert>
#include <cstring>
@@ -60,20 +61,26 @@ void checkDatabaseOpenError(const QSqlDatabase &db) {
}
}
+namespace {
+ QString incrementCounter() {
+ static QAtomicInt count = 0;
+ return QString::number(count.fetchAndAddAcquire(1));
+ }
+}
+
class DatabaseImpl {
public:
- DatabaseImpl(const char* filename, int flags) {
- static uint64_t count = 0;
- const QString connectionName = QString::number(uint64_t(QThread::currentThread())) + QString::number(count++);
-
+ DatabaseImpl(const char* filename, int flags)
+ : connectionName(QString::number(uint64_t(QThread::currentThread())) + incrementCounter())
+ {
if (!QSqlDatabase::drivers().contains("QSQLITE")) {
throw Exception { Exception::Code::CANTOPEN, "SQLite driver not found." };
}
assert(!QSqlDatabase::contains(connectionName));
- db.reset(new QSqlDatabase(QSqlDatabase::addDatabase("QSQLITE", connectionName)));
+ auto db = QSqlDatabase::addDatabase("QSQLITE", connectionName);
- QString connectOptions = db->connectOptions();
+ QString connectOptions = db.connectOptions();
if (flags & OpenFlag::ReadOnly) {
if (!connectOptions.isEmpty()) connectOptions.append(';');
connectOptions.append("QSQLITE_OPEN_READONLY");
@@ -83,26 +90,26 @@ public:
connectOptions.append("QSQLITE_ENABLE_SHARED_CACHE");
}
- db->setConnectOptions(connectOptions);
- db->setDatabaseName(QString(filename));
+ db.setConnectOptions(connectOptions);
+ db.setDatabaseName(QString(filename));
- if (!db->open()) {
- checkDatabaseOpenError(*db);
+ if (!db.open()) {
+ checkDatabaseOpenError(db);
}
}
~DatabaseImpl() {
- db->close();
- checkDatabaseError(*db);
+ auto db = QSqlDatabase::database(connectionName);
+ db.close();
+ checkDatabaseError(db);
}
- QScopedPointer<QSqlDatabase> db;
+ QString connectionName;
};
class StatementImpl {
public:
StatementImpl(const QString& sql, const QSqlDatabase& db) : query(db) {
- query.setForwardOnly(true);
if (!query.prepare(sql)) {
checkQueryError(query);
}
@@ -147,17 +154,18 @@ void Database::setBusyTimeout(std::chrono::milliseconds timeout) {
// internally to int, so we need to make sure the limits apply.
std::string timeoutStr = mbgl::util::toString(timeout.count() & INT_MAX);
- QString connectOptions = impl->db->connectOptions();
+ auto db = QSqlDatabase::database(impl->connectionName);
+ QString connectOptions = db.connectOptions();
if (connectOptions.isEmpty()) {
if (!connectOptions.isEmpty()) connectOptions.append(';');
connectOptions.append("QSQLITE_BUSY_TIMEOUT=").append(QString::fromStdString(timeoutStr));
}
- if (impl->db->isOpen()) {
- impl->db->close();
+ if (db.isOpen()) {
+ db.close();
}
- impl->db->setConnectOptions(connectOptions);
- if (!impl->db->open()) {
- checkDatabaseOpenError(*impl->db);
+ db.setConnectOptions(connectOptions);
+ if (!db.open()) {
+ checkDatabaseOpenError(db);
}
}
@@ -169,9 +177,9 @@ void Database::exec(const std::string &sql) {
if (!statement.endsWith(';')) {
statement.append(';');
}
- QSqlQuery query(*impl->db);
- query.setForwardOnly(true);
+ QSqlQuery query(QSqlDatabase::database(impl->connectionName));
query.prepare(statement);
+
if (!query.exec()) {
checkQueryError(query);
}
@@ -183,7 +191,7 @@ Statement Database::prepare(const char *query) {
}
Statement::Statement(Database *db, const char *sql)
- : impl(std::make_unique<StatementImpl>(QString(sql), *db->impl->db)) {
+ : impl(std::make_unique<StatementImpl>(QString(sql), QSqlDatabase::database(db->impl->connectionName))) {
assert(impl);
}
@@ -269,9 +277,13 @@ void Statement::bind(int offset, const char* value, std::size_t length, bool ret
throw std::range_error("value too long");
}
+ // Qt SQLite driver treats QByteArray as blob: we need to explicitly
+ // declare the variant type as string.
+ QVariant text(QVariant::Type::String);
+ text.setValue(retain ? QByteArray(value, length) : QByteArray::fromRawData(value, length));
+
// Field numbering starts at 0.
- impl->query.bindValue(offset - 1, retain ? QByteArray(value, length) :
- QByteArray::fromRawData(value, length), QSql::In);
+ impl->query.bindValue(offset - 1, std::move(text), QSql::In);
checkQueryError(impl->query);
}
@@ -281,7 +293,12 @@ void Statement::bind(int offset, const std::string& value, bool retain) {
}
void Statement::bindBlob(int offset, const void* value_, std::size_t length, bool retain) {
+ assert(impl);
const char* value = reinterpret_cast<const char*>(value_);
+ if (length > std::numeric_limits<int>::max()) {
+ // Kept for consistence with the default implementation.
+ throw std::range_error("value too long");
+ }
// Field numbering starts at 0.
impl->query.bindValue(offset - 1, retain ? QByteArray(value, length) :
@@ -296,20 +313,20 @@ void Statement::bindBlob(int offset, const std::vector<uint8_t>& value, bool ret
bool Statement::run() {
assert(impl);
- if (impl->query.isValid()) {
- return impl->query.next();
- }
- assert(!impl->query.isActive());
- impl->query.setForwardOnly(true);
- if (!impl->query.exec()) {
- checkQueryError(impl->query);
+ if (!impl->query.isValid()) {
+ if (impl->query.exec()) {
+ impl->lastInsertRowId = impl->query.lastInsertId().value<int64_t>();
+ impl->changes = impl->query.numRowsAffected();
+ } else {
+ checkQueryError(impl->query);
+ }
}
- impl->lastInsertRowId = impl->query.lastInsertId().value<int64_t>();
- impl->changes = impl->query.numRowsAffected();
+ const bool hasNext = impl->query.next();
+ if (!hasNext) impl->query.finish();
- return impl->query.next();
+ return hasNext;
}
template bool Statement::get(int);
diff --git a/platform/qt/test/qmapboxgl.test.cpp b/platform/qt/test/qmapboxgl.test.cpp
index c6ae3ed403..932460b932 100644
--- a/platform/qt/test/qmapboxgl.test.cpp
+++ b/platform/qt/test/qmapboxgl.test.cpp
@@ -7,6 +7,9 @@
// We're using QGLFramebufferObject, which is only available in Qt 5 and up.
#if QT_VERSION >= 0x050000
+#include <QOpenGLContext>
+#include <QOpenGLFunctions>
+
QMapboxGLTest::QMapboxGLTest() : size(512, 512), fbo((assert(widget.context()->isValid()), widget.makeCurrent(), size)), map(nullptr, settings, size) {
connect(&map, SIGNAL(mapChanged(QMapboxGL::MapChange)),
this, SLOT(onMapChanged(QMapboxGL::MapChange)));
@@ -37,7 +40,7 @@ void QMapboxGLTest::onMapChanged(QMapboxGL::MapChange change) {
void QMapboxGLTest::onNeedsRendering() {
widget.makeCurrent();
fbo.bind();
- glViewport(0, 0, fbo.width(), fbo.height());
+ QOpenGLContext::currentContext()->functions()->glViewport(0, 0, fbo.width(), fbo.height());
map.render();
}
diff --git a/scripts/generate-style-code.js b/scripts/generate-style-code.js
index fe9a1a906b..443f0c7cc9 100644
--- a/scripts/generate-style-code.js
+++ b/scripts/generate-style-code.js
@@ -186,8 +186,8 @@ for (const layer of layers) {
writeIfModified(`src/mbgl/style/layers/${layerFileName}_layer_properties.cpp`, propertiesCpp(layer));
}
-const propertySettersHpp = ejs.compile(fs.readFileSync('include/mbgl/style/conversion/make_property_setters.hpp.ejs', 'utf8'), {strict: true});
-writeIfModified('include/mbgl/style/conversion/make_property_setters.hpp', propertySettersHpp({layers: layers}));
+const propertySettersHpp = ejs.compile(fs.readFileSync('src/mbgl/style/conversion/make_property_setters.hpp.ejs', 'utf8'), {strict: true});
+writeIfModified('src/mbgl/style/conversion/make_property_setters.hpp', propertySettersHpp({layers: layers}));
// Light
const lightProperties = Object.keys(spec[`light`]).reduce((memo, name) => {
diff --git a/scripts/update_ca_bundle.sh b/scripts/update_ca_bundle.sh
index 992bd7030f..3bd268bd0c 100755
--- a/scripts/update_ca_bundle.sh
+++ b/scripts/update_ca_bundle.sh
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-cd common
+cd misc
curl https://raw.githubusercontent.com/curl/curl/master/lib/mk-ca-bundle.pl | perl
rm certdata.txt
diff --git a/src/mbgl/annotation/render_annotation_source.cpp b/src/mbgl/annotation/render_annotation_source.cpp
index ba80be0da0..a0b69af8d5 100644
--- a/src/mbgl/annotation/render_annotation_source.cpp
+++ b/src/mbgl/annotation/render_annotation_source.cpp
@@ -63,8 +63,9 @@ std::unordered_map<std::string, std::vector<Feature>>
RenderAnnotationSource::queryRenderedFeatures(const ScreenLineString& geometry,
const TransformState& transformState,
const std::vector<const RenderLayer*>& layers,
- const RenderedQueryOptions& options) const {
- return tilePyramid.queryRenderedFeatures(geometry, transformState, layers, options);
+ const RenderedQueryOptions& options,
+ const CollisionIndex& collisionIndex) const {
+ return tilePyramid.queryRenderedFeatures(geometry, transformState, layers, options, collisionIndex);
}
std::vector<Feature> RenderAnnotationSource::querySourceFeatures(const SourceQueryOptions&) const {
diff --git a/src/mbgl/annotation/render_annotation_source.hpp b/src/mbgl/annotation/render_annotation_source.hpp
index 9536b2e101..aa2578d4e3 100644
--- a/src/mbgl/annotation/render_annotation_source.hpp
+++ b/src/mbgl/annotation/render_annotation_source.hpp
@@ -27,7 +27,8 @@ public:
queryRenderedFeatures(const ScreenLineString& geometry,
const TransformState& transformState,
const std::vector<const RenderLayer*>& layers,
- const RenderedQueryOptions& options) const final;
+ const RenderedQueryOptions& options,
+ const CollisionIndex& collisionIndex) const final;
std::vector<Feature>
querySourceFeatures(const SourceQueryOptions&) const final;
@@ -43,7 +44,7 @@ private:
template <>
inline bool RenderSource::is<RenderAnnotationSource>() const {
- return baseImpl->type == SourceType::Annotations;
+ return baseImpl->type == style::SourceType::Annotations;
}
} // namespace mbgl
diff --git a/src/mbgl/geometry/feature_index.cpp b/src/mbgl/geometry/feature_index.cpp
index 1adb933e44..3b5e12b54a 100644
--- a/src/mbgl/geometry/feature_index.cpp
+++ b/src/mbgl/geometry/feature_index.cpp
@@ -2,7 +2,7 @@
#include <mbgl/renderer/render_layer.hpp>
#include <mbgl/renderer/query.hpp>
#include <mbgl/renderer/layers/render_symbol_layer.hpp>
-#include <mbgl/text/collision_tile.hpp>
+#include <mbgl/text/collision_index.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/math.hpp>
#include <mbgl/math/minmax.hpp>
@@ -18,7 +18,7 @@
namespace mbgl {
FeatureIndex::FeatureIndex()
- : grid(util::EXTENT, 16, 0) {
+ : grid(util::EXTENT, util::EXTENT, util::EXTENT / 16) { // 16x16 grid -> 32px cell
}
void FeatureIndex::insert(const GeometryCollection& geometries,
@@ -26,8 +26,9 @@ void FeatureIndex::insert(const GeometryCollection& geometries,
const std::string& sourceLayerName,
const std::string& bucketName) {
for (const auto& ring : geometries) {
- grid.insert(IndexedSubfeature { index, sourceLayerName, bucketName, sortIndex++ },
- mapbox::geometry::envelope(ring));
+ auto envelope = mapbox::geometry::envelope(ring);
+ grid.insert(IndexedSubfeature(index, sourceLayerName, bucketName, sortIndex++),
+ {convertPoint<float>(envelope.min), convertPoint<float>(envelope.max)});
}
}
@@ -47,9 +48,10 @@ void FeatureIndex::query(
const double scale,
const RenderedQueryOptions& queryOptions,
const GeometryTileData& geometryTileData,
- const CanonicalTileID& tileID,
+ const UnwrappedTileID& tileID,
+ const std::string& sourceID,
const std::vector<const RenderLayer*>& layers,
- const CollisionTile* collisionTile,
+ const CollisionIndex& collisionIndex,
const float additionalQueryRadius) const {
// Determine query radius
@@ -58,7 +60,8 @@ void FeatureIndex::query(
// Query the grid index
mapbox::geometry::box<int16_t> box = mapbox::geometry::envelope(queryGeometry);
- std::vector<IndexedSubfeature> features = grid.query({ box.min - additionalRadius, box.max + additionalRadius });
+ std::vector<IndexedSubfeature> features = grid.query({ convertPoint<float>(box.min - additionalRadius),
+ convertPoint<float>(box.max + additionalRadius) });
std::sort(features.begin(), features.end(), topDown);
@@ -69,18 +72,13 @@ void FeatureIndex::query(
if (indexedFeature.sortIndex == previousSortIndex) continue;
previousSortIndex = indexedFeature.sortIndex;
- addFeature(result, indexedFeature, queryGeometry, queryOptions, geometryTileData, tileID, layers, bearing, pixelsToTileUnits);
+ addFeature(result, indexedFeature, queryGeometry, queryOptions, geometryTileData, tileID.canonical, layers, bearing, pixelsToTileUnits);
}
- // Query symbol features, if they've been placed.
- if (!collisionTile) {
- return;
- }
-
- std::vector<IndexedSubfeature> symbolFeatures = collisionTile->queryRenderedSymbols(queryGeometry, scale);
+ std::vector<IndexedSubfeature> symbolFeatures = collisionIndex.queryRenderedSymbols(queryGeometry, tileID, sourceID);
std::sort(symbolFeatures.begin(), symbolFeatures.end(), topDownSymbols);
for (const auto& symbolFeature : symbolFeatures) {
- addFeature(result, symbolFeature, queryGeometry, queryOptions, geometryTileData, tileID, layers, bearing, pixelsToTileUnits);
+ addFeature(result, symbolFeature, queryGeometry, queryOptions, geometryTileData, tileID.canonical, layers, bearing, pixelsToTileUnits);
}
}
diff --git a/src/mbgl/geometry/feature_index.hpp b/src/mbgl/geometry/feature_index.hpp
index 2ae7da33df..e95bb94da6 100644
--- a/src/mbgl/geometry/feature_index.hpp
+++ b/src/mbgl/geometry/feature_index.hpp
@@ -2,6 +2,7 @@
#include <mbgl/style/types.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
+#include <mbgl/tile/tile_id.hpp>
#include <mbgl/util/grid_index.hpp>
#include <mbgl/util/feature.hpp>
@@ -14,16 +15,37 @@ namespace mbgl {
class RenderedQueryOptions;
class RenderLayer;
-class CollisionTile;
-class CanonicalTileID;
+class CollisionIndex;
class IndexedSubfeature {
public:
IndexedSubfeature() = delete;
- std::size_t index;
+ IndexedSubfeature(std::size_t index_, std::string sourceLayerName_, std::string bucketName_, size_t sortIndex_)
+ : index(index_)
+ , sourceLayerName(std::move(sourceLayerName_))
+ , bucketName(std::move(bucketName_))
+ , sortIndex(sortIndex_)
+ , tileID(0, 0, 0)
+ {}
+
+ IndexedSubfeature(std::size_t index_, std::string sourceLayerName_, std::string bucketName_, size_t sortIndex_,
+ std::string sourceID_, CanonicalTileID tileID_)
+ : index(index_)
+ , sourceLayerName(std::move(sourceLayerName_))
+ , bucketName(std::move(bucketName_))
+ , sortIndex(std::move(sortIndex_))
+ , sourceID(std::move(sourceID_))
+ , tileID(std::move(tileID_))
+ {}
+
+ size_t index;
std::string sourceLayerName;
std::string bucketName;
size_t sortIndex;
+
+ // Only used for symbol features
+ std::string sourceID;
+ CanonicalTileID tileID;
};
class FeatureIndex {
@@ -40,9 +62,10 @@ public:
const double scale,
const RenderedQueryOptions& options,
const GeometryTileData&,
- const CanonicalTileID&,
+ const UnwrappedTileID&,
+ const std::string&,
const std::vector<const RenderLayer*>&,
- const CollisionTile*,
+ const CollisionIndex&,
const float additionalQueryRadius) const;
static optional<GeometryCoordinates> translateQueryGeometry(
diff --git a/src/mbgl/gl/color_mode.hpp b/src/mbgl/gl/color_mode.hpp
index e73c8737eb..c6594a3a77 100644
--- a/src/mbgl/gl/color_mode.hpp
+++ b/src/mbgl/gl/color_mode.hpp
@@ -49,7 +49,7 @@ public:
struct Replace {
static constexpr BlendEquation equation = BlendEquation::Add;
static constexpr BlendFactor srcFactor = One;
- static constexpr BlendFactor dstFactor = One;
+ static constexpr BlendFactor dstFactor = Zero;
};
using Add = LinearBlend<BlendEquation::Add>;
diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp
index 22b446e6d0..cc5aa014ed 100644
--- a/src/mbgl/gl/context.cpp
+++ b/src/mbgl/gl/context.cpp
@@ -226,16 +226,25 @@ void Context::updateVertexBuffer(UniqueBuffer& buffer, const void* data, std::si
MBGL_CHECK_ERROR(glBufferSubData(GL_ARRAY_BUFFER, 0, size, data));
}
-UniqueBuffer Context::createIndexBuffer(const void* data, std::size_t size) {
+UniqueBuffer Context::createIndexBuffer(const void* data, std::size_t size, const BufferUsage usage) {
BufferID id = 0;
MBGL_CHECK_ERROR(glGenBuffers(1, &id));
UniqueBuffer result { std::move(id), { this } };
bindVertexArray = 0;
globalVertexArrayState.indexBuffer = result;
- MBGL_CHECK_ERROR(glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data, GL_STATIC_DRAW));
+ MBGL_CHECK_ERROR(glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data, static_cast<GLenum>(usage)));
return result;
}
+void Context::updateIndexBuffer(UniqueBuffer& buffer, const void* data, std::size_t size) {
+ // Be sure to unbind any existing vertex array object before binding the index buffer
+ // so that we don't mess up another VAO
+ bindVertexArray = 0;
+ globalVertexArrayState.indexBuffer = buffer;
+ MBGL_CHECK_ERROR(glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, size, data));
+}
+
+
UniqueTexture Context::createTexture() {
if (pooledTextures.empty()) {
pooledTextures.resize(TextureMax);
@@ -596,19 +605,19 @@ void Context::clear(optional<mbgl::Color> color,
if (color) {
mask |= GL_COLOR_BUFFER_BIT;
clearColor = *color;
- colorMask = { true, true, true, true };
+ colorMask = value::ColorMask::Default;
}
if (depth) {
mask |= GL_DEPTH_BUFFER_BIT;
clearDepth = *depth;
- depthMask = true;
+ depthMask = value::DepthMask::Default;
}
if (stencil) {
mask |= GL_STENCIL_BUFFER_BIT;
clearStencil = *stencil;
- stencilMask = 0xFF;
+ stencilMask = value::StencilMask::Default;
}
MBGL_CHECK_ERROR(glClear(mask));
diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp
index 528113cbba..14f078367f 100644
--- a/src/mbgl/gl/context.hpp
+++ b/src/mbgl/gl/context.hpp
@@ -61,7 +61,7 @@ public:
optional<std::pair<BinaryProgramFormat, std::string>> getBinaryProgram(ProgramID) const;
template <class Vertex, class DrawMode>
- VertexBuffer<Vertex, DrawMode> createVertexBuffer(VertexVector<Vertex, DrawMode>&& v, const BufferUsage usage=BufferUsage::StaticDraw) {
+ VertexBuffer<Vertex, DrawMode> createVertexBuffer(VertexVector<Vertex, DrawMode>&& v, const BufferUsage usage = BufferUsage::StaticDraw) {
return VertexBuffer<Vertex, DrawMode> {
v.vertexSize(),
createVertexBuffer(v.data(), v.byteSize(), usage)
@@ -75,11 +75,18 @@ public:
}
template <class DrawMode>
- IndexBuffer<DrawMode> createIndexBuffer(IndexVector<DrawMode>&& v) {
+ IndexBuffer<DrawMode> createIndexBuffer(IndexVector<DrawMode>&& v, const BufferUsage usage = BufferUsage::StaticDraw) {
return IndexBuffer<DrawMode> {
- createIndexBuffer(v.data(), v.byteSize())
+ v.indexSize(),
+ createIndexBuffer(v.data(), v.byteSize(), usage)
};
}
+
+ template <class DrawMode>
+ void updateIndexBuffer(IndexBuffer<DrawMode>& buffer, IndexVector<DrawMode>&& v) {
+ assert(v.indexSize() == buffer.indexCount);
+ updateIndexBuffer(buffer.buffer, v.data(), v.byteSize());
+ }
template <RenderbufferType type>
Renderbuffer<type> createRenderbuffer(const Size size) {
@@ -250,7 +257,8 @@ private:
UniqueBuffer createVertexBuffer(const void* data, std::size_t size, const BufferUsage usage);
void updateVertexBuffer(UniqueBuffer& buffer, const void* data, std::size_t size);
- UniqueBuffer createIndexBuffer(const void* data, std::size_t size);
+ UniqueBuffer createIndexBuffer(const void* data, std::size_t size, const BufferUsage usage);
+ void updateIndexBuffer(UniqueBuffer& buffer, const void* data, std::size_t size);
UniqueTexture createTexture(Size size, const void* data, TextureFormat, TextureUnit);
void updateTexture(TextureID, Size size, const void* data, TextureFormat, TextureUnit);
UniqueFramebuffer createFramebuffer();
@@ -281,8 +289,13 @@ private:
std::vector<RenderbufferID> abandonedRenderbuffers;
public:
- // For testing
+ // For testing and Windows because Qt + ANGLE
+ // crashes with VAO enabled.
+#if defined(_WINDOWS)
+ bool disableVAOExtension = true;
+#else
bool disableVAOExtension = false;
+#endif
};
} // namespace gl
diff --git a/src/mbgl/gl/gl.hpp b/src/mbgl/gl/gl.hpp
index 3e21731330..976b7d2f74 100644
--- a/src/mbgl/gl/gl.hpp
+++ b/src/mbgl/gl/gl.hpp
@@ -1,36 +1,10 @@
#pragma once
+#include <mbgl/gl/gl_impl.hpp>
+
#include <stdexcept>
#include <limits>
-#if __APPLE__
- #include "TargetConditionals.h"
- #if TARGET_OS_IPHONE
- #include <OpenGLES/ES2/gl.h>
- #include <OpenGLES/ES2/glext.h>
- #elif TARGET_IPHONE_SIMULATOR
- #include <OpenGLES/ES2/gl.h>
- #include <OpenGLES/ES2/glext.h>
- #elif TARGET_OS_MAC
- #include <OpenGL/OpenGL.h>
- #include <OpenGL/gl.h>
- #include <OpenGL/glext.h>
- #else
- #error Unsupported Apple platform
- #endif
-#elif __ANDROID__ || MBGL_USE_GLES2
- #define GL_GLEXT_PROTOTYPES
- #include <GLES2/gl2.h>
- #include <GLES2/gl2ext.h>
-#elif __QT__ && QT_VERSION >= 0x050000
- #define GL_GLEXT_PROTOTYPES
- #include <QtGui/qopengl.h>
-#else
- #define GL_GLEXT_PROTOTYPES
- #include <GL/gl.h>
- #include <GL/glext.h>
-#endif
-
namespace mbgl {
namespace gl {
diff --git a/src/mbgl/gl/index_buffer.hpp b/src/mbgl/gl/index_buffer.hpp
index 01b6396e00..87bfb6068f 100644
--- a/src/mbgl/gl/index_buffer.hpp
+++ b/src/mbgl/gl/index_buffer.hpp
@@ -35,6 +35,7 @@ private:
template <class DrawMode>
class IndexBuffer {
public:
+ std::size_t indexCount;
UniqueBuffer buffer;
};
diff --git a/src/mbgl/layout/symbol_instance.cpp b/src/mbgl/layout/symbol_instance.cpp
index 02fb800df6..6e152349ca 100644
--- a/src/mbgl/layout/symbol_instance.cpp
+++ b/src/mbgl/layout/symbol_instance.cpp
@@ -11,7 +11,6 @@ SymbolInstance::SymbolInstance(Anchor& anchor_,
optional<PositionedIcon> shapedIcon,
const SymbolLayoutProperties::Evaluated& layout,
const float layoutTextSize,
- const bool addToBuffers,
const uint32_t index_,
const float textBoxScale,
const float textPadding,
@@ -19,11 +18,12 @@ SymbolInstance::SymbolInstance(Anchor& anchor_,
const std::array<float, 2> textOffset_,
const float iconBoxScale,
const float iconPadding,
- const SymbolPlacementType iconPlacement,
const std::array<float, 2> iconOffset_,
const GlyphPositionMap& positions,
const IndexedSubfeature& indexedFeature,
- const std::size_t featureIndex_) :
+ const std::size_t featureIndex_,
+ const std::u16string& key_,
+ const float overscaling) :
anchor(anchor_),
line(line_),
index(index_),
@@ -31,25 +31,22 @@ SymbolInstance::SymbolInstance(Anchor& anchor_,
hasIcon(shapedIcon),
// Create the collision features that will be used to check whether this symbol instance can be placed
- textCollisionFeature(line_, anchor, shapedTextOrientations.second ?: shapedTextOrientations.first, textBoxScale, textPadding, textPlacement, indexedFeature),
- iconCollisionFeature(line_, anchor, shapedIcon, iconBoxScale, iconPadding, iconPlacement, indexedFeature),
+ textCollisionFeature(line_, anchor, shapedTextOrientations.first, textBoxScale, textPadding, textPlacement, indexedFeature, overscaling),
+ iconCollisionFeature(line_, anchor, shapedIcon, iconBoxScale, iconPadding, indexedFeature),
featureIndex(featureIndex_),
textOffset(textOffset_),
- iconOffset(iconOffset_) {
+ iconOffset(iconOffset_),
+ key(key_) {
// Create the quads used for rendering the icon and glyphs.
- if (addToBuffers) {
- if (shapedIcon) {
- iconQuad = getIconQuad(*shapedIcon, layout, layoutTextSize, shapedTextOrientations.first);
- }
- if (shapedTextOrientations.first) {
- auto quads = getGlyphQuads(shapedTextOrientations.first, layout, textPlacement, positions);
- glyphQuads.insert(glyphQuads.end(), quads.begin(), quads.end());
- }
- if (shapedTextOrientations.second) {
- auto quads = getGlyphQuads(shapedTextOrientations.second, layout, textPlacement, positions);
- glyphQuads.insert(glyphQuads.end(), quads.begin(), quads.end());
- }
+ if (shapedIcon) {
+ iconQuad = getIconQuad(*shapedIcon, layout, layoutTextSize, shapedTextOrientations.first);
+ }
+ if (shapedTextOrientations.first) {
+ horizontalGlyphQuads = getGlyphQuads(shapedTextOrientations.first, layout, textPlacement, positions);
+ }
+ if (shapedTextOrientations.second) {
+ verticalGlyphQuads = getGlyphQuads(shapedTextOrientations.second, layout, textPlacement, positions);
}
if (shapedTextOrientations.first && shapedTextOrientations.second) {
diff --git a/src/mbgl/layout/symbol_instance.hpp b/src/mbgl/layout/symbol_instance.hpp
index f1df416cd1..827a5dbbdb 100644
--- a/src/mbgl/layout/symbol_instance.hpp
+++ b/src/mbgl/layout/symbol_instance.hpp
@@ -5,6 +5,7 @@
#include <mbgl/text/collision_feature.hpp>
#include <mbgl/style/layers/symbol_layer_properties.hpp>
+
namespace mbgl {
class Anchor;
@@ -18,7 +19,6 @@ public:
optional<PositionedIcon> shapedIcon,
const style::SymbolLayoutProperties::Evaluated&,
const float layoutTextSize,
- const bool inside,
const uint32_t index,
const float textBoxScale,
const float textPadding,
@@ -26,18 +26,20 @@ public:
const std::array<float, 2> textOffset,
const float iconBoxScale,
const float iconPadding,
- style::SymbolPlacementType iconPlacement,
const std::array<float, 2> iconOffset,
const GlyphPositionMap&,
const IndexedSubfeature&,
- const std::size_t featureIndex);
+ const std::size_t featureIndex,
+ const std::u16string& key,
+ const float overscaling);
Anchor anchor;
GeometryCoordinates line;
uint32_t index;
bool hasText;
bool hasIcon;
- SymbolQuads glyphQuads;
+ SymbolQuads horizontalGlyphQuads;
+ SymbolQuads verticalGlyphQuads;
optional<SymbolQuad> iconQuad;
CollisionFeature textCollisionFeature;
CollisionFeature iconCollisionFeature;
@@ -45,6 +47,12 @@ public:
std::size_t featureIndex;
std::array<float, 2> textOffset;
std::array<float, 2> iconOffset;
+ std::u16string key;
+ bool isDuplicate;
+ optional<size_t> placedTextIndex;
+ optional<size_t> placedVerticalTextIndex;
+ optional<size_t> placedIconIndex;
+ uint32_t crossTileID = 0;
};
} // namespace mbgl
diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp
index 2c90b69b08..fc1ede56ff 100644
--- a/src/mbgl/layout/symbol_layout.cpp
+++ b/src/mbgl/layout/symbol_layout.cpp
@@ -8,7 +8,6 @@
#include <mbgl/renderer/image_atlas.hpp>
#include <mbgl/style/layers/symbol_layer_impl.hpp>
#include <mbgl/text/get_anchors.hpp>
-#include <mbgl/text/collision_tile.hpp>
#include <mbgl/text/shaping.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/utf.hpp>
@@ -43,8 +42,8 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters,
std::unique_ptr<GeometryTileLayer> sourceLayer_,
ImageDependencies& imageDependencies,
GlyphDependencies& glyphDependencies)
- : sourceLayer(std::move(sourceLayer_)),
- bucketName(layers.at(0)->getID()),
+ : bucketName(layers.at(0)->getID()),
+ sourceLayer(std::move(sourceLayer_)),
overscaling(parameters.tileID.overscaleFactor()),
zoom(parameters.tileID.overscaledZ),
mode(parameters.mode),
@@ -179,7 +178,8 @@ bool SymbolLayout::hasSymbolInstances() const {
}
void SymbolLayout::prepare(const GlyphMap& glyphMap, const GlyphPositions& glyphPositions,
- const ImageMap& imageMap, const ImagePositions& imagePositions) {
+ const ImageMap& imageMap, const ImagePositions& imagePositions,
+ const OverscaledTileID& tileID, const std::string& sourceID) {
const bool textAlongLine = layout.get<TextRotationAlignment>() == AlignmentType::Map &&
layout.get<SymbolPlacement>() == SymbolPlacementType::Line;
@@ -248,7 +248,7 @@ void SymbolLayout::prepare(const GlyphMap& glyphMap, const GlyphPositions& glyph
// if either shapedText or icon position is present, add the feature
if (shapedTextOrientations.first || shapedIcon) {
- addFeature(std::distance(features.begin(), it), feature, shapedTextOrientations, shapedIcon, glyphPositionMap);
+ addFeature(std::distance(features.begin(), it), feature, shapedTextOrientations, shapedIcon, glyphPositionMap, tileID, sourceID);
}
feature.geometry.clear();
@@ -261,7 +261,9 @@ void SymbolLayout::addFeature(const std::size_t index,
const SymbolFeature& feature,
const std::pair<Shaping, Shaping>& shapedTextOrientations,
optional<PositionedIcon> shapedIcon,
- const GlyphPositionMap& glyphPositionMap) {
+ const GlyphPositionMap& glyphPositionMap,
+ const OverscaledTileID& tileID,
+ const std::string& sourceID) {
const float minScale = 0.5f;
const float glyphSize = 24.0f;
@@ -288,12 +290,10 @@ void SymbolLayout::addFeature(const std::size_t index,
const SymbolPlacementType textPlacement = layout.get<TextRotationAlignment>() != AlignmentType::Map
? SymbolPlacementType::Point
: layout.get<SymbolPlacement>();
- const SymbolPlacementType iconPlacement = layout.get<IconRotationAlignment>() != AlignmentType::Map
- ? SymbolPlacementType::Point
- : layout.get<SymbolPlacement>();
+
const float textRepeatDistance = symbolSpacing / 2;
- IndexedSubfeature indexedFeature = { feature.index, sourceLayer->getName(), bucketName,
- symbolInstances.size() };
+ IndexedSubfeature indexedFeature(feature.index, sourceLayer->getName(), bucketName, symbolInstances.size(),
+ sourceID, tileID.canonical);
auto addSymbolInstance = [&] (const GeometryCoordinates& line, Anchor& anchor) {
// https://github.com/mapbox/vector-tile-spec/tree/master/2.1#41-layers
@@ -314,14 +314,14 @@ void SymbolLayout::addFeature(const std::size_t index,
if (avoidEdges && !inside) return;
- const bool addToBuffers = mode == MapMode::Still || withinPlus0;
-
- symbolInstances.emplace_back(anchor, line, shapedTextOrientations, shapedIcon,
- layout.evaluate(zoom, feature), layoutTextSize,
- addToBuffers, symbolInstances.size(),
- textBoxScale, textPadding, textPlacement, textOffset,
- iconBoxScale, iconPadding, iconPlacement, iconOffset,
- glyphPositionMap, indexedFeature, index);
+ if (mode == MapMode::Tile || withinPlus0) {
+ symbolInstances.emplace_back(anchor, line, shapedTextOrientations, shapedIcon,
+ layout.evaluate(zoom, feature), layoutTextSize,
+ symbolInstances.size(),
+ textBoxScale, textPadding, textPlacement, textOffset,
+ iconBoxScale, iconPadding, iconOffset,
+ glyphPositionMap, indexedFeature, index, feature.text.value_or(std::u16string()), overscaling);
+ }
};
const auto& type = feature.getType();
@@ -392,108 +392,93 @@ bool SymbolLayout::anchorIsTooClose(const std::u16string& text, const float repe
return false;
}
-std::unique_ptr<SymbolBucket> SymbolLayout::place(CollisionTile& collisionTile) {
- auto bucket = std::make_unique<SymbolBucket>(layout, layerPaintProperties, textSize, iconSize, zoom, sdfIcons, iconsNeedLinear);
-
- // Calculate which labels can be shown and when they can be shown and
- // create the bufers used for rendering.
-
- const SymbolPlacementType textPlacement = layout.get<TextRotationAlignment>() != AlignmentType::Map
- ? SymbolPlacementType::Point
- : layout.get<SymbolPlacement>();
- const SymbolPlacementType iconPlacement = layout.get<IconRotationAlignment>() != AlignmentType::Map
- ? SymbolPlacementType::Point
- : layout.get<SymbolPlacement>();
+// Analog of `addToLineVertexArray` in JS. This version doesn't need to build up a line array like the
+// JS version does, but it uses the same logic to calculate tile distances.
+std::vector<float> CalculateTileDistances(const GeometryCoordinates& line, const Anchor& anchor) {
+ std::vector<float> tileDistances(line.size());
+ if (anchor.segment != -1) {
+ auto sumForwardLength = util::dist<float>(anchor.point, line[anchor.segment + 1]);
+ auto sumBackwardLength = util::dist<float>(anchor.point, line[anchor.segment]);
+ for (size_t i = anchor.segment + 1; i < line.size(); i++) {
+ tileDistances[i] = sumForwardLength;
+ if (i < line.size() - 1) {
+ sumForwardLength += util::dist<float>(line[i + 1], line[i]);
+ }
+ }
+ for (auto i = anchor.segment; i >= 0; i--) {
+ tileDistances[i] = sumBackwardLength;
+ if (i > 0) {
+ sumBackwardLength += util::dist<float>(line[i - 1], line[i]);
+ }
+ }
+ }
+ return tileDistances;
+}
+std::unique_ptr<SymbolBucket> SymbolLayout::place(const bool showCollisionBoxes) {
const bool mayOverlap = layout.get<TextAllowOverlap>() || layout.get<IconAllowOverlap>() ||
layout.get<TextIgnorePlacement>() || layout.get<IconIgnorePlacement>();
+
+ auto bucket = std::make_unique<SymbolBucket>(layout, layerPaintProperties, textSize, iconSize, zoom, sdfIcons, iconsNeedLinear, mayOverlap, std::move(symbolInstances));
- const bool keepUpright = layout.get<TextKeepUpright>();
-
- // Sort symbols by their y position on the canvas so that they lower symbols
- // are drawn on top of higher symbols.
- // Don't sort symbols that won't overlap because it isn't necessary and
- // because it causes more labels to pop in and out when rotating.
- if (mayOverlap) {
- const float sin = std::sin(collisionTile.config.angle);
- const float cos = std::cos(collisionTile.config.angle);
-
- std::sort(symbolInstances.begin(), symbolInstances.end(), [sin, cos](SymbolInstance &a, SymbolInstance &b) {
- const int32_t aRotated = sin * a.anchor.point.x + cos * a.anchor.point.y;
- const int32_t bRotated = sin * b.anchor.point.x + cos * b.anchor.point.y;
- return aRotated != bRotated ?
- aRotated < bRotated :
- a.index > b.index;
- });
- }
-
- for (SymbolInstance &symbolInstance : symbolInstances) {
+ for (SymbolInstance &symbolInstance : bucket->symbolInstances) {
const bool hasText = symbolInstance.hasText;
const bool hasIcon = symbolInstance.hasIcon;
- const bool iconWithoutText = layout.get<TextOptional>() || !hasText;
- const bool textWithoutIcon = layout.get<IconOptional>() || !hasIcon;
-
- // Calculate the scales at which the text and icon can be placed without collision.
-
- float glyphScale = hasText ?
- collisionTile.placeFeature(symbolInstance.textCollisionFeature,
- layout.get<TextAllowOverlap>(), layout.get<SymbolAvoidEdges>()) :
- collisionTile.minScale;
- float iconScale = hasIcon ?
- collisionTile.placeFeature(symbolInstance.iconCollisionFeature,
- layout.get<IconAllowOverlap>(), layout.get<SymbolAvoidEdges>()) :
- collisionTile.minScale;
-
-
- // Combine the scales for icons and text.
-
- if (!iconWithoutText && !textWithoutIcon) {
- iconScale = glyphScale = util::max(iconScale, glyphScale);
- } else if (!textWithoutIcon && glyphScale) {
- glyphScale = util::max(iconScale, glyphScale);
- } else if (!iconWithoutText && iconScale) {
- iconScale = util::max(iconScale, glyphScale);
- }
-
const auto& feature = features.at(symbolInstance.featureIndex);
// Insert final placement into collision tree and add glyphs/icons to buffers
if (hasText) {
- const float placementZoom = util::max(util::log2(glyphScale) + zoom, 0.0f);
- collisionTile.insertFeature(symbolInstance.textCollisionFeature, glyphScale, layout.get<TextIgnorePlacement>());
- if (glyphScale < collisionTile.maxScale) {
-
- const float labelAngle = std::fmod((symbolInstance.anchor.angle + collisionTile.config.angle) + 2 * M_PI, 2 * M_PI);
- const bool inVerticalRange = (
- (labelAngle > M_PI * 1.0 / 4.0 && labelAngle <= M_PI * 3.0 / 4) ||
- (labelAngle > M_PI * 5.0 / 4.0 && labelAngle <= M_PI * 7.0 / 4));
- const bool useVerticalMode = symbolInstance.writingModes & WritingModeType::Vertical && inVerticalRange;
-
- const Range<float> sizeData = bucket->textSizeBinder->getVertexSizeData(feature);
+ const Range<float> sizeData = bucket->textSizeBinder->getVertexSizeData(feature);
+ bucket->text.placedSymbols.emplace_back(symbolInstance.anchor.point, symbolInstance.anchor.segment, sizeData.min, sizeData.max,
+ symbolInstance.textOffset, symbolInstance.writingModes, symbolInstance.line, CalculateTileDistances(symbolInstance.line, symbolInstance.anchor));
+ symbolInstance.placedTextIndex = bucket->text.placedSymbols.size() - 1;
+ PlacedSymbol& horizontalSymbol = bucket->text.placedSymbols.back();
+
+ bool firstHorizontal = true;
+ for (const auto& symbol : symbolInstance.horizontalGlyphQuads) {
+ size_t index = addSymbol(
+ bucket->text, sizeData, symbol,
+ symbolInstance.anchor, horizontalSymbol);
+ if (firstHorizontal) {
+ horizontalSymbol.vertexStartIndex = index;
+ firstHorizontal = false;
+ }
+ }
+
+ if (symbolInstance.writingModes & WritingModeType::Vertical) {
bucket->text.placedSymbols.emplace_back(symbolInstance.anchor.point, symbolInstance.anchor.segment, sizeData.min, sizeData.max,
- symbolInstance.textOffset, placementZoom, useVerticalMode, symbolInstance.line);
-
- for (const auto& symbol : symbolInstance.glyphQuads) {
- addSymbol(
- bucket->text, sizeData, symbol, placementZoom,
- keepUpright, textPlacement, symbolInstance.anchor, bucket->text.placedSymbols.back());
+ symbolInstance.textOffset, WritingModeType::Vertical, symbolInstance.line, CalculateTileDistances(symbolInstance.line, symbolInstance.anchor));
+ symbolInstance.placedVerticalTextIndex = bucket->text.placedSymbols.size() - 1;
+
+ PlacedSymbol& verticalSymbol = bucket->text.placedSymbols.back();
+ bool firstVertical = true;
+
+ for (const auto& symbol : symbolInstance.verticalGlyphQuads) {
+ size_t index = addSymbol(
+ bucket->text, sizeData, symbol,
+ symbolInstance.anchor, verticalSymbol);
+
+ if (firstVertical) {
+ verticalSymbol.vertexStartIndex = index;
+ firstVertical = false;
+ }
}
}
}
if (hasIcon) {
- const float placementZoom = util::max(util::log2(iconScale) + zoom, 0.0f);
- collisionTile.insertFeature(symbolInstance.iconCollisionFeature, iconScale, layout.get<IconIgnorePlacement>());
- if (iconScale < collisionTile.maxScale && symbolInstance.iconQuad) {
+ if (symbolInstance.iconQuad) {
const Range<float> sizeData = bucket->iconSizeBinder->getVertexSizeData(feature);
bucket->icon.placedSymbols.emplace_back(symbolInstance.anchor.point, symbolInstance.anchor.segment, sizeData.min, sizeData.max,
- symbolInstance.iconOffset, placementZoom, false, symbolInstance.line);
- addSymbol(
- bucket->icon, sizeData, *symbolInstance.iconQuad, placementZoom,
- keepUpright, iconPlacement, symbolInstance.anchor, bucket->icon.placedSymbols.back());
+ symbolInstance.iconOffset, WritingModeType::None, symbolInstance.line, std::vector<float>());
+ symbolInstance.placedIconIndex = bucket->icon.placedSymbols.size() - 1;
+ PlacedSymbol& iconSymbol = bucket->icon.placedSymbols.back();
+ iconSymbol.vertexStartIndex = addSymbol(
+ bucket->icon, sizeData, *symbolInstance.iconQuad,
+ symbolInstance.anchor, iconSymbol);
}
}
@@ -503,20 +488,17 @@ std::unique_ptr<SymbolBucket> SymbolLayout::place(CollisionTile& collisionTile)
}
}
- if (collisionTile.config.debug) {
- addToDebugBuffers(collisionTile, *bucket);
+ if (showCollisionBoxes) {
+ addToDebugBuffers(*bucket);
}
return bucket;
}
template <typename Buffer>
-void SymbolLayout::addSymbol(Buffer& buffer,
+size_t SymbolLayout::addSymbol(Buffer& buffer,
const Range<float> sizeData,
const SymbolQuad& symbol,
- const float placementZoom,
- const bool keepUpright,
- const style::SymbolPlacementType placement,
const Anchor& labelAnchor,
PlacedSymbol& placedSymbol) {
constexpr const uint16_t vertexLength = 4;
@@ -527,11 +509,6 @@ void SymbolLayout::addSymbol(Buffer& buffer,
const auto &br = symbol.br;
const auto &tex = symbol.tex;
- if (placement == style::SymbolPlacementType::Line && keepUpright) {
- // drop incorrectly oriented glyphs
- if ((symbol.writingMode == WritingModeType::Vertical) != placedSymbol.useVerticalMode) return;
- }
-
if (buffer.segments.empty() || buffer.segments.back().vertexLength + vertexLength > std::numeric_limits<uint16_t>::max()) {
buffer.segments.emplace_back(buffer.vertices.vertexSize(), buffer.triangles.indexSize());
}
@@ -548,11 +525,19 @@ void SymbolLayout::addSymbol(Buffer& buffer,
buffer.vertices.emplace_back(SymbolLayoutAttributes::vertex(labelAnchor.point, bl, symbol.glyphOffset.y, tex.x, tex.y + tex.h, sizeData));
buffer.vertices.emplace_back(SymbolLayoutAttributes::vertex(labelAnchor.point, br, symbol.glyphOffset.y, tex.x + tex.w, tex.y + tex.h, sizeData));
- auto dynamicVertex = SymbolDynamicLayoutAttributes::vertex(labelAnchor.point, 0, placementZoom);
+ // Dynamic/Opacity vertices are initialized so that the vertex count always agrees with
+ // the layout vertex buffer, but they will always be updated before rendering happens
+ auto dynamicVertex = SymbolDynamicLayoutAttributes::vertex(labelAnchor.point, 0);
buffer.dynamicVertices.emplace_back(dynamicVertex);
buffer.dynamicVertices.emplace_back(dynamicVertex);
buffer.dynamicVertices.emplace_back(dynamicVertex);
buffer.dynamicVertices.emplace_back(dynamicVertex);
+
+ auto opacityVertex = SymbolOpacityAttributes::vertex(1.0, 1.0);
+ buffer.opacityVertices.emplace_back(opacityVertex);
+ buffer.opacityVertices.emplace_back(opacityVertex);
+ buffer.opacityVertices.emplace_back(opacityVertex);
+ buffer.opacityVertices.emplace_back(opacityVertex);
// add the two triangles, referencing the four coordinates we just inserted.
buffer.triangles.emplace_back(index + 0, index + 1, index + 2);
@@ -562,54 +547,62 @@ void SymbolLayout::addSymbol(Buffer& buffer,
segment.indexLength += 6;
placedSymbol.glyphOffsets.push_back(symbol.glyphOffset.x);
+
+ return index;
}
-void SymbolLayout::addToDebugBuffers(CollisionTile& collisionTile, SymbolBucket& bucket) {
+void SymbolLayout::addToDebugBuffers(SymbolBucket& bucket) {
if (!hasSymbolInstances()) {
return;
}
- const float yStretch = collisionTile.yStretch;
-
- auto& collisionBox = bucket.collisionBox;
-
for (const SymbolInstance &symbolInstance : symbolInstances) {
auto populateCollisionBox = [&](const auto& feature) {
+ SymbolBucket::CollisionBuffer& collisionBuffer = feature.alongLine ?
+ static_cast<SymbolBucket::CollisionBuffer&>(bucket.collisionCircle) :
+ static_cast<SymbolBucket::CollisionBuffer&>(bucket.collisionBox);
for (const CollisionBox &box : feature.boxes) {
auto& anchor = box.anchor;
- Point<float> tl{box.x1, box.y1 * yStretch};
- Point<float> tr{box.x2, box.y1 * yStretch};
- Point<float> bl{box.x1, box.y2 * yStretch};
- Point<float> br{box.x2, box.y2 * yStretch};
- tl = util::matrixMultiply(collisionTile.reverseRotationMatrix, tl);
- tr = util::matrixMultiply(collisionTile.reverseRotationMatrix, tr);
- bl = util::matrixMultiply(collisionTile.reverseRotationMatrix, bl);
- br = util::matrixMultiply(collisionTile.reverseRotationMatrix, br);
-
- const float maxZoom = util::clamp(zoom + util::log2(box.maxScale), util::MIN_ZOOM_F, util::MAX_ZOOM_F);
- const float placementZoom = util::clamp(zoom + util::log2(box.placementScale), util::MIN_ZOOM_F, util::MAX_ZOOM_F);
+ Point<float> tl{box.x1, box.y1};
+ Point<float> tr{box.x2, box.y1};
+ Point<float> bl{box.x1, box.y2};
+ Point<float> br{box.x2, box.y2};
static constexpr std::size_t vertexLength = 4;
- static constexpr std::size_t indexLength = 8;
+ const std::size_t indexLength = feature.alongLine ? 6 : 8;
- if (collisionBox.segments.empty() || collisionBox.segments.back().vertexLength + vertexLength > std::numeric_limits<uint16_t>::max()) {
- collisionBox.segments.emplace_back(collisionBox.vertices.vertexSize(), collisionBox.lines.indexSize());
+ if (collisionBuffer.segments.empty() || collisionBuffer.segments.back().vertexLength + vertexLength > std::numeric_limits<uint16_t>::max()) {
+ collisionBuffer.segments.emplace_back(collisionBuffer.vertices.vertexSize(),
+ feature.alongLine? bucket.collisionCircle.triangles.indexSize() : bucket.collisionBox.lines.indexSize());
}
- auto& segment = collisionBox.segments.back();
+ auto& segment = collisionBuffer.segments.back();
uint16_t index = segment.vertexLength;
- collisionBox.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, symbolInstance.anchor.point, tl, maxZoom, placementZoom));
- collisionBox.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, symbolInstance.anchor.point, tr, maxZoom, placementZoom));
- collisionBox.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, symbolInstance.anchor.point, br, maxZoom, placementZoom));
- collisionBox.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, symbolInstance.anchor.point, bl, maxZoom, placementZoom));
-
- collisionBox.lines.emplace_back(index + 0, index + 1);
- collisionBox.lines.emplace_back(index + 1, index + 2);
- collisionBox.lines.emplace_back(index + 2, index + 3);
- collisionBox.lines.emplace_back(index + 3, index + 0);
+ collisionBuffer.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, symbolInstance.anchor.point, tl));
+ collisionBuffer.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, symbolInstance.anchor.point, tr));
+ collisionBuffer.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, symbolInstance.anchor.point, br));
+ collisionBuffer.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, symbolInstance.anchor.point, bl));
+
+ // Dynamic vertices are initialized so that the vertex count always agrees with
+ // the layout vertex buffer, but they will always be updated before rendering happens
+ auto dynamicVertex = CollisionBoxDynamicAttributes::vertex(false, false);
+ collisionBuffer.dynamicVertices.emplace_back(dynamicVertex);
+ collisionBuffer.dynamicVertices.emplace_back(dynamicVertex);
+ collisionBuffer.dynamicVertices.emplace_back(dynamicVertex);
+ collisionBuffer.dynamicVertices.emplace_back(dynamicVertex);
+
+ if (feature.alongLine) {
+ bucket.collisionCircle.triangles.emplace_back(index, index + 1, index + 2);
+ bucket.collisionCircle.triangles.emplace_back(index, index + 2, index + 3);
+ } else {
+ bucket.collisionBox.lines.emplace_back(index + 0, index + 1);
+ bucket.collisionBox.lines.emplace_back(index + 1, index + 2);
+ bucket.collisionBox.lines.emplace_back(index + 2, index + 3);
+ bucket.collisionBox.lines.emplace_back(index + 3, index + 0);
+ }
segment.vertexLength += vertexLength;
segment.indexLength += indexLength;
diff --git a/src/mbgl/layout/symbol_layout.hpp b/src/mbgl/layout/symbol_layout.hpp
index 90f5b3c91d..6951c29ada 100644
--- a/src/mbgl/layout/symbol_layout.hpp
+++ b/src/mbgl/layout/symbol_layout.hpp
@@ -16,7 +16,6 @@
namespace mbgl {
class BucketParameters;
-class CollisionTile;
class SymbolBucket;
class Anchor;
class RenderLayer;
@@ -35,42 +34,44 @@ public:
GlyphDependencies&);
void prepare(const GlyphMap&, const GlyphPositions&,
- const ImageMap&, const ImagePositions&);
+ const ImageMap&, const ImagePositions&,
+ const OverscaledTileID&, const std::string&);
- std::unique_ptr<SymbolBucket> place(CollisionTile&);
+ std::unique_ptr<SymbolBucket> place(const bool showCollisionBoxes);
bool hasSymbolInstances() const;
std::map<std::string,
std::pair<style::IconPaintProperties::PossiblyEvaluated, style::TextPaintProperties::PossiblyEvaluated>> layerPaintProperties;
+ const std::string bucketName;
+ std::vector<SymbolInstance> symbolInstances;
+
private:
void addFeature(const size_t,
const SymbolFeature&,
const std::pair<Shaping, Shaping>& shapedTextOrientations,
optional<PositionedIcon> shapedIcon,
- const GlyphPositionMap&);
+ const GlyphPositionMap&,
+ const OverscaledTileID&,
+ const std::string&);
bool anchorIsTooClose(const std::u16string& text, const float repeatDistance, const Anchor&);
std::map<std::u16string, std::vector<Anchor>> compareText;
- void addToDebugBuffers(CollisionTile&, SymbolBucket&);
+ void addToDebugBuffers(SymbolBucket&);
// Adds placed items to the buffer.
template <typename Buffer>
- void addSymbol(Buffer&,
+ size_t addSymbol(Buffer&,
const Range<float> sizeData,
const SymbolQuad&,
- float scale,
- const bool keepUpright,
- const style::SymbolPlacementType,
const Anchor& labelAnchor,
PlacedSymbol& placedSymbol);
// Stores the layer so that we can hold on to GeometryTileFeature instances in SymbolFeature,
// which may reference data from this object.
const std::unique_ptr<GeometryTileLayer> sourceLayer;
- const std::string bucketName;
const float overscaling;
const float zoom;
const MapMode mode;
@@ -87,7 +88,6 @@ private:
style::TextSize::UnevaluatedType textSize;
style::IconSize::UnevaluatedType iconSize;
- std::vector<SymbolInstance> symbolInstances;
std::vector<SymbolFeature> features;
BiDi bidi; // Consider moving this up to geometry tile worker to reduce reinstantiation costs; use of BiDi/ubiditransform object must be constrained to one thread
diff --git a/src/mbgl/layout/symbol_projection.cpp b/src/mbgl/layout/symbol_projection.cpp
index 279d251f8f..ee6385c93c 100644
--- a/src/mbgl/layout/symbol_projection.cpp
+++ b/src/mbgl/layout/symbol_projection.cpp
@@ -3,7 +3,6 @@
#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/renderer/buckets/symbol_bucket.hpp>
#include <mbgl/renderer/layers/render_symbol_layer.hpp>
-#include <mbgl/renderer/frame_history.hpp>
#include <mbgl/util/optional.hpp>
#include <mbgl/util/math.hpp>
@@ -93,9 +92,6 @@ namespace mbgl {
return m;
}
-
- typedef std::pair<Point<float>,float> PointAndCameraDistance;
-
PointAndCameraDistance project(const Point<float>& point, const mat4& matrix) {
vec4 pos = {{ point.x, point.y, 0, 1 }};
matrix::transformMat4(pos, pos, matrix);
@@ -114,7 +110,7 @@ namespace mbgl {
}
}
- bool isVisible(const vec4& anchorPos, const float placementZoom, const std::array<double, 2>& clippingBuffer, const FrameHistory& frameHistory) {
+ bool isVisible(const vec4& anchorPos, const std::array<double, 2>& clippingBuffer) {
const float x = anchorPos[0] / anchorPos[3];
const float y = anchorPos[1] / anchorPos[3];
const bool inPaddedViewport = (
@@ -122,12 +118,12 @@ namespace mbgl {
x <= clippingBuffer[0] &&
y >= -clippingBuffer[1] &&
y <= clippingBuffer[1]);
- return inPaddedViewport && frameHistory.isVisible(placementZoom);
+ return inPaddedViewport;
}
- void addDynamicAttributes(const Point<float>& anchorPoint, const float angle, const float placementZoom,
+ void addDynamicAttributes(const Point<float>& anchorPoint, const float angle,
gl::VertexVector<SymbolDynamicLayoutAttributes::Vertex>& dynamicVertexArray) {
- auto dynamicVertex = SymbolDynamicLayoutAttributes::vertex(anchorPoint, angle, placementZoom);
+ auto dynamicVertex = SymbolDynamicLayoutAttributes::vertex(anchorPoint, angle);
dynamicVertexArray.emplace_back(dynamicVertex);
dynamicVertexArray.emplace_back(dynamicVertex);
dynamicVertexArray.emplace_back(dynamicVertex);
@@ -137,20 +133,15 @@ namespace mbgl {
void hideGlyphs(size_t numGlyphs, gl::VertexVector<SymbolDynamicLayoutAttributes::Vertex>& dynamicVertexArray) {
const Point<float> offscreenPoint = { -INFINITY, -INFINITY };
for (size_t i = 0; i < numGlyphs; i++) {
- addDynamicAttributes(offscreenPoint, 0, 25, dynamicVertexArray);
+ addDynamicAttributes(offscreenPoint, 0, dynamicVertexArray);
}
}
- struct PlacedGlyph {
- PlacedGlyph(Point<float> point_, float angle_) : point(point_), angle(angle_) {}
- Point<float> point;
- float angle;
- };
-
enum PlacementResult {
OK,
NotEnoughRoom,
- NeedsFlipping
+ NeedsFlipping,
+ UseVertical
};
Point<float> projectTruncatedLineSegment(const Point<float>& previousTilePoint, const Point<float>& currentTilePoint, const Point<float>& previousProjectedPoint, const float minimumLength, const mat4& projectionMatrix) {
@@ -165,7 +156,7 @@ namespace mbgl {
}
optional<PlacedGlyph> placeGlyphAlongLine(const float offsetX, const float lineOffsetX, const float lineOffsetY, const bool flip,
- const Point<float>& projectedAnchorPoint, const Point<float>& tileAnchorPoint, const uint16_t anchorSegment, const GeometryCoordinates& line, const mat4& labelPlaneMatrix) {
+ const Point<float>& projectedAnchorPoint, const Point<float>& tileAnchorPoint, const uint16_t anchorSegment, const GeometryCoordinates& line, const std::vector<float>& tileDistances, const mat4& labelPlaneMatrix, const bool returnTileDistance) {
const float combinedOffsetX = flip ?
offsetX - lineOffsetX :
@@ -185,6 +176,7 @@ namespace mbgl {
int32_t currentIndex = dir > 0 ? anchorSegment : anchorSegment + 1;
+ const int32_t initialIndex = currentIndex;
Point<float> current = projectedAnchorPoint;
Point<float> prev = projectedAnchorPoint;
float distanceToPrev = 0.0;
@@ -195,7 +187,9 @@ namespace mbgl {
currentIndex += dir;
// offset does not fit on the projected line
- if (currentIndex < 0 || currentIndex >= static_cast<int32_t>(line.size())) return {};
+ if (currentIndex < 0 || currentIndex >= static_cast<int32_t>(line.size())) {
+ return {};
+ }
prev = current;
PointAndCameraDistance projection = project(convertPoint<float>(line.at(currentIndex)), labelPlaneMatrix);
@@ -225,7 +219,62 @@ namespace mbgl {
const float segmentAngle = angle + std::atan2(current.y - prev.y, current.x - prev.x);
- return {{ p, segmentAngle }};
+ return {{
+ p,
+ segmentAngle,
+ returnTileDistance ?
+ TileDistance(
+ (currentIndex - dir) == initialIndex ? 0 : tileDistances[currentIndex - dir],
+ absOffsetX - distanceToPrev
+ ) :
+ optional<TileDistance>()
+ }};
+ }
+
+ optional<std::pair<PlacedGlyph, PlacedGlyph>> placeFirstAndLastGlyph(const float fontScale,
+ const float lineOffsetX,
+ const float lineOffsetY,
+ const bool flip,
+ const Point<float>& anchorPoint,
+ const Point<float>& tileAnchorPoint,
+ const PlacedSymbol& symbol,
+ const mat4& labelPlaneMatrix,
+ const bool returnTileDistance) {
+
+ const float firstGlyphOffset = symbol.glyphOffsets.front();
+ const float lastGlyphOffset = symbol.glyphOffsets.back();;
+
+ optional<PlacedGlyph> firstPlacedGlyph = placeGlyphAlongLine(fontScale * firstGlyphOffset, lineOffsetX, lineOffsetY, flip, anchorPoint, tileAnchorPoint, symbol.segment, symbol.line, symbol.tileDistances, labelPlaneMatrix, returnTileDistance);
+ if (!firstPlacedGlyph)
+ return optional<std::pair<PlacedGlyph, PlacedGlyph>>();
+
+ optional<PlacedGlyph> lastPlacedGlyph = placeGlyphAlongLine(fontScale * lastGlyphOffset, lineOffsetX, lineOffsetY, flip, anchorPoint, tileAnchorPoint, symbol.segment, symbol.line, symbol.tileDistances, labelPlaneMatrix, returnTileDistance);
+ if (!lastPlacedGlyph)
+ return optional<std::pair<PlacedGlyph, PlacedGlyph>>();
+
+ return std::make_pair(*firstPlacedGlyph, *lastPlacedGlyph);
+ }
+
+ optional<PlacementResult> requiresOrientationChange(const WritingModeType writingModes, const Point<float>& firstPoint, const Point<float>& lastPoint, const float aspectRatio) {
+ if (writingModes == (WritingModeType::Horizontal | WritingModeType::Vertical)) {
+ // On top of choosing whether to flip, choose whether to render this version of the glyphs or the alternate
+ // vertical glyphs. We can't just filter out vertical glyphs in the horizontal range because the horizontal
+ // and vertical versions can have slightly different projections which could lead to angles where both or
+ // neither showed.
+ auto rise = std::abs(lastPoint.y - firstPoint.y);
+ auto run = std::abs(lastPoint.x - firstPoint.x) * aspectRatio;
+ if (rise > run) {
+ return PlacementResult::UseVertical;
+ }
+ }
+
+ if ((writingModes == WritingModeType::Vertical) ?
+ (firstPoint.y < lastPoint.y) :
+ (firstPoint.x > lastPoint.x)) {
+ // Includes "horizontalOnly" case for labels without vertical glyphs
+ return PlacementResult::NeedsFlipping;
+ }
+ return {};
}
PlacementResult placeGlyphsAlongLine(const PlacedSymbol& symbol,
@@ -236,7 +285,8 @@ namespace mbgl {
const mat4& labelPlaneMatrix,
const mat4& glCoordMatrix,
gl::VertexVector<SymbolDynamicLayoutAttributes::Vertex>& dynamicVertexArray,
- const Point<float>& projectedAnchorPoint) {
+ const Point<float>& projectedAnchorPoint,
+ const float aspectRatio) {
const float fontScale = fontSize / 24.0;
const float lineOffsetX = symbol.lineOffset[0] * fontSize;
const float lineOffsetY = symbol.lineOffset[1] * fontSize;
@@ -244,33 +294,30 @@ namespace mbgl {
std::vector<PlacedGlyph> placedGlyphs;
if (symbol.glyphOffsets.size() > 1) {
- const float firstGlyphOffset = symbol.glyphOffsets.front();
- const float lastGlyphOffset = symbol.glyphOffsets.back();
-
- optional<PlacedGlyph> firstPlacedGlyph = placeGlyphAlongLine(fontScale * firstGlyphOffset, lineOffsetX, lineOffsetY, flip, projectedAnchorPoint, symbol.anchorPoint, symbol.segment, symbol.line, labelPlaneMatrix);
- if (!firstPlacedGlyph)
- return PlacementResult::NotEnoughRoom;
-
- optional<PlacedGlyph> lastPlacedGlyph = placeGlyphAlongLine(fontScale * lastGlyphOffset, lineOffsetX, lineOffsetY, flip, projectedAnchorPoint, symbol.anchorPoint, symbol.segment, symbol.line, labelPlaneMatrix);
- if (!lastPlacedGlyph)
+ const optional<std::pair<PlacedGlyph, PlacedGlyph>> firstAndLastGlyph =
+ placeFirstAndLastGlyph(fontScale, lineOffsetX, lineOffsetY, flip, projectedAnchorPoint, symbol.anchorPoint, symbol, labelPlaneMatrix, false);
+ if (!firstAndLastGlyph) {
return PlacementResult::NotEnoughRoom;
+ }
- const Point<float> firstPoint = project(firstPlacedGlyph->point, glCoordMatrix).first;
- const Point<float> lastPoint = project(lastPlacedGlyph->point, glCoordMatrix).first;
+ const Point<float> firstPoint = project(firstAndLastGlyph->first.point, glCoordMatrix).first;
+ const Point<float> lastPoint = project(firstAndLastGlyph->second.point, glCoordMatrix).first;
- if (keepUpright && !flip &&
- (symbol.useVerticalMode ? firstPoint.y < lastPoint.y : firstPoint.x > lastPoint.x)) {
- return PlacementResult::NeedsFlipping;
+ if (keepUpright && !flip) {
+ auto orientationChange = requiresOrientationChange(symbol.writingModes, firstPoint, lastPoint, aspectRatio);
+ if (orientationChange) {
+ return *orientationChange;
+ }
}
- placedGlyphs.push_back(*firstPlacedGlyph);
+ placedGlyphs.push_back(firstAndLastGlyph->first);
for (size_t glyphIndex = 1; glyphIndex < symbol.glyphOffsets.size() - 1; glyphIndex++) {
const float glyphOffsetX = symbol.glyphOffsets[glyphIndex];
// Since first and last glyph fit on the line, we're sure that the rest of the glyphs can be placed
- auto placedGlyph = placeGlyphAlongLine(glyphOffsetX * fontScale, lineOffsetX, lineOffsetY, flip, projectedAnchorPoint, symbol.anchorPoint, symbol.segment, symbol.line, labelPlaneMatrix);
+ auto placedGlyph = placeGlyphAlongLine(glyphOffsetX * fontScale, lineOffsetX, lineOffsetY, flip, projectedAnchorPoint, symbol.anchorPoint, symbol.segment, symbol.line, symbol.tileDistances, labelPlaneMatrix, false);
placedGlyphs.push_back(*placedGlyph);
}
- placedGlyphs.push_back(*lastPlacedGlyph);
+ placedGlyphs.push_back(firstAndLastGlyph->second);
} else {
// Only a single glyph to place
// So, determine whether to flip based on projected angle of the line segment it's on
@@ -285,14 +332,15 @@ namespace mbgl {
projectedVertex.first :
projectTruncatedLineSegment(symbol.anchorPoint,tileSegmentEnd, a, 1, posMatrix);
- if (symbol.useVerticalMode ? b.y > a.y : b.x < a.x) {
- return PlacementResult::NeedsFlipping;
+ auto orientationChange = requiresOrientationChange(symbol.writingModes, a, b, aspectRatio);
+ if (orientationChange) {
+ return *orientationChange;
}
}
assert(symbol.glyphOffsets.size() == 1); // We are relying on SymbolInstance.hasText filtering out symbols without any glyphs at all
const float glyphOffsetX = symbol.glyphOffsets.front();
optional<PlacedGlyph> singleGlyph = placeGlyphAlongLine(fontScale * glyphOffsetX, lineOffsetX, lineOffsetY, flip, projectedAnchorPoint, symbol.anchorPoint, symbol.segment,
- symbol.line, labelPlaneMatrix);
+ symbol.line, symbol.tileDistances, labelPlaneMatrix, false);
if (!singleGlyph)
return PlacementResult::NotEnoughRoom;
@@ -300,7 +348,7 @@ namespace mbgl {
}
for (auto& placedGlyph : placedGlyphs) {
- addDynamicAttributes(placedGlyph.point, placedGlyph.angle, symbol.placementZoom, dynamicVertexArray);
+ addDynamicAttributes(placedGlyph.point, placedGlyph.angle, dynamicVertexArray);
}
return PlacementResult::OK;
@@ -309,7 +357,7 @@ namespace mbgl {
void reprojectLineLabels(gl::VertexVector<SymbolDynamicLayoutAttributes::Vertex>& dynamicVertexArray, const std::vector<PlacedSymbol>& placedSymbols,
const mat4& posMatrix, const style::SymbolPropertyValues& values,
- const RenderTile& tile, const SymbolSizeBinder& sizeBinder, const TransformState& state, const FrameHistory& frameHistory) {
+ const RenderTile& tile, const SymbolSizeBinder& sizeBinder, const TransformState& state) {
const ZoomEvaluatedSize partiallyEvaluatedSize = sizeBinder.evaluateForZoom(state.getZoom());
@@ -325,19 +373,31 @@ namespace mbgl {
const mat4 glCoordMatrix = getGlCoordMatrix(posMatrix, pitchWithMap, rotateWithMap, state, pixelsToTileUnits);
dynamicVertexArray.clear();
+
+ bool useVertical = false;
for (auto& placedSymbol : placedSymbols) {
+ // Don't do calculations for vertical glyphs unless the previous symbol was horizontal
+ // and we determined that vertical glyphs were necessary.
+ // Also don't do calculations for symbols that are collided and fully faded out
+ if (placedSymbol.hidden || (placedSymbol.writingModes == WritingModeType::Vertical && !useVertical)) {
+ hideGlyphs(placedSymbol.glyphOffsets.size(), dynamicVertexArray);
+ continue;
+ }
+ // Awkward... but we're counting on the paired "vertical" symbol coming immediately after its horizontal counterpart
+ useVertical = false;
+
vec4 anchorPos = {{ placedSymbol.anchorPoint.x, placedSymbol.anchorPoint.y, 0, 1 }};
matrix::transformMat4(anchorPos, anchorPos, posMatrix);
// Don't bother calculating the correct point for invisible labels.
- if (!isVisible(anchorPos, placedSymbol.placementZoom, clippingBuffer, frameHistory)) {
+ if (!isVisible(anchorPos, clippingBuffer)) {
hideGlyphs(placedSymbol.glyphOffsets.size(), dynamicVertexArray);
continue;
}
const float cameraToAnchorDistance = anchorPos[3];
- const float perspectiveRatio = 1 + 0.5 * ((cameraToAnchorDistance / state.getCameraToCenterDistance()) - 1.0);
+ const float perspectiveRatio = 0.5 + 0.5 * (cameraToAnchorDistance / state.getCameraToCenterDistance());
const float fontSize = evaluateSizeForFeature(partiallyEvaluatedSize, placedSymbol);
const float pitchScaledFontSize = values.pitchAlignment == style::AlignmentType::Map ?
@@ -346,11 +406,13 @@ namespace mbgl {
const Point<float> anchorPoint = project(placedSymbol.anchorPoint, labelPlaneMatrix).first;
- PlacementResult placeUnflipped = placeGlyphsAlongLine(placedSymbol, pitchScaledFontSize, false /*unflipped*/, values.keepUpright, posMatrix, labelPlaneMatrix, glCoordMatrix, dynamicVertexArray, anchorPoint);
+ PlacementResult placeUnflipped = placeGlyphsAlongLine(placedSymbol, pitchScaledFontSize, false /*unflipped*/, values.keepUpright, posMatrix, labelPlaneMatrix, glCoordMatrix, dynamicVertexArray, anchorPoint, state.getSize().aspectRatio());
+
+ useVertical = placeUnflipped == PlacementResult::UseVertical;
- if (placeUnflipped == PlacementResult::NotEnoughRoom ||
+ if (placeUnflipped == PlacementResult::NotEnoughRoom || useVertical ||
(placeUnflipped == PlacementResult::NeedsFlipping &&
- placeGlyphsAlongLine(placedSymbol, pitchScaledFontSize, true /*flipped*/, values.keepUpright, posMatrix, labelPlaneMatrix, glCoordMatrix, dynamicVertexArray, anchorPoint) == PlacementResult::NotEnoughRoom)) {
+ placeGlyphsAlongLine(placedSymbol, pitchScaledFontSize, true /*flipped*/, values.keepUpright, posMatrix, labelPlaneMatrix, glCoordMatrix, dynamicVertexArray, anchorPoint, state.getSize().aspectRatio()) == PlacementResult::NotEnoughRoom)) {
hideGlyphs(placedSymbol.glyphOffsets.size(), dynamicVertexArray);
}
}
diff --git a/src/mbgl/layout/symbol_projection.hpp b/src/mbgl/layout/symbol_projection.hpp
index 2652fe7ace..3e57d162fd 100644
--- a/src/mbgl/layout/symbol_projection.hpp
+++ b/src/mbgl/layout/symbol_projection.hpp
@@ -8,18 +8,56 @@ namespace mbgl {
class TransformState;
class RenderTile;
- class FrameHistory;
class SymbolSizeBinder;
class PlacedSymbol;
namespace style {
class SymbolPropertyValues;
} // end namespace style
+
+ struct TileDistance {
+ TileDistance(float prevTileDistance_, float lastSegmentViewportDistance_)
+ : prevTileDistance(prevTileDistance_), lastSegmentViewportDistance(lastSegmentViewportDistance_)
+ {}
+ float prevTileDistance;
+ float lastSegmentViewportDistance;
+ };
+
+ struct PlacedGlyph {
+ PlacedGlyph() = default;
+ PlacedGlyph(Point<float> point_, float angle_, optional<TileDistance> tileDistance_)
+ : point(point_), angle(angle_), tileDistance(std::move(tileDistance_))
+ {}
+ PlacedGlyph(PlacedGlyph&& other) noexcept
+ : point(std::move(other.point)), angle(other.angle), tileDistance(std::move(other.tileDistance))
+ {}
+ PlacedGlyph(const PlacedGlyph& other)
+ : point(std::move(other.point)), angle(other.angle), tileDistance(std::move(other.tileDistance))
+ {}
+ Point<float> point;
+ float angle;
+ optional<TileDistance> tileDistance;
+ };
+
+ float evaluateSizeForFeature(const ZoomEvaluatedSize& zoomEvaluatedSize, const PlacedSymbol& placedSymbol);
mat4 getLabelPlaneMatrix(const mat4& posMatrix, const bool pitchWithMap, const bool rotateWithMap, const TransformState& state, const float pixelsToTileUnits);
mat4 getGlCoordMatrix(const mat4& posMatrix, const bool pitchWithMap, const bool rotateWithMap, const TransformState& state, const float pixelsToTileUnits);
+
+ using PointAndCameraDistance = std::pair<Point<float>,float>;
+ PointAndCameraDistance project(const Point<float>& point, const mat4& matrix);
void reprojectLineLabels(gl::VertexVector<SymbolDynamicLayoutAttributes::Vertex>&, const std::vector<PlacedSymbol>&,
const mat4& posMatrix, const style::SymbolPropertyValues&,
- const RenderTile&, const SymbolSizeBinder& sizeBinder, const TransformState&, const FrameHistory& frameHistory);
+ const RenderTile&, const SymbolSizeBinder& sizeBinder, const TransformState&);
+
+ optional<std::pair<PlacedGlyph, PlacedGlyph>> placeFirstAndLastGlyph(const float fontScale,
+ const float lineOffsetX,
+ const float lineOffsetY,
+ const bool flip,
+ const Point<float>& anchorPoint,
+ const Point<float>& tileAnchorPoint,
+ const PlacedSymbol& symbol,
+ const mat4& labelPlaneMatrix,
+ const bool returnTileDistance);
} // end namespace mbgl
diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp
index 5e5063905e..947973415a 100644
--- a/src/mbgl/map/map.cpp
+++ b/src/mbgl/map/map.cpp
@@ -149,8 +149,8 @@ void Map::renderStill(StillImageCallback callback) {
return;
}
- if (impl->mode != MapMode::Still) {
- callback(std::make_exception_ptr(util::MisuseException("Map is not in still image render mode")));
+ if (impl->mode != MapMode::Static && impl->mode != MapMode::Tile) {
+ callback(std::make_exception_ptr(util::MisuseException("Map is not in static or tile image render modes")));
return;
}
@@ -617,6 +617,35 @@ ViewportMode Map::getViewportMode() const {
return impl->transform.getViewportMode();
}
+#pragma mark - Projection mode
+
+void Map::setAxonometric(bool axonometric) {
+ impl->transform.setAxonometric(axonometric);
+ impl->onUpdate();
+}
+
+bool Map::getAxonometric() const {
+ return impl->transform.getAxonometric();
+}
+
+void Map::setXSkew(double xSkew) {
+ impl->transform.setXSkew(xSkew);
+ impl->onUpdate();
+}
+
+double Map::getXSkew() const {
+ return impl->transform.getXSkew();
+}
+
+void Map::setYSkew(double ySkew) {
+ impl->transform.setYSkew(ySkew);
+ impl->onUpdate();
+}
+
+double Map::getYSkew() const {
+ return impl->transform.getYSkew();
+}
+
#pragma mark - Projection
ScreenCoordinate Map::pixelForLatLng(const LatLng& latLng) const {
@@ -765,7 +794,7 @@ void Map::Impl::onStyleError(std::exception_ptr error) {
}
void Map::Impl::onResourceError(std::exception_ptr error) {
- if (mode == MapMode::Still && stillImageRequest) {
+ if (mode != MapMode::Continuous && stillImageRequest) {
auto request = std::move(stillImageRequest);
request->callback(error);
}
diff --git a/src/mbgl/map/transform.cpp b/src/mbgl/map/transform.cpp
index 2bb25af28f..105adf0400 100644
--- a/src/mbgl/map/transform.cpp
+++ b/src/mbgl/map/transform.cpp
@@ -527,6 +527,32 @@ ViewportMode Transform::getViewportMode() const {
return state.getViewportMode();
}
+#pragma mark - Projection mode
+
+void Transform::setAxonometric(bool axonometric) {
+ state.axonometric = axonometric;
+}
+
+bool Transform::getAxonometric() const {
+ return state.axonometric;
+}
+
+void Transform::setXSkew(double xSkew) {
+ state.xSkew = xSkew;
+}
+
+double Transform::getXSkew() const {
+ return state.xSkew;
+}
+
+void Transform::setYSkew(double ySkew) {
+ state.ySkew = ySkew;
+}
+
+double Transform::getYSkew() const {
+ return state.ySkew;
+}
+
#pragma mark - Transition
void Transform::startTransition(const CameraOptions& camera,
diff --git a/src/mbgl/map/transform.hpp b/src/mbgl/map/transform.hpp
index 749228bdf5..d429c57661 100644
--- a/src/mbgl/map/transform.hpp
+++ b/src/mbgl/map/transform.hpp
@@ -125,6 +125,14 @@ public:
void setViewportMode(ViewportMode);
ViewportMode getViewportMode() const;
+ // Projection mode
+ void setAxonometric(bool);
+ bool getAxonometric() const;
+ void setXSkew(double xSkew);
+ double getXSkew() const;
+ void setYSkew(double ySkew);
+ double getYSkew() const;
+
// Transitions
bool inTransition() const;
void updateTransitions(const TimePoint& now);
diff --git a/src/mbgl/map/transform_state.cpp b/src/mbgl/map/transform_state.cpp
index d1a320beae..d79a65c61e 100644
--- a/src/mbgl/map/transform_state.cpp
+++ b/src/mbgl/map/transform_state.cpp
@@ -66,6 +66,15 @@ void TransformState::getProjMatrix(mat4& projMatrix, uint16_t nearZ) const {
matrix::translate(projMatrix, projMatrix, pixel_x() - size.width / 2.0f,
pixel_y() - size.height / 2.0f, 0);
+ if (axonometric) {
+ // mat[11] controls perspective
+ projMatrix[11] = 0;
+
+ // mat[8], mat[9] control x-skew, y-skew
+ projMatrix[8] = xSkew;
+ projMatrix[9] = ySkew;
+ }
+
matrix::scale(projMatrix, projMatrix, 1, 1,
1.0 / Projection::getMetersPerPixelAtLatitude(getLatLng(LatLng::Unwrapped).latitude(), getZoom()));
}
diff --git a/src/mbgl/map/transform_state.hpp b/src/mbgl/map/transform_state.hpp
index 59522d89fd..0dd6d5a15e 100644
--- a/src/mbgl/map/transform_state.hpp
+++ b/src/mbgl/map/transform_state.hpp
@@ -134,6 +134,9 @@ private:
// `fov = 2 * arctan((height / 2) / (height * 1.5))`
double fov = 0.6435011087932844;
double pitch = 0.0;
+ double xSkew = 0.0;
+ double ySkew = 1.0;
+ bool axonometric = false;
// cache values for spherical mercator math
double Bc = Projection::worldSize(scale) / util::DEGREES_MAX;
diff --git a/src/mbgl/programs/attributes.hpp b/src/mbgl/programs/attributes.hpp
index d023ec7d83..b0582b0bc2 100644
--- a/src/mbgl/programs/attributes.hpp
+++ b/src/mbgl/programs/attributes.hpp
@@ -28,8 +28,9 @@ MBGL_DEFINE_ATTRIBUTE(float, 3, a_projected_pos);
MBGL_DEFINE_ATTRIBUTE(int16_t, 2, a_label_pos);
MBGL_DEFINE_ATTRIBUTE(int16_t, 2, a_anchor_pos);
MBGL_DEFINE_ATTRIBUTE(uint16_t, 2, a_texture_pos);
-MBGL_DEFINE_ATTRIBUTE(int16_t, 3, a_normal);
-MBGL_DEFINE_ATTRIBUTE(uint16_t, 1, a_edgedistance);
+MBGL_DEFINE_ATTRIBUTE(int16_t, 4, a_normal_ed);
+MBGL_DEFINE_ATTRIBUTE(uint8_t, 1, a_fade_opacity);
+MBGL_DEFINE_ATTRIBUTE(uint8_t, 2, a_placed);
template <typename T, std::size_t N>
struct a_data {
diff --git a/src/mbgl/programs/collision_box_program.hpp b/src/mbgl/programs/collision_box_program.hpp
index ba99e0c087..8d712a3df3 100644
--- a/src/mbgl/programs/collision_box_program.hpp
+++ b/src/mbgl/programs/collision_box_program.hpp
@@ -4,6 +4,7 @@
#include <mbgl/programs/attributes.hpp>
#include <mbgl/programs/uniforms.hpp>
#include <mbgl/shaders/collision_box.hpp>
+#include <mbgl/shaders/collision_circle.hpp>
#include <mbgl/style/properties.hpp>
#include <mbgl/util/geometry.hpp>
@@ -11,37 +12,34 @@
namespace mbgl {
-namespace uniforms {
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_scale);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_maxzoom);
-} // namespace uniforms
-
-using CollisionBoxAttributes = gl::Attributes<
+using CollisionBoxLayoutAttributes = gl::Attributes<
attributes::a_pos,
attributes::a_anchor_pos,
- attributes::a_extrude,
- attributes::a_data<uint8_t, 2>>;
+ attributes::a_extrude>;
+
+struct CollisionBoxDynamicAttributes : gl::Attributes<attributes::a_placed> {
+ static Vertex vertex(bool placed, bool notUsed) {
+ return Vertex {
+ {{ static_cast<uint8_t>(placed), static_cast<uint8_t>(notUsed) }}
+ };
+ }
+};
class CollisionBoxProgram : public Program<
shaders::collision_box,
gl::Line,
- CollisionBoxAttributes,
+ gl::ConcatenateAttributes<CollisionBoxLayoutAttributes, CollisionBoxDynamicAttributes>,
gl::Uniforms<
uniforms::u_matrix,
- uniforms::u_scale,
- uniforms::u_zoom,
- uniforms::u_maxzoom,
- uniforms::u_collision_y_stretch,
- uniforms::u_camera_to_center_distance,
- uniforms::u_pitch,
- uniforms::u_fadetexture>,
+ uniforms::u_extrude_scale,
+ uniforms::u_camera_to_center_distance>,
style::Properties<>>
{
public:
using Program::Program;
- static LayoutVertex vertex(Point<float> a, Point<float> anchor, Point<float> o, float maxzoom, float placementZoom) {
- return LayoutVertex {
+ static CollisionBoxLayoutAttributes::Vertex vertex(Point<float> a, Point<float> anchor, Point<float> o) {
+ return CollisionBoxLayoutAttributes::Vertex {
{{
static_cast<int16_t>(a.x),
static_cast<int16_t>(a.y)
@@ -53,13 +51,131 @@ public:
{{
static_cast<int16_t>(::round(o.x)),
static_cast<int16_t>(::round(o.y))
+ }}
+ };
+ }
+
+ template <class DrawMode>
+ void draw(gl::Context& context,
+ DrawMode drawMode,
+ gl::DepthMode depthMode,
+ gl::StencilMode stencilMode,
+ gl::ColorMode colorMode,
+ const UniformValues& uniformValues,
+ const gl::VertexBuffer<CollisionBoxLayoutAttributes::Vertex>& layoutVertexBuffer,
+ const gl::VertexBuffer<CollisionBoxDynamicAttributes::Vertex>& dynamicVertexBuffer,
+ const gl::IndexBuffer<DrawMode>& indexBuffer,
+ const SegmentVector<Attributes>& segments,
+ const PaintPropertyBinders& paintPropertyBinders,
+ const typename PaintProperties::PossiblyEvaluated& currentProperties,
+ float currentZoom,
+ const std::string& layerID) {
+ typename AllUniforms::Values allUniformValues = uniformValues
+ .concat(paintPropertyBinders.uniformValues(currentZoom, currentProperties));
+
+ typename Attributes::Bindings allAttributeBindings = CollisionBoxLayoutAttributes::bindings(layoutVertexBuffer)
+ .concat(CollisionBoxDynamicAttributes::bindings(dynamicVertexBuffer))
+ .concat(paintPropertyBinders.attributeBindings(currentProperties));
+
+ assert(layoutVertexBuffer.vertexCount == dynamicVertexBuffer.vertexCount);
+
+ for (auto& segment : segments) {
+ auto vertexArrayIt = segment.vertexArrays.find(layerID);
+
+ if (vertexArrayIt == segment.vertexArrays.end()) {
+ vertexArrayIt = segment.vertexArrays.emplace(layerID, context.createVertexArray()).first;
+ }
+
+ program.draw(
+ context,
+ std::move(drawMode),
+ std::move(depthMode),
+ std::move(stencilMode),
+ std::move(colorMode),
+ allUniformValues,
+ vertexArrayIt->second,
+ Attributes::offsetBindings(allAttributeBindings, segment.vertexOffset),
+ indexBuffer,
+ segment.indexOffset,
+ segment.indexLength);
+ }
+ }
+};
+
+
+class CollisionCircleProgram : public Program<
+ shaders::collision_circle,
+ gl::Triangle,
+ gl::ConcatenateAttributes<CollisionBoxLayoutAttributes, CollisionBoxDynamicAttributes>,
+ gl::Uniforms<
+ uniforms::u_matrix,
+ uniforms::u_extrude_scale,
+ uniforms::u_camera_to_center_distance>,
+ style::Properties<>>
+{
+public:
+ using Program::Program;
+
+ static CollisionBoxLayoutAttributes::Vertex vertex(Point<float> a, Point<float> anchor, Point<float> o) {
+ return CollisionBoxLayoutAttributes::Vertex {
+ {{
+ static_cast<int16_t>(a.x),
+ static_cast<int16_t>(a.y)
+ }},
+ {{
+ static_cast<int16_t>(anchor.x),
+ static_cast<int16_t>(anchor.y)
}},
{{
- static_cast<uint8_t>(maxzoom * 10),
- static_cast<uint8_t>(placementZoom * 10)
+ static_cast<int16_t>(::round(o.x)),
+ static_cast<int16_t>(::round(o.y))
}}
};
}
+
+ template <class DrawMode>
+ void draw(gl::Context& context,
+ DrawMode drawMode,
+ gl::DepthMode depthMode,
+ gl::StencilMode stencilMode,
+ gl::ColorMode colorMode,
+ const UniformValues& uniformValues,
+ const gl::VertexBuffer<CollisionBoxLayoutAttributes::Vertex>& layoutVertexBuffer,
+ const gl::VertexBuffer<CollisionBoxDynamicAttributes::Vertex>& dynamicVertexBuffer,
+ const gl::IndexBuffer<DrawMode>& indexBuffer,
+ const SegmentVector<Attributes>& segments,
+ const PaintPropertyBinders& paintPropertyBinders,
+ const typename PaintProperties::PossiblyEvaluated& currentProperties,
+ float currentZoom,
+ const std::string& layerID) {
+ typename AllUniforms::Values allUniformValues = uniformValues
+ .concat(paintPropertyBinders.uniformValues(currentZoom, currentProperties));
+
+ typename Attributes::Bindings allAttributeBindings = CollisionBoxLayoutAttributes::bindings(layoutVertexBuffer)
+ .concat(CollisionBoxDynamicAttributes::bindings(dynamicVertexBuffer))
+ .concat(paintPropertyBinders.attributeBindings(currentProperties));
+
+ for (auto& segment : segments) {
+ auto vertexArrayIt = segment.vertexArrays.find(layerID);
+
+ if (vertexArrayIt == segment.vertexArrays.end()) {
+ vertexArrayIt = segment.vertexArrays.emplace(layerID, context.createVertexArray()).first;
+ }
+
+ program.draw(
+ context,
+ std::move(drawMode),
+ std::move(depthMode),
+ std::move(stencilMode),
+ std::move(colorMode),
+ allUniformValues,
+ vertexArrayIt->second,
+ Attributes::offsetBindings(allAttributeBindings, segment.vertexOffset),
+ indexBuffer,
+ segment.indexOffset,
+ segment.indexLength);
+ }
+ }
};
using CollisionBoxVertex = CollisionBoxProgram::LayoutVertex;
diff --git a/src/mbgl/programs/fill_extrusion_program.hpp b/src/mbgl/programs/fill_extrusion_program.hpp
index 820670068e..c499e9ef2d 100644
--- a/src/mbgl/programs/fill_extrusion_program.hpp
+++ b/src/mbgl/programs/fill_extrusion_program.hpp
@@ -30,8 +30,7 @@ MBGL_DEFINE_UNIFORM_SCALAR(float, u_height_factor);
struct FillExtrusionLayoutAttributes : gl::Attributes<
attributes::a_pos,
- attributes::a_normal,
- attributes::a_edgedistance>
+ attributes::a_normal_ed>
{};
struct FillExtrusionUniforms : gl::Uniforms<
@@ -100,12 +99,9 @@ public:
// We pack a bool (`t`) into the x component indicating whether it is an upper or lower vertex
static_cast<int16_t>(floor(nx * factor) * 2 + t),
static_cast<int16_t>(ny * factor * 2),
- static_cast<int16_t>(nz * factor * 2)
-
- }},
- {{
+ static_cast<int16_t>(nz * factor * 2),
// The edgedistance attribute is used for wrapping fill_extrusion patterns
- e
+ static_cast<int16_t>(e)
}}
};
}
diff --git a/src/mbgl/programs/programs.hpp b/src/mbgl/programs/programs.hpp
index 37ced32745..d769defaaf 100644
--- a/src/mbgl/programs/programs.hpp
+++ b/src/mbgl/programs/programs.hpp
@@ -32,7 +32,8 @@ public:
symbolIconSDF(context, programParameters),
symbolGlyph(context, programParameters),
debug(context, programParameters),
- collisionBox(context, programParameters) {
+ collisionBox(context, programParameters),
+ collisionCircle(context, programParameters) {
}
ProgramMap<CircleProgram> circle;
@@ -53,6 +54,7 @@ public:
DebugProgram debug;
CollisionBoxProgram collisionBox;
+ CollisionCircleProgram collisionCircle;
};
} // namespace mbgl
diff --git a/src/mbgl/programs/symbol_program.cpp b/src/mbgl/programs/symbol_program.cpp
index 58174ff8a7..84a7a53f1d 100644
--- a/src/mbgl/programs/symbol_program.cpp
+++ b/src/mbgl/programs/symbol_program.cpp
@@ -37,6 +37,7 @@ Values makeValues(const bool isText,
const bool alongLine,
const RenderTile& tile,
const TransformState& state,
+ const float symbolFadeChange,
Args&&... args) {
std::array<float, 2> extrudeScale;
@@ -82,9 +83,8 @@ Values makeValues(const bool isText,
uniforms::u_extrude_scale::Value{ extrudeScale },
uniforms::u_texsize::Value{ texsize },
uniforms::u_texture::Value{ 0 },
- uniforms::u_fadetexture::Value{ 1 },
+ uniforms::u_fade_change::Value{ symbolFadeChange },
uniforms::u_is_text::Value{ isText },
- uniforms::u_collision_y_stretch::Value{ tile.tile.yStretch() },
uniforms::u_camera_to_center_distance::Value{ state.getCameraToCenterDistance() },
uniforms::u_pitch::Value{ state.getPitch() },
uniforms::u_pitch_with_map::Value{ pitchWithMap },
@@ -102,7 +102,8 @@ SymbolIconProgram::uniformValues(const bool isText,
const std::array<float, 2>& pixelsToGLUnits,
const bool alongLine,
const RenderTile& tile,
- const TransformState& state)
+ const TransformState& state,
+ const float symbolFadeChange)
{
return makeValues<SymbolIconProgram::UniformValues>(
isText,
@@ -111,7 +112,8 @@ SymbolIconProgram::uniformValues(const bool isText,
pixelsToGLUnits,
alongLine,
tile,
- state
+ state,
+ symbolFadeChange
);
}
@@ -124,6 +126,7 @@ typename SymbolSDFProgram<PaintProperties>::UniformValues SymbolSDFProgram<Paint
const bool alongLine,
const RenderTile& tile,
const TransformState& state,
+ const float symbolFadeChange,
const SymbolSDFPart part)
{
const float gammaScale = (values.pitchAlignment == AlignmentType::Map
@@ -138,6 +141,7 @@ typename SymbolSDFProgram<PaintProperties>::UniformValues SymbolSDFProgram<Paint
alongLine,
tile,
state,
+ symbolFadeChange,
uniforms::u_gamma_scale::Value{ gammaScale },
uniforms::u_is_halo::Value{ part == SymbolSDFPart::Halo }
);
diff --git a/src/mbgl/programs/symbol_program.hpp b/src/mbgl/programs/symbol_program.hpp
index a7abf94f56..a14afac702 100644
--- a/src/mbgl/programs/symbol_program.hpp
+++ b/src/mbgl/programs/symbol_program.hpp
@@ -75,18 +75,24 @@ struct SymbolLayoutAttributes : gl::Attributes<
};
struct SymbolDynamicLayoutAttributes : gl::Attributes<attributes::a_projected_pos> {
- static Vertex vertex(Point<float> anchorPoint, float labelAngle, float labelminzoom) {
+ static Vertex vertex(Point<float> anchorPoint, float labelAngle) {
return Vertex {
{{
anchorPoint.x,
anchorPoint.y,
- static_cast<float>(mbgl::attributes::packUint8Pair(
- static_cast<uint8_t>(std::fmod(labelAngle + 2 * M_PI, 2 * M_PI) / (2 * M_PI) * 255),
- static_cast<uint8_t>(labelminzoom * 10)))
+ labelAngle
}}
};
}
};
+
+struct SymbolOpacityAttributes : gl::Attributes<attributes::a_fade_opacity> {
+ static Vertex vertex(bool placed, float opacity) {
+ return Vertex {
+ {{ static_cast<uint8_t>((static_cast<uint8_t>(opacity * 127) << 1) | static_cast<uint8_t>(placed)) }}
+ };
+ }
+};
struct ZoomEvaluatedSize {
bool isZoomConstant;
@@ -128,23 +134,6 @@ public:
}
};
-// Return the smallest range of stops that covers the interval [lowerZoom, upperZoom]
-template <class Stops>
-Range<float> getCoveringStops(Stops s, float lowerZoom, float upperZoom) {
- assert(!s.stops.empty());
- auto minIt = s.stops.lower_bound(lowerZoom);
- auto maxIt = s.stops.lower_bound(upperZoom);
-
- // lower_bound yields first element >= lowerZoom, but we want the *last*
- // element <= lowerZoom, so if we found a stop > lowerZoom, back up by one.
- if (minIt != s.stops.begin() && minIt != s.stops.end() && minIt->first > lowerZoom) {
- minIt--;
- }
- return Range<float> {
- minIt == s.stops.end() ? s.stops.rbegin()->first : minIt->first,
- maxIt == s.stops.end() ? s.stops.rbegin()->first : maxIt->first
- };
-}
class ConstantSymbolSizeBinder final : public SymbolSizeBinder {
public:
@@ -155,19 +144,12 @@ public:
: layoutSize(defaultValue) {}
ConstantSymbolSizeBinder(const float tileZoom, const style::CameraFunction<float>& function_, const float /*defaultValue*/)
- : layoutSize(function_.evaluate(tileZoom + 1)) {
- function_.stops.match(
- [&] (const style::ExponentialStops<float>& stops) {
- const auto& zoomLevels = getCoveringStops(stops, tileZoom, tileZoom + 1);
- coveringRanges = std::make_tuple(
- zoomLevels,
- Range<float> { function_.evaluate(zoomLevels.min), function_.evaluate(zoomLevels.max) }
- );
- functionInterpolationBase = stops.base;
- },
- [&] (const style::IntervalStops<float>&) {
- function = function_;
- }
+ : layoutSize(function_.evaluate(tileZoom + 1)),
+ function(function_) {
+ const Range<float> zoomLevels = function_.getCoveringStops(tileZoom, tileZoom + 1);
+ coveringRanges = std::make_tuple(
+ zoomLevels,
+ Range<float> { function_.evaluate(zoomLevels.min), function_.evaluate(zoomLevels.max) }
);
}
@@ -185,7 +167,7 @@ public:
const Range<float>& zoomLevels = std::get<0>(*coveringRanges);
const Range<float>& sizeLevels = std::get<1>(*coveringRanges);
float t = util::clamp(
- util::interpolationFactor(*functionInterpolationBase, zoomLevels, currentZoom),
+ function->interpolationFactor(zoomLevels, currentZoom),
0.0f, 1.0f
);
size = sizeLevels.min + t * (sizeLevels.max - sizeLevels.min);
@@ -198,10 +180,7 @@ public:
}
float layoutSize;
- // used for exponential functions
optional<std::tuple<Range<float>, Range<float>>> coveringRanges;
- optional<float> functionInterpolationBase;
- // used for interval functions
optional<style::CameraFunction<float>> function;
};
@@ -226,7 +205,7 @@ public:
return { true, false, unused, unused, unused };
}
- const style::SourceFunction<float>& function;
+ style::SourceFunction<float> function;
const float defaultValue;
};
@@ -237,9 +216,7 @@ public:
: function(function_),
defaultValue(defaultValue_),
layoutZoom(tileZoom + 1),
- coveringZoomStops(function.stops.match(
- [&] (const auto& stops) {
- return getCoveringStops(stops, tileZoom, tileZoom + 1); }))
+ coveringZoomStops(function.getCoveringStops(tileZoom, tileZoom + 1))
{}
Range<float> getVertexSizeData(const GeometryTileFeature& feature) override {
@@ -251,7 +228,7 @@ public:
ZoomEvaluatedSize evaluateForZoom(float currentZoom) const override {
float sizeInterpolationT = util::clamp(
- util::interpolationFactor(1.0f, coveringZoomStops, currentZoom),
+ function.interpolationFactor(coveringZoomStops, currentZoom),
0.0f, 1.0f
);
@@ -259,7 +236,7 @@ public:
return { false, false, sizeInterpolationT, unused, unused };
}
- const style::CompositeFunction<float>& function;
+ style::CompositeFunction<float> function;
const float defaultValue;
float layoutZoom;
Range<float> coveringZoomStops;
@@ -276,7 +253,7 @@ public:
using LayoutAttributes = LayoutAttrs;
using LayoutVertex = typename LayoutAttributes::Vertex;
- using LayoutAndSizeAttributes = gl::ConcatenateAttributes<LayoutAttributes, SymbolDynamicLayoutAttributes>;
+ using LayoutAndSizeAttributes = gl::ConcatenateAttributes<LayoutAttributes, gl::ConcatenateAttributes<SymbolDynamicLayoutAttributes, SymbolOpacityAttributes>>;
using PaintProperties = PaintProps;
using PaintPropertyBinders = typename PaintProperties::Binders;
@@ -310,6 +287,7 @@ public:
const UniformValues& uniformValues,
const gl::VertexBuffer<LayoutVertex>& layoutVertexBuffer,
const gl::VertexBuffer<SymbolDynamicLayoutAttributes::Vertex>& dynamicLayoutVertexBuffer,
+ const gl::VertexBuffer<SymbolOpacityAttributes::Vertex>& opacityVertexBuffer,
const SymbolSizeBinder& symbolSizeBinder,
const gl::IndexBuffer<DrawMode>& indexBuffer,
const SegmentVector<Attributes>& segments,
@@ -323,8 +301,12 @@ public:
typename Attributes::Bindings allAttributeBindings = LayoutAttributes::bindings(layoutVertexBuffer)
.concat(SymbolDynamicLayoutAttributes::bindings(dynamicLayoutVertexBuffer))
+ .concat(SymbolOpacityAttributes::bindings(opacityVertexBuffer))
.concat(paintPropertyBinders.attributeBindings(currentProperties));
+ assert(layoutVertexBuffer.vertexCount == dynamicLayoutVertexBuffer.vertexCount &&
+ layoutVertexBuffer.vertexCount == opacityVertexBuffer.vertexCount);
+
for (auto& segment : segments) {
auto vertexArrayIt = segment.vertexArrays.find(layerID);
@@ -359,9 +341,8 @@ class SymbolIconProgram : public SymbolProgram<
uniforms::u_extrude_scale,
uniforms::u_texsize,
uniforms::u_texture,
- uniforms::u_fadetexture,
+ uniforms::u_fade_change,
uniforms::u_is_text,
- uniforms::u_collision_y_stretch,
uniforms::u_camera_to_center_distance,
uniforms::u_pitch,
uniforms::u_pitch_with_map,
@@ -379,7 +360,8 @@ public:
const std::array<float, 2>& pixelsToGLUnits,
const bool alongLine,
const RenderTile&,
- const TransformState&);
+ const TransformState&,
+ const float symbolFadeChange);
};
enum class SymbolSDFPart {
@@ -399,9 +381,8 @@ class SymbolSDFProgram : public SymbolProgram<
uniforms::u_extrude_scale,
uniforms::u_texsize,
uniforms::u_texture,
- uniforms::u_fadetexture,
+ uniforms::u_fade_change,
uniforms::u_is_text,
- uniforms::u_collision_y_stretch,
uniforms::u_camera_to_center_distance,
uniforms::u_pitch,
uniforms::u_pitch_with_map,
@@ -423,9 +404,8 @@ public:
uniforms::u_extrude_scale,
uniforms::u_texsize,
uniforms::u_texture,
- uniforms::u_fadetexture,
+ uniforms::u_fade_change,
uniforms::u_is_text,
- uniforms::u_collision_y_stretch,
uniforms::u_camera_to_center_distance,
uniforms::u_pitch,
uniforms::u_pitch_with_map,
@@ -449,6 +429,7 @@ public:
const bool alongLine,
const RenderTile&,
const TransformState&,
+ const float SymbolFadeChange,
const SymbolSDFPart);
};
diff --git a/src/mbgl/programs/uniforms.hpp b/src/mbgl/programs/uniforms.hpp
index 285d243251..184f42e504 100644
--- a/src/mbgl/programs/uniforms.hpp
+++ b/src/mbgl/programs/uniforms.hpp
@@ -36,6 +36,7 @@ MBGL_DEFINE_UNIFORM_SCALAR(Size, u_world);
MBGL_DEFINE_UNIFORM_SCALAR(Size, u_texsize);
MBGL_DEFINE_UNIFORM_SCALAR(bool, u_pitch_with_map);
MBGL_DEFINE_UNIFORM_SCALAR(float, u_camera_to_center_distance);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_fade_change);
MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_extrude_scale);
diff --git a/src/mbgl/renderer/buckets/circle_bucket.cpp b/src/mbgl/renderer/buckets/circle_bucket.cpp
index 04126990b3..d23f0861f4 100644
--- a/src/mbgl/renderer/buckets/circle_bucket.cpp
+++ b/src/mbgl/renderer/buckets/circle_bucket.cpp
@@ -49,7 +49,7 @@ void CircleBucket::addFeature(const GeometryTileFeature& feature,
// Do not include points that are outside the tile boundaries.
// Include all points in Still mode. You need to include points from
// neighbouring tiles so that they are not clipped at tile boundaries.
- if ((mode != MapMode::Still) &&
+ if ((mode == MapMode::Continuous) &&
(x < 0 || x >= util::EXTENT || y < 0 || y >= util::EXTENT)) continue;
if (segments.empty() || segments.back().vertexLength + vertexLength > std::numeric_limits<uint16_t>::max()) {
diff --git a/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp b/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp
index 7f53326fe1..5e2c937091 100644
--- a/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp
+++ b/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp
@@ -101,13 +101,17 @@ void FillExtrusionBucket::addFeature(const GeometryTileFeature& feature,
const auto d2 = convertPoint<double>(p2);
const Point<double> perp = util::unit(util::perp(d1 - d2));
+ const auto dist = util::dist<int16_t>(d1, d2);
+ if (dist > std::numeric_limits<int16_t>::max()) {
+ edgeDistance = 0;
+ }
vertices.emplace_back(
FillExtrusionProgram::layoutVertex(p1, perp.x, perp.y, 0, 0, edgeDistance));
vertices.emplace_back(
FillExtrusionProgram::layoutVertex(p1, perp.x, perp.y, 0, 1, edgeDistance));
- edgeDistance += util::dist<int16_t>(d1, d2);
+ edgeDistance += dist;
vertices.emplace_back(
FillExtrusionProgram::layoutVertex(p2, perp.x, perp.y, 0, 0, edgeDistance));
diff --git a/src/mbgl/renderer/buckets/symbol_bucket.cpp b/src/mbgl/renderer/buckets/symbol_bucket.cpp
index a3f71f1f6e..60e8a0b504 100644
--- a/src/mbgl/renderer/buckets/symbol_bucket.cpp
+++ b/src/mbgl/renderer/buckets/symbol_bucket.cpp
@@ -16,10 +16,14 @@ SymbolBucket::SymbolBucket(style::SymbolLayoutProperties::PossiblyEvaluated layo
const style::DataDrivenPropertyValue<float>& iconSize,
float zoom,
bool sdfIcons_,
- bool iconsNeedLinear_)
+ bool iconsNeedLinear_,
+ bool sortFeaturesByY_,
+ const std::vector<SymbolInstance>&& symbolInstances_)
: layout(std::move(layout_)),
sdfIcons(sdfIcons_),
iconsNeedLinear(iconsNeedLinear_ || iconSize.isDataDriven() || !iconSize.isZoomConstant()),
+ sortFeaturesByY(sortFeaturesByY_),
+ symbolInstances(std::move(symbolInstances_)),
textSizeBinder(SymbolSizeBinder::create(zoom, textSize, TextSize::defaultValue())),
iconSizeBinder(SymbolSizeBinder::create(zoom, iconSize, IconSize::defaultValue())) {
@@ -36,28 +40,84 @@ SymbolBucket::SymbolBucket(style::SymbolLayoutProperties::PossiblyEvaluated layo
void SymbolBucket::upload(gl::Context& context) {
if (hasTextData()) {
- text.vertexBuffer = context.createVertexBuffer(std::move(text.vertices));
- text.dynamicVertexBuffer = context.createVertexBuffer(std::move(text.dynamicVertices), gl::BufferUsage::StreamDraw);
- text.indexBuffer = context.createIndexBuffer(std::move(text.triangles));
+ if (!staticUploaded) {
+ text.indexBuffer = context.createIndexBuffer(std::move(text.triangles), sortFeaturesByY ? gl::BufferUsage::StreamDraw : gl::BufferUsage::StaticDraw);
+ text.vertexBuffer = context.createVertexBuffer(std::move(text.vertices));
+ } else if (!sortUploaded) {
+ context.updateIndexBuffer(*text.indexBuffer, std::move(text.triangles));
+ }
+
+ if (!dynamicUploaded) {
+ text.dynamicVertexBuffer = context.createVertexBuffer(std::move(text.dynamicVertices), gl::BufferUsage::StreamDraw);
+ }
+ if (!placementChangesUploaded) {
+ if (!text.opacityVertexBuffer) {
+ text.opacityVertexBuffer = context.createVertexBuffer(std::move(text.opacityVertices), gl::BufferUsage::StreamDraw);
+ } else {
+ context.updateVertexBuffer(*text.opacityVertexBuffer, std::move(text.opacityVertices));
+ }
+ }
}
if (hasIconData()) {
- icon.vertexBuffer = context.createVertexBuffer(std::move(icon.vertices));
- icon.dynamicVertexBuffer = context.createVertexBuffer(std::move(icon.dynamicVertices), gl::BufferUsage::StreamDraw);
- icon.indexBuffer = context.createIndexBuffer(std::move(icon.triangles));
+ if (!staticUploaded) {
+ icon.indexBuffer = context.createIndexBuffer(std::move(icon.triangles), sortFeaturesByY ? gl::BufferUsage::StreamDraw : gl::BufferUsage::StaticDraw);
+ icon.vertexBuffer = context.createVertexBuffer(std::move(icon.vertices));
+ } else if (!sortUploaded) {
+ context.updateIndexBuffer(*icon.indexBuffer, std::move(icon.triangles));
+ }
+ if (!dynamicUploaded) {
+ icon.dynamicVertexBuffer = context.createVertexBuffer(std::move(icon.dynamicVertices), gl::BufferUsage::StreamDraw);
+ }
+ if (!placementChangesUploaded) {
+ if (!icon.opacityVertexBuffer) {
+ icon.opacityVertexBuffer = context.createVertexBuffer(std::move(icon.opacityVertices), gl::BufferUsage::StreamDraw);
+ } else {
+ context.updateVertexBuffer(*icon.opacityVertexBuffer, std::move(icon.opacityVertices));
+ }
+ }
}
- if (!collisionBox.vertices.empty()) {
- collisionBox.vertexBuffer = context.createVertexBuffer(std::move(collisionBox.vertices));
- collisionBox.indexBuffer = context.createIndexBuffer(std::move(collisionBox.lines));
+ if (hasCollisionBoxData()) {
+ if (!staticUploaded) {
+ collisionBox.indexBuffer = context.createIndexBuffer(std::move(collisionBox.lines));
+ collisionBox.vertexBuffer = context.createVertexBuffer(std::move(collisionBox.vertices));
+ }
+ if (!placementChangesUploaded) {
+ if (!collisionBox.dynamicVertexBuffer) {
+ collisionBox.dynamicVertexBuffer = context.createVertexBuffer(std::move(collisionBox.dynamicVertices), gl::BufferUsage::StreamDraw);
+ } else {
+ context.updateVertexBuffer(*collisionBox.dynamicVertexBuffer, std::move(collisionBox.dynamicVertices));
+ }
+ }
}
-
- for (auto& pair : paintPropertyBinders) {
- pair.second.first.upload(context);
- pair.second.second.upload(context);
+
+ if (hasCollisionCircleData()) {
+ if (!staticUploaded) {
+ collisionCircle.indexBuffer = context.createIndexBuffer(std::move(collisionCircle.triangles));
+ collisionCircle.vertexBuffer = context.createVertexBuffer(std::move(collisionCircle.vertices));
+ }
+ if (!placementChangesUploaded) {
+ if (!collisionCircle.dynamicVertexBuffer) {
+ collisionCircle.dynamicVertexBuffer = context.createVertexBuffer(std::move(collisionCircle.dynamicVertices), gl::BufferUsage::StreamDraw);
+ } else {
+ context.updateVertexBuffer(*collisionCircle.dynamicVertexBuffer, std::move(collisionCircle.dynamicVertices));
+ }
+ }
}
+ if (!staticUploaded) {
+ for (auto& pair : paintPropertyBinders) {
+ pair.second.first.upload(context);
+ pair.second.second.upload(context);
+ }
+ }
+
uploaded = true;
+ staticUploaded = true;
+ placementChangesUploaded = true;
+ dynamicUploaded = true;
+ sortUploaded = true;
}
bool SymbolBucket::hasData() const {
@@ -76,4 +136,83 @@ bool SymbolBucket::hasCollisionBoxData() const {
return !collisionBox.segments.empty();
}
+bool SymbolBucket::hasCollisionCircleData() const {
+ return !collisionCircle.segments.empty();
+}
+
+void SymbolBucket::updateOpacity() {
+ placementChangesUploaded = false;
+ uploaded = false;
+}
+
+void addPlacedSymbol(gl::IndexVector<gl::Triangles>& triangles, const PlacedSymbol& placedSymbol) {
+ auto endIndex = placedSymbol.vertexStartIndex + placedSymbol.glyphOffsets.size() * 4;
+ for (auto vertexIndex = placedSymbol.vertexStartIndex; vertexIndex < endIndex; vertexIndex += 4) {
+ triangles.emplace_back(vertexIndex + 0, vertexIndex + 1, vertexIndex + 2);
+ triangles.emplace_back(vertexIndex + 1, vertexIndex + 2, vertexIndex + 3);
+ }
+}
+
+void SymbolBucket::sortFeatures(const float angle) {
+ if (!sortFeaturesByY) {
+ return;
+ }
+
+ if (sortedAngle && *sortedAngle == angle) {
+ return;
+ }
+
+ sortedAngle = angle;
+
+ // The current approach to sorting doesn't sort across segments so don't try.
+ // Sorting within segments separately seemed not to be worth the complexity.
+ if (text.segments.size() > 1 || icon.segments.size() > 1) {
+ return;
+ }
+
+ sortUploaded = false;
+ uploaded = false;
+
+ // If the symbols are allowed to overlap sort them by their vertical screen position.
+ // The index array buffer is rewritten to reference the (unchanged) vertices in the
+ // sorted order.
+
+ // To avoid sorting the actual symbolInstance array we sort an array of indexes.
+ std::vector<size_t> symbolInstanceIndexes;
+ symbolInstanceIndexes.reserve(symbolInstances.size());
+ for (size_t i = 0; i < symbolInstances.size(); i++) {
+ symbolInstanceIndexes.push_back(i);
+ }
+
+ const float sin = std::sin(angle);
+ const float cos = std::cos(angle);
+
+ std::sort(symbolInstanceIndexes.begin(), symbolInstanceIndexes.end(), [sin, cos, this](size_t &aIndex, size_t &bIndex) {
+ const SymbolInstance& a = symbolInstances[aIndex];
+ const SymbolInstance& b = symbolInstances[bIndex];
+ const int32_t aRotated = sin * a.anchor.point.x + cos * a.anchor.point.y;
+ const int32_t bRotated = sin * b.anchor.point.x + cos * b.anchor.point.y;
+ return aRotated != bRotated ?
+ aRotated < bRotated :
+ a.index > b.index;
+ });
+
+ text.triangles.clear();
+ icon.triangles.clear();
+
+ for (auto i : symbolInstanceIndexes) {
+ const SymbolInstance& symbolInstance = symbolInstances[i];
+
+ if (symbolInstance.placedTextIndex) {
+ addPlacedSymbol(text.triangles, text.placedSymbols[*symbolInstance.placedTextIndex]);
+ }
+ if (symbolInstance.placedVerticalTextIndex) {
+ addPlacedSymbol(text.triangles, text.placedSymbols[*symbolInstance.placedVerticalTextIndex]);
+ }
+ if (symbolInstance.placedIconIndex) {
+ addPlacedSymbol(icon.triangles, icon.placedSymbols[*symbolInstance.placedIconIndex]);
+ }
+ }
+}
+
} // namespace mbgl
diff --git a/src/mbgl/renderer/buckets/symbol_bucket.hpp b/src/mbgl/renderer/buckets/symbol_bucket.hpp
index 32f976bcb2..4abea90508 100644
--- a/src/mbgl/renderer/buckets/symbol_bucket.hpp
+++ b/src/mbgl/renderer/buckets/symbol_bucket.hpp
@@ -10,6 +10,7 @@
#include <mbgl/text/glyph_range.hpp>
#include <mbgl/style/layers/symbol_layer_properties.hpp>
#include <mbgl/layout/symbol_feature.hpp>
+#include <mbgl/layout/symbol_instance.hpp>
#include <vector>
@@ -18,18 +19,22 @@ namespace mbgl {
class PlacedSymbol {
public:
PlacedSymbol(Point<float> anchorPoint_, uint16_t segment_, float lowerSize_, float upperSize_,
- std::array<float, 2> lineOffset_, float placementZoom_, bool useVerticalMode_, GeometryCoordinates line_) :
+ std::array<float, 2> lineOffset_, WritingModeType writingModes_, GeometryCoordinates line_, std::vector<float> tileDistances_) :
anchorPoint(anchorPoint_), segment(segment_), lowerSize(lowerSize_), upperSize(upperSize_),
- lineOffset(lineOffset_), placementZoom(placementZoom_), useVerticalMode(useVerticalMode_), line(std::move(line_)) {}
+ lineOffset(lineOffset_), writingModes(writingModes_), line(std::move(line_)), tileDistances(std::move(tileDistances_)), hidden(false), vertexStartIndex(0)
+ {
+ }
Point<float> anchorPoint;
uint16_t segment;
float lowerSize;
float upperSize;
std::array<float, 2> lineOffset;
- float placementZoom;
- bool useVerticalMode;
+ WritingModeType writingModes;
GeometryCoordinates line;
+ std::vector<float> tileDistances;
std::vector<float> glyphOffsets;
+ bool hidden;
+ size_t vertexStartIndex;
};
class SymbolBucket : public Bucket {
@@ -40,17 +45,33 @@ public:
const style::DataDrivenPropertyValue<float>& iconSize,
float zoom,
bool sdfIcons,
- bool iconsNeedLinear);
+ bool iconsNeedLinear,
+ bool sortFeaturesByY,
+ const std::vector<SymbolInstance>&&);
void upload(gl::Context&) override;
bool hasData() const override;
bool hasTextData() const;
bool hasIconData() const;
bool hasCollisionBoxData() const;
+ bool hasCollisionCircleData() const;
+
+ void updateOpacity();
+ void sortFeatures(const float angle);
const style::SymbolLayoutProperties::PossiblyEvaluated layout;
const bool sdfIcons;
const bool iconsNeedLinear;
+ const bool sortFeaturesByY;
+
+ optional<float> sortedAngle;
+
+ bool staticUploaded = false;
+ bool placementChangesUploaded = false;
+ bool dynamicUploaded = false;
+ bool sortUploaded = false;
+
+ std::vector<SymbolInstance> symbolInstances;
std::map<std::string, std::pair<
SymbolIconProgram::PaintPropertyBinders,
@@ -61,12 +82,14 @@ public:
struct TextBuffer {
gl::VertexVector<SymbolLayoutVertex> vertices;
gl::VertexVector<SymbolDynamicLayoutAttributes::Vertex> dynamicVertices;
+ gl::VertexVector<SymbolOpacityAttributes::Vertex> opacityVertices;
gl::IndexVector<gl::Triangles> triangles;
SegmentVector<SymbolTextAttributes> segments;
std::vector<PlacedSymbol> placedSymbols;
optional<gl::VertexBuffer<SymbolLayoutVertex>> vertexBuffer;
optional<gl::VertexBuffer<SymbolDynamicLayoutAttributes::Vertex>> dynamicVertexBuffer;
+ optional<gl::VertexBuffer<SymbolOpacityAttributes::Vertex>> opacityVertexBuffer;
optional<gl::IndexBuffer<gl::Triangles>> indexBuffer;
} text;
@@ -75,6 +98,7 @@ public:
struct IconBuffer {
gl::VertexVector<SymbolLayoutVertex> vertices;
gl::VertexVector<SymbolDynamicLayoutAttributes::Vertex> dynamicVertices;
+ gl::VertexVector<SymbolOpacityAttributes::Vertex> opacityVertices;
gl::IndexVector<gl::Triangles> triangles;
SegmentVector<SymbolIconAttributes> segments;
std::vector<PlacedSymbol> placedSymbols;
@@ -82,18 +106,30 @@ public:
optional<gl::VertexBuffer<SymbolLayoutVertex>> vertexBuffer;
optional<gl::VertexBuffer<SymbolDynamicLayoutAttributes::Vertex>> dynamicVertexBuffer;
+ optional<gl::VertexBuffer<SymbolOpacityAttributes::Vertex>> opacityVertexBuffer;
optional<gl::IndexBuffer<gl::Triangles>> indexBuffer;
} icon;
- struct CollisionBoxBuffer {
- gl::VertexVector<CollisionBoxVertex> vertices;
- gl::IndexVector<gl::Lines> lines;
- SegmentVector<CollisionBoxAttributes> segments;
+ struct CollisionBuffer {
+ gl::VertexVector<CollisionBoxLayoutAttributes::Vertex> vertices;
+ gl::VertexVector<CollisionBoxDynamicAttributes::Vertex> dynamicVertices;
+ SegmentVector<CollisionBoxProgram::Attributes> segments;
- optional<gl::VertexBuffer<CollisionBoxVertex>> vertexBuffer;
- optional<gl::VertexBuffer<SymbolDynamicLayoutAttributes::Vertex>> dynamicVertexBuffer;
+ optional<gl::VertexBuffer<CollisionBoxLayoutAttributes::Vertex>> vertexBuffer;
+ optional<gl::VertexBuffer<CollisionBoxDynamicAttributes::Vertex>> dynamicVertexBuffer;
+ };
+
+ struct CollisionBoxBuffer : public CollisionBuffer {
+ gl::IndexVector<gl::Lines> lines;
optional<gl::IndexBuffer<gl::Lines>> indexBuffer;
} collisionBox;
+
+ struct CollisionCircleBuffer : public CollisionBuffer {
+ gl::IndexVector<gl::Triangles> triangles;
+ optional<gl::IndexBuffer<gl::Triangles>> indexBuffer;
+ } collisionCircle;
+
+ uint32_t bucketInstanceId = 0;
};
} // namespace mbgl
diff --git a/src/mbgl/renderer/frame_history.cpp b/src/mbgl/renderer/frame_history.cpp
deleted file mode 100644
index de153b6963..0000000000
--- a/src/mbgl/renderer/frame_history.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-#include <mbgl/renderer/frame_history.hpp>
-#include <mbgl/math/minmax.hpp>
-#include <mbgl/gl/context.hpp>
-
-#include <cassert>
-
-namespace mbgl {
-
-FrameHistory::FrameHistory() {
- changeOpacities.fill(0);
- opacities.fill(0);
-}
-
-void FrameHistory::record(const TimePoint& now, float zoom, const Duration& duration) {
-
- int16_t zoomIndex = std::floor(zoom * 10.0);
-
- if (firstFrame) {
- changeTimes.fill(now);
-
- for (int16_t z = 0; z <= zoomIndex; z++) {
- opacities.data[z] = 255u;
- }
- firstFrame = false;
- }
-
- if (zoomIndex < previousZoomIndex) {
- for (int16_t z = zoomIndex + 1; z <= previousZoomIndex; z++) {
- changeTimes[z] = now;
- changeOpacities[z] = opacities.data[z];
- }
- } else {
- for (int16_t z = zoomIndex; z > previousZoomIndex; z--) {
- changeTimes[z] = now;
- changeOpacities[z] = opacities.data[z];
- }
- }
-
- for (int16_t z = 0; z <= 255; z++) {
- const std::chrono::duration<float> timeDiff = now - changeTimes[z];
- const int32_t opacityChange = (duration == Milliseconds(0) ? 1 : (timeDiff / duration)) * 255;
- const uint8_t opacity = z <= zoomIndex
- ? util::min(255, changeOpacities[z] + opacityChange)
- : util::max(0, changeOpacities[z] - opacityChange);
- if (opacities.data[z] != opacity) {
- opacities.data[z] = opacity;
- dirty = true;
- }
- }
-
- if (zoomIndex != previousZoomIndex) {
- previousZoomIndex = zoomIndex;
- previousTime = now;
- }
-
- time = now;
-}
-
-bool FrameHistory::needsAnimation(const Duration& duration) const {
- return (time - previousTime) < duration;
-}
-
-void FrameHistory::upload(gl::Context& context, uint32_t unit) {
- if (!texture) {
- texture = context.createTexture(opacities, unit);
- } else if (dirty) {
- context.updateTexture(*texture, opacities, unit);
- }
- dirty = false;
-}
-
-void FrameHistory::bind(gl::Context& context, uint32_t unit) {
- upload(context, unit);
- context.bindTexture(*texture, unit);
-}
-
-bool FrameHistory::isVisible(const float zoom) const {
- return opacities.data[std::floor(zoom * 10)] != 0;
-}
-
-} // namespace mbgl
diff --git a/src/mbgl/renderer/frame_history.hpp b/src/mbgl/renderer/frame_history.hpp
deleted file mode 100644
index 75a8b60a71..0000000000
--- a/src/mbgl/renderer/frame_history.hpp
+++ /dev/null
@@ -1,41 +0,0 @@
-#pragma once
-
-#include <array>
-
-#include <mbgl/util/platform.hpp>
-#include <mbgl/gl/texture.hpp>
-#include <mbgl/util/chrono.hpp>
-#include <mbgl/util/image.hpp>
-#include <mbgl/util/optional.hpp>
-
-namespace mbgl {
-
-namespace gl {
-class Context;
-} // namespace gl
-
-class FrameHistory {
-public:
- FrameHistory();
- void record(const TimePoint&, float zoom, const Duration&);
-
- bool needsAnimation(const Duration&) const;
- void bind(gl::Context&, uint32_t);
- void upload(gl::Context&, uint32_t);
- bool isVisible(const float zoom) const;
-
-private:
- std::array<TimePoint, 256> changeTimes;
- std::array<uint8_t, 256> changeOpacities;
- AlphaImage opacities{ { 256, 1 } };
-
- int16_t previousZoomIndex = 0;
- TimePoint previousTime;
- TimePoint time;
- bool firstFrame = true;
- bool dirty = true;
-
- mbgl::optional<gl::Texture> texture;
-};
-
-} // namespace mbgl
diff --git a/src/mbgl/renderer/layers/render_circle_layer.cpp b/src/mbgl/renderer/layers/render_circle_layer.cpp
index e7b022f3ee..fe2e7cd42d 100644
--- a/src/mbgl/renderer/layers/render_circle_layer.cpp
+++ b/src/mbgl/renderer/layers/render_circle_layer.cpp
@@ -63,7 +63,7 @@ void RenderCircleLayer::render(PaintParameters& parameters, RenderSource*) {
parameters.context,
gl::Triangles(),
parameters.depthModeForSublayer(0, gl::DepthMode::ReadOnly),
- parameters.mapMode == MapMode::Still
+ parameters.mapMode != MapMode::Continuous
? parameters.stencilModeForClipping(tile.clip)
: gl::StencilMode::disabled(),
parameters.colorModeForRenderPass(),
diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp
index 1376e8a3d8..04fcb2c3ab 100644
--- a/src/mbgl/renderer/layers/render_symbol_layer.cpp
+++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp
@@ -4,7 +4,6 @@
#include <mbgl/renderer/property_evaluation_parameters.hpp>
#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
-#include <mbgl/renderer/frame_history.hpp>
#include <mbgl/text/glyph_atlas.hpp>
#include <mbgl/programs/programs.hpp>
#include <mbgl/programs/symbol_program.hpp>
@@ -81,8 +80,6 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) {
const auto& layout = bucket.layout;
- parameters.frameHistory.bind(parameters.context, 1);
-
auto draw = [&] (auto& program,
auto&& uniformValues,
const auto& buffers,
@@ -91,22 +88,18 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) {
const auto& binders,
const auto& paintProperties)
{
- // We clip symbols to their tile extent in still mode.
- const bool needsClipping = parameters.mapMode == MapMode::Still;
-
program.get(paintProperties).draw(
parameters.context,
gl::Triangles(),
values_.pitchAlignment == AlignmentType::Map
? parameters.depthModeForSublayer(0, gl::DepthMode::ReadOnly)
: gl::DepthMode::disabled(),
- needsClipping
- ? parameters.stencilModeForClipping(tile.clip)
- : gl::StencilMode::disabled(),
+ gl::StencilMode::disabled(),
parameters.colorModeForRenderPass(),
std::move(uniformValues),
*buffers.vertexBuffer,
*buffers.dynamicVertexBuffer,
+ *buffers.opacityVertexBuffer,
*symbolSizeBinder,
*buffers.indexBuffer,
buffers.segments,
@@ -134,8 +127,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) {
values,
tile,
*bucket.iconSizeBinder,
- parameters.state,
- parameters.frameHistory);
+ parameters.state);
parameters.context.updateVertexBuffer(*bucket.icon.dynamicVertexBuffer, std::move(bucket.icon.dynamicVertices));
}
@@ -152,7 +144,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) {
if (bucket.sdfIcons) {
if (values.hasHalo) {
draw(parameters.programs.symbolIconSDF,
- SymbolSDFIconProgram::uniformValues(false, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, SymbolSDFPart::Halo),
+ SymbolSDFIconProgram::uniformValues(false, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Halo),
bucket.icon,
bucket.iconSizeBinder,
values,
@@ -162,7 +154,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) {
if (values.hasFill) {
draw(parameters.programs.symbolIconSDF,
- SymbolSDFIconProgram::uniformValues(false, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, SymbolSDFPart::Fill),
+ SymbolSDFIconProgram::uniformValues(false, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Fill),
bucket.icon,
bucket.iconSizeBinder,
values,
@@ -171,7 +163,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) {
}
} else {
draw(parameters.programs.symbolIcon,
- SymbolIconProgram::uniformValues(false, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state),
+ SymbolIconProgram::uniformValues(false, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange),
bucket.icon,
bucket.iconSizeBinder,
values,
@@ -196,8 +188,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) {
values,
tile,
*bucket.textSizeBinder,
- parameters.state,
- parameters.frameHistory);
+ parameters.state);
parameters.context.updateVertexBuffer(*bucket.text.dynamicVertexBuffer, std::move(bucket.text.dynamicVertices));
}
@@ -206,7 +197,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) {
if (values.hasHalo) {
draw(parameters.programs.symbolGlyph,
- SymbolSDFTextProgram::uniformValues(true, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, SymbolSDFPart::Halo),
+ SymbolSDFTextProgram::uniformValues(true, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Halo),
bucket.text,
bucket.textSizeBinder,
values,
@@ -216,7 +207,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) {
if (values.hasFill) {
draw(parameters.programs.symbolGlyph,
- SymbolSDFTextProgram::uniformValues(true, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, SymbolSDFPart::Fill),
+ SymbolSDFTextProgram::uniformValues(true, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Fill),
bucket.text,
bucket.textSizeBinder,
values,
@@ -229,23 +220,27 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) {
static const style::Properties<>::PossiblyEvaluated properties {};
static const CollisionBoxProgram::PaintPropertyBinders paintAttributeData(properties, 0);
+ auto pixelRatio = tile.id.pixelsToTileUnits(1, parameters.state.getZoom());
+ auto scale = std::pow(2.0f, float(parameters.state.getZoom() - tile.tile.id.overscaledZ));
+ std::array<float,2> extrudeScale =
+ {{
+ parameters.pixelsToGLUnits[0] / (pixelRatio * scale),
+ parameters.pixelsToGLUnits[1] / (pixelRatio * scale)
+
+ }};
parameters.programs.collisionBox.draw(
parameters.context,
gl::Lines { 1.0f },
gl::DepthMode::disabled(),
- parameters.stencilModeForClipping(tile.clip),
+ gl::StencilMode::disabled(),
parameters.colorModeForRenderPass(),
CollisionBoxProgram::UniformValues {
uniforms::u_matrix::Value{ tile.matrix },
- uniforms::u_scale::Value{ std::pow(2.0f, float(parameters.state.getZoom() - tile.tile.id.overscaledZ)) },
- uniforms::u_zoom::Value{ float(parameters.state.getZoom() * 10) },
- uniforms::u_maxzoom::Value{ float((tile.id.canonical.z + 1) * 10) },
- uniforms::u_collision_y_stretch::Value{ tile.tile.yStretch() },
- uniforms::u_camera_to_center_distance::Value{ parameters.state.getCameraToCenterDistance() },
- uniforms::u_pitch::Value{ parameters.state.getPitch() },
- uniforms::u_fadetexture::Value{ 1 }
+ uniforms::u_extrude_scale::Value{ extrudeScale },
+ uniforms::u_camera_to_center_distance::Value{ parameters.state.getCameraToCenterDistance() }
},
*bucket.collisionBox.vertexBuffer,
+ *bucket.collisionBox.dynamicVertexBuffer,
*bucket.collisionBox.indexBuffer,
bucket.collisionBox.segments,
paintAttributeData,
@@ -254,6 +249,41 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) {
getID()
);
}
+ if (bucket.hasCollisionCircleData()) {
+ static const style::Properties<>::PossiblyEvaluated properties {};
+ static const CollisionBoxProgram::PaintPropertyBinders paintAttributeData(properties, 0);
+
+ auto pixelRatio = tile.id.pixelsToTileUnits(1, parameters.state.getZoom());
+ auto scale = std::pow(2.0f, float(parameters.state.getZoom() - tile.tile.id.overscaledZ));
+ std::array<float,2> extrudeScale =
+ {{
+ parameters.pixelsToGLUnits[0] / (pixelRatio * scale),
+ parameters.pixelsToGLUnits[1] / (pixelRatio * scale)
+
+ }};
+
+ parameters.programs.collisionCircle.draw(
+ parameters.context,
+ gl::Triangles(),
+ gl::DepthMode::disabled(),
+ gl::StencilMode::disabled(),
+ parameters.colorModeForRenderPass(),
+ CollisionBoxProgram::UniformValues {
+ uniforms::u_matrix::Value{ tile.matrix },
+ uniforms::u_extrude_scale::Value{ extrudeScale },
+ uniforms::u_camera_to_center_distance::Value{ parameters.state.getCameraToCenterDistance() }
+ },
+ *bucket.collisionCircle.vertexBuffer,
+ *bucket.collisionCircle.dynamicVertexBuffer,
+ *bucket.collisionCircle.indexBuffer,
+ bucket.collisionCircle.segments,
+ paintAttributeData,
+ properties,
+ parameters.state.getZoom(),
+ getID()
+ );
+
+ }
}
}
diff --git a/src/mbgl/renderer/paint_parameters.cpp b/src/mbgl/renderer/paint_parameters.cpp
index 299db844bc..58dd5597a5 100644
--- a/src/mbgl/renderer/paint_parameters.cpp
+++ b/src/mbgl/renderer/paint_parameters.cpp
@@ -12,7 +12,6 @@ PaintParameters::PaintParameters(gl::Context& context_,
const UpdateParameters& updateParameters,
const EvaluatedLight& evaluatedLight_,
RenderStaticData& staticData_,
- FrameHistory& frameHistory_,
ImageManager& imageManager_,
LineAtlas& lineAtlas_)
: context(context_),
@@ -20,7 +19,6 @@ PaintParameters::PaintParameters(gl::Context& context_,
state(updateParameters.transformState),
evaluatedLight(evaluatedLight_),
staticData(staticData_),
- frameHistory(frameHistory_),
imageManager(imageManager_),
lineAtlas(lineAtlas_),
mapMode(updateParameters.mode),
diff --git a/src/mbgl/renderer/paint_parameters.hpp b/src/mbgl/renderer/paint_parameters.hpp
index 4a2c2c6f12..5c934c2239 100644
--- a/src/mbgl/renderer/paint_parameters.hpp
+++ b/src/mbgl/renderer/paint_parameters.hpp
@@ -2,6 +2,7 @@
#include <mbgl/renderer/render_pass.hpp>
#include <mbgl/renderer/render_light.hpp>
+#include <mbgl/renderer/mode.hpp>
#include <mbgl/map/mode.hpp>
#include <mbgl/gl/depth_mode.hpp>
#include <mbgl/gl/stencil_mode.hpp>
@@ -16,7 +17,6 @@ namespace mbgl {
class RendererBackend;
class UpdateParameters;
class RenderStaticData;
-class FrameHistory;
class Programs;
class TransformState;
class ImageManager;
@@ -32,7 +32,6 @@ public:
const UpdateParameters&,
const EvaluatedLight&,
RenderStaticData&,
- FrameHistory&,
ImageManager&,
LineAtlas&);
@@ -43,7 +42,6 @@ public:
const EvaluatedLight& evaluatedLight;
RenderStaticData& staticData;
- FrameHistory& frameHistory;
ImageManager& imageManager;
LineAtlas& lineAtlas;
@@ -73,6 +71,8 @@ public:
uint32_t currentLayer;
float depthRangeSize;
const float depthEpsilon = 1.0f / (1 << 16);
+
+ float symbolFadeChange;
};
} // namespace mbgl
diff --git a/src/mbgl/renderer/paint_property_binder.hpp b/src/mbgl/renderer/paint_property_binder.hpp
index 652948c8df..3a49882f12 100644
--- a/src/mbgl/renderer/paint_property_binder.hpp
+++ b/src/mbgl/renderer/paint_property_binder.hpp
@@ -190,11 +190,11 @@ public:
CompositeFunctionPaintPropertyBinder(style::CompositeFunction<T> function_, float zoom, T defaultValue_)
: function(std::move(function_)),
defaultValue(std::move(defaultValue_)),
- rangeOfCoveringRanges(function.rangeOfCoveringRanges({zoom, zoom + 1})) {
+ zoomRange({zoom, zoom + 1}) {
}
void populateVertexVector(const GeometryTileFeature& feature, std::size_t length) override {
- Range<T> range = function.evaluate(rangeOfCoveringRanges, feature, defaultValue);
+ Range<T> range = function.evaluate(zoomRange, feature, defaultValue);
this->statistics.add(range.min);
this->statistics.add(range.max);
AttributeValue value = zoomInterpolatedAttributeValue(
@@ -219,9 +219,9 @@ public:
float interpolationFactor(float currentZoom) const override {
if (function.useIntegerZoom) {
- return util::interpolationFactor(1.0f, { rangeOfCoveringRanges.min.zoom, rangeOfCoveringRanges.max.zoom }, std::floor(currentZoom));
+ return function.interpolationFactor(zoomRange, std::floor(currentZoom));
} else {
- return util::interpolationFactor(1.0f, { rangeOfCoveringRanges.min.zoom, rangeOfCoveringRanges.max.zoom }, currentZoom);
+ return function.interpolationFactor(zoomRange, currentZoom);
}
}
@@ -237,8 +237,7 @@ public:
private:
style::CompositeFunction<T> function;
T defaultValue;
- using CoveringRanges = typename style::CompositeFunction<T>::CoveringRanges;
- Range<CoveringRanges> rangeOfCoveringRanges;
+ Range<float> zoomRange;
gl::VertexVector<Vertex> vertexVector;
optional<gl::VertexBuffer<Vertex>> vertexBuffer;
};
diff --git a/src/mbgl/renderer/render_layer.hpp b/src/mbgl/renderer/render_layer.hpp
index dfc6bcf2fd..55831cb72c 100644
--- a/src/mbgl/renderer/render_layer.hpp
+++ b/src/mbgl/renderer/render_layer.hpp
@@ -82,13 +82,16 @@ public:
friend std::string layoutKey(const RenderLayer&);
protected:
+ // renderTiles are exposed directly to CrossTileSymbolIndex and Placement so they
+ // can update opacities in the symbol buckets immediately before rendering
+ friend class CrossTileSymbolIndex;
+ friend class Placement;
+ // Stores current set of tiles to be rendered for this layer.
+ std::vector<std::reference_wrapper<RenderTile>> renderTiles;
+
// Stores what render passes this layer is currently enabled for. This depends on the
// evaluated StyleProperties object and is updated accordingly.
RenderPass passes = RenderPass::None;
-
- //Stores current set of tiles to be rendered for this layer.
- std::vector<std::reference_wrapper<RenderTile>> renderTiles;
-
};
} // namespace mbgl
diff --git a/src/mbgl/renderer/render_source.cpp b/src/mbgl/renderer/render_source.cpp
index 7723a1c7ca..6624bb7d96 100644
--- a/src/mbgl/renderer/render_source.cpp
+++ b/src/mbgl/renderer/render_source.cpp
@@ -6,6 +6,7 @@
#include <mbgl/renderer/tile_parameters.hpp>
#include <mbgl/annotation/render_annotation_source.hpp>
#include <mbgl/renderer/sources/render_image_source.hpp>
+#include <mbgl/renderer/sources/render_custom_geometry_source.hpp>
#include <mbgl/tile/tile.hpp>
namespace mbgl {
@@ -27,6 +28,8 @@ std::unique_ptr<RenderSource> RenderSource::create(Immutable<Source::Impl> impl)
return std::make_unique<RenderAnnotationSource>(staticImmutableCast<AnnotationSource::Impl>(impl));
case SourceType::Image:
return std::make_unique<RenderImageSource>(staticImmutableCast<ImageSource::Impl>(impl));
+ case SourceType::CustomVector:
+ return std::make_unique<RenderCustomGeometrySource>(staticImmutableCast<CustomGeometrySource::Impl>(impl));
}
// Not reachable, but placate GCC.
diff --git a/src/mbgl/renderer/render_source.hpp b/src/mbgl/renderer/render_source.hpp
index 8293923ff6..8c84af4f1e 100644
--- a/src/mbgl/renderer/render_source.hpp
+++ b/src/mbgl/renderer/render_source.hpp
@@ -24,6 +24,7 @@ class SourceQueryOptions;
class Tile;
class RenderSourceObserver;
class TileParameters;
+class CollisionIndex;
class RenderSource : protected TileObserver {
public:
@@ -63,7 +64,8 @@ public:
queryRenderedFeatures(const ScreenLineString& geometry,
const TransformState& transformState,
const std::vector<const RenderLayer*>& layers,
- const RenderedQueryOptions& options) const = 0;
+ const RenderedQueryOptions& options,
+ const CollisionIndex& collisionIndex) const = 0;
virtual std::vector<Feature>
querySourceFeatures(const SourceQueryOptions&) const = 0;
diff --git a/src/mbgl/renderer/renderer_backend.cpp b/src/mbgl/renderer/renderer_backend.cpp
index 159ef432b3..22d263313c 100644
--- a/src/mbgl/renderer/renderer_backend.cpp
+++ b/src/mbgl/renderer/renderer_backend.cpp
@@ -16,7 +16,7 @@ gl::Context& RendererBackend::getContext() {
context = std::make_unique<gl::Context>();
context->enableDebugging();
context->initializeExtensions(
- std::bind(&RendererBackend::initializeExtension, this, std::placeholders::_1));
+ std::bind(&RendererBackend::getExtensionFunctionPointer, this, std::placeholders::_1));
});
return *context;
}
diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp
index 3a7afdb03d..4bed0e251b 100644
--- a/src/mbgl/renderer/renderer_impl.cpp
+++ b/src/mbgl/renderer/renderer_impl.cpp
@@ -57,7 +57,8 @@ Renderer::Impl::Impl(RendererBackend& backend_,
, imageImpls(makeMutable<std::vector<Immutable<style::Image::Impl>>>())
, sourceImpls(makeMutable<std::vector<Immutable<style::Source::Impl>>>())
, layerImpls(makeMutable<std::vector<Immutable<style::Layer::Impl>>>())
- , renderLight(makeMutable<Light::Impl>()) {
+ , renderLight(makeMutable<Light::Impl>())
+ , placement(std::make_unique<Placement>(TransformState{}, MapMode::Static)) {
glyphManager->setObserver(this);
}
@@ -81,7 +82,7 @@ void Renderer::Impl::setObserver(RendererObserver* observer_) {
}
void Renderer::Impl::render(const UpdateParameters& updateParameters) {
- if (updateParameters.mode == MapMode::Still) {
+ if (updateParameters.mode != MapMode::Continuous) {
// Don't load/render anyting in still mode until explicitly requested.
if (!updateParameters.stillImageRequest) {
return;
@@ -253,13 +254,12 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
updateParameters,
renderLight.getEvaluated(),
*staticData,
- frameHistory,
*imageManager,
*lineAtlas
};
bool loaded = updateParameters.styleLoaded && isLoaded();
- if (updateParameters.mode == MapMode::Still && !loaded) {
+ if (updateParameters.mode != MapMode::Continuous && !loaded) {
return;
}
@@ -299,7 +299,9 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
if (const RenderBackgroundLayer* background = layer->as<RenderBackgroundLayer>()) {
const BackgroundPaintProperties::PossiblyEvaluated& paint = background->evaluated;
- if (layerImpl.get() == layerImpls->at(0).get() && paint.get<BackgroundPattern>().from.empty()) {
+ if (parameters.contextMode == GLContextMode::Unique
+ && layerImpl.get() == layerImpls->at(0).get()
+ && paint.get<BackgroundPattern>().from.empty()) {
// This is a solid background. We can use glClear().
backgroundColor = paint.get<BackgroundColor>() * paint.get<BackgroundOpacity>();
} else {
@@ -333,11 +335,15 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
auto par = util::rotate(pa, parameters.state.getAngle());
auto pbr = util::rotate(pb, parameters.state.getAngle());
- return std::tie(par.y, par.x) < std::tie(pbr.y, pbr.x);
+ return std::tie(b.id.canonical.z, par.y, par.x) < std::tie(a.id.canonical.z, pbr.y, pbr.x);
});
} else {
std::sort(sortedTiles.begin(), sortedTiles.end(),
[](const auto& a, const auto& b) { return a.get().id < b.get().id; });
+ // Don't render non-symbol layers for tiles that we're only holding on to for symbol fading
+ sortedTiles.erase(std::remove_if(sortedTiles.begin(), sortedTiles.end(),
+ [](const auto& tile) { return tile.get().tile.holdForFade(); }),
+ sortedTiles.end());
}
std::vector<std::reference_wrapper<RenderTile>> sortedTilesForInsertion;
@@ -347,35 +353,13 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
continue;
}
- // We're not clipping symbol layers, so when we have both parents and children of symbol
- // layers, we drop all children in favor of their parent to avoid duplicate labels.
- // See https://github.com/mapbox/mapbox-gl-native/issues/2482
- if (symbolLayer) {
- bool skip = false;
- // Look back through the buckets we decided to render to find out whether there is
- // already a bucket from this layer that is a parent of this tile. Tiles are ordered
- // by zoom level when we obtain them from getTiles().
- for (auto it = sortedTilesForInsertion.rbegin();
- it != sortedTilesForInsertion.rend(); ++it) {
- if (tile.tile.id.isChildOf(it->get().tile.id)) {
- skip = true;
- break;
- }
- }
- if (skip) {
- continue;
- }
- }
-
auto bucket = tile.tile.getBucket(*layer->baseImpl);
if (bucket) {
sortedTilesForInsertion.emplace_back(tile);
tile.used = true;
- // We only need clipping when we're _not_ drawing a symbol layer. The only exception
- // for symbol layers is when we're rendering still images. See render_symbol_layer.cpp
- // for the exception we make there.
- if (!symbolLayer || parameters.mapMode == MapMode::Still) {
+ // We only need clipping when we're _not_ drawing a symbol layer.
+ if (!symbolLayer) {
tile.needsClipping = true;
}
}
@@ -384,9 +368,47 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
order.emplace_back(RenderItem { *layer, source });
}
- frameHistory.record(parameters.timePoint,
- parameters.state.getZoom(),
- parameters.mapMode == MapMode::Continuous ? util::DEFAULT_TRANSITION_DURATION : Milliseconds(0));
+ bool symbolBucketsChanged = false;
+ if (parameters.mapMode != MapMode::Continuous) {
+ // TODO: Think about right way for symbol index to handle still rendering
+ crossTileSymbolIndex.reset();
+ }
+ for (auto it = order.rbegin(); it != order.rend(); ++it) {
+ if (it->layer.is<RenderSymbolLayer>()) {
+ if (crossTileSymbolIndex.addLayer(*it->layer.as<RenderSymbolLayer>())) symbolBucketsChanged = true;
+ }
+ }
+
+ bool placementChanged = false;
+ if (!placement->stillRecent(parameters.timePoint)) {
+ auto newPlacement = std::make_unique<Placement>(parameters.state, parameters.mapMode);
+ for (auto it = order.rbegin(); it != order.rend(); ++it) {
+ if (it->layer.is<RenderSymbolLayer>()) {
+ newPlacement->placeLayer(*it->layer.as<RenderSymbolLayer>(), parameters.projMatrix, parameters.debugOptions & MapDebugOptions::Collision);
+ }
+ }
+
+ placementChanged = newPlacement->commit(*placement, parameters.timePoint);
+ if (placementChanged || symbolBucketsChanged) {
+ placement = std::move(newPlacement);
+ }
+
+ placement->setRecent(parameters.timePoint);
+
+ updateFadingTiles();
+ } else {
+ placement->setStale();
+ }
+
+ parameters.symbolFadeChange = placement->symbolFadeChange(parameters.timePoint);
+
+ if (placementChanged || symbolBucketsChanged) {
+ for (auto it = order.rbegin(); it != order.rend(); ++it) {
+ if (it->layer.is<RenderSymbolLayer>()) {
+ placement->updateLayerOpacities(*it->layer.as<RenderSymbolLayer>());
+ }
+ }
+ }
// - UPLOAD PASS -------------------------------------------------------------------------------
// Uploads all required buffers and images before we do any actual rendering.
@@ -395,8 +417,7 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
parameters.imageManager.upload(parameters.context, 0);
parameters.lineAtlas.upload(parameters.context, 0);
- parameters.frameHistory.upload(parameters.context, 0);
-
+
// Update all clipping IDs + upload buckets.
for (const auto& entry : renderSources) {
if (entry.second->isEnabled()) {
@@ -435,13 +456,17 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
// Renders the backdrop of the OpenGL view. This also paints in areas where we don't have any
// tiles whatsoever.
{
+ using namespace gl::value;
+
MBGL_DEBUG_GROUP(parameters.context, "clear");
parameters.backend.bind();
- parameters.context.clear((parameters.debugOptions & MapDebugOptions::Overdraw)
- ? Color::black()
- : backgroundColor,
- 1.0f,
- 0);
+ if (parameters.debugOptions & MapDebugOptions::Overdraw) {
+ parameters.context.clear(Color::black(), ClearDepth::Default, ClearStencil::Default);
+ } else if (parameters.contextMode == GLContextMode::Shared) {
+ parameters.context.clear({}, ClearDepth::Default, ClearStencil::Default);
+ } else {
+ parameters.context.clear(backgroundColor, ClearDepth::Default, ClearStencil::Default);
+ }
}
// - CLIPPING MASKS ----------------------------------------------------------------------------
@@ -602,7 +627,7 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
observer->onDidFinishRenderingFrame(
loaded ? RendererObserver::RenderMode::Full : RendererObserver::RenderMode::Partial,
- updateParameters.mode == MapMode::Continuous && (hasTransitions() || frameHistory.needsAnimation(util::DEFAULT_TRANSITION_DURATION))
+ updateParameters.mode == MapMode::Continuous && hasTransitions(parameters.timePoint)
);
if (!loaded) {
@@ -642,7 +667,7 @@ std::vector<Feature> Renderer::Impl::queryRenderedFeatures(const ScreenLineStrin
std::unordered_map<std::string, std::vector<Feature>> resultsByLayer;
for (const auto& sourceID : sourceIDs) {
if (RenderSource* renderSource = getRenderSource(sourceID)) {
- auto sourceResults = renderSource->queryRenderedFeatures(geometry, transformState, layers, options);
+ auto sourceResults = renderSource->queryRenderedFeatures(geometry, transformState, layers, options, placement->getCollisionIndex());
std::move(sourceResults.begin(), sourceResults.end(), std::inserter(resultsByLayer, resultsByLayer.begin()));
}
}
@@ -722,7 +747,7 @@ RenderSource* Renderer::Impl::getRenderSource(const std::string& id) const {
return it != renderSources.end() ? it->second.get() : nullptr;
}
-bool Renderer::Impl::hasTransitions() const {
+bool Renderer::Impl::hasTransitions(TimePoint timePoint) const {
if (renderLight.hasTransition()) {
return true;
}
@@ -733,9 +758,30 @@ bool Renderer::Impl::hasTransitions() const {
}
}
+ if (placement->hasTransitions(timePoint)) {
+ return true;
+ }
+
+ if (fadingTiles) {
+ return true;
+ }
+
return false;
}
+void Renderer::Impl::updateFadingTiles() {
+ fadingTiles = false;
+ for (auto& source : renderSources) {
+ for (auto& renderTile : source.second->getRenderTiles()) {
+ Tile& tile = renderTile.get().tile;
+ if (tile.holdForFade()) {
+ fadingTiles = true;
+ tile.performedFadePlacement();
+ }
+ }
+ }
+}
+
bool Renderer::Impl::isLoaded() const {
for (const auto& entry: renderSources) {
if (!entry.second->isLoaded()) {
diff --git a/src/mbgl/renderer/renderer_impl.hpp b/src/mbgl/renderer/renderer_impl.hpp
index a199cec4d0..5d0200a5df 100644
--- a/src/mbgl/renderer/renderer_impl.hpp
+++ b/src/mbgl/renderer/renderer_impl.hpp
@@ -1,16 +1,17 @@
#pragma once
+#include <mbgl/renderer/mode.hpp>
#include <mbgl/renderer/renderer.hpp>
#include <mbgl/renderer/render_source_observer.hpp>
#include <mbgl/renderer/render_light.hpp>
-#include <mbgl/renderer/frame_history.hpp>
#include <mbgl/style/image.hpp>
#include <mbgl/style/source.hpp>
#include <mbgl/style/layer.hpp>
#include <mbgl/map/transform_state.hpp>
#include <mbgl/map/zoom_history.hpp>
-#include <mbgl/map/mode.hpp>
+#include <mbgl/text/cross_tile_symbol_index.hpp>
#include <mbgl/text/glyph_manager_observer.hpp>
+#include <mbgl/text/placement.hpp>
#include <memory>
#include <string>
@@ -31,6 +32,7 @@ class Scheduler;
class GlyphManager;
class ImageManager;
class LineAtlas;
+class CrossTileSymbolIndex;
class Renderer::Impl : public GlyphManagerObserver,
public RenderSourceObserver{
@@ -56,7 +58,7 @@ public:
private:
bool isLoaded() const;
- bool hasTransitions() const;
+ bool hasTransitions(TimePoint) const;
RenderSource* getRenderSource(const std::string& id) const;
@@ -72,6 +74,8 @@ private:
void onTileChanged(RenderSource&, const OverscaledTileID&) override;
void onTileError(RenderSource&, const OverscaledTileID&, std::exception_ptr) override;
+ void updateFadingTiles();
+
friend class Renderer;
RendererBackend& backend;
@@ -91,7 +95,6 @@ private:
};
RenderState renderState = RenderState::Never;
- FrameHistory frameHistory;
ZoomHistory zoomHistory;
TransformState transformState;
@@ -108,7 +111,11 @@ private:
std::unordered_map<std::string, std::unique_ptr<RenderLayer>> renderLayers;
RenderLight renderLight;
+ CrossTileSymbolIndex crossTileSymbolIndex;
+ std::unique_ptr<Placement> placement;
+
bool contextLost = false;
+ bool fadingTiles = false;
};
} // namespace mbgl
diff --git a/src/mbgl/renderer/sources/render_custom_geometry_source.cpp b/src/mbgl/renderer/sources/render_custom_geometry_source.cpp
new file mode 100644
index 0000000000..111f0234ed
--- /dev/null
+++ b/src/mbgl/renderer/sources/render_custom_geometry_source.cpp
@@ -0,0 +1,86 @@
+#include <mbgl/renderer/sources/render_custom_geometry_source.hpp>
+#include <mbgl/renderer/render_tile.hpp>
+#include <mbgl/renderer/paint_parameters.hpp>
+#include <mbgl/tile/custom_geometry_tile.hpp>
+
+#include <mbgl/algorithm/generate_clip_ids.hpp>
+#include <mbgl/algorithm/generate_clip_ids_impl.hpp>
+
+namespace mbgl {
+
+using namespace style;
+
+RenderCustomGeometrySource::RenderCustomGeometrySource(Immutable<style::CustomGeometrySource::Impl> impl_)
+ : RenderSource(impl_) {
+ tilePyramid.setObserver(this);
+}
+
+const style::CustomGeometrySource::Impl& RenderCustomGeometrySource::impl() const {
+ return static_cast<const style::CustomGeometrySource::Impl&>(*baseImpl);
+}
+
+bool RenderCustomGeometrySource::isLoaded() const {
+ return tilePyramid.isLoaded();
+}
+
+void RenderCustomGeometrySource::update(Immutable<style::Source::Impl> baseImpl_,
+ const std::vector<Immutable<Layer::Impl>>& layers,
+ const bool needsRendering,
+ const bool needsRelayout,
+ const TileParameters& parameters) {
+ std::swap(baseImpl, baseImpl_);
+
+ enabled = needsRendering;
+
+ auto tileLoader = impl().getTileLoader();
+ if (!tileLoader) {
+ return;
+ }
+
+ tilePyramid.update(layers,
+ needsRendering,
+ needsRelayout,
+ parameters,
+ SourceType::CustomVector,
+ util::tileSize,
+ impl().getZoomRange(),
+ [&] (const OverscaledTileID& tileID) {
+ return std::make_unique<CustomGeometryTile>(tileID, impl().id, parameters, impl().getTileOptions(), *tileLoader);
+ });
+}
+
+void RenderCustomGeometrySource::startRender(PaintParameters& parameters) {
+ parameters.clipIDGenerator.update(tilePyramid.getRenderTiles());
+ tilePyramid.startRender(parameters);
+}
+
+void RenderCustomGeometrySource::finishRender(PaintParameters& parameters) {
+ tilePyramid.finishRender(parameters);
+}
+
+std::vector<std::reference_wrapper<RenderTile>> RenderCustomGeometrySource::getRenderTiles() {
+ return tilePyramid.getRenderTiles();
+}
+
+std::unordered_map<std::string, std::vector<Feature>>
+RenderCustomGeometrySource::queryRenderedFeatures(const ScreenLineString& geometry,
+ const TransformState& transformState,
+ const std::vector<const RenderLayer*>& layers,
+ const RenderedQueryOptions& options,
+ const CollisionIndex& collisionIndex) const {
+ return tilePyramid.queryRenderedFeatures(geometry, transformState, layers, options, collisionIndex);
+}
+
+std::vector<Feature> RenderCustomGeometrySource::querySourceFeatures(const SourceQueryOptions& options) const {
+ return tilePyramid.querySourceFeatures(options);
+}
+
+void RenderCustomGeometrySource::onLowMemory() {
+ tilePyramid.onLowMemory();
+}
+
+void RenderCustomGeometrySource::dumpDebugLogs() const {
+ tilePyramid.dumpDebugLogs();
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/sources/render_custom_geometry_source.hpp b/src/mbgl/renderer/sources/render_custom_geometry_source.hpp
new file mode 100644
index 0000000000..82e691d5c9
--- /dev/null
+++ b/src/mbgl/renderer/sources/render_custom_geometry_source.hpp
@@ -0,0 +1,50 @@
+#pragma once
+
+#include <mbgl/renderer/render_source.hpp>
+#include <mbgl/renderer/tile_pyramid.hpp>
+#include <mbgl/style/sources/custom_geometry_source_impl.hpp>
+
+namespace mbgl {
+
+class RenderCustomGeometrySource : public RenderSource {
+public:
+ RenderCustomGeometrySource(Immutable<style::CustomGeometrySource::Impl>);
+
+ bool isLoaded() const final;
+
+ void update(Immutable<style::Source::Impl>,
+ const std::vector<Immutable<style::Layer::Impl>>&,
+ bool needsRendering,
+ bool needsRelayout,
+ const TileParameters&) final;
+
+ void startRender(PaintParameters&) final;
+ void finishRender(PaintParameters&) final;
+
+ std::vector<std::reference_wrapper<RenderTile>> getRenderTiles() final;
+
+ std::unordered_map<std::string, std::vector<Feature>>
+ queryRenderedFeatures(const ScreenLineString& geometry,
+ const TransformState& transformState,
+ const std::vector<const RenderLayer*>& layers,
+ const RenderedQueryOptions& options,
+ const CollisionIndex& collisionIndex) const final;
+
+ std::vector<Feature>
+ querySourceFeatures(const SourceQueryOptions&) const final;
+
+ void onLowMemory() final;
+ void dumpDebugLogs() const final;
+
+private:
+ const style::CustomGeometrySource::Impl& impl() const;
+
+ TilePyramid tilePyramid;
+};
+
+template <>
+inline bool RenderSource::is<RenderCustomGeometrySource>() const {
+ return baseImpl->type == style::SourceType::CustomVector;
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/sources/render_geojson_source.cpp b/src/mbgl/renderer/sources/render_geojson_source.cpp
index 504db78ea3..d07cfcdc41 100644
--- a/src/mbgl/renderer/sources/render_geojson_source.cpp
+++ b/src/mbgl/renderer/sources/render_geojson_source.cpp
@@ -84,8 +84,9 @@ std::unordered_map<std::string, std::vector<Feature>>
RenderGeoJSONSource::queryRenderedFeatures(const ScreenLineString& geometry,
const TransformState& transformState,
const std::vector<const RenderLayer*>& layers,
- const RenderedQueryOptions& options) const {
- return tilePyramid.queryRenderedFeatures(geometry, transformState, layers, options);
+ const RenderedQueryOptions& options,
+ const CollisionIndex& collisionIndex) const {
+ return tilePyramid.queryRenderedFeatures(geometry, transformState, layers, options, collisionIndex);
}
std::vector<Feature> RenderGeoJSONSource::querySourceFeatures(const SourceQueryOptions& options) const {
diff --git a/src/mbgl/renderer/sources/render_geojson_source.hpp b/src/mbgl/renderer/sources/render_geojson_source.hpp
index 72ab4879ef..55166ea901 100644
--- a/src/mbgl/renderer/sources/render_geojson_source.hpp
+++ b/src/mbgl/renderer/sources/render_geojson_source.hpp
@@ -31,7 +31,8 @@ public:
queryRenderedFeatures(const ScreenLineString& geometry,
const TransformState& transformState,
const std::vector<const RenderLayer*>& layers,
- const RenderedQueryOptions& options) const final;
+ const RenderedQueryOptions& options,
+ const CollisionIndex&) const final;
std::vector<Feature>
querySourceFeatures(const SourceQueryOptions&) const final;
@@ -48,7 +49,7 @@ private:
template <>
inline bool RenderSource::is<RenderGeoJSONSource>() const {
- return baseImpl->type == SourceType::GeoJSON;
+ return baseImpl->type == style::SourceType::GeoJSON;
}
} // namespace mbgl
diff --git a/src/mbgl/renderer/sources/render_image_source.cpp b/src/mbgl/renderer/sources/render_image_source.cpp
index 9140e01711..d215dc8d13 100644
--- a/src/mbgl/renderer/sources/render_image_source.cpp
+++ b/src/mbgl/renderer/sources/render_image_source.cpp
@@ -84,7 +84,8 @@ std::unordered_map<std::string, std::vector<Feature>>
RenderImageSource::queryRenderedFeatures(const ScreenLineString&,
const TransformState&,
const std::vector<const RenderLayer*>&,
- const RenderedQueryOptions&) const {
+ const RenderedQueryOptions&,
+ const CollisionIndex&) const {
return std::unordered_map<std::string, std::vector<Feature>> {};
}
@@ -113,44 +114,43 @@ void RenderImageSource::update(Immutable<style::Source::Impl> baseImpl_,
return;
}
- auto size = transformState.getSize();
- const double viewportHeight = size.height;
-
- // Compute the screen coordinates at wrap=0 for the given LatLng
- ScreenCoordinate nePixel = { -INFINITY, -INFINITY };
- ScreenCoordinate swPixel = { INFINITY, INFINITY };
-
+ // Compute the z0 tile coordinates for the given LatLngs
+ TileCoordinatePoint nePoint = { -INFINITY, -INFINITY };
+ TileCoordinatePoint swPoint = { INFINITY, INFINITY };
+ std::vector<TileCoordinatePoint> tileCoordinates;
for (LatLng latLng : coords) {
- ScreenCoordinate pixel = transformState.latLngToScreenCoordinate(latLng);
- swPixel.x = std::min(swPixel.x, pixel.x);
- nePixel.x = std::max(nePixel.x, pixel.x);
- swPixel.y = std::min(swPixel.y, viewportHeight - pixel.y);
- nePixel.y = std::max(nePixel.y, viewportHeight - pixel.y);
- }
- const double width = nePixel.x - swPixel.x;
- const double height = nePixel.y - swPixel.y;
+ auto point = TileCoordinate::fromLatLng(0, latLng).p;
+ tileCoordinates.push_back(point);
+ swPoint.x = std::min(swPoint.x, point.x);
+ nePoint.x = std::max(nePoint.x, point.x);
+ swPoint.y = std::min(swPoint.y, point.y);
+ nePoint.y = std::max(nePoint.y, point.y);
+ }
- // Don't bother drawing the ImageSource unless it occupies >4 screen pixels
- enabled = (width * height > 4);
+ // Calculate the optimum zoom level to determine the tile ids to use for transforms
+ 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(-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
+ // A tile coordinate unit represents the length of one tile (tileSize) at a given zoom.
+ // To convert a tile coordinate to pixels, multiply by tileSize.
+ // Here dMax is in z0 tile units, so we also scale by 2^z to match current zoom.
+ enabled = dMax * std::pow(2.0, transformState.getZoom()) * util::tileSize > 2.0;
if (!enabled) {
return;
}
- // Calculate the optimum zoom level to determine the tile ids to use for transforms
- double minScale = INFINITY;
- double scaleX = double(size.width) / width;
- double scaleY = double(size.height) / height;
- minScale = util::min(scaleX, scaleY);
- double zoom = transformState.getZoom() + util::log2(minScale);
- zoom = std::floor(util::clamp(zoom, transformState.getMinZoom(), transformState.getMaxZoom()));
auto imageBounds = LatLngBounds::hull(coords[0], coords[1]);
imageBounds.extend(coords[2]);
imageBounds.extend(coords[3]);
auto tileCover = util::tileCover(imageBounds, zoom);
tileIds.clear();
tileIds.push_back(tileCover[0]);
- bool hasVisibleTile = false;
+ bool hasVisibleTile = false;
// Add additional wrapped tile ids if neccessary
auto idealTiles = util::tileCover(transformState, transformState.getZoom());
for (auto tile : idealTiles) {
@@ -176,9 +176,8 @@ void RenderImageSource::update(Immutable<style::Source::Impl> baseImpl_,
// Calculate Geometry Coordinates based on tile cover at ideal zoom
GeometryCoordinates geomCoords;
- for (auto latLng : coords) {
- auto tc = TileCoordinate::fromLatLng(0, latLng);
- auto gc = TileCoordinate::toGeometryCoordinate(tileIds[0], tc.p);
+ for (auto tileCoords : tileCoordinates) {
+ auto gc = TileCoordinate::toGeometryCoordinate(tileIds[0], tileCoords);
geomCoords.push_back(gc);
}
if (!bucket) {
diff --git a/src/mbgl/renderer/sources/render_image_source.hpp b/src/mbgl/renderer/sources/render_image_source.hpp
index 7b69d09fa7..72cf4cea61 100644
--- a/src/mbgl/renderer/sources/render_image_source.hpp
+++ b/src/mbgl/renderer/sources/render_image_source.hpp
@@ -32,7 +32,8 @@ public:
queryRenderedFeatures(const ScreenLineString& geometry,
const TransformState& transformState,
const std::vector<const RenderLayer*>& layers,
- const RenderedQueryOptions& options) const final;
+ const RenderedQueryOptions& options,
+ const CollisionIndex& collisionIndex) const final;
std::vector<Feature> querySourceFeatures(const SourceQueryOptions&) const final;
@@ -52,7 +53,7 @@ private:
template <>
inline bool RenderSource::is<RenderImageSource>() const {
- return baseImpl->type == SourceType::Image;
+ return baseImpl->type == style::SourceType::Image;
}
} // namespace mbgl
diff --git a/src/mbgl/renderer/sources/render_raster_source.cpp b/src/mbgl/renderer/sources/render_raster_source.cpp
index bcd719365d..f11f9b7aed 100644
--- a/src/mbgl/renderer/sources/render_raster_source.cpp
+++ b/src/mbgl/renderer/sources/render_raster_source.cpp
@@ -74,7 +74,8 @@ std::unordered_map<std::string, std::vector<Feature>>
RenderRasterSource::queryRenderedFeatures(const ScreenLineString&,
const TransformState&,
const std::vector<const RenderLayer*>&,
- const RenderedQueryOptions&) const {
+ const RenderedQueryOptions&,
+ const CollisionIndex& ) const {
return std::unordered_map<std::string, std::vector<Feature>> {};
}
diff --git a/src/mbgl/renderer/sources/render_raster_source.hpp b/src/mbgl/renderer/sources/render_raster_source.hpp
index 01de812309..25041fde43 100644
--- a/src/mbgl/renderer/sources/render_raster_source.hpp
+++ b/src/mbgl/renderer/sources/render_raster_source.hpp
@@ -27,7 +27,8 @@ public:
queryRenderedFeatures(const ScreenLineString& geometry,
const TransformState& transformState,
const std::vector<const RenderLayer*>& layers,
- const RenderedQueryOptions& options) const final;
+ const RenderedQueryOptions& options,
+ const CollisionIndex& collisionIndex) const final;
std::vector<Feature>
querySourceFeatures(const SourceQueryOptions&) const final;
@@ -44,7 +45,7 @@ private:
template <>
inline bool RenderSource::is<RenderRasterSource>() const {
- return baseImpl->type == SourceType::Raster;
+ return baseImpl->type == style::SourceType::Raster;
}
} // namespace mbgl
diff --git a/src/mbgl/renderer/sources/render_vector_source.cpp b/src/mbgl/renderer/sources/render_vector_source.cpp
index ca3071c6b0..49f8fdff2c 100644
--- a/src/mbgl/renderer/sources/render_vector_source.cpp
+++ b/src/mbgl/renderer/sources/render_vector_source.cpp
@@ -77,8 +77,9 @@ std::unordered_map<std::string, std::vector<Feature>>
RenderVectorSource::queryRenderedFeatures(const ScreenLineString& geometry,
const TransformState& transformState,
const std::vector<const RenderLayer*>& layers,
- const RenderedQueryOptions& options) const {
- return tilePyramid.queryRenderedFeatures(geometry, transformState, layers, options);
+ const RenderedQueryOptions& options,
+ const CollisionIndex& collisionIndex) const {
+ return tilePyramid.queryRenderedFeatures(geometry, transformState, layers, options, collisionIndex);
}
std::vector<Feature> RenderVectorSource::querySourceFeatures(const SourceQueryOptions& options) const {
diff --git a/src/mbgl/renderer/sources/render_vector_source.hpp b/src/mbgl/renderer/sources/render_vector_source.hpp
index 5e5c6d1108..4a992e854f 100644
--- a/src/mbgl/renderer/sources/render_vector_source.hpp
+++ b/src/mbgl/renderer/sources/render_vector_source.hpp
@@ -27,7 +27,8 @@ public:
queryRenderedFeatures(const ScreenLineString& geometry,
const TransformState& transformState,
const std::vector<const RenderLayer*>& layers,
- const RenderedQueryOptions& options) const final;
+ const RenderedQueryOptions& options,
+ const CollisionIndex& collisionIndex) const final;
std::vector<Feature>
querySourceFeatures(const SourceQueryOptions&) const final;
@@ -44,7 +45,7 @@ private:
template <>
inline bool RenderSource::is<RenderVectorSource>() const {
- return baseImpl->type == SourceType::Vector;
+ return baseImpl->type == style::SourceType::Vector;
}
} // namespace mbgl
diff --git a/src/mbgl/renderer/tile_pyramid.cpp b/src/mbgl/renderer/tile_pyramid.cpp
index 3e2311089d..870d9050bc 100644
--- a/src/mbgl/renderer/tile_pyramid.cpp
+++ b/src/mbgl/renderer/tile_pyramid.cpp
@@ -5,7 +5,6 @@
#include <mbgl/renderer/tile_parameters.hpp>
#include <mbgl/renderer/query.hpp>
#include <mbgl/map/transform.hpp>
-#include <mbgl/text/placement_config.hpp>
#include <mbgl/math/clamp.hpp>
#include <mbgl/util/tile_cover.hpp>
#include <mbgl/util/enum.hpp>
@@ -94,14 +93,11 @@ void TilePyramid::update(const std::vector<Immutable<style::Layer::Impl>>& layer
if (overscaledZoom >= zoomRange.min) {
int32_t idealZoom = std::min<int32_t>(zoomRange.max, overscaledZoom);
- // Make sure we're not reparsing overzoomed raster tiles.
- if (type == SourceType::Raster) {
+ // Only attempt prefetching in continuous mode.
+ if (parameters.mode == MapMode::Continuous) {
tileZoom = idealZoom;
- // FIXME: Prefetching is only enabled for raster
- // tiles until we fix #7026.
-
- // Request lower zoom level tiles (if configure to do so) in an attempt
+ // Request lower zoom level tiles (if configured to do so) in an attempt
// to show something on the screen faster at the cost of a little of bandwidth.
if (parameters.prefetchZoomDelta) {
panZoom = std::max<int32_t>(tileZoom - parameters.prefetchZoomDelta, zoomRange.min);
@@ -120,6 +116,7 @@ void TilePyramid::update(const std::vector<Immutable<style::Layer::Impl>>& layer
// use because they're still loading. In addition to that, we also need to retain all tiles that
// we're actively using, e.g. as a replacement for tile that aren't loaded yet.
std::set<OverscaledTileID> retain;
+ std::set<UnwrappedTileID> rendered;
auto retainTileFn = [&](Tile& tile, TileNecessity necessity) -> void {
if (retain.emplace(tile.id).second) {
@@ -148,8 +145,17 @@ void TilePyramid::update(const std::vector<Immutable<style::Layer::Impl>>& layer
}
return tiles.emplace(tileID, std::move(tile)).first->second.get();
};
+
+ std::map<UnwrappedTileID, Tile*> previouslyRenderedTiles;
+ for (auto& renderTile : renderTiles) {
+ previouslyRenderedTiles[renderTile.id] = &renderTile.tile;
+ }
+
auto renderTileFn = [&](const UnwrappedTileID& tileID, Tile& tile) {
renderTiles.emplace_back(tileID, tile);
+ rendered.emplace(tileID);
+ previouslyRenderedTiles.erase(tileID); // Still rendering this tile, no need for special fading logic.
+ tile.markRenderedIdeal();
};
renderTiles.clear();
@@ -161,6 +167,18 @@ void TilePyramid::update(const std::vector<Immutable<style::Layer::Impl>>& layer
algorithm::updateRenderables(getTileFn, createTileFn, retainTileFn, renderTileFn,
idealTiles, zoomRange, tileZoom);
+
+ for (auto previouslyRenderedTile : previouslyRenderedTiles) {
+ Tile& tile = *previouslyRenderedTile.second;
+ tile.markRenderedPreviously();
+ if (tile.holdForFade()) {
+ // Since it was rendered in the last frame, we know we have it
+ // Don't mark the tile "Required" to avoid triggering a new network request
+ retainTileFn(tile, TileNecessity::Optional);
+ renderTiles.emplace_back(previouslyRenderedTile.first, tile);
+ rendered.emplace(previouslyRenderedTile.first);
+ }
+ }
if (type != SourceType::Annotations) {
size_t conservativeCacheSize =
@@ -177,6 +195,13 @@ void TilePyramid::update(const std::vector<Immutable<style::Layer::Impl>>& layer
auto tilesIt = tiles.begin();
auto retainIt = retain.begin();
while (tilesIt != tiles.end()) {
+ auto renderedIt = rendered.find(tilesIt->first.toUnwrapped());
+ if (renderedIt == rendered.end()) {
+ // Since this tile isn't in the render set, crossTileIDs won't be kept
+ // updated by CrossTileSymbolIndex. We need to reset the stored crossTileIDs
+ // so they're not reused if/when this tile is re-added to the render set
+ tilesIt->second->resetCrossTileIDs();
+ }
if (retainIt == retain.end() || tilesIt->first < *retainIt) {
if (!needsRelayout) {
tilesIt->second->setNecessity(TileNecessity::Optional);
@@ -193,20 +218,15 @@ void TilePyramid::update(const std::vector<Immutable<style::Layer::Impl>>& layer
}
for (auto& pair : tiles) {
- const PlacementConfig config { parameters.transformState.getAngle(),
- parameters.transformState.getPitch(),
- parameters.transformState.getCameraToCenterDistance(),
- parameters.transformState.getCameraToTileDistance(pair.first.toUnwrapped()),
- parameters.debugOptions & MapDebugOptions::Collision };
-
- pair.second->setPlacementConfig(config);
+ pair.second->setShowCollisionBoxes(parameters.debugOptions & MapDebugOptions::Collision);
}
}
std::unordered_map<std::string, std::vector<Feature>> TilePyramid::queryRenderedFeatures(const ScreenLineString& geometry,
const TransformState& transformState,
const std::vector<const RenderLayer*>& layers,
- const RenderedQueryOptions& options) const {
+ const RenderedQueryOptions& options,
+ const CollisionIndex& collisionIndex) const {
std::unordered_map<std::string, std::vector<Feature>> result;
if (renderTiles.empty() || geometry.empty()) {
return result;
@@ -249,7 +269,8 @@ std::unordered_map<std::string, std::vector<Feature>> TilePyramid::queryRendered
tileSpaceQueryGeometry,
transformState,
layers,
- options);
+ options,
+ collisionIndex);
}
return result;
diff --git a/src/mbgl/renderer/tile_pyramid.hpp b/src/mbgl/renderer/tile_pyramid.hpp
index 73a8d34c1c..feab8a838c 100644
--- a/src/mbgl/renderer/tile_pyramid.hpp
+++ b/src/mbgl/renderer/tile_pyramid.hpp
@@ -37,7 +37,7 @@ public:
bool needsRendering,
bool needsRelayout,
const TileParameters&,
- SourceType type,
+ style::SourceType type,
uint16_t tileSize,
Range<uint8_t> zoomRange,
std::function<std::unique_ptr<Tile> (const OverscaledTileID&)> createTile);
@@ -51,7 +51,8 @@ public:
queryRenderedFeatures(const ScreenLineString& geometry,
const TransformState& transformState,
const std::vector<const RenderLayer*>&,
- const RenderedQueryOptions& options) const;
+ const RenderedQueryOptions& options,
+ const CollisionIndex& collisionIndex) const;
std::vector<Feature> querySourceFeatures(const SourceQueryOptions&) const;
diff --git a/src/mbgl/shaders/collision_box.cpp b/src/mbgl/shaders/collision_box.cpp
index 07fa94e338..9d11640bf4 100644
--- a/src/mbgl/shaders/collision_box.cpp
+++ b/src/mbgl/shaders/collision_box.cpp
@@ -10,77 +10,50 @@ const char* collision_box::vertexSource = R"MBGL_SHADER(
attribute vec2 a_pos;
attribute vec2 a_anchor_pos;
attribute vec2 a_extrude;
-attribute vec2 a_data;
+attribute vec2 a_placed;
uniform mat4 u_matrix;
-uniform float u_scale;
-uniform float u_pitch;
-uniform float u_collision_y_stretch;
+uniform vec2 u_extrude_scale;
uniform float u_camera_to_center_distance;
-varying float v_max_zoom;
-varying float v_placement_zoom;
-varying float v_perspective_zoom_adjust;
-varying vec2 v_fade_tex;
+varying float v_placed;
+varying float v_notUsed;
void main() {
vec4 projectedPoint = u_matrix * vec4(a_anchor_pos, 0, 1);
highp float camera_to_anchor_distance = projectedPoint.w;
- highp float collision_perspective_ratio = 1.0 + 0.5 * ((camera_to_anchor_distance / u_camera_to_center_distance) - 1.0);
+ highp float collision_perspective_ratio = 0.5 + 0.5 * (u_camera_to_center_distance / camera_to_anchor_distance);
- highp float incidence_stretch = camera_to_anchor_distance / (u_camera_to_center_distance * cos(u_pitch));
- highp float collision_adjustment = max(1.0, incidence_stretch / u_collision_y_stretch);
+ gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0);
+ gl_Position.xy += a_extrude * u_extrude_scale * gl_Position.w * collision_perspective_ratio;
- gl_Position = u_matrix * vec4(a_pos + a_extrude * collision_perspective_ratio * collision_adjustment / u_scale, 0.0, 1.0);
-
- v_max_zoom = a_data.x;
- v_placement_zoom = a_data.y;
-
- v_perspective_zoom_adjust = floor(log2(collision_perspective_ratio * collision_adjustment) * 10.0);
- v_fade_tex = vec2((v_placement_zoom + v_perspective_zoom_adjust) / 255.0, 0.0);
+ v_placed = a_placed.x;
+ v_notUsed = a_placed.y;
}
)MBGL_SHADER";
const char* collision_box::fragmentSource = R"MBGL_SHADER(
-uniform float u_zoom;
-// u_maxzoom is derived from the maximum scale considered by the CollisionTile
-// Labels with placement zoom greater than this value will not be placed,
-// regardless of perspective effects.
-uniform float u_maxzoom;
-uniform sampler2D u_fadetexture;
-
-// v_max_zoom is a collision-box-specific value that controls when line-following
-// collision boxes are used.
-varying float v_max_zoom;
-varying float v_placement_zoom;
-varying float v_perspective_zoom_adjust;
-varying vec2 v_fade_tex;
+
+varying float v_placed;
+varying float v_notUsed;
void main() {
float alpha = 0.5;
- // Green = no collisions, label is showing
- gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0) * alpha;
+ // Red = collision, hide label
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0) * alpha;
- // Red = collision, label hidden
- if (texture2D(u_fadetexture, v_fade_tex).a < 1.0) {
- gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0) * alpha;
+ // Blue = no collision, label is showing
+ if (v_placed > 0.5) {
+ gl_FragColor = vec4(0.0, 0.0, 1.0, 0.5) * alpha;
}
- // Faded black = this collision box is not used at this zoom (for curved labels)
- if (u_zoom >= v_max_zoom + v_perspective_zoom_adjust) {
- gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0) * alpha * 0.25;
- }
-
- // Faded blue = the placement scale for this label is beyond the CollisionTile
- // max scale, so it's impossible for this label to show without collision detection
- // being run again (the label's glyphs haven't even been added to the symbol bucket)
- if (v_placement_zoom >= u_maxzoom) {
- gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0) * alpha * 0.2;
+ if (v_notUsed > 0.5) {
+ // This box not used, fade it out
+ gl_FragColor *= .1;
}
}
-
)MBGL_SHADER";
} // namespace shaders
diff --git a/src/mbgl/shaders/collision_circle.cpp b/src/mbgl/shaders/collision_circle.cpp
new file mode 100644
index 0000000000..1e85d99a33
--- /dev/null
+++ b/src/mbgl/shaders/collision_circle.cpp
@@ -0,0 +1,83 @@
+// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
+
+#include <mbgl/shaders/collision_circle.hpp>
+
+namespace mbgl {
+namespace shaders {
+
+const char* collision_circle::name = "collision_circle";
+const char* collision_circle::vertexSource = R"MBGL_SHADER(
+attribute vec2 a_pos;
+attribute vec2 a_anchor_pos;
+attribute vec2 a_extrude;
+attribute vec2 a_placed;
+
+uniform mat4 u_matrix;
+uniform vec2 u_extrude_scale;
+uniform float u_camera_to_center_distance;
+
+varying float v_placed;
+varying float v_notUsed;
+varying float v_radius;
+
+varying vec2 v_extrude;
+varying vec2 v_extrude_scale;
+
+void main() {
+ vec4 projectedPoint = u_matrix * vec4(a_anchor_pos, 0, 1);
+ highp float camera_to_anchor_distance = projectedPoint.w;
+ highp float collision_perspective_ratio = 0.5 + 0.5 * (camera_to_anchor_distance / u_camera_to_center_distance);
+
+ gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0);
+
+ highp float padding_factor = 1.2; // Pad the vertices slightly to make room for anti-alias blur
+ gl_Position.xy += a_extrude * u_extrude_scale * padding_factor * gl_Position.w / collision_perspective_ratio;
+
+ v_placed = a_placed.x;
+ v_notUsed = a_placed.y;
+ v_radius = abs(a_extrude.y); // We don't pitch the circles, so both units of the extrusion vector are equal in magnitude to the radius
+
+ v_extrude = a_extrude * padding_factor;
+ v_extrude_scale = u_extrude_scale * u_camera_to_center_distance / collision_perspective_ratio;
+}
+
+)MBGL_SHADER";
+const char* collision_circle::fragmentSource = R"MBGL_SHADER(
+
+varying float v_placed;
+varying float v_notUsed;
+varying float v_radius;
+varying vec2 v_extrude;
+varying vec2 v_extrude_scale;
+
+void main() {
+ float alpha = 0.5;
+
+ // Red = collision, hide label
+ vec4 color = vec4(1.0, 0.0, 0.0, 1.0) * alpha;
+
+ // Blue = no collision, label is showing
+ if (v_placed > 0.5) {
+ color = vec4(0.0, 0.0, 1.0, 0.5) * alpha;
+ }
+
+ if (v_notUsed > 0.5) {
+ // This box not used, fade it out
+ color *= .2;
+ }
+
+ float extrude_scale_length = length(v_extrude_scale);
+ float extrude_length = length(v_extrude) * extrude_scale_length;
+ float stroke_width = 3.0;
+ float radius = v_radius * extrude_scale_length;
+
+ float distance_to_edge = abs(extrude_length - radius);
+ float opacity_t = smoothstep(-stroke_width, 0.0, -distance_to_edge);
+
+ gl_FragColor = opacity_t * color;
+}
+
+)MBGL_SHADER";
+
+} // namespace shaders
+} // namespace mbgl
diff --git a/src/mbgl/shaders/collision_circle.hpp b/src/mbgl/shaders/collision_circle.hpp
new file mode 100644
index 0000000000..12b1bcd445
--- /dev/null
+++ b/src/mbgl/shaders/collision_circle.hpp
@@ -0,0 +1,16 @@
+// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
+
+#pragma once
+
+namespace mbgl {
+namespace shaders {
+
+class collision_circle {
+public:
+ static const char* name;
+ static const char* vertexSource;
+ static const char* fragmentSource;
+};
+
+} // namespace shaders
+} // namespace mbgl
diff --git a/src/mbgl/shaders/debug.cpp b/src/mbgl/shaders/debug.cpp
index d18f3be5d1..9012cfa755 100644
--- a/src/mbgl/shaders/debug.cpp
+++ b/src/mbgl/shaders/debug.cpp
@@ -12,12 +12,7 @@ attribute vec2 a_pos;
uniform mat4 u_matrix;
void main() {
- // We are using Int16 for texture position coordinates to give us enough precision for
- // fractional coordinates. We use 8192 to scale the texture coordinates in the buffer
- // as an arbitrarily high number to preserve adequate precision when rendering.
- // This is also the same value as the EXTENT we are using for our tile buffer pos coordinates,
- // so math for modifying either is consistent.
- gl_Position = u_matrix * vec4(a_pos, step(8192.0, a_pos.x), 1);
+ gl_Position = u_matrix * vec4(a_pos, 0, 1);
}
)MBGL_SHADER";
diff --git a/src/mbgl/shaders/fill_extrusion.cpp b/src/mbgl/shaders/fill_extrusion.cpp
index 817f73391c..5bb2b9cd07 100644
--- a/src/mbgl/shaders/fill_extrusion.cpp
+++ b/src/mbgl/shaders/fill_extrusion.cpp
@@ -13,8 +13,7 @@ uniform lowp vec3 u_lightpos;
uniform lowp float u_lightintensity;
attribute vec2 a_pos;
-attribute vec3 a_normal;
-attribute float a_edgedistance;
+attribute vec4 a_normal_ed;
varying vec4 v_color;
@@ -70,11 +69,12 @@ void main() {
#endif
+ vec3 normal = a_normal_ed.xyz;
+
base = max(0.0, base);
height = max(0.0, height);
- float ed = a_edgedistance; // use each attrib in order to not trip a VAO assert
- float t = mod(a_normal.x, 2.0);
+ float t = mod(normal.x, 2.0);
gl_Position = u_matrix * vec4(a_pos, t > 0.0 ? height : base, 1);
@@ -88,7 +88,7 @@ void main() {
color += ambientlight;
// Calculate cos(theta), where theta is the angle between surface normal and diffuse light ray
- float directional = clamp(dot(a_normal / 16384.0, u_lightpos), 0.0, 1.0);
+ float directional = clamp(dot(normal / 16384.0, u_lightpos), 0.0, 1.0);
// Adjust directional so that
// the range of values for highlight/shading is narrower
@@ -97,7 +97,7 @@ void main() {
directional = mix((1.0 - u_lightintensity), max((1.0 - colorvalue + u_lightintensity), 1.0), directional);
// Add gradient along z axis of side surfaces
- if (a_normal.y != 0.0) {
+ if (normal.y != 0.0) {
directional *= clamp((t + base) * pow(height / 150.0, 0.5), mix(0.7, 0.98, 1.0 - u_lightintensity), 1.0);
}
diff --git a/src/mbgl/shaders/fill_extrusion_pattern.cpp b/src/mbgl/shaders/fill_extrusion_pattern.cpp
index d3e5eef1bf..466d0e04fe 100644
--- a/src/mbgl/shaders/fill_extrusion_pattern.cpp
+++ b/src/mbgl/shaders/fill_extrusion_pattern.cpp
@@ -22,8 +22,7 @@ uniform lowp vec3 u_lightpos;
uniform lowp float u_lightintensity;
attribute vec2 a_pos;
-attribute vec3 a_normal;
-attribute float a_edgedistance;
+attribute vec4 a_normal_ed;
varying vec2 v_pos_a;
varying vec2 v_pos_b;
@@ -65,26 +64,29 @@ void main() {
#endif
+ vec3 normal = a_normal_ed.xyz;
+ float edgedistance = a_normal_ed.w;
+
base = max(0.0, base);
height = max(0.0, height);
- float t = mod(a_normal.x, 2.0);
+ float t = mod(normal.x, 2.0);
float z = t > 0.0 ? height : base;
gl_Position = u_matrix * vec4(a_pos, z, 1);
- vec2 pos = a_normal.x == 1.0 && a_normal.y == 0.0 && a_normal.z == 16384.0
+ vec2 pos = normal.x == 1.0 && normal.y == 0.0 && normal.z == 16384.0
? a_pos // extrusion top
- : vec2(a_edgedistance, z * u_height_factor); // extrusion side
+ : vec2(edgedistance, z * u_height_factor); // extrusion side
v_pos_a = get_pattern_pos(u_pixel_coord_upper, u_pixel_coord_lower, u_scale_a * u_pattern_size_a, u_tile_units_to_pixels, pos);
v_pos_b = get_pattern_pos(u_pixel_coord_upper, u_pixel_coord_lower, u_scale_b * u_pattern_size_b, u_tile_units_to_pixels, pos);
v_lighting = vec4(0.0, 0.0, 0.0, 1.0);
- float directional = clamp(dot(a_normal / 16383.0, u_lightpos), 0.0, 1.0);
+ float directional = clamp(dot(normal / 16383.0, u_lightpos), 0.0, 1.0);
directional = mix((1.0 - u_lightintensity), max((0.5 + u_lightintensity), 1.0), directional);
- if (a_normal.y != 0.0) {
+ if (normal.y != 0.0) {
directional *= clamp((t + base) * pow(height / 150.0, 0.5), mix(0.7, 0.98, 1.0 - u_lightintensity), 1.0);
}
diff --git a/src/mbgl/shaders/preludes.cpp b/src/mbgl/shaders/preludes.cpp
index feb185a684..6baa488a10 100644
--- a/src/mbgl/shaders/preludes.cpp
+++ b/src/mbgl/shaders/preludes.cpp
@@ -34,6 +34,10 @@ vec2 unpack_float(const float packedValue) {
return vec2(v0, packedIntValue - v0 * 256);
}
+vec2 unpack_opacity(const float packedOpacity) {
+ int intOpacity = int(packedOpacity) / 2;
+ return vec2(float(intOpacity) / 127.0, mod(packedOpacity, 2.0));
+}
// To minimize the number of attributes needed, we encode a 4-component
// color into a pair of floats (i.e. a vec2) as follows:
diff --git a/src/mbgl/shaders/symbol_icon.cpp b/src/mbgl/shaders/symbol_icon.cpp
index 1e96194738..f5c2bbe22d 100644
--- a/src/mbgl/shaders/symbol_icon.cpp
+++ b/src/mbgl/shaders/symbol_icon.cpp
@@ -12,6 +12,7 @@ const float PI = 3.141592653589793;
attribute vec4 a_pos_offset;
attribute vec4 a_data;
attribute vec3 a_projected_pos;
+attribute float a_fade_opacity;
uniform bool u_is_size_zoom_constant;
uniform bool u_is_size_feature_constant;
@@ -21,7 +22,7 @@ uniform highp float u_camera_to_center_distance;
uniform highp float u_pitch;
uniform bool u_rotate_symbol;
uniform highp float u_aspect_ratio;
-uniform highp float u_collision_y_stretch;
+uniform float u_fade_change;
#ifndef HAS_UNIFORM_u_opacity
@@ -43,7 +44,7 @@ uniform bool u_pitch_with_map;
uniform vec2 u_texsize;
varying vec2 v_tex;
-varying vec2 v_fade_tex;
+varying float v_fade_opacity;
void main() {
@@ -60,9 +61,7 @@ void main() {
vec2 a_tex = a_data.xy;
vec2 a_size = a_data.zw;
- highp vec2 angle_labelminzoom = unpack_float(a_projected_pos[2]);
- highp float segment_angle = -angle_labelminzoom[0] / 255.0 * 2.0 * PI;
- mediump float a_labelminzoom = angle_labelminzoom[1];
+ highp float segment_angle = -a_projected_pos[2];
float size;
if (!u_is_size_zoom_constant && !u_is_size_feature_constant) {
@@ -106,19 +105,14 @@ void main() {
gl_Position = u_gl_coord_matrix * vec4(projected_pos.xy / projected_pos.w + rotation_matrix * (a_offset / 64.0 * fontScale), 0.0, 1.0);
v_tex = a_tex / u_texsize;
- // See comments in symbol_sdf.vertex
- highp float incidence_stretch = camera_to_anchor_distance / (u_camera_to_center_distance * cos(u_pitch));
- highp float collision_adjustment = max(1.0, incidence_stretch / u_collision_y_stretch);
-
- highp float collision_perspective_ratio = 1.0 + 0.5*((camera_to_anchor_distance / u_camera_to_center_distance) - 1.0);
- highp float perspective_zoom_adjust = floor(log2(collision_perspective_ratio * collision_adjustment) * 10.0);
- v_fade_tex = vec2((a_labelminzoom + perspective_zoom_adjust) / 255.0, 0.0);
+ vec2 fade_opacity = unpack_opacity(a_fade_opacity);
+ float fade_change = fade_opacity[1] > 0.5 ? u_fade_change : -u_fade_change;
+ v_fade_opacity = max(0.0, min(1.0, fade_opacity[0] + fade_change));
}
)MBGL_SHADER";
const char* symbol_icon::fragmentSource = R"MBGL_SHADER(
uniform sampler2D u_texture;
-uniform sampler2D u_fadetexture;
#ifndef HAS_UNIFORM_u_opacity
@@ -129,7 +123,7 @@ uniform lowp float u_opacity;
varying vec2 v_tex;
-varying vec2 v_fade_tex;
+varying float v_fade_opacity;
void main() {
@@ -138,7 +132,7 @@ void main() {
#endif
- lowp float alpha = texture2D(u_fadetexture, v_fade_tex).a * opacity;
+ lowp float alpha = opacity * v_fade_opacity;
gl_FragColor = texture2D(u_texture, v_tex) * alpha;
#ifdef OVERDRAW_INSPECTOR
diff --git a/src/mbgl/shaders/symbol_sdf.cpp b/src/mbgl/shaders/symbol_sdf.cpp
index a4427f31ab..441eaf7aac 100644
--- a/src/mbgl/shaders/symbol_sdf.cpp
+++ b/src/mbgl/shaders/symbol_sdf.cpp
@@ -12,6 +12,7 @@ const float PI = 3.141592653589793;
attribute vec4 a_pos_offset;
attribute vec4 a_data;
attribute vec3 a_projected_pos;
+attribute float a_fade_opacity;
// contents of a_size vary based on the type of property value
// used for {text,icon}-size.
@@ -81,12 +82,12 @@ uniform highp float u_pitch;
uniform bool u_rotate_symbol;
uniform highp float u_aspect_ratio;
uniform highp float u_camera_to_center_distance;
-uniform highp float u_collision_y_stretch;
+uniform float u_fade_change;
uniform vec2 u_texsize;
-varying vec4 v_data0;
-varying vec2 v_data1;
+varying vec2 v_data0;
+varying vec3 v_data1;
void main() {
@@ -131,9 +132,7 @@ void main() {
vec2 a_tex = a_data.xy;
vec2 a_size = a_data.zw;
- highp vec2 angle_labelminzoom = unpack_float(a_projected_pos[2]);
- highp float segment_angle = -angle_labelminzoom[0] / 255.0 * 2.0 * PI;
- mediump float a_labelminzoom = angle_labelminzoom[1];
+ highp float segment_angle = -a_projected_pos[2];
float size;
if (!u_is_size_zoom_constant && !u_is_size_feature_constant) {
@@ -185,31 +184,12 @@ void main() {
float gamma_scale = gl_Position.w;
vec2 tex = a_tex / u_texsize;
- // incidence_stretch is the ratio of how much y space a label takes up on a tile while drawn perpendicular to the viewport vs
- // how much space it would take up if it were drawn flat on the tile
- // Using law of sines, camera_to_anchor/sin(ground_angle) = camera_to_center/sin(incidence_angle)
- // sin(incidence_angle) = 1/incidence_stretch
- // Incidence angle 90 -> head on, sin(incidence_angle) = 1, no incidence stretch
- // Incidence angle 1 -> very oblique, sin(incidence_angle) =~ 0, lots of incidence stretch
- // ground_angle = u_pitch + PI/2 -> sin(ground_angle) = cos(u_pitch)
- // This 2D calculation is only exactly correct when gl_Position.x is in the center of the viewport,
- // but it's a close enough approximation for our purposes
- highp float incidence_stretch = camera_to_anchor_distance / (u_camera_to_center_distance * cos(u_pitch));
- // incidence_stretch only applies to the y-axis, but without re-calculating the collision tile, we can't
- // adjust the size of only one axis. So, we do a crude approximation at placement time to get the aspect ratio
- // about right, and then do the rest of the adjustment here: there will be some extra padding on the x-axis,
- // but hopefully not too much.
- // Never make the adjustment less than 1.0: instead of allowing collisions on the x-axis, be conservative on
- // the y-axis.
- highp float collision_adjustment = max(1.0, incidence_stretch / u_collision_y_stretch);
-
- // Floor to 1/10th zoom to dodge precision issues that can cause partially hidden labels
- highp float collision_perspective_ratio = 1.0 + 0.5*((camera_to_anchor_distance / u_camera_to_center_distance) - 1.0);
- highp float perspective_zoom_adjust = floor(log2(collision_perspective_ratio * collision_adjustment) * 10.0);
- vec2 fade_tex = vec2((a_labelminzoom + perspective_zoom_adjust) / 255.0, 0.0);
-
- v_data0 = vec4(tex.x, tex.y, fade_tex.x, fade_tex.y);
- v_data1 = vec2(gamma_scale, size);
+ vec2 fade_opacity = unpack_opacity(a_fade_opacity);
+ float fade_change = fade_opacity[1] > 0.5 ? u_fade_change : -u_fade_change;
+ float interpolated_fade_opacity = max(0.0, min(1.0, fade_opacity[0] + fade_change));
+
+ v_data0 = vec2(tex.x, tex.y);
+ v_data1 = vec3(gamma_scale, size, interpolated_fade_opacity);
}
)MBGL_SHADER";
@@ -255,12 +235,11 @@ uniform lowp float u_halo_blur;
uniform sampler2D u_texture;
-uniform sampler2D u_fadetexture;
uniform highp float u_gamma_scale;
uniform bool u_is_text;
-varying vec4 v_data0;
-varying vec2 v_data1;
+varying vec2 v_data0;
+varying vec3 v_data1;
void main() {
@@ -290,9 +269,9 @@ void main() {
vec2 tex = v_data0.xy;
- vec2 fade_tex = v_data0.zw;
float gamma_scale = v_data1.x;
float size = v_data1.y;
+ float fade_opacity = v_data1[2];
float fontScale = u_is_text ? size / 24.0 : size;
@@ -306,11 +285,10 @@ void main() {
}
lowp float dist = texture2D(u_texture, tex).a;
- lowp float fade_alpha = texture2D(u_fadetexture, fade_tex).a;
highp float gamma_scaled = gamma * gamma_scale;
- highp float alpha = smoothstep(buff - gamma_scaled, buff + gamma_scaled, dist) * fade_alpha;
+ highp float alpha = smoothstep(buff - gamma_scaled, buff + gamma_scaled, dist);
- gl_FragColor = color * (alpha * opacity);
+ gl_FragColor = color * (alpha * opacity * fade_opacity);
#ifdef OVERDRAW_INSPECTOR
gl_FragColor = vec4(1.0);
diff --git a/src/mbgl/style/conversion/constant.cpp b/src/mbgl/style/conversion/constant.cpp
new file mode 100644
index 0000000000..e837c4e70b
--- /dev/null
+++ b/src/mbgl/style/conversion/constant.cpp
@@ -0,0 +1,94 @@
+#include <mbgl/style/conversion/constant.hpp>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+optional<bool> Converter<bool>::operator()(const Convertible& value, Error& error) const {
+ optional<bool> converted = toBool(value);
+ if (!converted) {
+ error = { "value must be a boolean" };
+ return {};
+ }
+ return *converted;
+}
+
+optional<float> Converter<float>::operator()(const Convertible& value, Error& error) const {
+ optional<float> converted = toNumber(value);
+ if (!converted) {
+ error = { "value must be a number" };
+ return {};
+ }
+ return *converted;
+}
+
+optional<std::string> Converter<std::string>::operator()(const Convertible& value, Error& error) const {
+ optional<std::string> converted = toString(value);
+ if (!converted) {
+ error = { "value must be a string" };
+ return {};
+ }
+ return *converted;
+}
+
+optional<Color> Converter<Color>::operator()(const Convertible& value, Error& error) const {
+ optional<std::string> string = toString(value);
+ if (!string) {
+ error = { "value must be a string" };
+ return {};
+ }
+
+ optional<Color> color = Color::parse(*string);
+ if (!color) {
+ error = { "value must be a valid color" };
+ return {};
+ }
+
+ return *color;
+}
+
+optional<std::vector<float>> Converter<std::vector<float>>::operator()(const Convertible& value, Error& error) const {
+ if (!isArray(value)) {
+ error = { "value must be an array" };
+ return {};
+ }
+
+ std::vector<float> result;
+ result.reserve(arrayLength(value));
+
+ for (std::size_t i = 0; i < arrayLength(value); ++i) {
+ optional<float> number = toNumber(arrayMember(value, i));
+ if (!number) {
+ error = { "value must be an array of numbers" };
+ return {};
+ }
+ result.push_back(*number);
+ }
+
+ return result;
+}
+
+optional<std::vector<std::string>> Converter<std::vector<std::string>>::operator()(const Convertible& value, Error& error) const {
+ if (!isArray(value)) {
+ error = { "value must be an array" };
+ return {};
+ }
+
+ std::vector<std::string> result;
+ result.reserve(arrayLength(value));
+
+ for (std::size_t i = 0; i < arrayLength(value); ++i) {
+ optional<std::string> string = toString(arrayMember(value, i));
+ if (!string) {
+ error = { "value must be an array of strings" };
+ return {};
+ }
+ result.push_back(*string);
+ }
+
+ return result;
+}
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/conversion/coordinate.cpp b/src/mbgl/style/conversion/coordinate.cpp
new file mode 100644
index 0000000000..9b2be3381e
--- /dev/null
+++ b/src/mbgl/style/conversion/coordinate.cpp
@@ -0,0 +1,29 @@
+#include <mbgl/style/conversion/coordinate.hpp>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+optional<LatLng> Converter<LatLng>::operator() (const Convertible& value, Error& error) const {
+ if (!isArray(value) || arrayLength(value) < 2 ) {
+ error = { "coordinate array must contain numeric longitude and latitude values" };
+ return {};
+ }
+ //Style spec uses GeoJSON convention for specifying coordinates
+ optional<double> latitude = toDouble(arrayMember(value, 1));
+ optional<double> longitude = toDouble(arrayMember(value, 0));
+
+ if (!latitude || !longitude) {
+ error = { "coordinate array must contain numeric longitude and latitude values" };
+ return {};
+ }
+ if (*latitude < -90 || *latitude > 90 ){
+ error = { "coordinate latitude must be between -90 and 90" };
+ return {};
+ }
+ return LatLng(*latitude, *longitude);
+}
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/conversion/filter.cpp b/src/mbgl/style/conversion/filter.cpp
new file mode 100644
index 0000000000..bb7bb6ea98
--- /dev/null
+++ b/src/mbgl/style/conversion/filter.cpp
@@ -0,0 +1,248 @@
+#include <mbgl/style/conversion/filter.hpp>
+#include <mbgl/util/geometry.hpp>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+static optional<Value> normalizeValue(const optional<Value>& value, Error& error) {
+ if (!value) {
+ error = { "filter expression value must be a boolean, number, or string" };
+ return {};
+ } else {
+ return *value;
+ }
+}
+
+static optional<FeatureType> toFeatureType(const Convertible& value, Error& error) {
+ optional<std::string> type = toString(value);
+ if (!type) {
+ error = { "value for $type filter must be a string" };
+ return {};
+ } else if (*type == "Point") {
+ return FeatureType::Point;
+ } else if (*type == "LineString") {
+ return FeatureType::LineString;
+ } else if (*type == "Polygon") {
+ return FeatureType::Polygon;
+ } else {
+ error = { "value for $type filter must be Point, LineString, or Polygon" };
+ return {};
+ }
+}
+
+static optional<FeatureIdentifier> toFeatureIdentifier(const Convertible& value, Error& error) {
+ optional<Value> identifier = toValue(value);
+ if (!identifier) {
+ error = { "filter expression value must be a boolean, number, or string" };
+ return {};
+ } else {
+ return (*identifier).match(
+ [] (uint64_t t) -> optional<FeatureIdentifier> { return { t }; },
+ [] ( int64_t t) -> optional<FeatureIdentifier> { return { t }; },
+ [] ( double t) -> optional<FeatureIdentifier> { return { t }; },
+ [] (const std::string& t) -> optional<FeatureIdentifier> { return { t }; },
+ [&] (const auto&) -> optional<FeatureIdentifier> {
+ error = { "filter expression value must be a boolean, number, or string" };
+ return {};
+ });
+ }
+}
+
+template <class FilterType, class IdentifierFilterType>
+optional<Filter> convertUnaryFilter(const Convertible& value, Error& error) {
+ if (arrayLength(value) < 2) {
+ error = { "filter expression must have 2 elements" };
+ return {};
+ }
+
+ optional<std::string> key = toString(arrayMember(value, 1));
+ if (!key) {
+ error = { "filter expression key must be a string" };
+ return {};
+ }
+
+ if (*key == "$id") {
+ return { IdentifierFilterType {} };
+ } else {
+ return { FilterType { *key } };
+ }
+}
+
+template <class FilterType, class TypeFilterType, class IdentifierFilterType>
+optional<Filter> convertEqualityFilter(const Convertible& value, Error& error) {
+ if (arrayLength(value) < 3) {
+ error = { "filter expression must have 3 elements" };
+ return {};
+ }
+
+ optional<std::string> key = toString(arrayMember(value, 1));
+ if (!key) {
+ error = { "filter expression key must be a string" };
+ return {};
+ }
+
+ if (*key == "$type") {
+ optional<FeatureType> filterValue = toFeatureType(arrayMember(value, 2), error);
+ if (!filterValue) {
+ return {};
+ }
+
+ return { TypeFilterType { *filterValue } };
+
+ } else if (*key == "$id") {
+ optional<FeatureIdentifier> filterValue = toFeatureIdentifier(arrayMember(value, 2), error);
+ if (!filterValue) {
+ return {};
+ }
+
+ return { IdentifierFilterType { *filterValue } };
+
+ } else {
+ optional<Value> filterValue = normalizeValue(toValue(arrayMember(value, 2)), error);
+ if (!filterValue) {
+ return {};
+ }
+
+ return { FilterType { *key, *filterValue } };
+ }
+}
+
+template <class FilterType>
+optional<Filter> convertBinaryFilter(const Convertible& value, Error& error) {
+ if (arrayLength(value) < 3) {
+ error = { "filter expression must have 3 elements" };
+ return {};
+ }
+
+ optional<std::string> key = toString(arrayMember(value, 1));
+ if (!key) {
+ error = { "filter expression key must be a string" };
+ return {};
+ }
+
+ optional<Value> filterValue = normalizeValue(toValue(arrayMember(value, 2)), error);
+ if (!filterValue) {
+ return {};
+ }
+
+ return { FilterType { *key, *filterValue } };
+}
+
+template <class FilterType, class TypeFilterType, class IdentifierFilterType>
+optional<Filter> convertSetFilter(const Convertible& value, Error& error) {
+ if (arrayLength(value) < 2) {
+ error = { "filter expression must at least 2 elements" };
+ return {};
+ }
+
+ optional<std::string> key = toString(arrayMember(value, 1));
+ if (!key) {
+ error = { "filter expression key must be a string" };
+ return {};
+ }
+
+ if (*key == "$type") {
+ std::vector<FeatureType> values;
+ for (std::size_t i = 2; i < arrayLength(value); ++i) {
+ optional<FeatureType> filterValue = toFeatureType(arrayMember(value, i), error);
+ if (!filterValue) {
+ return {};
+ }
+ values.push_back(*filterValue);
+ }
+
+ return { TypeFilterType { std::move(values) } };
+
+ } else if (*key == "$id") {
+ std::vector<FeatureIdentifier> values;
+ for (std::size_t i = 2; i < arrayLength(value); ++i) {
+ optional<FeatureIdentifier> filterValue = toFeatureIdentifier(arrayMember(value, i), error);
+ if (!filterValue) {
+ return {};
+ }
+ values.push_back(*filterValue);
+ }
+
+ return { IdentifierFilterType { std::move(values) } };
+
+ } else {
+ std::vector<Value> values;
+ for (std::size_t i = 2; i < arrayLength(value); ++i) {
+ optional<Value> filterValue = normalizeValue(toValue(arrayMember(value, i)), error);
+ if (!filterValue) {
+ return {};
+ }
+ values.push_back(*filterValue);
+ }
+
+ return { FilterType { *key, std::move(values) } };
+ }
+}
+
+template <class FilterType>
+optional<Filter> convertCompoundFilter(const Convertible& value, Error& error) {
+ std::vector<Filter> filters;
+ for (std::size_t i = 1; i < arrayLength(value); ++i) {
+ optional<Filter> element = convert<Filter>(arrayMember(value, i), error);
+ if (!element) {
+ return {};
+ }
+ filters.push_back(*element);
+ }
+
+ return { FilterType { std::move(filters) } };
+}
+
+optional<Filter> Converter<Filter>::operator()(const Convertible& value, Error& error) const {
+ if (!isArray(value)) {
+ error = { "filter expression must be an array" };
+ return {};
+ }
+
+ if (arrayLength(value) < 1) {
+ error = { "filter expression must have at least 1 element" };
+ return {};
+ }
+
+ optional<std::string> op = toString(arrayMember(value, 0));
+ if (!op) {
+ error = { "filter operator must be a string" };
+ return {};
+ }
+
+ if (*op == "==") {
+ return convertEqualityFilter<EqualsFilter, TypeEqualsFilter, IdentifierEqualsFilter>(value, error);
+ } else if (*op == "!=") {
+ return convertEqualityFilter<NotEqualsFilter, TypeNotEqualsFilter, IdentifierNotEqualsFilter>(value, error);
+ } else if (*op == ">") {
+ return convertBinaryFilter<GreaterThanFilter>(value, error);
+ } else if (*op == ">=") {
+ return convertBinaryFilter<GreaterThanEqualsFilter>(value, error);
+ } else if (*op == "<") {
+ return convertBinaryFilter<LessThanFilter>(value, error);
+ } else if (*op == "<=") {
+ return convertBinaryFilter<LessThanEqualsFilter>(value, error);
+ } else if (*op == "in") {
+ return convertSetFilter<InFilter, TypeInFilter, IdentifierInFilter>(value, error);
+ } else if (*op == "!in") {
+ return convertSetFilter<NotInFilter, TypeNotInFilter, IdentifierNotInFilter>(value, error);
+ } else if (*op == "all") {
+ return convertCompoundFilter<AllFilter>(value, error);
+ } else if (*op == "any") {
+ return convertCompoundFilter<AnyFilter>(value, error);
+ } else if (*op == "none") {
+ return convertCompoundFilter<NoneFilter>(value, error);
+ } else if (*op == "has") {
+ return convertUnaryFilter<HasFilter, HasIdentifierFilter>(value, error);
+ } else if (*op == "!has") {
+ return convertUnaryFilter<NotHasFilter, NotHasIdentifierFilter>(value, error);
+ }
+
+ error = { R"(filter operator must be one of "==", "!=", ">", ">=", "<", "<=", "in", "!in", "all", "any", "none", "has", or "!has")" };
+ return {};
+}
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/conversion/geojson.cpp b/src/mbgl/style/conversion/geojson.cpp
index 8103e9014a..e39a1a80eb 100644
--- a/src/mbgl/style/conversion/geojson.cpp
+++ b/src/mbgl/style/conversion/geojson.cpp
@@ -1,26 +1,16 @@
#include <mbgl/style/conversion/geojson.hpp>
#include <mbgl/style/conversion/json.hpp>
-#include <mbgl/util/rapidjson.hpp>
-
-#include <mapbox/geojson.hpp>
-#include <mapbox/geojson/rapidjson.hpp>
namespace mbgl {
namespace style {
namespace conversion {
-optional<GeoJSON> Converter<GeoJSON>::operator()(const std::string& value, Error& error) const {
- return convertJSON<GeoJSON>(value, error);
+optional<GeoJSON> Converter<GeoJSON>::operator()(const Convertible& value, Error& error) const {
+ return toGeoJSON(value, error);
}
-template <>
-optional<GeoJSON> Converter<GeoJSON>::operator()(const JSValue& value, Error& error) const {
- try {
- return mapbox::geojson::convert(value);
- } catch (const std::exception& ex) {
- error = { ex.what() };
- return {};
- }
+optional<GeoJSON> parseGeoJSON(const std::string& value, Error& error) {
+ return convertJSON<GeoJSON>(value, error);
}
} // namespace conversion
diff --git a/src/mbgl/style/conversion/geojson_options.cpp b/src/mbgl/style/conversion/geojson_options.cpp
new file mode 100644
index 0000000000..a2c5ed8816
--- /dev/null
+++ b/src/mbgl/style/conversion/geojson_options.cpp
@@ -0,0 +1,85 @@
+#include <mbgl/style/conversion/geojson_options.hpp>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+optional<GeoJSONOptions> Converter<GeoJSONOptions>::operator()(const Convertible& value, Error& error) const {
+ GeoJSONOptions options;
+
+ const auto minzoomValue = objectMember(value, "minzoom");
+ if (minzoomValue) {
+ if (toNumber(*minzoomValue)) {
+ options.minzoom = static_cast<uint8_t>(*toNumber(*minzoomValue));
+ } else {
+ error = { "GeoJSON source minzoom value must be a number" };
+ return {};
+ }
+ }
+
+ const auto maxzoomValue = objectMember(value, "maxzoom");
+ if (maxzoomValue) {
+ if (toNumber(*maxzoomValue)) {
+ options.maxzoom = static_cast<uint8_t>(*toNumber(*maxzoomValue));
+ } else {
+ error = { "GeoJSON source maxzoom value must be a number" };
+ return {};
+ }
+ }
+
+ const auto bufferValue = objectMember(value, "buffer");
+ if (bufferValue) {
+ if (toNumber(*bufferValue)) {
+ options.buffer = static_cast<uint16_t>(*toNumber(*bufferValue));
+ } else {
+ error = { "GeoJSON source buffer value must be a number" };
+ return {};
+ }
+ }
+
+ const auto toleranceValue = objectMember(value, "tolerance");
+ if (toleranceValue) {
+ if (toNumber(*toleranceValue)) {
+ options.tolerance = static_cast<double>(*toNumber(*toleranceValue));
+ } else {
+ error = { "GeoJSON source tolerance value must be a number" };
+ return {};
+ }
+ }
+
+ const auto clusterValue = objectMember(value, "cluster");
+ if (clusterValue) {
+ if (toBool(*clusterValue)) {
+ options.cluster = *toBool(*clusterValue);
+ } else {
+ error = { "GeoJSON source cluster value must be a boolean" };
+ return {};
+ }
+ }
+
+ const auto clusterMaxZoomValue = objectMember(value, "clusterMaxZoom");
+ if (clusterMaxZoomValue) {
+ if (toNumber(*clusterMaxZoomValue)) {
+ options.clusterMaxZoom = static_cast<uint8_t>(*toNumber(*clusterMaxZoomValue));
+ } else {
+ error = { "GeoJSON source clusterMaxZoom value must be a number" };
+ return {};
+ }
+ }
+
+ const auto clusterRadiusValue = objectMember(value, "clusterRadius");
+ if (clusterRadiusValue) {
+ if (toNumber(*clusterRadiusValue)) {
+ options.clusterRadius = static_cast<double>(*toNumber(*clusterRadiusValue));
+ } else {
+ error = { "GeoJSON source clusterRadius value must be a number" };
+ return {};
+ }
+ }
+
+ return { options };
+}
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/conversion/get_json_type.cpp b/src/mbgl/style/conversion/get_json_type.cpp
new file mode 100644
index 0000000000..cd3b4608b1
--- /dev/null
+++ b/src/mbgl/style/conversion/get_json_type.cpp
@@ -0,0 +1,34 @@
+#include <mbgl/style/conversion/get_json_type.hpp>
+#include <mbgl/util/feature.hpp>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+std::string getJSONType(const Convertible& value) {
+ if (isUndefined(value)) {
+ return "null";
+ }
+ if (isArray(value)) {
+ return "array";
+ }
+ if (isObject(value)) {
+ return "object";
+ }
+ optional<mbgl::Value> v = toValue(value);
+
+ // Since we've already checked the non-atomic types above, value must then
+ // be a string, number, or boolean -- thus, assume that the toValue()
+ // conversion succeeds.
+ assert(v);
+
+ return v->match(
+ [&] (const std::string&) { return "string"; },
+ [&] (bool) { return "boolean"; },
+ [&] (auto) { return "number"; }
+ );
+}
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/conversion/json.hpp b/src/mbgl/style/conversion/json.hpp
index 0817ac09df..7dd2378f6b 100644
--- a/src/mbgl/style/conversion/json.hpp
+++ b/src/mbgl/style/conversion/json.hpp
@@ -20,7 +20,7 @@ optional<T> convertJSON(const std::string& json, Error& error, Args&&...args) {
return {};
}
- return convert<T, JSValue>(document, error, std::forward<Args>(args)...);
+ return convert<T>(document, error, std::forward<Args>(args)...);
}
} // namespace conversion
diff --git a/src/mbgl/style/conversion/layer.cpp b/src/mbgl/style/conversion/layer.cpp
new file mode 100644
index 0000000000..0ca582f8dc
--- /dev/null
+++ b/src/mbgl/style/conversion/layer.cpp
@@ -0,0 +1,206 @@
+#include <mbgl/style/conversion/layer.hpp>
+#include <mbgl/style/conversion/constant.hpp>
+#include <mbgl/style/conversion/filter.hpp>
+#include <mbgl/style/conversion/make_property_setters.hpp>
+#include <mbgl/style/layers/background_layer.hpp>
+#include <mbgl/style/layers/circle_layer.hpp>
+#include <mbgl/style/layers/fill_layer.hpp>
+#include <mbgl/style/layers/fill_extrusion_layer.hpp>
+#include <mbgl/style/layers/line_layer.hpp>
+#include <mbgl/style/layers/raster_layer.hpp>
+#include <mbgl/style/layers/symbol_layer.hpp>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+optional<Error> setLayoutProperty(Layer& layer, const std::string& name, const Convertible& value) {
+ static const auto setters = makeLayoutPropertySetters();
+ auto it = setters.find(name);
+ if (it == setters.end()) {
+ return Error { "property not found" };
+ }
+ return it->second(layer, value);
+}
+
+optional<Error> setPaintProperty(Layer& layer, const std::string& name, const Convertible& value) {
+ static const auto setters = makePaintPropertySetters();
+ auto it = setters.find(name);
+ if (it == setters.end()) {
+ return Error { "property not found" };
+ }
+ return it->second(layer, value);
+}
+
+optional<Error> setPaintProperties(Layer& layer, const Convertible& value) {
+ auto paintValue = objectMember(value, "paint");
+ if (!paintValue) {
+ return {};
+ }
+ return eachMember(*paintValue, [&] (const std::string& k, const Convertible& v) {
+ return setPaintProperty(layer, k, v);
+ });
+}
+
+template <class LayerType>
+optional<std::unique_ptr<Layer>> convertVectorLayer(const std::string& id, const Convertible& value, Error& error) {
+ auto sourceValue = objectMember(value, "source");
+ if (!sourceValue) {
+ error = { "layer must have a source" };
+ return {};
+ }
+
+ optional<std::string> source = toString(*sourceValue);
+ if (!source) {
+ error = { "layer source must be a string" };
+ return {};
+ }
+
+ std::unique_ptr<LayerType> layer = std::make_unique<LayerType>(id, *source);
+
+ auto sourceLayerValue = objectMember(value, "source-layer");
+ if (sourceLayerValue) {
+ optional<std::string> sourceLayer = toString(*sourceLayerValue);
+ if (!sourceLayer) {
+ error = { "layer source-layer must be a string" };
+ return {};
+ }
+ layer->setSourceLayer(*sourceLayer);
+ }
+
+ auto filterValue = objectMember(value, "filter");
+ if (filterValue) {
+ optional<Filter> filter = convert<Filter>(*filterValue, error);
+ if (!filter) {
+ return {};
+ }
+ layer->setFilter(*filter);
+ }
+
+ return { std::move(layer) };
+}
+
+static optional<std::unique_ptr<Layer>> convertRasterLayer(const std::string& id, const Convertible& value, Error& error) {
+ auto sourceValue = objectMember(value, "source");
+ if (!sourceValue) {
+ error = { "layer must have a source" };
+ return {};
+ }
+
+ optional<std::string> source = toString(*sourceValue);
+ if (!source) {
+ error = { "layer source must be a string" };
+ return {};
+ }
+
+ return { std::make_unique<RasterLayer>(id, *source) };
+}
+
+static optional<std::unique_ptr<Layer>> convertBackgroundLayer(const std::string& id, const Convertible&, Error&) {
+ return { std::make_unique<BackgroundLayer>(id) };
+}
+
+optional<std::unique_ptr<Layer>> Converter<std::unique_ptr<Layer>>::operator()(const Convertible& value, Error& error) const {
+ if (!isObject(value)) {
+ error = { "layer must be an object" };
+ return {};
+ }
+
+ auto idValue = objectMember(value, "id");
+ if (!idValue) {
+ error = { "layer must have an id" };
+ return {};
+ }
+
+ optional<std::string> id = toString(*idValue);
+ if (!id) {
+ error = { "layer id must be a string" };
+ return {};
+ }
+
+ auto typeValue = objectMember(value, "type");
+ if (!typeValue) {
+ error = { "layer must have a type" };
+ return {};
+ }
+
+ optional<std::string> type = toString(*typeValue);
+ if (!type) {
+ error = { "layer type must be a string" };
+ return {};
+ }
+
+ optional<std::unique_ptr<Layer>> converted;
+
+ if (*type == "fill") {
+ converted = convertVectorLayer<FillLayer>(*id, value, error);
+ } else if (*type == "fill-extrusion") {
+ converted = convertVectorLayer<FillExtrusionLayer>(*id, value, error);
+ } else if (*type == "line") {
+ converted = convertVectorLayer<LineLayer>(*id, value, error);
+ } else if (*type == "circle") {
+ converted = convertVectorLayer<CircleLayer>(*id, value, error);
+ } else if (*type == "symbol") {
+ converted = convertVectorLayer<SymbolLayer>(*id, value, error);
+ } else if (*type == "raster") {
+ converted = convertRasterLayer(*id, value, error);
+ } else if (*type == "background") {
+ converted = convertBackgroundLayer(*id, value, error);
+ } else {
+ error = { "invalid layer type" };
+ return {};
+ }
+
+ if (!converted) {
+ return converted;
+ }
+
+ std::unique_ptr<Layer> layer = std::move(*converted);
+
+ auto minzoomValue = objectMember(value, "minzoom");
+ if (minzoomValue) {
+ optional<float> minzoom = toNumber(*minzoomValue);
+ if (!minzoom) {
+ error = { "minzoom must be numeric" };
+ return {};
+ }
+ layer->setMinZoom(*minzoom);
+ }
+
+ auto maxzoomValue = objectMember(value, "maxzoom");
+ if (maxzoomValue) {
+ optional<float> maxzoom = toNumber(*maxzoomValue);
+ if (!maxzoom) {
+ error = { "maxzoom must be numeric" };
+ return {};
+ }
+ layer->setMaxZoom(*maxzoom);
+ }
+
+ auto layoutValue = objectMember(value, "layout");
+ if (layoutValue) {
+ if (!isObject(*layoutValue)) {
+ error = { "layout must be an object" };
+ return {};
+ }
+ optional<Error> error_ = eachMember(*layoutValue, [&] (const std::string& k, const Convertible& v) {
+ return setLayoutProperty(*layer, k, v);
+ });
+ if (error_) {
+ error = *error_;
+ return {};
+ }
+ }
+
+ optional<Error> error_ = setPaintProperties(*layer, value);
+ if (error_) {
+ error = *error_;
+ return {};
+ }
+
+ return std::move(layer);
+}
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/conversion/light.cpp b/src/mbgl/style/conversion/light.cpp
new file mode 100644
index 0000000000..f521f74386
--- /dev/null
+++ b/src/mbgl/style/conversion/light.cpp
@@ -0,0 +1,115 @@
+#include <mbgl/style/conversion/light.hpp>
+#include <mbgl/style/conversion/position.hpp>
+#include <mbgl/style/conversion/property_value.hpp>
+#include <mbgl/style/conversion/transition_options.hpp>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+optional<Light> Converter<Light>::operator()(const Convertible& value, Error& error) const {
+ if (!isObject(value)) {
+ error = { "light must be an object" };
+ return {};
+ }
+
+ Light light;
+
+ const auto anchor = objectMember(value, "anchor");
+ if (anchor) {
+ optional<PropertyValue<LightAnchorType>> convertedAnchor =
+ convert<PropertyValue<LightAnchorType>>(*anchor, error);
+
+ if (convertedAnchor) {
+ light.setAnchor(*convertedAnchor);
+ } else {
+ return {};
+ }
+ }
+
+ const auto anchorTransition = objectMember(value, "anchor-transition");
+ if (anchorTransition) {
+ optional<TransitionOptions> transition =
+ convert<TransitionOptions>(*anchorTransition, error);
+ if (transition) {
+ light.setAnchorTransition(*transition);
+ } else {
+ return {};
+ }
+ }
+
+ const auto color = objectMember(value, "color");
+ if (color) {
+ optional<PropertyValue<Color>> convertedColor =
+ convert<PropertyValue<Color>>(*color, error);
+
+ if (convertedColor) {
+ light.setColor(*convertedColor);
+ } else {
+ return {};
+ }
+ }
+
+ const auto colorTransition = objectMember(value, "color-transition");
+ if (colorTransition) {
+ optional<TransitionOptions> transition =
+ convert<TransitionOptions>(*colorTransition, error);
+ if (transition) {
+ light.setColorTransition(*transition);
+ } else {
+ return {};
+ }
+ }
+
+ const auto position = objectMember(value, "position");
+ if (position) {
+ optional<PropertyValue<Position>> convertedPosition =
+ convert<PropertyValue<Position>>(*position, error);
+
+ if (convertedPosition) {
+ light.setPosition(*convertedPosition);
+ } else {
+ return {};
+ }
+ }
+
+ const auto positionTransition = objectMember(value, "position-transition");
+ if (positionTransition) {
+ optional<TransitionOptions> transition =
+ convert<TransitionOptions>(*positionTransition, error);
+ if (transition) {
+ light.setPositionTransition(*transition);
+ } else {
+ return {};
+ }
+ }
+
+ const auto intensity = objectMember(value, "intensity");
+ if (intensity) {
+ optional<PropertyValue<float>> convertedIntensity =
+ convert<PropertyValue<float>>(*intensity, error);
+
+ if (convertedIntensity) {
+ light.setIntensity(*convertedIntensity);
+ } else {
+ return {};
+ }
+ }
+
+ const auto intensityTransition = objectMember(value, "intensity-transition");
+ if (intensityTransition) {
+ optional<TransitionOptions> transition =
+ convert<TransitionOptions>(*intensityTransition, error);
+ if (transition) {
+ light.setIntensityTransition(*transition);
+ } else {
+ return {};
+ }
+ }
+
+ return { std::move(light) };
+}
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/conversion/make_property_setters.hpp b/src/mbgl/style/conversion/make_property_setters.hpp
new file mode 100644
index 0000000000..074d7eb730
--- /dev/null
+++ b/src/mbgl/style/conversion/make_property_setters.hpp
@@ -0,0 +1,209 @@
+#pragma once
+
+// This file is generated. Edit make_property_setters.hpp.ejs, then run `make style-code`.
+
+#include <mbgl/style/conversion/property_setter.hpp>
+
+#include <mbgl/style/layers/fill_layer.hpp>
+#include <mbgl/style/layers/line_layer.hpp>
+#include <mbgl/style/layers/symbol_layer.hpp>
+#include <mbgl/style/layers/circle_layer.hpp>
+#include <mbgl/style/layers/fill_extrusion_layer.hpp>
+#include <mbgl/style/layers/raster_layer.hpp>
+#include <mbgl/style/layers/background_layer.hpp>
+
+#include <unordered_map>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+inline auto makeLayoutPropertySetters() {
+ std::unordered_map<std::string, PropertySetter> result;
+
+ result["visibility"] = &setVisibility;
+
+
+ result["line-cap"] = &setProperty<LineLayer, PropertyValue<LineCapType>, &LineLayer::setLineCap>;
+ result["line-join"] = &setProperty<LineLayer, DataDrivenPropertyValue<LineJoinType>, &LineLayer::setLineJoin>;
+ result["line-miter-limit"] = &setProperty<LineLayer, PropertyValue<float>, &LineLayer::setLineMiterLimit>;
+ result["line-round-limit"] = &setProperty<LineLayer, PropertyValue<float>, &LineLayer::setLineRoundLimit>;
+
+ result["symbol-placement"] = &setProperty<SymbolLayer, PropertyValue<SymbolPlacementType>, &SymbolLayer::setSymbolPlacement>;
+ result["symbol-spacing"] = &setProperty<SymbolLayer, PropertyValue<float>, &SymbolLayer::setSymbolSpacing>;
+ result["symbol-avoid-edges"] = &setProperty<SymbolLayer, PropertyValue<bool>, &SymbolLayer::setSymbolAvoidEdges>;
+ result["icon-allow-overlap"] = &setProperty<SymbolLayer, PropertyValue<bool>, &SymbolLayer::setIconAllowOverlap>;
+ result["icon-ignore-placement"] = &setProperty<SymbolLayer, PropertyValue<bool>, &SymbolLayer::setIconIgnorePlacement>;
+ result["icon-optional"] = &setProperty<SymbolLayer, PropertyValue<bool>, &SymbolLayer::setIconOptional>;
+ result["icon-rotation-alignment"] = &setProperty<SymbolLayer, PropertyValue<AlignmentType>, &SymbolLayer::setIconRotationAlignment>;
+ result["icon-size"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconSize>;
+ result["icon-text-fit"] = &setProperty<SymbolLayer, PropertyValue<IconTextFitType>, &SymbolLayer::setIconTextFit>;
+ result["icon-text-fit-padding"] = &setProperty<SymbolLayer, PropertyValue<std::array<float, 4>>, &SymbolLayer::setIconTextFitPadding>;
+ result["icon-image"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<std::string>, &SymbolLayer::setIconImage>;
+ result["icon-rotate"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconRotate>;
+ result["icon-padding"] = &setProperty<SymbolLayer, PropertyValue<float>, &SymbolLayer::setIconPadding>;
+ result["icon-keep-upright"] = &setProperty<SymbolLayer, PropertyValue<bool>, &SymbolLayer::setIconKeepUpright>;
+ result["icon-offset"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<std::array<float, 2>>, &SymbolLayer::setIconOffset>;
+ result["icon-anchor"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<SymbolAnchorType>, &SymbolLayer::setIconAnchor>;
+ result["icon-pitch-alignment"] = &setProperty<SymbolLayer, PropertyValue<AlignmentType>, &SymbolLayer::setIconPitchAlignment>;
+ result["text-pitch-alignment"] = &setProperty<SymbolLayer, PropertyValue<AlignmentType>, &SymbolLayer::setTextPitchAlignment>;
+ result["text-rotation-alignment"] = &setProperty<SymbolLayer, PropertyValue<AlignmentType>, &SymbolLayer::setTextRotationAlignment>;
+ result["text-field"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<std::string>, &SymbolLayer::setTextField>;
+ result["text-font"] = &setProperty<SymbolLayer, PropertyValue<std::vector<std::string>>, &SymbolLayer::setTextFont>;
+ result["text-size"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextSize>;
+ result["text-max-width"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextMaxWidth>;
+ result["text-line-height"] = &setProperty<SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextLineHeight>;
+ result["text-letter-spacing"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextLetterSpacing>;
+ result["text-justify"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<TextJustifyType>, &SymbolLayer::setTextJustify>;
+ result["text-anchor"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<SymbolAnchorType>, &SymbolLayer::setTextAnchor>;
+ result["text-max-angle"] = &setProperty<SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextMaxAngle>;
+ result["text-rotate"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextRotate>;
+ result["text-padding"] = &setProperty<SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextPadding>;
+ result["text-keep-upright"] = &setProperty<SymbolLayer, PropertyValue<bool>, &SymbolLayer::setTextKeepUpright>;
+ result["text-transform"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<TextTransformType>, &SymbolLayer::setTextTransform>;
+ result["text-offset"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<std::array<float, 2>>, &SymbolLayer::setTextOffset>;
+ result["text-allow-overlap"] = &setProperty<SymbolLayer, PropertyValue<bool>, &SymbolLayer::setTextAllowOverlap>;
+ result["text-ignore-placement"] = &setProperty<SymbolLayer, PropertyValue<bool>, &SymbolLayer::setTextIgnorePlacement>;
+ result["text-optional"] = &setProperty<SymbolLayer, PropertyValue<bool>, &SymbolLayer::setTextOptional>;
+
+
+
+
+
+ return result;
+}
+
+inline auto makePaintPropertySetters() {
+ std::unordered_map<std::string, PropertySetter> result;
+
+ result["fill-antialias"] = &setProperty<FillLayer, PropertyValue<bool>, &FillLayer::setFillAntialias>;
+ result["fill-antialias-transition"] = &setTransition<FillLayer, &FillLayer::setFillAntialiasTransition>;
+ result["fill-opacity"] = &setProperty<FillLayer, DataDrivenPropertyValue<float>, &FillLayer::setFillOpacity>;
+ result["fill-opacity-transition"] = &setTransition<FillLayer, &FillLayer::setFillOpacityTransition>;
+ result["fill-color"] = &setProperty<FillLayer, DataDrivenPropertyValue<Color>, &FillLayer::setFillColor>;
+ result["fill-color-transition"] = &setTransition<FillLayer, &FillLayer::setFillColorTransition>;
+ result["fill-outline-color"] = &setProperty<FillLayer, DataDrivenPropertyValue<Color>, &FillLayer::setFillOutlineColor>;
+ result["fill-outline-color-transition"] = &setTransition<FillLayer, &FillLayer::setFillOutlineColorTransition>;
+ result["fill-translate"] = &setProperty<FillLayer, PropertyValue<std::array<float, 2>>, &FillLayer::setFillTranslate>;
+ result["fill-translate-transition"] = &setTransition<FillLayer, &FillLayer::setFillTranslateTransition>;
+ result["fill-translate-anchor"] = &setProperty<FillLayer, PropertyValue<TranslateAnchorType>, &FillLayer::setFillTranslateAnchor>;
+ result["fill-translate-anchor-transition"] = &setTransition<FillLayer, &FillLayer::setFillTranslateAnchorTransition>;
+ result["fill-pattern"] = &setProperty<FillLayer, PropertyValue<std::string>, &FillLayer::setFillPattern>;
+ result["fill-pattern-transition"] = &setTransition<FillLayer, &FillLayer::setFillPatternTransition>;
+
+ result["line-opacity"] = &setProperty<LineLayer, DataDrivenPropertyValue<float>, &LineLayer::setLineOpacity>;
+ result["line-opacity-transition"] = &setTransition<LineLayer, &LineLayer::setLineOpacityTransition>;
+ result["line-color"] = &setProperty<LineLayer, DataDrivenPropertyValue<Color>, &LineLayer::setLineColor>;
+ result["line-color-transition"] = &setTransition<LineLayer, &LineLayer::setLineColorTransition>;
+ result["line-translate"] = &setProperty<LineLayer, PropertyValue<std::array<float, 2>>, &LineLayer::setLineTranslate>;
+ result["line-translate-transition"] = &setTransition<LineLayer, &LineLayer::setLineTranslateTransition>;
+ result["line-translate-anchor"] = &setProperty<LineLayer, PropertyValue<TranslateAnchorType>, &LineLayer::setLineTranslateAnchor>;
+ result["line-translate-anchor-transition"] = &setTransition<LineLayer, &LineLayer::setLineTranslateAnchorTransition>;
+ result["line-width"] = &setProperty<LineLayer, DataDrivenPropertyValue<float>, &LineLayer::setLineWidth>;
+ result["line-width-transition"] = &setTransition<LineLayer, &LineLayer::setLineWidthTransition>;
+ result["line-gap-width"] = &setProperty<LineLayer, DataDrivenPropertyValue<float>, &LineLayer::setLineGapWidth>;
+ result["line-gap-width-transition"] = &setTransition<LineLayer, &LineLayer::setLineGapWidthTransition>;
+ result["line-offset"] = &setProperty<LineLayer, DataDrivenPropertyValue<float>, &LineLayer::setLineOffset>;
+ result["line-offset-transition"] = &setTransition<LineLayer, &LineLayer::setLineOffsetTransition>;
+ result["line-blur"] = &setProperty<LineLayer, DataDrivenPropertyValue<float>, &LineLayer::setLineBlur>;
+ result["line-blur-transition"] = &setTransition<LineLayer, &LineLayer::setLineBlurTransition>;
+ result["line-dasharray"] = &setProperty<LineLayer, PropertyValue<std::vector<float>>, &LineLayer::setLineDasharray>;
+ result["line-dasharray-transition"] = &setTransition<LineLayer, &LineLayer::setLineDasharrayTransition>;
+ result["line-pattern"] = &setProperty<LineLayer, PropertyValue<std::string>, &LineLayer::setLinePattern>;
+ result["line-pattern-transition"] = &setTransition<LineLayer, &LineLayer::setLinePatternTransition>;
+
+ result["icon-opacity"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconOpacity>;
+ result["icon-opacity-transition"] = &setTransition<SymbolLayer, &SymbolLayer::setIconOpacityTransition>;
+ result["icon-color"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<Color>, &SymbolLayer::setIconColor>;
+ result["icon-color-transition"] = &setTransition<SymbolLayer, &SymbolLayer::setIconColorTransition>;
+ result["icon-halo-color"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<Color>, &SymbolLayer::setIconHaloColor>;
+ result["icon-halo-color-transition"] = &setTransition<SymbolLayer, &SymbolLayer::setIconHaloColorTransition>;
+ result["icon-halo-width"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconHaloWidth>;
+ result["icon-halo-width-transition"] = &setTransition<SymbolLayer, &SymbolLayer::setIconHaloWidthTransition>;
+ result["icon-halo-blur"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconHaloBlur>;
+ result["icon-halo-blur-transition"] = &setTransition<SymbolLayer, &SymbolLayer::setIconHaloBlurTransition>;
+ result["icon-translate"] = &setProperty<SymbolLayer, PropertyValue<std::array<float, 2>>, &SymbolLayer::setIconTranslate>;
+ result["icon-translate-transition"] = &setTransition<SymbolLayer, &SymbolLayer::setIconTranslateTransition>;
+ result["icon-translate-anchor"] = &setProperty<SymbolLayer, PropertyValue<TranslateAnchorType>, &SymbolLayer::setIconTranslateAnchor>;
+ result["icon-translate-anchor-transition"] = &setTransition<SymbolLayer, &SymbolLayer::setIconTranslateAnchorTransition>;
+ result["text-opacity"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextOpacity>;
+ result["text-opacity-transition"] = &setTransition<SymbolLayer, &SymbolLayer::setTextOpacityTransition>;
+ result["text-color"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<Color>, &SymbolLayer::setTextColor>;
+ result["text-color-transition"] = &setTransition<SymbolLayer, &SymbolLayer::setTextColorTransition>;
+ result["text-halo-color"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<Color>, &SymbolLayer::setTextHaloColor>;
+ result["text-halo-color-transition"] = &setTransition<SymbolLayer, &SymbolLayer::setTextHaloColorTransition>;
+ result["text-halo-width"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextHaloWidth>;
+ result["text-halo-width-transition"] = &setTransition<SymbolLayer, &SymbolLayer::setTextHaloWidthTransition>;
+ result["text-halo-blur"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextHaloBlur>;
+ result["text-halo-blur-transition"] = &setTransition<SymbolLayer, &SymbolLayer::setTextHaloBlurTransition>;
+ result["text-translate"] = &setProperty<SymbolLayer, PropertyValue<std::array<float, 2>>, &SymbolLayer::setTextTranslate>;
+ result["text-translate-transition"] = &setTransition<SymbolLayer, &SymbolLayer::setTextTranslateTransition>;
+ result["text-translate-anchor"] = &setProperty<SymbolLayer, PropertyValue<TranslateAnchorType>, &SymbolLayer::setTextTranslateAnchor>;
+ result["text-translate-anchor-transition"] = &setTransition<SymbolLayer, &SymbolLayer::setTextTranslateAnchorTransition>;
+
+ result["circle-radius"] = &setProperty<CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleRadius>;
+ result["circle-radius-transition"] = &setTransition<CircleLayer, &CircleLayer::setCircleRadiusTransition>;
+ result["circle-color"] = &setProperty<CircleLayer, DataDrivenPropertyValue<Color>, &CircleLayer::setCircleColor>;
+ result["circle-color-transition"] = &setTransition<CircleLayer, &CircleLayer::setCircleColorTransition>;
+ result["circle-blur"] = &setProperty<CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleBlur>;
+ result["circle-blur-transition"] = &setTransition<CircleLayer, &CircleLayer::setCircleBlurTransition>;
+ result["circle-opacity"] = &setProperty<CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleOpacity>;
+ result["circle-opacity-transition"] = &setTransition<CircleLayer, &CircleLayer::setCircleOpacityTransition>;
+ result["circle-translate"] = &setProperty<CircleLayer, PropertyValue<std::array<float, 2>>, &CircleLayer::setCircleTranslate>;
+ result["circle-translate-transition"] = &setTransition<CircleLayer, &CircleLayer::setCircleTranslateTransition>;
+ result["circle-translate-anchor"] = &setProperty<CircleLayer, PropertyValue<TranslateAnchorType>, &CircleLayer::setCircleTranslateAnchor>;
+ result["circle-translate-anchor-transition"] = &setTransition<CircleLayer, &CircleLayer::setCircleTranslateAnchorTransition>;
+ result["circle-pitch-scale"] = &setProperty<CircleLayer, PropertyValue<CirclePitchScaleType>, &CircleLayer::setCirclePitchScale>;
+ result["circle-pitch-scale-transition"] = &setTransition<CircleLayer, &CircleLayer::setCirclePitchScaleTransition>;
+ result["circle-pitch-alignment"] = &setProperty<CircleLayer, PropertyValue<AlignmentType>, &CircleLayer::setCirclePitchAlignment>;
+ result["circle-pitch-alignment-transition"] = &setTransition<CircleLayer, &CircleLayer::setCirclePitchAlignmentTransition>;
+ result["circle-stroke-width"] = &setProperty<CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleStrokeWidth>;
+ result["circle-stroke-width-transition"] = &setTransition<CircleLayer, &CircleLayer::setCircleStrokeWidthTransition>;
+ result["circle-stroke-color"] = &setProperty<CircleLayer, DataDrivenPropertyValue<Color>, &CircleLayer::setCircleStrokeColor>;
+ result["circle-stroke-color-transition"] = &setTransition<CircleLayer, &CircleLayer::setCircleStrokeColorTransition>;
+ result["circle-stroke-opacity"] = &setProperty<CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleStrokeOpacity>;
+ result["circle-stroke-opacity-transition"] = &setTransition<CircleLayer, &CircleLayer::setCircleStrokeOpacityTransition>;
+
+ result["fill-extrusion-opacity"] = &setProperty<FillExtrusionLayer, PropertyValue<float>, &FillExtrusionLayer::setFillExtrusionOpacity>;
+ result["fill-extrusion-opacity-transition"] = &setTransition<FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionOpacityTransition>;
+ result["fill-extrusion-color"] = &setProperty<FillExtrusionLayer, DataDrivenPropertyValue<Color>, &FillExtrusionLayer::setFillExtrusionColor>;
+ result["fill-extrusion-color-transition"] = &setTransition<FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionColorTransition>;
+ result["fill-extrusion-translate"] = &setProperty<FillExtrusionLayer, PropertyValue<std::array<float, 2>>, &FillExtrusionLayer::setFillExtrusionTranslate>;
+ result["fill-extrusion-translate-transition"] = &setTransition<FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionTranslateTransition>;
+ result["fill-extrusion-translate-anchor"] = &setProperty<FillExtrusionLayer, PropertyValue<TranslateAnchorType>, &FillExtrusionLayer::setFillExtrusionTranslateAnchor>;
+ result["fill-extrusion-translate-anchor-transition"] = &setTransition<FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionTranslateAnchorTransition>;
+ result["fill-extrusion-pattern"] = &setProperty<FillExtrusionLayer, PropertyValue<std::string>, &FillExtrusionLayer::setFillExtrusionPattern>;
+ result["fill-extrusion-pattern-transition"] = &setTransition<FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionPatternTransition>;
+ result["fill-extrusion-height"] = &setProperty<FillExtrusionLayer, DataDrivenPropertyValue<float>, &FillExtrusionLayer::setFillExtrusionHeight>;
+ result["fill-extrusion-height-transition"] = &setTransition<FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionHeightTransition>;
+ result["fill-extrusion-base"] = &setProperty<FillExtrusionLayer, DataDrivenPropertyValue<float>, &FillExtrusionLayer::setFillExtrusionBase>;
+ result["fill-extrusion-base-transition"] = &setTransition<FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionBaseTransition>;
+
+ result["raster-opacity"] = &setProperty<RasterLayer, PropertyValue<float>, &RasterLayer::setRasterOpacity>;
+ result["raster-opacity-transition"] = &setTransition<RasterLayer, &RasterLayer::setRasterOpacityTransition>;
+ result["raster-hue-rotate"] = &setProperty<RasterLayer, PropertyValue<float>, &RasterLayer::setRasterHueRotate>;
+ result["raster-hue-rotate-transition"] = &setTransition<RasterLayer, &RasterLayer::setRasterHueRotateTransition>;
+ result["raster-brightness-min"] = &setProperty<RasterLayer, PropertyValue<float>, &RasterLayer::setRasterBrightnessMin>;
+ result["raster-brightness-min-transition"] = &setTransition<RasterLayer, &RasterLayer::setRasterBrightnessMinTransition>;
+ result["raster-brightness-max"] = &setProperty<RasterLayer, PropertyValue<float>, &RasterLayer::setRasterBrightnessMax>;
+ result["raster-brightness-max-transition"] = &setTransition<RasterLayer, &RasterLayer::setRasterBrightnessMaxTransition>;
+ result["raster-saturation"] = &setProperty<RasterLayer, PropertyValue<float>, &RasterLayer::setRasterSaturation>;
+ result["raster-saturation-transition"] = &setTransition<RasterLayer, &RasterLayer::setRasterSaturationTransition>;
+ result["raster-contrast"] = &setProperty<RasterLayer, PropertyValue<float>, &RasterLayer::setRasterContrast>;
+ result["raster-contrast-transition"] = &setTransition<RasterLayer, &RasterLayer::setRasterContrastTransition>;
+ result["raster-fade-duration"] = &setProperty<RasterLayer, PropertyValue<float>, &RasterLayer::setRasterFadeDuration>;
+ result["raster-fade-duration-transition"] = &setTransition<RasterLayer, &RasterLayer::setRasterFadeDurationTransition>;
+
+ result["background-color"] = &setProperty<BackgroundLayer, PropertyValue<Color>, &BackgroundLayer::setBackgroundColor>;
+ result["background-color-transition"] = &setTransition<BackgroundLayer, &BackgroundLayer::setBackgroundColorTransition>;
+ result["background-pattern"] = &setProperty<BackgroundLayer, PropertyValue<std::string>, &BackgroundLayer::setBackgroundPattern>;
+ result["background-pattern-transition"] = &setTransition<BackgroundLayer, &BackgroundLayer::setBackgroundPatternTransition>;
+ result["background-opacity"] = &setProperty<BackgroundLayer, PropertyValue<float>, &BackgroundLayer::setBackgroundOpacity>;
+ result["background-opacity-transition"] = &setTransition<BackgroundLayer, &BackgroundLayer::setBackgroundOpacityTransition>;
+
+ return result;
+}
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/conversion/make_property_setters.hpp.ejs b/src/mbgl/style/conversion/make_property_setters.hpp.ejs
new file mode 100644
index 0000000000..2975cb19f2
--- /dev/null
+++ b/src/mbgl/style/conversion/make_property_setters.hpp.ejs
@@ -0,0 +1,46 @@
+#pragma once
+
+// This file is generated. Edit make_property_setters.hpp.ejs, then run `make style-code`.
+
+#include <mbgl/style/conversion/property_setter.hpp>
+
+<% for (const layer of locals.layers) { -%>
+#include <mbgl/style/layers/<%- layer.type.replace('-', '_') %>_layer.hpp>
+<% } -%>
+
+#include <unordered_map>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+inline auto makeLayoutPropertySetters() {
+ std::unordered_map<std::string, PropertySetter> result;
+
+ result["visibility"] = &setVisibility;
+
+<% for (const layer of locals.layers) { -%>
+<% for (const property of layer.layoutProperties) { -%>
+ result["<%- property.name %>"] = &setProperty<<%- camelize(layer.type) %>Layer, <%- propertyValueType(property) %>, &<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>>;
+<% } -%>
+
+<% } -%>
+ return result;
+}
+
+inline auto makePaintPropertySetters() {
+ std::unordered_map<std::string, PropertySetter> result;
+
+<% for (const layer of locals.layers) { -%>
+<% for (const property of layer.paintProperties) { -%>
+ result["<%- property.name %>"] = &setProperty<<%- camelize(layer.type) %>Layer, <%- propertyValueType(property) %>, &<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>>;
+ result["<%- property.name %>-transition"] = &setTransition<<%- camelize(layer.type) %>Layer, &<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>Transition>;
+<% } -%>
+
+<% } -%>
+ return result;
+}
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/conversion/position.cpp b/src/mbgl/style/conversion/position.cpp
new file mode 100644
index 0000000000..702d250dbf
--- /dev/null
+++ b/src/mbgl/style/conversion/position.cpp
@@ -0,0 +1,22 @@
+#include <mbgl/style/conversion/position.hpp>
+#include <mbgl/style/conversion/constant.hpp>
+
+#include <array>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+optional<Position> Converter<Position>::operator()(const Convertible& value, Error& error) const {
+ optional<std::array<float, 3>> spherical = convert<std::array<float, 3>>(value, error);
+
+ if (!spherical) {
+ return {};
+ }
+
+ return Position(*spherical);
+}
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/conversion/property_setter.hpp b/src/mbgl/style/conversion/property_setter.hpp
index 759c4512cc..9e382b9c38 100644
--- a/include/mbgl/style/conversion/property_setter.hpp
+++ b/src/mbgl/style/conversion/property_setter.hpp
@@ -13,11 +13,10 @@ namespace mbgl {
namespace style {
namespace conversion {
-template <class V>
-using PropertySetter = optional<Error> (*) (Layer&, const V&);
+using PropertySetter = optional<Error> (*) (Layer&, const Convertible&);
-template <class V, class L, class PropertyValue, void (L::*setter)(PropertyValue)>
-optional<Error> setProperty(Layer& layer, const V& value) {
+template <class L, class PropertyValue, void (L::*setter)(PropertyValue)>
+optional<Error> setProperty(Layer& layer, const Convertible& value) {
auto* typedLayer = layer.as<L>();
if (!typedLayer) {
return Error { "layer doesn't support this property" };
@@ -33,8 +32,8 @@ optional<Error> setProperty(Layer& layer, const V& value) {
return {};
}
-template <class V, class L, void (L::*setter)(const TransitionOptions&)>
-optional<Error> setTransition(Layer& layer, const V& value) {
+template <class L, void (L::*setter)(const TransitionOptions&)>
+optional<Error> setTransition(Layer& layer, const Convertible& value) {
auto* typedLayer = layer.as<L>();
if (!typedLayer) {
return Error { "layer doesn't support this property" };
@@ -50,8 +49,7 @@ optional<Error> setTransition(Layer& layer, const V& value) {
return {};
}
-template <class V>
-optional<Error> setVisibility(Layer& layer, const V& value) {
+inline optional<Error> setVisibility(Layer& layer, const Convertible& value) {
if (isUndefined(value)) {
layer.setVisibility(VisibilityType::Visible);
return {};
diff --git a/src/mbgl/style/conversion/source.cpp b/src/mbgl/style/conversion/source.cpp
new file mode 100644
index 0000000000..c10d0babcf
--- /dev/null
+++ b/src/mbgl/style/conversion/source.cpp
@@ -0,0 +1,175 @@
+#include <mbgl/style/conversion/source.hpp>
+#include <mbgl/style/conversion/coordinate.hpp>
+#include <mbgl/style/conversion/geojson.hpp>
+#include <mbgl/style/conversion/geojson_options.hpp>
+#include <mbgl/style/conversion/tileset.hpp>
+#include <mbgl/style/sources/geojson_source.hpp>
+#include <mbgl/style/sources/raster_source.hpp>
+#include <mbgl/style/sources/vector_source.hpp>
+#include <mbgl/style/sources/image_source.hpp>
+#include <mbgl/util/geo.hpp>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+// A tile source can either specify a URL to TileJSON, or inline TileJSON.
+static optional<variant<std::string, Tileset>> convertURLOrTileset(const Convertible& value, Error& error) {
+ auto urlVal = objectMember(value, "url");
+ if (!urlVal) {
+ optional<Tileset> tileset = convert<Tileset>(value, error);
+ if (!tileset) {
+ return {};
+ }
+ return { *tileset };
+ }
+
+ optional<std::string> url = toString(*urlVal);
+ if (!url) {
+ error = { "source url must be a string" };
+ return {};
+ }
+
+ return { *url };
+}
+
+static optional<std::unique_ptr<Source>> convertRasterSource(const std::string& id,
+ const Convertible& value,
+ Error& error) {
+ optional<variant<std::string, Tileset>> urlOrTileset = convertURLOrTileset(value, error);
+ if (!urlOrTileset) {
+ return {};
+ }
+
+ uint16_t tileSize = util::tileSize;
+ auto tileSizeValue = objectMember(value, "tileSize");
+ if (tileSizeValue) {
+ optional<float> size = toNumber(*tileSizeValue);
+ if (!size || *size < 0 || *size > std::numeric_limits<uint16_t>::max()) {
+ error = { "invalid tileSize" };
+ return {};
+ }
+ tileSize = *size;
+ }
+
+ return { std::make_unique<RasterSource>(id, std::move(*urlOrTileset), tileSize) };
+}
+
+static optional<std::unique_ptr<Source>> convertVectorSource(const std::string& id,
+ const Convertible& value,
+ Error& error) {
+ optional<variant<std::string, Tileset>> urlOrTileset = convertURLOrTileset(value, error);
+ if (!urlOrTileset) {
+ return {};
+ }
+
+ return { std::make_unique<VectorSource>(id, std::move(*urlOrTileset)) };
+}
+
+static optional<std::unique_ptr<Source>> convertGeoJSONSource(const std::string& id,
+ const Convertible& value,
+ Error& error) {
+ auto dataValue = objectMember(value, "data");
+ if (!dataValue) {
+ error = { "GeoJSON source must have a data value" };
+ return {};
+ }
+
+ optional<GeoJSONOptions> options = convert<GeoJSONOptions>(value, error);
+ if (!options) {
+ return {};
+ }
+
+ auto result = std::make_unique<GeoJSONSource>(id, *options);
+
+ if (isObject(*dataValue)) {
+ optional<GeoJSON> geoJSON = convert<GeoJSON>(*dataValue, error);
+ if (!geoJSON) {
+ return {};
+ }
+ result->setGeoJSON(std::move(*geoJSON));
+ } else if (toString(*dataValue)) {
+ result->setURL(*toString(*dataValue));
+ } else {
+ error = { "GeoJSON data must be a URL or an object" };
+ return {};
+ }
+
+ return { std::move(result) };
+}
+
+static optional<std::unique_ptr<Source>> convertImageSource(const std::string& id,
+ const Convertible& value,
+ Error& error) {
+ auto urlValue = objectMember(value, "url");
+ if (!urlValue) {
+ error = { "Image source must have a url value" };
+ return {};
+ }
+
+ auto urlString = toString(*urlValue);
+ if (!urlString) {
+ error = { "Image url must be a URL string" };
+ return {};
+ }
+
+ auto coordinatesValue = objectMember(value, "coordinates");
+ if (!coordinatesValue) {
+ error = { "Image source must have a coordinates values" };
+ return {};
+ }
+
+ if (!isArray(*coordinatesValue) || arrayLength(*coordinatesValue) != 4) {
+ error = { "Image coordinates must be an array of four longitude latitude pairs" };
+ return {};
+ }
+
+ std::array<LatLng, 4> coordinates;
+ for (std::size_t i=0; i < 4; i++) {
+ auto latLng = conversion::convert<LatLng>(arrayMember(*coordinatesValue,i), error);
+ if (!latLng) {
+ return {};
+ }
+ coordinates[i] = *latLng;
+ }
+ auto result = std::make_unique<ImageSource>(id, coordinates);
+ result->setURL(*urlString);
+
+ return { std::move(result) };
+}
+
+optional<std::unique_ptr<Source>> Converter<std::unique_ptr<Source>>::operator()(const Convertible& value, Error& error, const std::string& id) const {
+ if (!isObject(value)) {
+ error = { "source must be an object" };
+ return {};
+ }
+
+ auto typeValue = objectMember(value, "type");
+ if (!typeValue) {
+ error = { "source must have a type" };
+ return {};
+ }
+
+ optional<std::string> type = toString(*typeValue);
+ if (!type) {
+ error = { "source type must be a string" };
+ return {};
+ }
+
+ if (*type == "raster") {
+ return convertRasterSource(id, value, error);
+ } else if (*type == "vector") {
+ return convertVectorSource(id, value, error);
+ } else if (*type == "geojson") {
+ return convertGeoJSONSource(id, value, error);
+ } else if (*type == "image") {
+ return convertImageSource(id, value, error);
+ } else {
+ error = { "invalid source type" };
+ return {};
+ }
+}
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/conversion/tileset.cpp b/src/mbgl/style/conversion/tileset.cpp
new file mode 100644
index 0000000000..b9383c41b8
--- /dev/null
+++ b/src/mbgl/style/conversion/tileset.cpp
@@ -0,0 +1,73 @@
+#include <mbgl/style/conversion/tileset.hpp>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+optional<Tileset> Converter<Tileset>::operator()(const Convertible& value, Error& error) const {
+ Tileset result;
+
+ auto tiles = objectMember(value, "tiles");
+ if (!tiles) {
+ error = { "source must have tiles" };
+ return {};
+ }
+
+ if (!isArray(*tiles)) {
+ error = { "source tiles must be an array" };
+ return {};
+ }
+
+ for (std::size_t i = 0; i < arrayLength(*tiles); i++) {
+ optional<std::string> urlTemplate = toString(arrayMember(*tiles, i));
+ if (!urlTemplate) {
+ error = { "source tiles member must be a string" };
+ return {};
+ }
+ result.tiles.push_back(std::move(*urlTemplate));
+ }
+
+ auto schemeValue = objectMember(value, "scheme");
+ if (schemeValue) {
+ optional<std::string> scheme = toString(*schemeValue);
+ if (scheme && *scheme == "tms") {
+ result.scheme = Tileset::Scheme::TMS;
+ }
+ }
+
+ auto minzoomValue = objectMember(value, "minzoom");
+ if (minzoomValue) {
+ optional<float> minzoom = toNumber(*minzoomValue);
+ if (!minzoom || *minzoom < 0 || *minzoom > std::numeric_limits<uint8_t>::max()) {
+ error = { "invalid minzoom" };
+ return {};
+ }
+ result.zoomRange.min = *minzoom;
+ }
+
+ auto maxzoomValue = objectMember(value, "maxzoom");
+ if (maxzoomValue) {
+ optional<float> maxzoom = toNumber(*maxzoomValue);
+ if (!maxzoom || *maxzoom < 0 || *maxzoom > std::numeric_limits<uint8_t>::max()) {
+ error = { "invalid maxzoom" };
+ return {};
+ }
+ result.zoomRange.max = *maxzoom;
+ }
+
+ auto attributionValue = objectMember(value, "attribution");
+ if (attributionValue) {
+ optional<std::string> attribution = toString(*attributionValue);
+ if (!attribution) {
+ error = { "source attribution must be a string" };
+ return {};
+ }
+ result.attribution = std::move(*attribution);
+ }
+
+ return result;
+}
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/conversion/transition_options.cpp b/src/mbgl/style/conversion/transition_options.cpp
new file mode 100644
index 0000000000..8a60c5bfd8
--- /dev/null
+++ b/src/mbgl/style/conversion/transition_options.cpp
@@ -0,0 +1,40 @@
+#include <mbgl/style/conversion/transition_options.hpp>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+optional<TransitionOptions> Converter<TransitionOptions>::operator()(const Convertible& value, Error& error) const {
+ if (!isObject(value)) {
+ error = { "transition must be an object" };
+ return {};
+ }
+
+ TransitionOptions result;
+
+ auto duration = objectMember(value, "duration");
+ if (duration) {
+ auto number = toNumber(*duration);
+ if (!number) {
+ error = { "duration must be a number" };
+ return {};
+ }
+ result.duration = { std::chrono::milliseconds(int64_t(*number)) };
+ }
+
+ auto delay = objectMember(value, "delay");
+ if (delay) {
+ auto number = toNumber(*delay);
+ if (!number) {
+ error = { "delay must be a number" };
+ return {};
+ }
+ result.delay = { std::chrono::milliseconds(int64_t(*number)) };
+ }
+
+ return result;
+}
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/custom_tile_loader.cpp b/src/mbgl/style/custom_tile_loader.cpp
new file mode 100644
index 0000000000..76248b84bd
--- /dev/null
+++ b/src/mbgl/style/custom_tile_loader.cpp
@@ -0,0 +1,109 @@
+#include <mbgl/style/custom_tile_loader.hpp>
+#include <mbgl/tile/custom_geometry_tile.hpp>
+
+namespace mbgl {
+namespace style {
+
+CustomTileLoader::CustomTileLoader(const TileFunction& fetchTileFn, const TileFunction& cancelTileFn) {
+ fetchTileFunction = fetchTileFn;
+ cancelTileFunction = cancelTileFn;
+}
+
+void CustomTileLoader::fetchTile(const OverscaledTileID& tileID, ActorRef<CustomGeometryTile> tileRef) {
+ auto cachedTileData = dataCache.find(tileID.canonical);
+ if (cachedTileData != dataCache.end()) {
+ tileRef.invoke(&CustomGeometryTile::setTileData, *(cachedTileData->second));
+ }
+ auto tileCallbacks = tileCallbackMap.find(tileID.canonical);
+ if (tileCallbacks == tileCallbackMap.end()) {
+ auto tuple = std::make_tuple(tileID.overscaledZ, tileID.wrap, tileRef);
+ tileCallbackMap.insert({ tileID.canonical, std::vector<OverscaledIDFunctionTuple>(1, tuple) });
+ } else {
+ for (auto iter = tileCallbacks->second.begin(); iter != tileCallbacks->second.end(); iter++) {
+ if (std::get<0>(*iter) == tileID.overscaledZ && std::get<1>(*iter) == tileID.wrap ) {
+ std::get<2>(*iter) = tileRef;
+ return;
+ }
+ }
+ tileCallbacks->second.emplace_back(std::make_tuple(tileID.overscaledZ, tileID.wrap, tileRef));
+ }
+ if (cachedTileData == dataCache.end()) {
+ invokeTileFetch(tileID.canonical);
+ }
+}
+
+void CustomTileLoader::cancelTile(const OverscaledTileID& tileID) {
+ if (tileCallbackMap.find(tileID.canonical) != tileCallbackMap.end()) {
+ invokeTileCancel(tileID.canonical);
+ }
+}
+
+void CustomTileLoader::removeTile(const OverscaledTileID& tileID) {
+ auto tileCallbacks = tileCallbackMap.find(tileID.canonical);
+ if (tileCallbacks == tileCallbackMap.end()) return;
+ for (auto iter = tileCallbacks->second.begin(); iter != tileCallbacks->second.end(); iter++) {
+ if (std::get<0>(*iter) == tileID.overscaledZ && std::get<1>(*iter) == tileID.wrap ) {
+ tileCallbacks->second.erase(iter);
+ invokeTileCancel(tileID.canonical);
+ break;
+ }
+ }
+ if (tileCallbacks->second.size() == 0) {
+ tileCallbackMap.erase(tileCallbacks);
+ dataCache.erase(tileID.canonical);
+ }
+}
+
+void CustomTileLoader::setTileData(const CanonicalTileID& tileID, const GeoJSON& data) {
+
+ auto iter = tileCallbackMap.find(tileID);
+ if (iter == tileCallbackMap.end()) return;
+ auto dataPtr = std::make_unique<mapbox::geojson::geojson>(std::move(data));
+ for (auto tuple : iter->second) {
+ auto actor = std::get<2>(tuple);
+ actor.invoke(&CustomGeometryTile::setTileData, *dataPtr);
+ }
+ dataCache[tileID] = std::move(dataPtr);
+}
+
+void CustomTileLoader::invalidateTile(const CanonicalTileID& tileID) {
+ auto tileCallbacks = tileCallbackMap.find(tileID);
+ if (tileCallbacks == tileCallbackMap.end()) { return; }
+ for (auto iter = tileCallbacks->second.begin(); iter != tileCallbacks->second.end(); iter++) {
+ auto actor = std::get<2>(*iter);
+ actor.invoke(&CustomGeometryTile::invalidateTileData);
+ invokeTileCancel(tileID);
+ }
+ tileCallbackMap.erase(tileCallbacks);
+ dataCache.erase(tileID);
+}
+
+void CustomTileLoader::invalidateRegion(const LatLngBounds& bounds, Range<uint8_t> ) {
+ for (auto idtuple= tileCallbackMap.begin(); idtuple != tileCallbackMap.end(); idtuple++) {
+ const LatLngBounds tileBounds(idtuple->first);
+ if (tileBounds.intersects(bounds, LatLng::Wrapped) || bounds.contains(tileBounds, LatLng::Wrapped) || tileBounds.contains(bounds, LatLng::Wrapped)) {
+ for (auto iter = idtuple->second.begin(); iter != idtuple->second.end(); iter++) {
+ auto actor = std::get<2>(*iter);
+ actor.invoke(&CustomGeometryTile::invalidateTileData);
+ invokeTileCancel(idtuple->first);
+ dataCache.erase(idtuple->first);
+ }
+ idtuple->second.clear();
+ }
+ }
+}
+
+void CustomTileLoader::invokeTileFetch(const CanonicalTileID& tileID) {
+ if (fetchTileFunction != nullptr) {
+ fetchTileFunction(tileID);
+ }
+}
+
+void CustomTileLoader::invokeTileCancel(const CanonicalTileID& tileID) {
+ if (cancelTileFunction != nullptr) {
+ cancelTileFunction(tileID);
+ }
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/custom_tile_loader.hpp b/src/mbgl/style/custom_tile_loader.hpp
new file mode 100644
index 0000000000..335d8c6143
--- /dev/null
+++ b/src/mbgl/style/custom_tile_loader.hpp
@@ -0,0 +1,45 @@
+#pragma once
+
+#include <mbgl/style/sources/custom_geometry_source.hpp>
+#include <mbgl/tile/tile_id.hpp>
+#include <mbgl/util/geojson.hpp>
+#include <mbgl/actor/actor_ref.hpp>
+
+#include <map>
+
+namespace mbgl {
+
+class CustomGeometryTile;
+
+namespace style {
+
+class CustomTileLoader : private util::noncopyable {
+public:
+
+ using OverscaledIDFunctionTuple = std::tuple<uint8_t, int16_t, ActorRef<CustomGeometryTile>>;
+
+ CustomTileLoader(const TileFunction& fetchTileFn, const TileFunction& cancelTileFn);
+
+ void fetchTile(const OverscaledTileID& tileID, ActorRef<CustomGeometryTile> tileRef);
+ void cancelTile(const OverscaledTileID& tileID);
+
+ void removeTile(const OverscaledTileID& tileID);
+ void setTileData(const CanonicalTileID& tileID, const GeoJSON& data);
+
+ void invalidateTile(const CanonicalTileID&);
+ void invalidateRegion(const LatLngBounds&, Range<uint8_t>);
+
+private:
+ void invokeTileFetch(const CanonicalTileID& tileID);
+ void invokeTileCancel(const CanonicalTileID& tileID);
+
+ TileFunction fetchTileFunction;
+ TileFunction cancelTileFunction;
+ std::unordered_map<CanonicalTileID, std::vector<OverscaledIDFunctionTuple>> tileCallbackMap;
+ // Keep around a cache of tile data to serve back for wrapped and over-zooomed tiles
+ std::map<CanonicalTileID, std::unique_ptr<GeoJSON>> dataCache;
+
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/expression/array_assertion.cpp b/src/mbgl/style/expression/array_assertion.cpp
new file mode 100644
index 0000000000..29f6a47b10
--- /dev/null
+++ b/src/mbgl/style/expression/array_assertion.cpp
@@ -0,0 +1,86 @@
+#include <mbgl/style/expression/array_assertion.hpp>
+#include <mbgl/style/expression/check_subtype.hpp>
+#include <mbgl/util/string.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+EvaluationResult ArrayAssertion::evaluate(const EvaluationContext& params) const {
+ auto result = input->evaluate(params);
+ if (!result) {
+ return result.error();
+ }
+ type::Type expected = getType();
+ type::Type actual = typeOf(*result);
+ if (checkSubtype(expected, actual)) {
+ return EvaluationError {
+ "Expected value to be of type " + toString(expected) +
+ ", but found " + toString(actual) + " instead."
+ };
+ }
+ return *result;
+}
+
+void ArrayAssertion::eachChild(const std::function<void(const Expression&)>& visit) const {
+ visit(*input);
+}
+
+using namespace mbgl::style::conversion;
+ParseResult ArrayAssertion::parse(const Convertible& value, ParsingContext& ctx) {
+
+ static std::unordered_map<std::string, type::Type> itemTypes {
+ {"string", type::String},
+ {"number", type::Number},
+ {"boolean", type::Boolean}
+ };
+
+ auto length = arrayLength(value);
+ if (length < 2 || length > 4) {
+ ctx.error("Expected 1, 2, or 3 arguments, but found " + util::toString(length - 1) + " instead.");
+ return ParseResult();
+ }
+
+ optional<type::Type> itemType;
+ optional<std::size_t> N;
+ if (length > 2) {
+ optional<std::string> itemTypeName = toString(arrayMember(value, 1));
+ auto it = itemTypeName ? itemTypes.find(*itemTypeName) : itemTypes.end();
+ if (it == itemTypes.end()) {
+ ctx.error(
+ R"(The item type argument of "array" must be one of string, number, boolean)",
+ 1
+ );
+ return ParseResult();
+ }
+ itemType = it->second;
+ } else {
+ itemType = {type::Value};
+ }
+
+ if (length > 3) {
+ auto n = toNumber(arrayMember(value, 2));
+ if (!n || *n != std::floor(*n)) {
+ ctx.error(
+ R"(The length argument to "array" must be a positive integer literal.)",
+ 2
+ );
+ return ParseResult();
+ }
+ N = optional<std::size_t>(*n);
+ }
+
+ auto input = ctx.parse(arrayMember(value, length - 1), length - 1, {type::Value});
+ if (!input) {
+ return input;
+ }
+
+ return ParseResult(std::make_unique<ArrayAssertion>(
+ type::Array(*itemType, N),
+ std::move(*input)
+ ));
+}
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/expression/assertion.cpp b/src/mbgl/style/expression/assertion.cpp
new file mode 100644
index 0000000000..a17c53cf54
--- /dev/null
+++ b/src/mbgl/style/expression/assertion.cpp
@@ -0,0 +1,73 @@
+#include <mbgl/style/expression/assertion.hpp>
+#include <mbgl/style/expression/check_subtype.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+using namespace mbgl::style::conversion;
+ParseResult Assertion::parse(const Convertible& value, ParsingContext& ctx) {
+ static std::unordered_map<std::string, type::Type> types {
+ {"string", type::String},
+ {"number", type::Number},
+ {"boolean", type::Boolean},
+ {"object", type::Object}
+ };
+
+ std::size_t length = arrayLength(value);
+
+ if (length < 2) {
+ ctx.error("Expected at least one argument.");
+ return ParseResult();
+ }
+
+ auto it = types.find(*toString(arrayMember(value, 0)));
+ assert(it != types.end());
+
+ std::vector<std::unique_ptr<Expression>> parsed;
+ parsed.reserve(length - 1);
+ for (std::size_t i = 1; i < length; i++) {
+ ParseResult input = ctx.parse(arrayMember(value, i), i, {type::Value});
+ if (!input) return ParseResult();
+ parsed.push_back(std::move(*input));
+ }
+
+ return ParseResult(std::make_unique<Assertion>(it->second, std::move(parsed)));
+}
+
+EvaluationResult Assertion::evaluate(const EvaluationContext& params) const {
+ for (std::size_t i = 0; i < inputs.size(); i++) {
+ EvaluationResult value = inputs[i]->evaluate(params);
+ if (!value) return value;
+ if (!type::checkSubtype(getType(), typeOf(*value))) {
+ return value;
+ } else if (i == inputs.size() - 1) {
+ return EvaluationError {
+ "Expected value to be of type " + toString(getType()) +
+ ", but found " + toString(typeOf(*value)) + " instead."
+ };
+ }
+ }
+
+ assert(false);
+ return EvaluationError { "Unreachable" };
+};
+
+void Assertion::eachChild(const std::function<void(const Expression&)>& visit) const {
+ for(const std::unique_ptr<Expression>& input : inputs) {
+ visit(*input);
+ }
+};
+
+bool Assertion::operator==(const Expression& e) const {
+ if (auto rhs = dynamic_cast<const Assertion*>(&e)) {
+ return getType() == rhs->getType() && Expression::childrenEqual(inputs, rhs->inputs);
+ }
+ return false;
+}
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
+
+
diff --git a/src/mbgl/style/expression/at.cpp b/src/mbgl/style/expression/at.cpp
new file mode 100644
index 0000000000..e447d33bc7
--- /dev/null
+++ b/src/mbgl/style/expression/at.cpp
@@ -0,0 +1,64 @@
+#include <mbgl/style/expression/at.hpp>
+#include <mbgl/util/string.hpp>
+
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+EvaluationResult At::evaluate(const EvaluationContext& params) const {
+ const EvaluationResult evaluatedIndex = index->evaluate(params);
+ const EvaluationResult evaluatedInput = input->evaluate(params);
+ if (!evaluatedIndex) {
+ return evaluatedIndex.error();
+ }
+ if (!evaluatedInput) {
+ return evaluatedInput.error();
+ }
+
+ const auto i = evaluatedIndex->get<double>();
+ const auto inputArray = evaluatedInput->get<std::vector<Value>>();
+
+ if (i < 0 || i >= inputArray.size()) {
+ return EvaluationError {
+ "Array index out of bounds: " + stringify(i) +
+ " > " + util::toString(inputArray.size()) + "."
+ };
+ }
+ if (i != std::floor(i)) {
+ return EvaluationError {
+ "Array index must be an integer, but found " + stringify(i) + " instead."
+ };
+ }
+ return inputArray[static_cast<std::size_t>(i)];
+}
+
+void At::eachChild(const std::function<void(const Expression&)>& visit) const {
+ visit(*index);
+ visit(*input);
+}
+
+using namespace mbgl::style::conversion;
+ParseResult At::parse(const Convertible& value, ParsingContext& ctx) {
+ assert(isArray(value));
+
+ std::size_t length = arrayLength(value);
+ if (length != 3) {
+ ctx.error("Expected 2 arguments, but found " + util::toString(length - 1) + " instead.");
+ return ParseResult();
+ }
+
+ ParseResult index = ctx.parse(arrayMember(value, 1), 1, {type::Number});
+
+ type::Type inputType = type::Array(ctx.getExpected() ? *ctx.getExpected() : type::Value);
+ ParseResult input = ctx.parse(arrayMember(value, 2), 2, {inputType});
+
+ if (!index || !input) return ParseResult();
+
+ return ParseResult(std::make_unique<At>(std::move(*index), std::move(*input)));
+
+}
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/expression/boolean_operator.cpp b/src/mbgl/style/expression/boolean_operator.cpp
new file mode 100644
index 0000000000..88797f965a
--- /dev/null
+++ b/src/mbgl/style/expression/boolean_operator.cpp
@@ -0,0 +1,87 @@
+#include <mbgl/style/expression/boolean_operator.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+EvaluationResult Any::evaluate(const EvaluationContext& params) const {
+ for (auto it = inputs.begin(); it != inputs.end(); it++) {
+ const EvaluationResult result = (*it)->evaluate(params);
+ if (!result) return result;
+ if (result->get<bool>()) return EvaluationResult(true);
+ }
+ return EvaluationResult(false);
+}
+
+void Any::eachChild(const std::function<void(const Expression&)>& visit) const {
+ for (const std::unique_ptr<Expression>& input : inputs) {
+ visit(*input);
+ }
+}
+
+bool Any::operator==(const Expression& e) const {
+ if (auto rhs = dynamic_cast<const Any*>(&e)) {
+ return Expression::childrenEqual(inputs, rhs->inputs);
+ }
+ return false;
+}
+
+
+EvaluationResult All::evaluate(const EvaluationContext& params) const {
+ for (auto it = inputs.begin(); it != inputs.end(); it++) {
+ const EvaluationResult result = (*it)->evaluate(params);
+ if (!result) return result;
+ if (!result->get<bool>()) return EvaluationResult(false);
+ }
+ return EvaluationResult(true);
+}
+
+void All::eachChild(const std::function<void(const Expression&)>& visit) const {
+ for (const std::unique_ptr<Expression>& input : inputs) {
+ visit(*input);
+ }
+}
+
+bool All::operator==(const Expression& e) const {
+ if (auto rhs = dynamic_cast<const All*>(&e)) {
+ return Expression::childrenEqual(inputs, rhs->inputs);
+ }
+ return false;
+}
+
+using namespace mbgl::style::conversion;
+
+template <class T>
+ParseResult parseBooleanOp(const Convertible& value, ParsingContext& ctx) {
+
+ assert(isArray(value));
+ auto length = arrayLength(value);
+
+ std::vector<std::unique_ptr<Expression>> parsedInputs;
+
+ parsedInputs.reserve(length - 1);
+ for (std::size_t i = 1; i < length; i++) {
+ auto parsed = ctx.parse(arrayMember(value, i), i, {type::Boolean});
+ if (!parsed) {
+ return parsed;
+ }
+
+ parsedInputs.push_back(std::move(*parsed));
+ }
+
+ return ParseResult(std::make_unique<T>(std::move(parsedInputs)));
+}
+
+ParseResult Any::parse(const Convertible& value, ParsingContext& ctx) {
+ return parseBooleanOp<Any>(value, ctx);
+}
+
+ParseResult All::parse(const Convertible& value, ParsingContext& ctx) {
+ return parseBooleanOp<All>(value, ctx);
+}
+
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
+
diff --git a/src/mbgl/style/expression/case.cpp b/src/mbgl/style/expression/case.cpp
new file mode 100644
index 0000000000..049f258606
--- /dev/null
+++ b/src/mbgl/style/expression/case.cpp
@@ -0,0 +1,91 @@
+#include <mbgl/style/expression/case.hpp>
+#include <mbgl/util/string.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+EvaluationResult Case::evaluate(const EvaluationContext& params) const {
+ for (const auto& branch : branches) {
+ const EvaluationResult evaluatedTest = branch.first->evaluate(params);
+ if (!evaluatedTest) {
+ return evaluatedTest.error();
+ }
+ if (evaluatedTest->get<bool>()) {
+ return branch.second->evaluate(params);
+ }
+ }
+
+ return otherwise->evaluate(params);
+}
+
+void Case::eachChild(const std::function<void(const Expression&)>& visit) const {
+ for (const Branch& branch : branches) {
+ visit(*branch.first);
+ visit(*branch.second);
+ }
+ visit(*otherwise);
+}
+
+bool Case::operator==(const Expression& e) const {
+ if (auto rhs = dynamic_cast<const Case*>(&e)) {
+ return *otherwise == *(rhs->otherwise) && Expression::childrenEqual(branches, rhs->branches);
+ }
+ return false;
+}
+
+using namespace mbgl::style::conversion;
+ParseResult Case::parse(const Convertible& value, ParsingContext& ctx) {
+ assert(isArray(value));
+ auto length = arrayLength(value);
+ if (length < 4) {
+ ctx.error("Expected at least 3 arguments, but found only " + util::toString(length - 1) + ".");
+ return ParseResult();
+ }
+
+ // Expect even-length array: ["case", 2 * (n pairs)..., otherwise]
+ if (length % 2 != 0) {
+ ctx.error("Expected an odd number of arguments");
+ return ParseResult();
+ }
+
+ optional<type::Type> outputType;
+ if (ctx.getExpected() && *ctx.getExpected() != type::Value) {
+ outputType = ctx.getExpected();
+ }
+
+ std::vector<Case::Branch> branches;
+ branches.reserve((length - 2) / 2);
+ for (size_t i = 1; i + 1 < length; i += 2) {
+ auto test = ctx.parse(arrayMember(value, i), i, {type::Boolean});
+ if (!test) {
+ return test;
+ }
+
+ auto output = ctx.parse(arrayMember(value, i + 1), i + 1, outputType);
+ if (!output) {
+ return output;
+ }
+
+ if (!outputType) {
+ outputType = (*output)->getType();
+ }
+
+ branches.push_back(std::make_pair(std::move(*test), std::move(*output)));
+ }
+
+ assert(outputType);
+
+ auto otherwise = ctx.parse(arrayMember(value, length - 1), length - 1, outputType);
+ if (!otherwise) {
+ return otherwise;
+ }
+
+ return ParseResult(std::make_unique<Case>(*outputType,
+ std::move(branches),
+ std::move(*otherwise)));
+}
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/expression/check_subtype.cpp b/src/mbgl/style/expression/check_subtype.cpp
new file mode 100644
index 0000000000..04a1643f0c
--- /dev/null
+++ b/src/mbgl/style/expression/check_subtype.cpp
@@ -0,0 +1,60 @@
+#include <string>
+#include <mbgl/style/expression/check_subtype.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+namespace type {
+
+std::string errorMessage(const Type& expected, const Type& t) {
+ return {"Expected " + toString(expected) + " but found " + toString(t) + " instead."};
+}
+
+optional<std::string> checkSubtype(const Type& expected, const Type& t) {
+ if (t.is<ErrorType>()) return {};
+
+ optional<std::string> result = expected.match(
+ [&] (const Array& expectedArray) -> optional<std::string> {
+ if (!t.is<Array>()) { return {errorMessage(expected, t)}; }
+ const auto& actualArray = t.get<Array>();
+ const auto err = checkSubtype(expectedArray.itemType, actualArray.itemType);
+ if (err) return { errorMessage(expected, t) };
+ if (expectedArray.N && expectedArray.N != actualArray.N) return { errorMessage(expected, t) };
+ return {};
+ },
+ [&] (const ValueType&) -> optional<std::string> {
+ if (t.is<ValueType>()) return {};
+
+ const Type members[] = {
+ Null,
+ Boolean,
+ Number,
+ String,
+ Object,
+ Color,
+ Array(Value)
+ };
+
+ for (const auto& member : members) {
+ const auto err = checkSubtype(member, t);
+ if (!err) {
+ return {};
+ }
+ }
+ return { errorMessage(expected, t) };
+ },
+ [&] (const auto&) -> optional<std::string> {
+ if (expected != t) {
+ return { errorMessage(expected, t) };
+ }
+ return {};
+ }
+ );
+
+ return result;
+}
+
+} // namespace type
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/expression/coalesce.cpp b/src/mbgl/style/expression/coalesce.cpp
new file mode 100644
index 0000000000..bfde3c7581
--- /dev/null
+++ b/src/mbgl/style/expression/coalesce.cpp
@@ -0,0 +1,62 @@
+#include <mbgl/style/expression/coalesce.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+EvaluationResult Coalesce::evaluate(const EvaluationContext& params) const {
+ EvaluationResult result = Null;
+ for (const auto& arg : args) {
+ result = arg->evaluate(params);
+ if (!result || *result != Null) break;
+ }
+ return result;
+}
+
+void Coalesce::eachChild(const std::function<void(const Expression&)>& visit) const {
+ for (const std::unique_ptr<Expression>& arg : args) {
+ visit(*arg);
+ }
+}
+
+bool Coalesce::operator==(const Expression& e) const {
+ if (auto rhs = dynamic_cast<const Coalesce*>(&e)) {
+ return Expression::childrenEqual(args, rhs->args);
+ }
+ return false;
+}
+
+using namespace mbgl::style::conversion;
+ParseResult Coalesce::parse(const Convertible& value, ParsingContext& ctx) {
+ assert(isArray(value));
+ auto length = arrayLength(value);
+ if (length < 2) {
+ ctx.error("Expected at least one argument.");
+ return ParseResult();
+ }
+
+ optional<type::Type> outputType;
+ if (ctx.getExpected() && *ctx.getExpected() != type::Value) {
+ outputType = ctx.getExpected();
+ }
+
+ Coalesce::Args args;
+ args.reserve(length - 1);
+ for (std::size_t i = 1; i < length; i++) {
+ auto parsed = ctx.parse(arrayMember(value, i), i, outputType);
+ if (!parsed) {
+ return parsed;
+ }
+ if (!outputType) {
+ outputType = (*parsed)->getType();
+ }
+ args.push_back(std::move(*parsed));
+ }
+
+ assert(outputType);
+ return ParseResult(std::make_unique<Coalesce>(*outputType, std::move(args)));
+}
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/expression/coercion.cpp b/src/mbgl/style/expression/coercion.cpp
new file mode 100644
index 0000000000..8ed8e160dd
--- /dev/null
+++ b/src/mbgl/style/expression/coercion.cpp
@@ -0,0 +1,144 @@
+#include <mbgl/style/expression/coercion.hpp>
+#include <mbgl/style/expression/check_subtype.hpp>
+#include <mbgl/style/expression/util.hpp>
+#include <mbgl/util/string.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+EvaluationResult toNumber(const Value& v) {
+ optional<double> result = v.match(
+ [](const double f) -> optional<double> { return f; },
+ [](const std::string& s) -> optional<double> {
+ try {
+ return util::stof(s);
+ } catch(std::exception) {
+ return optional<double>();
+ }
+ },
+ [](const auto&) { return optional<double>(); }
+ );
+ if (!result) {
+ return EvaluationError {
+ "Could not convert " + stringify(v) + " to number."
+ };
+ }
+ return *result;
+}
+
+EvaluationResult toColor(const Value& colorValue) {
+ return colorValue.match(
+ [&](const std::string& colorString) -> EvaluationResult {
+ const optional<Color> result = Color::parse(colorString);
+ if (result) {
+ return *result;
+ } else {
+ return EvaluationError{
+ "Could not parse color from value '" + colorString + "'"
+ };
+ }
+ },
+ [&](const std::vector<Value>& components) -> EvaluationResult {
+ std::size_t len = components.size();
+ bool isNumeric = std::all_of(components.begin(), components.end(), [](const Value& item) {
+ return item.template is<double>();
+ });
+ if ((len == 3 || len == 4) && isNumeric) {
+ Result<Color> c = {rgba(
+ components[0].template get<double>(),
+ components[1].template get<double>(),
+ components[2].template get<double>(),
+ len == 4 ? components[3].template get<double>() : 1.0
+ )};
+ if (!c) return c.error();
+ return *c;
+ } else {
+ return EvaluationError{
+ "Invalid rbga value " + stringify(colorValue) + ": expected an array containing either three or four numeric values."
+ };
+ }
+ },
+ [&](const auto&) -> EvaluationResult {
+ return EvaluationError{
+ "Could not parse color from value '" + stringify(colorValue) + "'"
+ };
+ }
+ );
+}
+
+Coercion::Coercion(type::Type type_, std::vector<std::unique_ptr<Expression>> inputs_) :
+ Expression(std::move(type_)),
+ inputs(std::move(inputs_))
+{
+ type::Type t = getType();
+ if (t.is<type::NumberType>()) {
+ coerceSingleValue = toNumber;
+ } else if (t.is<type::ColorType>()) {
+ coerceSingleValue = toColor;
+ } else {
+ assert(false);
+ }
+}
+
+using namespace mbgl::style::conversion;
+ParseResult Coercion::parse(const Convertible& value, ParsingContext& ctx) {
+ static std::unordered_map<std::string, type::Type> types {
+ {"to-number", type::Number},
+ {"to-color", type::Color}
+ };
+
+ std::size_t length = arrayLength(value);
+
+ if (length < 2) {
+ ctx.error("Expected at least one argument.");
+ return ParseResult();
+ }
+
+ auto it = types.find(*toString(arrayMember(value, 0)));
+ assert(it != types.end());
+
+ std::vector<std::unique_ptr<Expression>> parsed;
+ parsed.reserve(length - 1);
+ for (std::size_t i = 1; i < length; i++) {
+ ParseResult input = ctx.parse(arrayMember(value, i), i, {type::Value});
+ if (!input) return ParseResult();
+ parsed.push_back(std::move(*input));
+ }
+
+ return ParseResult(std::make_unique<Coercion>(it->second, std::move(parsed)));
+}
+
+EvaluationResult Coercion::evaluate(const EvaluationContext& params) const {
+ for (std::size_t i = 0; i < inputs.size(); i++) {
+ EvaluationResult value = inputs[i]->evaluate(params);
+ if (!value) return value;
+ EvaluationResult coerced = coerceSingleValue(*value);
+ if (coerced || i == inputs.size() - 1) {
+ return coerced;
+ }
+ }
+
+ assert(false);
+ return EvaluationError { "Unreachable" };
+};
+
+void Coercion::eachChild(const std::function<void(const Expression&)>& visit) const {
+ for(const std::unique_ptr<Expression>& input : inputs) {
+ visit(*input);
+ }
+};
+
+bool Coercion::operator==(const Expression& e) const {
+ if (auto rhs = dynamic_cast<const Coercion*>(&e)) {
+ return getType() == rhs->getType() && Expression::childrenEqual(inputs, rhs->inputs);
+ }
+ return false;
+}
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
+
+
+
diff --git a/src/mbgl/style/expression/compound_expression.cpp b/src/mbgl/style/expression/compound_expression.cpp
new file mode 100644
index 0000000000..70bc6dfd95
--- /dev/null
+++ b/src/mbgl/style/expression/compound_expression.cpp
@@ -0,0 +1,568 @@
+#include <mbgl/style/expression/compound_expression.hpp>
+#include <mbgl/style/expression/check_subtype.hpp>
+#include <mbgl/style/expression/util.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
+#include <mbgl/math/log2.hpp>
+#include <mbgl/util/ignore.hpp>
+#include <mbgl/util/string.hpp>
+#include <mbgl/util/platform.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+namespace detail {
+
+/*
+ The Signature<Fn> structs are wrappers around an "evaluate()" function whose
+ purpose is to extract the necessary Type data from the evaluate function's
+ type. There are three key (partial) specializations:
+
+ Signature<R (Params...)>:
+ Wraps a simple evaluate function (const T0&, const T1&, ...) -> Result<U>
+
+ Signature<R (const Varargs<T>&)>:
+ Wraps an evaluate function that takes an arbitrary number of arguments (via
+ a Varargs<T>, which is just an alias for std::vector).
+
+ Signature<R (const EvaluationContext&, Params...)>:
+ Wraps an evaluate function that needs to access the expression evaluation
+ parameters in addition to its subexpressions, i.e.,
+ (const EvaluationParams& const T0&, const T1&, ...) -> Result<U>. Needed
+ for expressions like ["zoom"], ["get", key], etc.
+
+ In each of the above evaluate signatures, T0, T1, etc. are the types of
+ the successfully evaluated subexpressions.
+*/
+template <class, class Enable = void>
+struct Signature;
+
+// Simple evaluate function (const T0&, const T1&, ...) -> Result<U>
+template <class R, class... Params>
+struct Signature<R (Params...)> : SignatureBase {
+ using Args = std::array<std::unique_ptr<Expression>, sizeof...(Params)>;
+
+ Signature(R (*evaluate_)(Params...)) :
+ SignatureBase(
+ valueTypeToExpressionType<std::decay_t<typename R::Value>>(),
+ std::vector<type::Type> {valueTypeToExpressionType<std::decay_t<Params>>()...}
+ ),
+ evaluate(evaluate_)
+ {}
+
+ EvaluationResult apply(const EvaluationContext& evaluationParameters, const Args& args) const {
+ return applyImpl(evaluationParameters, args, std::index_sequence_for<Params...>{});
+ }
+
+ std::unique_ptr<Expression> makeExpression(const std::string& name,
+ std::vector<std::unique_ptr<Expression>> args) const override {
+ typename Signature::Args argsArray;
+ std::copy_n(std::make_move_iterator(args.begin()), sizeof...(Params), argsArray.begin());
+ return std::make_unique<CompoundExpression<Signature>>(name, *this, std::move(argsArray));
+ }
+
+ R (*evaluate)(Params...);
+private:
+ template <std::size_t ...I>
+ EvaluationResult applyImpl(const EvaluationContext& evaluationParameters, const Args& args, std::index_sequence<I...>) const {
+ const std::array<EvaluationResult, sizeof...(I)> evaluated = {{std::get<I>(args)->evaluate(evaluationParameters)...}};
+ for (const auto& arg : evaluated) {
+ if(!arg) return arg.error();
+ }
+ const R value = evaluate(*fromExpressionValue<std::decay_t<Params>>(*(evaluated[I]))...);
+ if (!value) return value.error();
+ return *value;
+ }
+};
+
+// Varargs evaluate function (const Varargs<T>&) -> Result<U>
+template <class R, typename T>
+struct Signature<R (const Varargs<T>&)> : SignatureBase {
+ using Args = std::vector<std::unique_ptr<Expression>>;
+
+ Signature(R (*evaluate_)(const Varargs<T>&)) :
+ SignatureBase(
+ valueTypeToExpressionType<std::decay_t<typename R::Value>>(),
+ VarargsType { valueTypeToExpressionType<T>() }
+ ),
+ evaluate(evaluate_)
+ {}
+
+ std::unique_ptr<Expression> makeExpression(const std::string& name,
+ std::vector<std::unique_ptr<Expression>> args) const override {
+ return std::make_unique<CompoundExpression<Signature>>(name, *this, std::move(args));
+ };
+
+ EvaluationResult apply(const EvaluationContext& evaluationParameters, const Args& args) const {
+ Varargs<T> evaluated;
+ evaluated.reserve(args.size());
+ for (const auto& arg : args) {
+ const EvaluationResult evaluatedArg = arg->evaluate(evaluationParameters);
+ if(!evaluatedArg) return evaluatedArg.error();
+ evaluated.push_back(*fromExpressionValue<std::decay_t<T>>(*evaluatedArg));
+ }
+ const R value = evaluate(evaluated);
+ if (!value) return value.error();
+ return *value;
+ }
+
+ R (*evaluate)(const Varargs<T>&);
+};
+
+// Evaluate function needing parameter access,
+// (const EvaluationParams&, const T0&, const T1&, ...) -> Result<U>
+template <class R, class... Params>
+struct Signature<R (const EvaluationContext&, Params...)> : SignatureBase {
+ using Args = std::array<std::unique_ptr<Expression>, sizeof...(Params)>;
+
+ Signature(R (*evaluate_)(const EvaluationContext&, Params...)) :
+ SignatureBase(
+ valueTypeToExpressionType<std::decay_t<typename R::Value>>(),
+ std::vector<type::Type> {valueTypeToExpressionType<std::decay_t<Params>>()...}
+ ),
+ evaluate(evaluate_)
+ {}
+
+ std::unique_ptr<Expression> makeExpression(const std::string& name,
+ std::vector<std::unique_ptr<Expression>> args) const override {
+ typename Signature::Args argsArray;
+ std::copy_n(std::make_move_iterator(args.begin()), sizeof...(Params), argsArray.begin());
+ return std::make_unique<CompoundExpression<Signature>>(name, *this, std::move(argsArray));
+ }
+
+ EvaluationResult apply(const EvaluationContext& evaluationParameters, const Args& args) const {
+ return applyImpl(evaluationParameters, args, std::index_sequence_for<Params...>{});
+ }
+
+private:
+ template <std::size_t ...I>
+ EvaluationResult applyImpl(const EvaluationContext& evaluationParameters, const Args& args, std::index_sequence<I...>) const {
+ const std::array<EvaluationResult, sizeof...(I)> evaluated = {{std::get<I>(args)->evaluate(evaluationParameters)...}};
+ for (const auto& arg : evaluated) {
+ if(!arg) return arg.error();
+ }
+ // TODO: assert correct runtime type of each arg value
+ const R value = evaluate(evaluationParameters, *fromExpressionValue<std::decay_t<Params>>(*(evaluated[I]))...);
+ if (!value) return value.error();
+ return *value;
+ }
+
+ R (*evaluate)(const EvaluationContext&, Params...);
+};
+
+// Machinery to pull out function types from class methods, lambdas, etc.
+template <class R, class... Params>
+struct Signature<R (*)(Params...)>
+ : Signature<R (Params...)>
+{ using Signature<R (Params...)>::Signature; };
+
+template <class T, class R, class... Params>
+struct Signature<R (T::*)(Params...) const>
+ : Signature<R (Params...)>
+{ using Signature<R (Params...)>::Signature; };
+
+template <class T, class R, class... Params>
+struct Signature<R (T::*)(Params...)>
+ : Signature<R (Params...)>
+{ using Signature<R (Params...)>::Signature; };
+
+template <class Lambda>
+struct Signature<Lambda, std::enable_if_t<std::is_class<Lambda>::value>>
+ : Signature<decltype(&Lambda::operator())>
+{ using Signature<decltype(&Lambda::operator())>::Signature; };
+
+} // namespace detail
+
+using Definition = CompoundExpressionRegistry::Definition;
+
+template <typename T>
+Result<bool> equal(const T& lhs, const T& rhs) { return lhs == rhs; }
+
+template <typename T>
+Result<bool> notEqual(const T& lhs, const T& rhs) { return lhs != rhs; }
+
+template <typename Fn>
+static std::unique_ptr<detail::SignatureBase> makeSignature(Fn evaluateFunction) {
+ return std::make_unique<detail::Signature<Fn>>(evaluateFunction);
+}
+
+std::unordered_map<std::string, CompoundExpressionRegistry::Definition> initializeDefinitions() {
+ std::unordered_map<std::string, CompoundExpressionRegistry::Definition> definitions;
+ auto define = [&](std::string name, auto fn) {
+ definitions[name].push_back(makeSignature(fn));
+ };
+
+ define("e", []() -> Result<double> { return 2.718281828459045; });
+ define("pi", []() -> Result<double> { return 3.141592653589793; });
+ define("ln2", []() -> Result<double> { return 0.6931471805599453; });
+
+ define("typeof", [](const Value& v) -> Result<std::string> { return toString(typeOf(v)); });
+
+ define("to-string", [](const Value& value) -> Result<std::string> {
+ return value.match(
+ [](const Color& c) -> Result<std::string> { return c.stringify(); }, // avoid quoting
+ [](const std::string& s) -> Result<std::string> { return s; }, // avoid quoting
+ [](const auto& v) -> Result<std::string> { return stringify(v); }
+ );
+ });
+
+ define("to-boolean", [](const Value& v) -> Result<bool> {
+ return v.match(
+ [&] (double f) { return (bool)f; },
+ [&] (const std::string& s) { return s.length() > 0; },
+ [&] (bool b) { return b; },
+ [&] (const NullValue&) { return false; },
+ [&] (const auto&) { return true; }
+ );
+ });
+ define("to-rgba", [](const Color& color) -> Result<std::array<double, 4>> {
+ return std::array<double, 4> {{ color.r, color.g, color.b, color.a }};
+ });
+
+ define("rgba", rgba);
+ define("rgb", [](double r, double g, double b) { return rgba(r, g, b, 1.0f); });
+
+ define("zoom", [](const EvaluationContext& params) -> Result<double> {
+ if (!params.zoom) {
+ return EvaluationError {
+ "The 'zoom' expression is unavailable in the current evaluation context."
+ };
+ }
+ return *(params.zoom);
+ });
+
+ define("heatmap-density", [](const EvaluationContext& params) -> Result<double> {
+ if (!params.heatmapDensity) {
+ return EvaluationError {
+ "The 'heatmap-density' expression is unavailable in the current evaluation context."
+ };
+ }
+ return *(params.heatmapDensity);
+ });
+
+ define("has", [](const EvaluationContext& params, const std::string& key) -> Result<bool> {
+ if (!params.feature) {
+ return EvaluationError {
+ "Feature data is unavailable in the current evaluation context."
+ };
+ }
+
+ return params.feature->getValue(key) ? true : false;
+ });
+ define("has", [](const std::string& key, const std::unordered_map<std::string, Value>& object) -> Result<bool> {
+ return object.find(key) != object.end();
+ });
+
+ define("get", [](const EvaluationContext& params, const std::string& key) -> Result<Value> {
+ if (!params.feature) {
+ return EvaluationError {
+ "Feature data is unavailable in the current evaluation context."
+ };
+ }
+
+ auto propertyValue = params.feature->getValue(key);
+ if (!propertyValue) {
+ return Null;
+ }
+ return Value(toExpressionValue(*propertyValue));
+ });
+ define("get", [](const std::string& key, const std::unordered_map<std::string, Value>& object) -> Result<Value> {
+ if (object.find(key) == object.end()) {
+ return Null;
+ }
+ return object.at(key);
+ });
+
+ define("length", [](const std::vector<Value>& arr) -> Result<double> {
+ return arr.size();
+ });
+ define("length", [] (const std::string s) -> Result<double> {
+ return s.size();
+ });
+
+ define("properties", [](const EvaluationContext& params) -> Result<std::unordered_map<std::string, Value>> {
+ if (!params.feature) {
+ return EvaluationError {
+ "Feature data is unavailable in the current evaluation context."
+ };
+ }
+ std::unordered_map<std::string, Value> result;
+ const PropertyMap properties = params.feature->getProperties();
+ for (const auto& entry : properties) {
+ result[entry.first] = toExpressionValue(entry.second);
+ }
+ return result;
+ });
+
+ define("geometry-type", [](const EvaluationContext& params) -> Result<std::string> {
+ if (!params.feature) {
+ return EvaluationError {
+ "Feature data is unavailable in the current evaluation context."
+ };
+ }
+
+ auto type = params.feature->getType();
+ if (type == FeatureType::Point) {
+ return "Point";
+ } else if (type == FeatureType::LineString) {
+ return "LineString";
+ } else if (type == FeatureType::Polygon) {
+ return "Polygon";
+ } else {
+ return "Unknown";
+ }
+ });
+
+ define("id", [](const EvaluationContext& params) -> Result<Value> {
+ if (!params.feature) {
+ return EvaluationError {
+ "Feature data is unavailable in the current evaluation context."
+ };
+ }
+
+ auto id = params.feature->getID();
+ if (!id) {
+ return Null;
+ }
+ return id->match(
+ [](const auto& idValue) {
+ return toExpressionValue(mbgl::Value(idValue));
+ }
+ );
+ });
+
+ define("+", [](const Varargs<double>& args) -> Result<double> {
+ double sum = 0.0f;
+ for (auto arg : args) {
+ sum += arg;
+ }
+ return sum;
+ });
+ define("-", [](double a, double b) -> Result<double> { return a - b; });
+ define("-", [](double a) -> Result<double> { return -a; });
+ define("*", [](const Varargs<double>& args) -> Result<double> {
+ double prod = 1.0f;
+ for (auto arg : args) {
+ prod *= arg;
+ }
+ return prod;
+ });
+ define("/", [](double a, double b) -> Result<double> { return a / b; });
+ define("%", [](double a, double b) -> Result<double> { return fmod(a, b); });
+ define("^", [](double a, double b) -> Result<double> { return pow(a, b); });
+ define("sqrt", [](double x) -> Result<double> { return sqrt(x); });
+ define("log10", [](double x) -> Result<double> { return log10(x); });
+ define("ln", [](double x) -> Result<double> { return log(x); });
+ define("log2", [](double x) -> Result<double> { return util::log2(x); });
+ define("sin", [](double x) -> Result<double> { return sin(x); });
+ define("cos", [](double x) -> Result<double> { return cos(x); });
+ define("tan", [](double x) -> Result<double> { return tan(x); });
+ define("asin", [](double x) -> Result<double> { return asin(x); });
+ define("acos", [](double x) -> Result<double> { return acos(x); });
+ define("atan", [](double x) -> Result<double> { return atan(x); });
+
+ define("min", [](const Varargs<double>& args) -> Result<double> {
+ double result = std::numeric_limits<double>::infinity();
+ for (double arg : args) {
+ result = fmin(arg, result);
+ }
+ return result;
+ });
+ define("max", [](const Varargs<double>& args) -> Result<double> {
+ double result = -std::numeric_limits<double>::infinity();
+ for (double arg : args) {
+ result = fmax(arg, result);
+ }
+ return result;
+ });
+
+ define("==", equal<double>);
+ define("==", equal<const std::string&>);
+ define("==", equal<bool>);
+ define("==", equal<NullValue>);
+
+ define("!=", notEqual<double>);
+ define("!=", notEqual<const std::string&>);
+ define("!=", notEqual<bool>);
+ define("!=", notEqual<NullValue>);
+
+ define(">", [](double lhs, double rhs) -> Result<bool> { return lhs > rhs; });
+ define(">", [](const std::string& lhs, const std::string& rhs) -> Result<bool> { return lhs > rhs; });
+ define(">=", [](double lhs, double rhs) -> Result<bool> { return lhs >= rhs; });
+ define(">=",[](const std::string& lhs, const std::string& rhs) -> Result<bool> { return lhs >= rhs; });
+ define("<", [](double lhs, double rhs) -> Result<bool> { return lhs < rhs; });
+ define("<", [](const std::string& lhs, const std::string& rhs) -> Result<bool> { return lhs < rhs; });
+ define("<=", [](double lhs, double rhs) -> Result<bool> { return lhs <= rhs; });
+ define("<=", [](const std::string& lhs, const std::string& rhs) -> Result<bool> { return lhs <= rhs; });
+
+ define("!", [](bool e) -> Result<bool> { return !e; });
+
+ define("upcase", [](const std::string& input) -> Result<std::string> {
+ return platform::uppercase(input);
+ });
+ define("downcase", [](const std::string& input) -> Result<std::string> {
+ return platform::lowercase(input);
+ });
+ define("concat", [](const Varargs<std::string>& args) -> Result<std::string> {
+ std::string s;
+ for (const std::string& arg : args) {
+ s += arg;
+ }
+ return s;
+ });
+ define("error", [](const std::string& input) -> Result<type::ErrorType> {
+ return EvaluationError { input };
+ });
+
+ return definitions;
+}
+
+std::unordered_map<std::string, Definition> CompoundExpressionRegistry::definitions = initializeDefinitions();
+
+using namespace mbgl::style::conversion;
+ParseResult parseCompoundExpression(const std::string name, const Convertible& value, ParsingContext& ctx) {
+ assert(isArray(value) && arrayLength(value) > 0);
+
+ auto it = CompoundExpressionRegistry::definitions.find(name);
+ if (it == CompoundExpressionRegistry::definitions.end()) {
+ ctx.error(
+ R"(Unknown expression ")" + name + R"(". If you wanted a literal array, use ["literal", [...]].)",
+ 0
+ );
+ return ParseResult();
+ }
+ const CompoundExpressionRegistry::Definition& definition = it->second;
+
+ auto length = arrayLength(value);
+
+ // Check if we have a single signature with the correct number of
+ // parameters. If so, then use that signature's parameter types for parsing
+ // (and inferring the types of) the arguments.
+ optional<std::size_t> singleMatchingSignature;
+ for (std::size_t j = 0; j < definition.size(); j++) {
+ const std::unique_ptr<detail::SignatureBase>& signature = definition[j];
+ if (
+ signature->params.is<VarargsType>() ||
+ signature->params.get<std::vector<type::Type>>().size() == length - 1
+ ) {
+ if (singleMatchingSignature) {
+ singleMatchingSignature = {};
+ } else {
+ singleMatchingSignature = j;
+ }
+ }
+ }
+
+ // parse subexpressions first
+ std::vector<std::unique_ptr<Expression>> args;
+ args.reserve(length - 1);
+ for (std::size_t i = 1; i < length; i++) {
+ optional<type::Type> expected;
+
+ if (singleMatchingSignature) {
+ expected = definition[*singleMatchingSignature]->params.match(
+ [](const VarargsType& varargs) { return varargs.type; },
+ [&](const std::vector<type::Type>& params_) { return params_[i - 1]; }
+ );
+ }
+
+ auto parsed = ctx.parse(arrayMember(value, i), i, expected);
+ if (!parsed) {
+ return parsed;
+ }
+ args.push_back(std::move(*parsed));
+ }
+ return createCompoundExpression(name, definition, std::move(args), ctx);
+}
+
+
+ParseResult createCompoundExpression(const std::string& name,
+ std::vector<std::unique_ptr<Expression>> args,
+ ParsingContext& ctx)
+{
+ return createCompoundExpression(name, CompoundExpressionRegistry::definitions.at(name), std::move(args), ctx);
+}
+
+
+ParseResult createCompoundExpression(const std::string& name,
+ const Definition& definition,
+ std::vector<std::unique_ptr<Expression>> args,
+ ParsingContext& ctx)
+{
+ ParsingContext signatureContext(ctx.getKey());
+
+ for (const std::unique_ptr<detail::SignatureBase>& signature : definition) {
+ signatureContext.clearErrors();
+
+ if (signature->params.is<std::vector<type::Type>>()) {
+ const std::vector<type::Type>& params = signature->params.get<std::vector<type::Type>>();
+ if (params.size() != args.size()) {
+ signatureContext.error(
+ "Expected " + util::toString(params.size()) +
+ " arguments, but found " + util::toString(args.size()) + " instead."
+ );
+ continue;
+ }
+
+ for (std::size_t i = 0; i < args.size(); i++) {
+ const std::unique_ptr<Expression>& arg = args[i];
+ optional<std::string> err = type::checkSubtype(params.at(i), arg->getType());
+ if (err) {
+ signatureContext.error(*err, i + 1);
+ }
+ }
+ } else if (signature->params.is<VarargsType>()) {
+ const type::Type& paramType = signature->params.get<VarargsType>().type;
+ for (std::size_t i = 0; i < args.size(); i++) {
+ const std::unique_ptr<Expression>& arg = args[i];
+ optional<std::string> err = type::checkSubtype(paramType, arg->getType());
+ if (err) {
+ signatureContext.error(*err, i + 1);
+ }
+ }
+ }
+
+ if (signatureContext.getErrors().size() == 0) {
+ return ParseResult(signature->makeExpression(name, std::move(args)));
+ }
+ }
+
+ if (definition.size() == 1) {
+ ctx.appendErrors(std::move(signatureContext));
+ } else {
+ std::string signatures;
+ for (const auto& signature : definition) {
+ signatures += (signatures.size() > 0 ? " | " : "");
+ signature->params.match(
+ [&](const VarargsType& varargs) {
+ signatures += "(" + toString(varargs.type) + ")";
+ },
+ [&](const std::vector<type::Type>& params) {
+ signatures += "(";
+ bool first = true;
+ for (const type::Type& param : params) {
+ if (!first) signatures += ", ";
+ signatures += toString(param);
+ first = false;
+ }
+ signatures += ")";
+ }
+ );
+
+ }
+ std::string actualTypes;
+ for (const auto& arg : args) {
+ if (actualTypes.size() > 0) {
+ actualTypes += ", ";
+ }
+ actualTypes += toString(arg->getType());
+ }
+ ctx.error("Expected arguments of type " + signatures + ", but found (" + actualTypes + ") instead.");
+ }
+
+ return ParseResult();
+}
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/expression/find_zoom_curve.cpp b/src/mbgl/style/expression/find_zoom_curve.cpp
new file mode 100644
index 0000000000..5d39e0791e
--- /dev/null
+++ b/src/mbgl/style/expression/find_zoom_curve.cpp
@@ -0,0 +1,76 @@
+#include <mbgl/style/expression/find_zoom_curve.hpp>
+#include <mbgl/style/expression/compound_expression.hpp>
+#include <mbgl/style/expression/let.hpp>
+#include <mbgl/style/expression/coalesce.hpp>
+
+#include <mbgl/util/variant.hpp>
+#include <mbgl/util/optional.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+optional<variant<const InterpolateBase*, const Step*, ParsingError>> findZoomCurve(const expression::Expression* e) {
+ optional<variant<const InterpolateBase*, const Step*, ParsingError>> result;
+
+ if (auto let = dynamic_cast<const Let*>(e)) {
+ result = findZoomCurve(let->getResult());
+ } else if (auto coalesce = dynamic_cast<const Coalesce*>(e)) {
+ std::size_t length = coalesce->getLength();
+ for (std::size_t i = 0; i < length; i++) {
+ result = findZoomCurve(coalesce->getChild(i));
+ if (result) {
+ break;
+ }
+ }
+ } else if (auto curve = dynamic_cast<const InterpolateBase*>(e)) {
+ auto z = dynamic_cast<CompoundExpressionBase*>(curve->getInput().get());
+ if (z && z->getName() == "zoom") {
+ result = {curve};
+ }
+ } else if (auto step = dynamic_cast<const Step*>(e)) {
+ auto z = dynamic_cast<CompoundExpressionBase*>(step->getInput().get());
+ if (z && z->getName() == "zoom") {
+ result = {step};
+ }
+ }
+
+ if (result && result->is<ParsingError>()) {
+ return result;
+ }
+
+ e->eachChild([&](const Expression& child) {
+ optional<variant<const InterpolateBase*, const Step*, ParsingError>> childResult(findZoomCurve(&child));
+ if (childResult) {
+ if (childResult->is<ParsingError>()) {
+ result = childResult;
+ } else if (!result && childResult) {
+ result = {ParsingError {
+ R"("zoom" expression may only be used as input to a top-level "step" or "interpolate" expression.)", ""
+ }};
+ } else if (result && childResult && result != childResult) {
+ result = {ParsingError {
+ R"(Only one zoom-based "step" or "interpolate" subexpression may be used in an expression.)", ""
+ }};
+ }
+ }
+ });
+
+ return result;
+}
+
+variant<const InterpolateBase*, const Step*> findZoomCurveChecked(const expression::Expression* e) {
+ return findZoomCurve(e)->match(
+ [](const ParsingError&) -> variant<const InterpolateBase*, const Step*> {
+ assert(false);
+ return {};
+ },
+ [](auto zoomCurve) -> variant<const InterpolateBase*, const Step*> {
+ return {std::move(zoomCurve)};
+ }
+ );
+}
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/expression/get_covering_stops.cpp b/src/mbgl/style/expression/get_covering_stops.cpp
new file mode 100644
index 0000000000..c9f87d93ac
--- /dev/null
+++ b/src/mbgl/style/expression/get_covering_stops.cpp
@@ -0,0 +1,26 @@
+#include <mbgl/style/expression/get_covering_stops.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+Range<float> getCoveringStops(const std::map<double, std::unique_ptr<Expression>>& stops,
+ const double lower, const double upper) {
+ assert(!stops.empty());
+ auto minIt = stops.lower_bound(lower);
+ auto maxIt = stops.lower_bound(upper);
+
+ // lower_bound yields first element >= lowerZoom, but we want the *last*
+ // element <= lowerZoom, so if we found a stop > lowerZoom, back up by one.
+ if (minIt != stops.begin() && minIt != stops.end() && minIt->first > lower) {
+ minIt--;
+ }
+ return Range<float> {
+ static_cast<float>(minIt == stops.end() ? stops.rbegin()->first : minIt->first),
+ static_cast<float>(maxIt == stops.end() ? stops.rbegin()->first : maxIt->first)
+ };
+}
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/expression/interpolate.cpp b/src/mbgl/style/expression/interpolate.cpp
new file mode 100644
index 0000000000..5ddfca8e9f
--- /dev/null
+++ b/src/mbgl/style/expression/interpolate.cpp
@@ -0,0 +1,211 @@
+#include <mbgl/style/expression/interpolate.hpp>
+#include <mbgl/util/string.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+using Interpolator = variant<ExponentialInterpolator,
+ CubicBezierInterpolator>;
+
+using namespace mbgl::style::conversion;
+
+ParseResult parseInterpolate(const Convertible& value, ParsingContext& ctx) {
+ assert(isArray(value));
+
+ auto length = arrayLength(value);
+
+ if (length < 2) {
+ ctx.error("Expected an interpolation type expression.");
+ return ParseResult();
+ }
+
+ const Convertible& interp = arrayMember(value, 1);
+ if (!isArray(interp) || arrayLength(interp) == 0) {
+ ctx.error("Expected an interpolation type expression.");
+ return ParseResult();
+ }
+
+ optional<Interpolator> interpolator;
+
+ const optional<std::string> interpName = toString(arrayMember(interp, 0));
+ if (interpName && *interpName == "linear") {
+ interpolator = {ExponentialInterpolator(1.0)};
+ } else if (interpName && *interpName == "exponential") {
+ optional<double> base;
+ if (arrayLength(interp) == 2) {
+ base = toDouble(arrayMember(interp, 1));
+ }
+ if (!base) {
+ ctx.error("Exponential interpolation requires a numeric base.", 1, 1);
+ return ParseResult();
+ }
+ interpolator = {ExponentialInterpolator(*base)};
+ } else if (interpName && *interpName == "cubic-bezier") {
+ optional<double> x1;
+ optional<double> y1;
+ optional<double> x2;
+ optional<double> y2;
+ if (arrayLength(interp) == 5) {
+ x1 = toDouble(arrayMember(interp, 1));
+ y1 = toDouble(arrayMember(interp, 2));
+ x2 = toDouble(arrayMember(interp, 3));
+ y2 = toDouble(arrayMember(interp, 4));
+ }
+ if (
+ !x1 || !y1 || !x2 || !y2 ||
+ *x1 < 0 || *x1 > 1 ||
+ *y1 < 0 || *y1 > 1 ||
+ *x2 < 0 || *x2 > 1 ||
+ *y2 < 0 || *y2 > 1
+ ) {
+ ctx.error("Cubic bezier interpolation requires four numeric arguments with values between 0 and 1.", 1);
+ return ParseResult();
+
+ }
+ interpolator = {CubicBezierInterpolator(*x1, *y1, *x2, *y2)};
+ }
+
+ if (!interpolator) {
+ ctx.error("Unknown interpolation type " + (interpName ? *interpName : ""), 1, 0);
+ return ParseResult();
+ }
+
+ std::size_t minArgs = 4;
+ if (length - 1 < minArgs) {
+ ctx.error("Expected at least 4 arguments, but found only " + util::toString(length - 1) + ".");
+ return ParseResult();
+ }
+
+ // [interpolation, interp_type, input, 2 * (n pairs)...]
+ if ((length - 1) % 2 != 0) {
+ ctx.error("Expected an even number of arguments.");
+ return ParseResult();
+ }
+
+ ParseResult input = ctx.parse(arrayMember(value, 2), 2, {type::Number});
+ if (!input) {
+ return input;
+ }
+
+ std::map<double, std::unique_ptr<Expression>> stops;
+ optional<type::Type> outputType;
+ if (ctx.getExpected() && *ctx.getExpected() != type::Value) {
+ outputType = ctx.getExpected();
+ }
+
+ double previous = - std::numeric_limits<double>::infinity();
+
+ for (std::size_t i = 3; i + 1 < length; i += 2) {
+ const optional<mbgl::Value> labelValue = toValue(arrayMember(value, i));
+ optional<double> label;
+ optional<std::string> labelError;
+ if (labelValue) {
+ labelValue->match(
+ [&](uint64_t n) {
+ if (n > std::numeric_limits<double>::max()) {
+ label = {std::numeric_limits<double>::infinity()};
+ } else {
+ label = {static_cast<double>(n)};
+ }
+ },
+ [&](int64_t n) {
+ if (n > std::numeric_limits<double>::max()) {
+ label = {std::numeric_limits<double>::infinity()};
+ } else {
+ label = {static_cast<double>(n)};
+ }
+ },
+ [&](double n) {
+ if (n > std::numeric_limits<double>::max()) {
+ label = {std::numeric_limits<double>::infinity()};
+ } else {
+ label = {static_cast<double>(n)};
+ }
+ },
+ [&](const auto&) {}
+ );
+ }
+ if (!label) {
+ ctx.error(labelError ? *labelError :
+ R"(Input/output pairs for "interpolate" expressions must be defined using literal numeric values (not computed expressions) for the input values.)",
+ i);
+ return ParseResult();
+ }
+
+ if (*label <= previous) {
+ ctx.error(
+ R"(Input/output pairs for "interpolate" expressions must be arranged with input values in strictly ascending order.)",
+ i
+ );
+ return ParseResult();
+ }
+ previous = *label;
+
+ auto output = ctx.parse(arrayMember(value, i + 1), i + 1, outputType);
+ if (!output) {
+ return ParseResult();
+ }
+ if (!outputType) {
+ outputType = (*output)->getType();
+ }
+
+ stops.emplace(*label, std::move(*output));
+ }
+
+ assert(outputType);
+
+ if (
+ *outputType != type::Number &&
+ *outputType != type::Color &&
+ !(
+ outputType->is<type::Array>() &&
+ outputType->get<type::Array>().itemType == type::Number &&
+ outputType->get<type::Array>().N
+ )
+ )
+ {
+ ctx.error("Type " + toString(*outputType) + " is not interpolatable.");
+ return ParseResult();
+ }
+
+ return outputType->match(
+ [&](const type::NumberType&) -> ParseResult {
+ return interpolator->match([&](const auto& interpolator_) {
+ return ParseResult(std::make_unique<Interpolate<double>>(
+ *outputType, interpolator_, std::move(*input), std::move(stops)
+ ));
+ });
+ },
+ [&](const type::ColorType&) -> ParseResult {
+ return interpolator->match([&](const auto& interpolator_) {
+ return ParseResult(std::make_unique<Interpolate<Color>>(
+ *outputType, interpolator_, std::move(*input), std::move(stops)
+ ));
+ });
+ },
+ [&](const type::Array& arrayType) -> ParseResult {
+ return interpolator->match(
+ [&](const auto& continuousInterpolator) {
+ if (arrayType.itemType != type::Number || !arrayType.N) {
+ assert(false); // interpolability already checked above.
+ return ParseResult();
+ }
+ return ParseResult(std::make_unique<Interpolate<std::vector<Value>>>(
+ *outputType, continuousInterpolator, std::move(*input), std::move(stops)
+ ));
+ }
+ );
+ },
+ [&](const auto&) {
+ // unreachable: Null, Boolean, String, Object, Value output types
+ // are not interpolatable, and interpolability was already checked above
+ assert(false);
+ return ParseResult();
+ }
+ );
+}
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/expression/is_constant.cpp b/src/mbgl/style/expression/is_constant.cpp
new file mode 100644
index 0000000000..0ebb37faa9
--- /dev/null
+++ b/src/mbgl/style/expression/is_constant.cpp
@@ -0,0 +1,40 @@
+#include <mbgl/style/expression/is_constant.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+bool isFeatureConstant(const Expression& expression) {
+ if (auto e = dynamic_cast<const CompoundExpressionBase*>(&expression)) {
+ const std::string name = e->getName();
+ optional<std::size_t> parameterCount = e->getParameterCount();
+ if (name == "get" && parameterCount && *parameterCount == 1) {
+ return false;
+ } else if (name == "has" && parameterCount && *parameterCount == 1) {
+ return false;
+ } else if (
+ name == "properties" ||
+ name == "geometry-type" ||
+ name == "id"
+ ) {
+ return false;
+ }
+ }
+
+ bool featureConstant = true;
+ expression.eachChild([&](const Expression& e) {
+ if (featureConstant && !isFeatureConstant(e)) {
+ featureConstant = false;
+ }
+ });
+ return featureConstant;
+}
+
+bool isZoomConstant(const Expression& e) {
+ return isGlobalPropertyConstant(e, std::array<std::string, 1>{{"zoom"}});
+}
+
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/expression/is_expression.cpp b/src/mbgl/style/expression/is_expression.cpp
new file mode 100644
index 0000000000..77212f6a1e
--- /dev/null
+++ b/src/mbgl/style/expression/is_expression.cpp
@@ -0,0 +1,29 @@
+#include <mbgl/style/expression/is_expression.hpp>
+#include <mbgl/style/expression/compound_expression.hpp>
+#include <mbgl/style/expression/parsing_context.hpp>
+
+#include <mbgl/style/conversion.hpp>
+
+#include <unordered_set>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+using namespace mbgl::style::conversion;
+
+bool isExpression(const Convertible& value) {
+ const ExpressionRegistry& registry = getExpressionRegistry();
+
+ if (!isArray(value) || arrayLength(value) == 0) return false;
+ optional<std::string> name = toString(arrayMember(value, 0));
+ if (!name) return false;
+
+ return (registry.find(*name) != registry.end()) ||
+ (CompoundExpressionRegistry::definitions.find(*name) != CompoundExpressionRegistry::definitions.end());
+}
+
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/expression/let.cpp b/src/mbgl/style/expression/let.cpp
new file mode 100644
index 0000000000..561e8515d4
--- /dev/null
+++ b/src/mbgl/style/expression/let.cpp
@@ -0,0 +1,92 @@
+#include <mbgl/style/expression/let.hpp>
+#include <mbgl/style/conversion/get_json_type.hpp>
+#include <mbgl/util/string.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+EvaluationResult Let::evaluate(const EvaluationContext& params) const {
+ return result->evaluate(params);
+}
+
+void Let::eachChild(const std::function<void(const Expression&)>& visit) const {
+ for (auto it = bindings.begin(); it != bindings.end(); it++) {
+ visit(*it->second);
+ }
+ visit(*result);
+}
+
+using namespace mbgl::style::conversion;
+
+ParseResult Let::parse(const Convertible& value, ParsingContext& ctx) {
+ assert(isArray(value));
+
+ std::size_t length = arrayLength(value);
+
+ if (length < 4) {
+ ctx.error("Expected at least 3 arguments, but found " + util::toString(length - 1) + " instead.");
+ return ParseResult();
+ }
+
+ std::map<std::string, std::shared_ptr<Expression>> bindings_;
+ for(std::size_t i = 1; i < length - 1; i += 2) {
+ optional<std::string> name = toString(arrayMember(value, i));
+ if (!name) {
+ ctx.error("Expected string, but found " + getJSONType(arrayMember(value, i)) + " instead.", i);
+ return ParseResult();
+ }
+
+ bool isValidName = std::all_of(name->begin(), name->end(), [](unsigned char c) {
+ return std::isalnum(c) || c == '_';
+ });
+ if (!isValidName) {
+ ctx.error("Variable names must contain only alphanumeric characters or '_'.", 1);
+ return ParseResult();
+ }
+
+ ParseResult bindingValue = ctx.parse(arrayMember(value, i + 1), i + 1);
+ if (!bindingValue) {
+ return ParseResult();
+ }
+
+ bindings_.emplace(*name, std::move(*bindingValue));
+ }
+
+ ParseResult result_ = ctx.parse(arrayMember(value, length - 1), length - 1, ctx.getExpected(), bindings_);
+ if (!result_) {
+ return ParseResult();
+ }
+
+ return ParseResult(std::make_unique<Let>(std::move(bindings_), std::move(*result_)));
+}
+
+EvaluationResult Var::evaluate(const EvaluationContext& params) const {
+ return value->evaluate(params);
+}
+
+void Var::eachChild(const std::function<void(const Expression&)>&) const {}
+
+ParseResult Var::parse(const Convertible& value_, ParsingContext& ctx) {
+ assert(isArray(value_));
+
+ if (arrayLength(value_) != 2 || !toString(arrayMember(value_, 1))) {
+ ctx.error("'var' expression requires exactly one string literal argument.");
+ return ParseResult();
+ }
+
+ std::string name_ = *toString(arrayMember(value_, 1));
+
+ optional<std::shared_ptr<Expression>> bindingValue = ctx.getBinding(name_);
+ if (!bindingValue) {
+ ctx.error(R"(Unknown variable ")" + name_ + R"(". Make sure ")" +
+ name_ + R"(" has been bound in an enclosing "let" expression before using it.)", 1);
+ return ParseResult();
+ }
+
+ return ParseResult(std::make_unique<Var>(name_, std::move(*bindingValue)));
+}
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/expression/literal.cpp b/src/mbgl/style/expression/literal.cpp
new file mode 100644
index 0000000000..7e79fcbfe6
--- /dev/null
+++ b/src/mbgl/style/expression/literal.cpp
@@ -0,0 +1,108 @@
+#include <mbgl/style/expression/literal.hpp>
+#include <mbgl/util/string.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+template <typename T>
+optional<Value> checkNumber(T n) {
+ if (n > std::numeric_limits<double>::max()) {
+ return {std::numeric_limits<double>::infinity()};
+ } else {
+ return {static_cast<double>(n)};
+ }
+}
+
+using namespace mbgl::style::conversion;
+optional<Value> parseValue(const Convertible& value, ParsingContext& ctx) {
+ if (isUndefined(value)) return {Null};
+ if (isObject(value)) {
+ std::unordered_map<std::string, Value> result;
+ bool error = false;
+ eachMember(value, [&] (const std::string& k, const mbgl::style::conversion::Convertible& v) -> optional<conversion::Error> {
+ if (!error) {
+ optional<Value> memberValue = parseValue(v, ctx);
+ if (memberValue) {
+ result.emplace(k, *memberValue);
+ } else {
+ error = true;
+ }
+ }
+ return {};
+ });
+ return error ? optional<Value>() : optional<Value>(result);
+ }
+
+ if (isArray(value)) {
+ std::vector<Value> result;
+ const auto length = arrayLength(value);
+ for(std::size_t i = 0; i < length; i++) {
+ optional<Value> item = parseValue(arrayMember(value, i), ctx);
+ if (item) {
+ result.emplace_back(*item);
+ } else {
+ return optional<Value>();
+ }
+ }
+ return optional<Value>(result);
+ }
+
+ optional<mbgl::Value> v = toValue(value);
+ // since value represents a JSON value, if it's not undefined, object, or
+ // array, it must be convertible to mbgl::Value
+ assert(v);
+
+ return v->match(
+ [&](uint64_t n) { return checkNumber(n); },
+ [&](int64_t n) { return checkNumber(n); },
+ [&](double n) { return checkNumber(n); },
+ [&](const auto&) {
+ return optional<Value>(toExpressionValue(*v));
+ }
+ );
+}
+
+ParseResult Literal::parse(const Convertible& value, ParsingContext& ctx) {
+ if (isObject(value)) {
+ ctx.error(R"(Bare objects invalid. Use ["literal", {...}] instead.)");
+ return ParseResult();
+ } else if (isArray(value)) {
+ // object or array value, quoted with ["literal", value]
+ if (arrayLength(value) != 2) {
+ ctx.error("'literal' expression requires exactly one argument, but found " + util::toString(arrayLength(value) - 1) + " instead.");
+ return ParseResult();
+ }
+ const optional<Value> parsedValue = parseValue(arrayMember(value, 1), ctx);
+ if (!parsedValue) {
+ return ParseResult();
+ }
+
+ // special case: infer the item type if possible for zero-length arrays
+ if (
+ ctx.getExpected() &&
+ ctx.getExpected()->template is<type::Array>() &&
+ parsedValue->template is<std::vector<Value>>()
+ ) {
+ auto type = typeOf(*parsedValue).template get<type::Array>();
+ auto expected = ctx.getExpected()->template get<type::Array>();
+ if (
+ type.N && (*type.N == 0) &&
+ (!expected.N || (*expected.N == 0))
+ ) {
+ return ParseResult(std::make_unique<Literal>(expected, parsedValue->template get<std::vector<Value>>()));
+ }
+ }
+
+ return ParseResult(std::make_unique<Literal>(*parsedValue));
+ } else {
+ // bare primitive value (string, number, boolean, null)
+ const optional<Value> parsedValue = parseValue(value, ctx);
+ return ParseResult(std::make_unique<Literal>(*parsedValue));
+ }
+}
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
+
diff --git a/src/mbgl/style/expression/match.cpp b/src/mbgl/style/expression/match.cpp
new file mode 100644
index 0000000000..35356747c9
--- /dev/null
+++ b/src/mbgl/style/expression/match.cpp
@@ -0,0 +1,263 @@
+#include <mbgl/style/expression/match.hpp>
+#include <mbgl/style/expression/check_subtype.hpp>
+#include <mbgl/style/expression/parsing_context.hpp>
+#include <mbgl/util/string.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+template <typename T>
+void Match<T>::eachChild(const std::function<void(const Expression&)>& visit) const {
+ visit(*input);
+ for (const std::pair<T, std::shared_ptr<Expression>>& branch : branches) {
+ visit(*branch.second);
+ }
+ visit(*otherwise);
+}
+
+template <typename T>
+bool Match<T>::operator==(const Expression& e) const {
+ if (auto rhs = dynamic_cast<const Match*>(&e)) {
+ return (*input == *(rhs->input) &&
+ *otherwise == *(rhs->otherwise) &&
+ Expression::childrenEqual(branches, rhs->branches));
+ }
+ return false;
+}
+
+
+template<> EvaluationResult Match<std::string>::evaluate(const EvaluationContext& params) const {
+ const EvaluationResult inputValue = input->evaluate(params);
+ if (!inputValue) {
+ return inputValue.error();
+ }
+
+ auto it = branches.find(inputValue->get<std::string>());
+ if (it != branches.end()) {
+ return (*it).second->evaluate(params);
+ }
+
+ return otherwise->evaluate(params);
+}
+
+template<> EvaluationResult Match<int64_t>::evaluate(const EvaluationContext& params) const {
+ const EvaluationResult inputValue = input->evaluate(params);
+ if (!inputValue) {
+ return inputValue.error();
+ }
+
+ const auto numeric = inputValue->get<double>();
+ int64_t rounded = std::floor(numeric);
+ if (numeric == rounded) {
+ auto it = branches.find(rounded);
+ if (it != branches.end()) {
+ return (*it).second->evaluate(params);
+ }
+ }
+
+ return otherwise->evaluate(params);
+}
+
+template class Match<int64_t>;
+template class Match<std::string>;
+
+using InputType = variant<int64_t, std::string>;
+
+using namespace mbgl::style::conversion;
+optional<InputType> parseInputValue(const Convertible& input, ParsingContext& parentContext, std::size_t index, optional<type::Type>& inputType) {
+ using namespace mbgl::style::conversion;
+ optional<InputType> result;
+ optional<type::Type> type;
+
+ auto value = toValue(input);
+
+ if (value) {
+ value->match(
+ [&] (uint64_t n) {
+ if (!Value::isSafeInteger(n)) {
+ parentContext.error("Branch labels must be integers no larger than " + util::toString(Value::maxSafeInteger()) + ".", index);
+ } else {
+ type = {type::Number};
+ result = {static_cast<int64_t>(n)};
+ }
+ },
+ [&] (int64_t n) {
+ if (!Value::isSafeInteger(n)) {
+ parentContext.error("Branch labels must be integers no larger than " + util::toString(Value::maxSafeInteger()) + ".", index);
+ } else {
+ type = {type::Number};
+ result = {n};
+ }
+ },
+ [&] (double n) {
+ if (!Value::isSafeInteger(n)) {
+ parentContext.error("Branch labels must be integers no larger than " + util::toString(Value::maxSafeInteger()) + ".", index);
+ } else if (n != std::floor(n)) {
+ parentContext.error("Numeric branch labels must be integer values.", index);
+ } else {
+ type = {type::Number};
+ result = {static_cast<int64_t>(n)};
+ }
+ },
+ [&] (const std::string& s) {
+ type = {type::String};
+ result = {s};
+ },
+ [&] (const auto&) {
+ parentContext.error("Branch labels must be numbers or strings.", index);
+ }
+ );
+ } else {
+ parentContext.error("Branch labels must be numbers or strings.", index);
+ }
+
+ if (!type) {
+ return result;
+ }
+
+ if (!inputType) {
+ inputType = type;
+ } else {
+ optional<std::string> err = type::checkSubtype(*inputType, *type);
+ if (err) {
+ parentContext.error(*err, index);
+ return optional<InputType>();
+ }
+ }
+
+ return result;
+}
+
+template <typename T>
+static ParseResult create(type::Type outputType,
+ std::unique_ptr<Expression>input,
+ std::vector<std::pair<std::vector<InputType>,
+ std::unique_ptr<Expression>>> branches,
+ std::unique_ptr<Expression> otherwise,
+ ParsingContext& ctx) {
+ typename Match<T>::Branches typedBranches;
+
+ std::size_t index = 2;
+
+ typedBranches.reserve(branches.size());
+ for (std::pair<std::vector<InputType>,
+ std::unique_ptr<Expression>>& pair : branches) {
+ std::shared_ptr<Expression> result = std::move(pair.second);
+ for (const InputType& label : pair.first) {
+ const auto& typedLabel = label.template get<T>();
+ if (typedBranches.find(typedLabel) != typedBranches.end()) {
+ ctx.error("Branch labels must be unique.", index);
+ return ParseResult();
+ }
+ typedBranches.emplace(typedLabel, result);
+ }
+
+ index += 2;
+ }
+ return ParseResult(std::make_unique<Match<T>>(
+ outputType,
+ std::move(input),
+ std::move(typedBranches),
+ std::move(otherwise)
+ ));
+}
+
+ParseResult parseMatch(const Convertible& value, ParsingContext& ctx) {
+ assert(isArray(value));
+ auto length = arrayLength(value);
+ if (length < 5) {
+ ctx.error(
+ "Expected at least 4 arguments, but found only " + util::toString(length - 1) + "."
+ );
+ return ParseResult();
+ }
+
+ // Expect odd-length array: ["match", input, 2 * (n pairs)..., otherwise]
+ if (length % 2 != 1) {
+ ctx.error("Expected an even number of arguments.");
+ return ParseResult();
+ }
+
+ optional<type::Type> inputType;
+ optional<type::Type> outputType;
+ if (ctx.getExpected() && *ctx.getExpected() != type::Value) {
+ outputType = ctx.getExpected();
+ }
+
+ std::vector<std::pair<std::vector<InputType>,
+ std::unique_ptr<Expression>>> branches;
+
+ branches.reserve((length - 3) / 2);
+ for (size_t i = 2; i + 1 < length; i += 2) {
+ const auto& label = arrayMember(value, i);
+
+ std::vector<InputType> labels;
+ // Match pair inputs are provided as either a literal value or a
+ // raw JSON array of string / number / boolean values.
+ if (isArray(label)) {
+ auto groupLength = arrayLength(label);
+ if (groupLength == 0) {
+ ctx.error("Expected at least one branch label.", i);
+ return ParseResult();
+ }
+
+ labels.reserve(groupLength);
+ for (size_t j = 0; j < groupLength; j++) {
+ const optional<InputType> inputValue = parseInputValue(arrayMember(label, j), ctx, i, inputType);
+ if (!inputValue) {
+ return ParseResult();
+ }
+ labels.push_back(*inputValue);
+ }
+ } else {
+ const optional<InputType> inputValue = parseInputValue(label, ctx, i, inputType);
+ if (!inputValue) {
+ return ParseResult();
+ }
+ labels.push_back(*inputValue);
+ }
+
+ ParseResult output = ctx.parse(arrayMember(value, i + 1), i + 1, outputType);
+ if (!output) {
+ return ParseResult();
+ }
+
+ if (!outputType) {
+ outputType = (*output)->getType();
+ }
+
+ branches.push_back(std::make_pair(std::move(labels), std::move(*output)));
+ }
+
+ auto input = ctx.parse(arrayMember(value, 1), 1, inputType);
+ if (!input) {
+ return ParseResult();
+ }
+
+ auto otherwise = ctx.parse(arrayMember(value, length - 1), length - 1, outputType);
+ if (!otherwise) {
+ return ParseResult();
+ }
+
+ assert(inputType && outputType);
+
+ return inputType->match(
+ [&](const type::NumberType&) {
+ return create<int64_t>(*outputType, std::move(*input), std::move(branches), std::move(*otherwise), ctx);
+ },
+ [&](const type::StringType&) {
+ return create<std::string>(*outputType, std::move(*input), std::move(branches), std::move(*otherwise), ctx);
+ },
+ [&](const auto&) {
+ // unreachable: inputType is set by parseInputValue(), which only
+ // accepts string and (integer) numeric values.
+ assert(false);
+ return ParseResult();
+ }
+ );
+}
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/expression/parsing_context.cpp b/src/mbgl/style/expression/parsing_context.cpp
new file mode 100644
index 0000000000..501ba2749f
--- /dev/null
+++ b/src/mbgl/style/expression/parsing_context.cpp
@@ -0,0 +1,208 @@
+
+#include <mbgl/style/expression/parsing_context.hpp>
+#include <mbgl/style/expression/check_subtype.hpp>
+#include <mbgl/style/expression/is_constant.hpp>
+#include <mbgl/style/expression/type.hpp>
+
+#include <mbgl/style/expression/expression.hpp>
+#include <mbgl/style/expression/at.hpp>
+#include <mbgl/style/expression/array_assertion.hpp>
+#include <mbgl/style/expression/assertion.hpp>
+#include <mbgl/style/expression/boolean_operator.hpp>
+#include <mbgl/style/expression/case.hpp>
+#include <mbgl/style/expression/coalesce.hpp>
+#include <mbgl/style/expression/coercion.hpp>
+#include <mbgl/style/expression/compound_expression.hpp>
+#include <mbgl/style/expression/interpolate.hpp>
+#include <mbgl/style/expression/let.hpp>
+#include <mbgl/style/expression/literal.hpp>
+#include <mbgl/style/expression/match.hpp>
+#include <mbgl/style/expression/step.hpp>
+
+#include <mbgl/style/expression/find_zoom_curve.hpp>
+
+#include <mbgl/style/conversion/get_json_type.hpp>
+
+#include <mbgl/util/string.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+bool isConstant(const Expression& expression) {
+ if (dynamic_cast<const Var*>(&expression)) {
+ return false;
+ }
+
+ if (auto compound = dynamic_cast<const CompoundExpressionBase*>(&expression)) {
+ if (compound->getName() == "error") {
+ return false;
+ }
+ }
+
+ bool literalArgs = true;
+ expression.eachChild([&](const Expression& child) {
+ if (!dynamic_cast<const Literal*>(&child)) {
+ literalArgs = false;
+ }
+ });
+ if (!literalArgs) {
+ return false;
+ }
+
+ return isFeatureConstant(expression) &&
+ isGlobalPropertyConstant(expression, std::array<std::string, 2>{{"zoom", "heatmap-density"}});
+}
+
+using namespace mbgl::style::conversion;
+
+ParseResult ParsingContext::parse(const Convertible& value, std::size_t index_, optional<type::Type> expected_) {
+ ParsingContext child(key + "[" + util::toString(index_) + "]",
+ errors,
+ std::move(expected_),
+ scope);
+ return child.parse(value);
+}
+
+ParseResult ParsingContext::parse(const Convertible& value, std::size_t index_, optional<type::Type> expected_,
+ const std::map<std::string, std::shared_ptr<Expression>>& bindings) {
+ ParsingContext child(key + "[" + util::toString(index_) + "]",
+ errors,
+ std::move(expected_),
+ std::make_shared<detail::Scope>(bindings, scope));
+ return child.parse(value);
+}
+
+const ExpressionRegistry& getExpressionRegistry() {
+ static ExpressionRegistry registry {{
+ {"all", All::parse},
+ {"any", Any::parse},
+ {"array", ArrayAssertion::parse},
+ {"at", At::parse},
+ {"boolean", Assertion::parse},
+ {"case", Case::parse},
+ {"coalesce", Coalesce::parse},
+ {"interpolate", parseInterpolate},
+ {"let", Let::parse},
+ {"literal", Literal::parse},
+ {"match", parseMatch},
+ {"number", Assertion::parse},
+ {"object", Assertion::parse},
+ {"step", Step::parse},
+ {"string", Assertion::parse},
+ {"to-color", Coercion::parse},
+ {"to-number", Coercion::parse},
+ {"var", Var::parse}
+ }};
+ return registry;
+}
+
+ParseResult ParsingContext::parse(const Convertible& value)
+{
+ ParseResult parsed;
+
+ if (isArray(value)) {
+ const std::size_t length = arrayLength(value);
+ if (length == 0) {
+ error(R"(Expected an array with at least one element. If you wanted a literal array, use ["literal", []].)");
+ return ParseResult();
+ }
+
+ const optional<std::string> op = toString(arrayMember(value, 0));
+ if (!op) {
+ error(
+ "Expression name must be a string, but found " + getJSONType(arrayMember(value, 0)) +
+ R"( instead. If you wanted a literal array, use ["literal", [...]].)",
+ 0
+ );
+ return ParseResult();
+ }
+
+ const ExpressionRegistry& registry = getExpressionRegistry();
+ auto parseFunction = registry.find(*op);
+ if (parseFunction != registry.end()) {
+ parsed = parseFunction->second(value, *this);
+ } else {
+ parsed = parseCompoundExpression(*op, value, *this);
+ }
+ } else {
+ parsed = Literal::parse(value, *this);
+ }
+
+ if (!parsed) {
+ assert(errors->size() > 0);
+ } else if (expected) {
+ auto wrapForType = [&](const type::Type& target, std::unique_ptr<Expression> expression) -> std::unique_ptr<Expression> {
+ std::vector<std::unique_ptr<Expression>> args;
+ args.push_back(std::move(expression));
+ if (target == type::Color) {
+ return std::make_unique<Coercion>(target, std::move(args));
+ } else {
+ return std::make_unique<Assertion>(target, std::move(args));
+ }
+ };
+
+ const type::Type actual = (*parsed)->getType();
+ if (*expected == type::Color && (actual == type::String || actual == type::Value)) {
+ parsed = wrapForType(type::Color, std::move(*parsed));
+ } else if ((*expected == type::String || *expected == type::Number || *expected == type::Boolean) && actual == type::Value) {
+ parsed = wrapForType(*expected, std::move(*parsed));
+ }
+
+ checkType((*parsed)->getType());
+ if (errors->size() > 0) {
+ return ParseResult();
+ }
+ }
+
+ // If an expression's arguments are all literals, we can evaluate
+ // it immediately and replace it with a literal value in the
+ // parsed result.
+ if (parsed && !dynamic_cast<Literal *>(parsed->get()) && isConstant(**parsed)) {
+ EvaluationContext params(nullptr);
+ EvaluationResult evaluated((*parsed)->evaluate(params));
+ if (!evaluated) {
+ error(evaluated.error().message);
+ return ParseResult();
+ }
+
+ const type::Type type = (*parsed)->getType();
+ if (type.is<type::Array>()) {
+ // keep the original expression's array type, even if the evaluated
+ // type is more specific.
+ return ParseResult(std::make_unique<Literal>(
+ type.get<type::Array>(),
+ evaluated->get<std::vector<Value>>())
+ );
+ } else {
+ return ParseResult(std::make_unique<Literal>(*evaluated));
+ }
+ }
+
+ // if this is the root expression, enforce constraints on the use ["zoom"].
+ if (key.size() == 0 && parsed && !isZoomConstant(**parsed)) {
+ optional<variant<const InterpolateBase*, const Step*, ParsingError>> zoomCurve = findZoomCurve(parsed->get());
+ if (!zoomCurve) {
+ error(R"("zoom" expression may only be used as input to a top-level "step" or "interpolate" expression.)");
+ return ParseResult();
+ } else if (zoomCurve->is<ParsingError>()) {
+ error(zoomCurve->get<ParsingError>().message);
+ return ParseResult();
+ }
+ }
+
+ return parsed;
+}
+
+optional<std::string> ParsingContext::checkType(const type::Type& t) {
+ assert(expected);
+ optional<std::string> err = type::checkSubtype(*expected, t);
+ if (err) {
+ error(*err);
+ }
+ return err;
+}
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/expression/step.cpp b/src/mbgl/style/expression/step.cpp
new file mode 100644
index 0000000000..bfcb6fd270
--- /dev/null
+++ b/src/mbgl/style/expression/step.cpp
@@ -0,0 +1,152 @@
+#include <mbgl/style/expression/step.hpp>
+#include <mbgl/style/expression/get_covering_stops.hpp>
+#include <mbgl/util/string.hpp>
+
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+EvaluationResult Step::evaluate(const EvaluationContext& params) const {
+ const EvaluationResult evaluatedInput = input->evaluate(params);
+ if (!evaluatedInput) { return evaluatedInput.error(); }
+ float x = *fromExpressionValue<float>(*evaluatedInput);
+
+ if (stops.empty()) {
+ return EvaluationError { "No stops in step curve." };
+ }
+
+ auto it = stops.upper_bound(x);
+ if (it == stops.end()) {
+ return stops.rbegin()->second->evaluate(params);
+ } else if (it == stops.begin()) {
+ return stops.begin()->second->evaluate(params);
+ } else {
+ return std::prev(it)->second->evaluate(params);
+ }
+}
+
+void Step::eachChild(const std::function<void(const Expression&)>& visit) const {
+ visit(*input);
+ for (auto it = stops.begin(); it != stops.end(); it++) {
+ visit(*it->second);
+ }
+}
+
+bool Step::operator==(const Expression& e) const {
+ if (auto rhs = dynamic_cast<const Step*>(&e)) {
+ return *input == *(rhs->input) && Expression::childrenEqual(stops, rhs->stops);
+ }
+ return false;
+}
+
+Range<float> Step::getCoveringStops(const double lower, const double upper) const {
+ return ::mbgl::style::expression::getCoveringStops(stops, lower, upper);
+}
+
+
+ParseResult Step::parse(const mbgl::style::conversion::Convertible& value, ParsingContext& ctx) {
+ assert(isArray(value));
+
+ auto length = arrayLength(value);
+
+ if (length - 1 < 4) {
+ ctx.error("Expected at least 4 arguments, but found only " + util::toString(length - 1) + ".");
+ return ParseResult();
+ }
+
+ // [step, input, firstOutput_value, 2 * (n pairs)...]
+ if ((length - 1) % 2 != 0) {
+ ctx.error("Expected an even number of arguments.");
+ return ParseResult();
+ }
+
+ ParseResult input = ctx.parse(arrayMember(value, 1), 1, {type::Number});
+ if (!input) {
+ return input;
+ }
+
+ std::map<double, std::unique_ptr<Expression>> stops;
+ optional<type::Type> outputType;
+ if (ctx.getExpected() && *ctx.getExpected() != type::Value) {
+ outputType = ctx.getExpected();
+ }
+
+ double previous = - std::numeric_limits<double>::infinity();
+
+ // consume the first output value, which doesn't have a corresponding input value,
+ // before proceeding into the "stops" loop below.
+ auto firstOutput = ctx.parse(arrayMember(value, 2), 2, outputType);
+ if (!firstOutput) {
+ return ParseResult();
+ }
+ if (!outputType) {
+ outputType = (*firstOutput)->getType();
+ }
+ stops.emplace(-std::numeric_limits<double>::infinity(), std::move(*firstOutput));
+
+
+ for (std::size_t i = 3; i + 1 < length; i += 2) {
+ const optional<mbgl::Value> labelValue = toValue(arrayMember(value, i));
+ optional<double> label;
+ if (labelValue) {
+ labelValue->match(
+ [&](uint64_t n) {
+ if (n > std::numeric_limits<double>::max()) {
+ label = {std::numeric_limits<double>::infinity()};
+ } else {
+ label = {static_cast<double>(n)};
+ }
+ },
+ [&](int64_t n) {
+ if (n > std::numeric_limits<double>::max()) {
+ label = {std::numeric_limits<double>::infinity()};
+ } else {
+ label = {static_cast<double>(n)};
+ }
+ },
+ [&](double n) {
+ if (n > std::numeric_limits<double>::max()) {
+ label = {std::numeric_limits<double>::infinity()};
+ } else {
+ label = {static_cast<double>(n)};
+ }
+ },
+ [&](const auto&) {}
+ );
+ }
+ if (!label) {
+ ctx.error(R"(Input/output pairs for "step" expressions must be defined using literal numeric values (not computed expressions) for the input values.)", i);
+ return ParseResult();
+ }
+
+ if (*label <= previous) {
+ ctx.error(
+ R"(Input/output pairs for "step" expressions must be arranged with input values in strictly ascending order.)",
+ i
+ );
+ return ParseResult();
+ }
+ previous = *label;
+
+ auto output = ctx.parse(arrayMember(value, i + 1), i + 1, outputType);
+ if (!output) {
+ return ParseResult();
+ }
+ if (!outputType) {
+ outputType = (*output)->getType();
+ }
+
+ stops.emplace(*label, std::move(*output));
+ }
+
+ assert(outputType);
+
+ return ParseResult(std::make_unique<Step>(*outputType, std::move(*input), std::move(stops)));
+}
+
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
+
diff --git a/src/mbgl/style/expression/util.cpp b/src/mbgl/style/expression/util.cpp
new file mode 100644
index 0000000000..f198fb3e1b
--- /dev/null
+++ b/src/mbgl/style/expression/util.cpp
@@ -0,0 +1,39 @@
+
+#include <mbgl/style/expression/util.hpp>
+#include <mbgl/style/expression/value.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+std::string stringifyColor(double r, double g, double b, double a) {
+ return stringify(r) + ", " +
+ stringify(g) + ", " +
+ stringify(b) + ", " +
+ stringify(a);
+}
+
+Result<Color> rgba(double r, double g, double b, double a) {
+ if (
+ r < 0 || r > 255 ||
+ g < 0 || g > 255 ||
+ b < 0 || b > 255
+ ) {
+ return EvaluationError {
+ "Invalid rgba value [" + stringifyColor(r, g, b, a) +
+ "]: 'r', 'g', and 'b' must be between 0 and 255."
+ };
+ }
+ if (a < 0 || a > 1) {
+ return EvaluationError {
+ "Invalid rgba value [" + stringifyColor(r, g, b, a) +
+ "]: 'a' must be between 0 and 1."
+ };
+ }
+ return Color(r / 255, g / 255, b / 255, a);
+}
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
+
diff --git a/src/mbgl/style/expression/util.hpp b/src/mbgl/style/expression/util.hpp
new file mode 100644
index 0000000000..b6fc408ed9
--- /dev/null
+++ b/src/mbgl/style/expression/util.hpp
@@ -0,0 +1,14 @@
+#pragma once
+
+#include <mbgl/style/expression/expression.hpp>
+#include <mbgl/util/color.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+Result<Color> rgba(double r, double g, double b, double a);
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/expression/value.cpp b/src/mbgl/style/expression/value.cpp
new file mode 100644
index 0000000000..b75f471ce3
--- /dev/null
+++ b/src/mbgl/style/expression/value.cpp
@@ -0,0 +1,322 @@
+#include <rapidjson/writer.h>
+#include <rapidjson/stringbuffer.h>
+#include <mbgl/style/expression/value.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+type::Type typeOf(const Value& value) {
+ return value.match(
+ [&](bool) -> type::Type { return type::Boolean; },
+ [&](double) -> type::Type { return type::Number; },
+ [&](const std::string&) -> type::Type { return type::String; },
+ [&](const Color&) -> type::Type { return type::Color; },
+ [&](const NullValue&) -> type::Type { return type::Null; },
+ [&](const std::unordered_map<std::string, Value>&) -> type::Type { return type::Object; },
+ [&](const std::vector<Value>& arr) -> type::Type {
+ optional<type::Type> itemType;
+ for (const auto& item : arr) {
+ const type::Type t = typeOf(item);
+ if (!itemType) {
+ itemType = {t};
+ } else if (*itemType == t) {
+ continue;
+ } else {
+ itemType = {type::Value};
+ break;
+ }
+ }
+
+ return type::Array(itemType.value_or(type::Value), arr.size());
+ }
+ );
+}
+
+void writeJSON(rapidjson::Writer<rapidjson::StringBuffer>& writer, const Value& value) {
+ value.match(
+ [&] (const NullValue&) { writer.Null(); },
+ [&] (bool b) { writer.Bool(b); },
+ [&] (double f) {
+ // make sure integer values are stringified without trailing ".0".
+ f == std::floor(f) ? writer.Int(f) : writer.Double(f);
+ },
+ [&] (const std::string& s) { writer.String(s); },
+ [&] (const Color& c) { writer.String(c.stringify()); },
+ [&] (const std::vector<Value>& arr) {
+ writer.StartArray();
+ for(const auto& item : arr) {
+ writeJSON(writer, item);
+ }
+ writer.EndArray();
+ },
+ [&] (const std::unordered_map<std::string, Value>& obj) {
+ writer.StartObject();
+ for(const auto& entry : obj) {
+ writer.Key(entry.first.c_str());
+ writeJSON(writer, entry.second);
+ }
+ writer.EndObject();
+ }
+ );
+}
+
+std::string stringify(const Value& value) {
+ rapidjson::StringBuffer buffer;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+ writeJSON(writer, value);
+ return buffer.GetString();
+}
+
+struct FromMBGLValue {
+ Value operator()(const std::vector<mbgl::Value>& v) {
+ std::vector<Value> result;
+ result.reserve(v.size());
+ for(const auto& item : v) {
+ result.emplace_back(toExpressionValue(item));
+ }
+ return result;
+ }
+
+ Value operator()(const std::unordered_map<std::string, mbgl::Value>& v) {
+ std::unordered_map<std::string, Value> result;
+ result.reserve(v.size());
+ for(const auto& entry : v) {
+ result.emplace(entry.first, toExpressionValue(entry.second));
+ }
+ return result;
+ }
+
+ Value operator()(const std::string& s) { return s; }
+ Value operator()(const bool b) { return b; }
+ Value operator()(const NullValue) { return Null; }
+ Value operator()(const double v) { return v; }
+ Value operator()(const uint64_t& v) {
+ return static_cast<double>(v);
+ }
+ Value operator()(const int64_t& v) {
+ return static_cast<double>(v);
+ }
+};
+
+Value ValueConverter<mbgl::Value>::toExpressionValue(const mbgl::Value& value) {
+ return mbgl::Value::visit(value, FromMBGLValue());
+}
+
+Value ValueConverter<float>::toExpressionValue(const float value) {
+ return static_cast<double>(value);
+}
+
+optional<float> ValueConverter<float>::fromExpressionValue(const Value& value) {
+ if (value.template is<double>()) {
+ double v = value.template get<double>();
+ if (v <= std::numeric_limits<float>::max()) {
+ return static_cast<float>(v);
+ }
+ }
+ return optional<float>();
+}
+
+
+template <typename T, typename Container>
+std::vector<Value> toArrayValue(const Container& value) {
+ std::vector<Value> result;
+ result.reserve(value.size());
+ for (const T& item : value) {
+ result.push_back(ValueConverter<T>::toExpressionValue(item));
+ }
+ return result;
+}
+
+template <typename T, std::size_t N>
+Value ValueConverter<std::array<T, N>>::toExpressionValue(const std::array<T, N>& value) {
+ return toArrayValue<T>(value);
+}
+
+template <typename T, std::size_t N>
+optional<std::array<T, N>> ValueConverter<std::array<T, N>>::fromExpressionValue(const Value& value) {
+ return value.match(
+ [&] (const std::vector<Value>& v) -> optional<std::array<T, N>> {
+ if (v.size() != N) return optional<std::array<T, N>>();
+ std::array<T, N> result;
+ auto it = result.begin();
+ for(const Value& item : v) {
+ optional<T> convertedItem = ValueConverter<T>::fromExpressionValue(item);
+ if (!convertedItem) {
+ return optional<std::array<T, N>>();
+ }
+ *it = *convertedItem;
+ it = std::next(it);
+ }
+ return result;
+ },
+ [&] (const auto&) { return optional<std::array<T, N>>(); }
+ );
+}
+
+
+template <typename T>
+Value ValueConverter<std::vector<T>>::toExpressionValue(const std::vector<T>& value) {
+ return toArrayValue<T>(value);
+}
+
+template <typename T>
+optional<std::vector<T>> ValueConverter<std::vector<T>>::fromExpressionValue(const Value& value) {
+ return value.match(
+ [&] (const std::vector<Value>& v) -> optional<std::vector<T>> {
+ std::vector<T> result;
+ result.reserve(v.size());
+ for(const Value& item : v) {
+ optional<T> convertedItem = ValueConverter<T>::fromExpressionValue(item);
+ if (!convertedItem) {
+ return optional<std::vector<T>>();
+ }
+ result.push_back(*convertedItem);
+ }
+ return result;
+ },
+ [&] (const auto&) { return optional<std::vector<T>>(); }
+ );
+}
+
+Value ValueConverter<Position>::toExpressionValue(const mbgl::style::Position& value) {
+ return ValueConverter<std::array<float, 3>>::toExpressionValue(value.getSpherical());
+}
+
+optional<Position> ValueConverter<Position>::fromExpressionValue(const Value& v) {
+ auto pos = ValueConverter<std::array<float, 3>>::fromExpressionValue(v);
+ return pos ? optional<Position>(Position(*pos)) : optional<Position>();
+}
+
+template <typename T>
+Value ValueConverter<T, std::enable_if_t< std::is_enum<T>::value >>::toExpressionValue(const T& value) {
+ return std::string(Enum<T>::toString(value));
+}
+
+template <typename T>
+optional<T> ValueConverter<T, std::enable_if_t< std::is_enum<T>::value >>::fromExpressionValue(const Value& value) {
+ return value.match(
+ [&] (const std::string& v) { return Enum<T>::toEnum(v); },
+ [&] (const auto&) { return optional<T>(); }
+ );
+}
+
+
+Value toExpressionValue(const Value& v) {
+ return v;
+}
+
+template <typename T, typename Enable>
+Value toExpressionValue(const T& value) {
+ return ValueConverter<T>::toExpressionValue(value);
+}
+
+optional<Value> fromExpressionValue(const Value& v) {
+ return optional<Value>(v);
+}
+
+template <typename T>
+std::enable_if_t< !std::is_convertible<T, Value>::value,
+optional<T>> fromExpressionValue(const Value& v)
+{
+ return ValueConverter<T>::fromExpressionValue(v);
+}
+
+template <typename T>
+type::Type valueTypeToExpressionType() {
+ return ValueConverter<T>::expressionType();
+}
+
+template <> type::Type valueTypeToExpressionType<Value>() { return type::Value; }
+template <> type::Type valueTypeToExpressionType<NullValue>() { return type::Null; }
+template <> type::Type valueTypeToExpressionType<bool>() { return type::Boolean; }
+template <> type::Type valueTypeToExpressionType<double>() { return type::Number; }
+template <> type::Type valueTypeToExpressionType<std::string>() { return type::String; }
+template <> type::Type valueTypeToExpressionType<Color>() { return type::Color; }
+template <> type::Type valueTypeToExpressionType<std::unordered_map<std::string, Value>>() { return type::Object; }
+template <> type::Type valueTypeToExpressionType<std::vector<Value>>() { return type::Array(type::Value); }
+
+// used only for the special (and private) "error" expression
+template <> type::Type valueTypeToExpressionType<type::ErrorType>() { return type::Error; }
+
+
+template Value toExpressionValue(const mbgl::Value&);
+
+
+// for to_rgba expression
+template type::Type valueTypeToExpressionType<std::array<double, 4>>();
+template optional<std::array<double, 4>> fromExpressionValue<std::array<double, 4>>(const Value&);
+template Value toExpressionValue(const std::array<double, 4>&);
+
+// layout/paint property types
+template type::Type valueTypeToExpressionType<float>();
+template optional<float> fromExpressionValue<float>(const Value&);
+template Value toExpressionValue(const float&);
+
+template type::Type valueTypeToExpressionType<std::array<float, 2>>();
+template optional<std::array<float, 2>> fromExpressionValue<std::array<float, 2>>(const Value&);
+template Value toExpressionValue(const std::array<float, 2>&);
+
+template type::Type valueTypeToExpressionType<std::array<float, 4>>();
+template optional<std::array<float, 4>> fromExpressionValue<std::array<float, 4>>(const Value&);
+template Value toExpressionValue(const std::array<float, 4>&);
+
+template type::Type valueTypeToExpressionType<std::vector<float>>();
+template optional<std::vector<float>> fromExpressionValue<std::vector<float>>(const Value&);
+template Value toExpressionValue(const std::vector<float>&);
+
+template type::Type valueTypeToExpressionType<std::vector<std::string>>();
+template optional<std::vector<std::string>> fromExpressionValue<std::vector<std::string>>(const Value&);
+template Value toExpressionValue(const std::vector<std::string>&);
+
+template type::Type valueTypeToExpressionType<AlignmentType>();
+template optional<AlignmentType> fromExpressionValue<AlignmentType>(const Value&);
+template Value toExpressionValue(const AlignmentType&);
+
+template type::Type valueTypeToExpressionType<CirclePitchScaleType>();
+template optional<CirclePitchScaleType> fromExpressionValue<CirclePitchScaleType>(const Value&);
+template Value toExpressionValue(const CirclePitchScaleType&);
+
+template type::Type valueTypeToExpressionType<IconTextFitType>();
+template optional<IconTextFitType> fromExpressionValue<IconTextFitType>(const Value&);
+template Value toExpressionValue(const IconTextFitType&);
+
+template type::Type valueTypeToExpressionType<LineCapType>();
+template optional<LineCapType> fromExpressionValue<LineCapType>(const Value&);
+template Value toExpressionValue(const LineCapType&);
+
+template type::Type valueTypeToExpressionType<LineJoinType>();
+template optional<LineJoinType> fromExpressionValue<LineJoinType>(const Value&);
+template Value toExpressionValue(const LineJoinType&);
+
+template type::Type valueTypeToExpressionType<SymbolPlacementType>();
+template optional<SymbolPlacementType> fromExpressionValue<SymbolPlacementType>(const Value&);
+template Value toExpressionValue(const SymbolPlacementType&);
+
+template type::Type valueTypeToExpressionType<SymbolAnchorType>();
+template optional<SymbolAnchorType> fromExpressionValue<SymbolAnchorType>(const Value&);
+template Value toExpressionValue(const SymbolAnchorType&);
+
+template type::Type valueTypeToExpressionType<TextJustifyType>();
+template optional<TextJustifyType> fromExpressionValue<TextJustifyType>(const Value&);
+template Value toExpressionValue(const TextJustifyType&);
+
+template type::Type valueTypeToExpressionType<TextTransformType>();
+template optional<TextTransformType> fromExpressionValue<TextTransformType>(const Value&);
+template Value toExpressionValue(const TextTransformType&);
+
+template type::Type valueTypeToExpressionType<TranslateAnchorType>();
+template optional<TranslateAnchorType> fromExpressionValue<TranslateAnchorType>(const Value&);
+template Value toExpressionValue(const TranslateAnchorType&);
+
+template type::Type valueTypeToExpressionType<LightAnchorType>();
+template optional<LightAnchorType> fromExpressionValue<LightAnchorType>(const Value&);
+template Value toExpressionValue(const LightAnchorType&);
+
+template type::Type valueTypeToExpressionType<Position>();
+template optional<Position> fromExpressionValue<Position>(const Value&);
+template Value toExpressionValue(const Position&);
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/function/expression.cpp b/src/mbgl/style/function/expression.cpp
new file mode 100644
index 0000000000..d9dbbfa1d3
--- /dev/null
+++ b/src/mbgl/style/function/expression.cpp
@@ -0,0 +1,38 @@
+#include <mbgl/style/expression/expression.hpp>
+#include <mbgl/style/expression/compound_expression.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+class GeoJSONFeature : public GeometryTileFeature {
+public:
+ const Feature& feature;
+
+ GeoJSONFeature(const Feature& feature_) : feature(feature_) {}
+
+ FeatureType getType() const override {
+ return apply_visitor(ToFeatureType(), feature.geometry);
+ }
+ PropertyMap getProperties() const override { return feature.properties; }
+ optional<FeatureIdentifier> getID() const override { return feature.id; }
+ GeometryCollection getGeometries() const override { return {}; }
+ optional<mbgl::Value> getValue(const std::string& key) const override {
+ auto it = feature.properties.find(key);
+ if (it != feature.properties.end()) {
+ return optional<mbgl::Value>(it->second);
+ }
+ return optional<mbgl::Value>();
+ }
+};
+
+
+EvaluationResult Expression::evaluate(optional<float> zoom, const Feature& feature, optional<double> heatmapDensity) const {
+ GeoJSONFeature f(feature);
+ return this->evaluate(EvaluationContext(zoom, &f, heatmapDensity));
+}
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/parser.cpp b/src/mbgl/style/parser.cpp
index a83897dbf5..10fce33986 100644
--- a/src/mbgl/style/parser.cpp
+++ b/src/mbgl/style/parser.cpp
@@ -1,11 +1,13 @@
#include <mbgl/style/parser.hpp>
#include <mbgl/style/layer_impl.hpp>
+#include <mbgl/style/layers/symbol_layer.hpp>
#include <mbgl/style/rapidjson_conversion.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/coordinate.hpp>
#include <mbgl/style/conversion/source.hpp>
#include <mbgl/style/conversion/layer.hpp>
#include <mbgl/style/conversion/light.hpp>
+#include <mbgl/style/conversion/transition_options.hpp>
#include <mbgl/util/logging.hpp>
#include <mbgl/util/string.hpp>
@@ -149,7 +151,7 @@ void Parser::parseSources(const JSValue& value) {
}
for (const auto& property : value.GetObject()) {
- std::string id = *conversion::toString(property.name);
+ std::string id { property.name.GetString(), property.name.GetStringLength() };
conversion::Error error;
optional<std::unique_ptr<Source>> source =
@@ -256,7 +258,7 @@ void Parser::parseLayer(const std::string& id, const JSValue& value, std::unique
}
layer = reference->cloneRef(id);
- conversion::setPaintProperties(*layer, value);
+ conversion::setPaintProperties(*layer, conversion::Convertible(&value));
} else {
conversion::Error error;
optional<std::unique_ptr<Layer>> converted = conversion::convert<std::unique_ptr<Layer>>(value, error);
diff --git a/src/mbgl/style/rapidjson_conversion.hpp b/src/mbgl/style/rapidjson_conversion.hpp
index 48a764ccb4..79bd9c928b 100644
--- a/src/mbgl/style/rapidjson_conversion.hpp
+++ b/src/mbgl/style/rapidjson_conversion.hpp
@@ -1,103 +1,125 @@
#pragma once
#include <mbgl/util/rapidjson.hpp>
-#include <mbgl/util/feature.hpp>
#include <mbgl/style/conversion.hpp>
+#include <mapbox/geojson.hpp>
+#include <mapbox/geojson/rapidjson.hpp>
+
namespace mbgl {
namespace style {
namespace conversion {
-inline bool isUndefined(const JSValue& value) {
- return value.IsNull();
-}
-
-inline bool isArray(const JSValue& value) {
- return value.IsArray();
-}
+template <>
+class ConversionTraits<const JSValue*> {
+public:
+ static bool isUndefined(const JSValue* value) {
+ return value->IsNull();
+ }
-inline std::size_t arrayLength(const JSValue& value) {
- return value.Size();
-}
+ static bool isArray(const JSValue* value) {
+ return value->IsArray();
+ }
-inline const JSValue& arrayMember(const JSValue& value, std::size_t i) {
- return value[rapidjson::SizeType(i)];
-}
+ static std::size_t arrayLength(const JSValue* value) {
+ return value->Size();
+ }
-inline bool isObject(const JSValue& value) {
- return value.IsObject();
-}
+ static const JSValue* arrayMember(const JSValue* value, std::size_t i) {
+ return &(*value)[rapidjson::SizeType(i)];
+ }
-inline const JSValue* objectMember(const JSValue& value, const char * name) {
- if (!value.HasMember(name)) {
- return nullptr;
+ static bool isObject(const JSValue* value) {
+ return value->IsObject();
}
- return &value[name];
-}
-template <class Fn>
-optional<Error> eachMember(const JSValue& value, Fn&& fn) {
- assert(value.IsObject());
- for (const auto& property : value.GetObject()) {
- optional<Error> result =
- fn({ property.name.GetString(), property.name.GetStringLength() }, property.value);
- if (result) {
- return result;
+ static optional<const JSValue*> objectMember(const JSValue* value, const char * name) {
+ if (!value->HasMember(name)) {
+ return optional<const JSValue*>();
}
+ const JSValue* const& member = &(*value)[name];
+ return {member};
}
- return {};
-}
-inline optional<bool> toBool(const JSValue& value) {
- if (!value.IsBool()) {
+ template <class Fn>
+ static optional<Error> eachMember(const JSValue* value, Fn&& fn) {
+ assert(value->IsObject());
+ for (const auto& property : value->GetObject()) {
+ optional<Error> result =
+ fn({ property.name.GetString(), property.name.GetStringLength() }, &property.value);
+ if (result) {
+ return result;
+ }
+ }
return {};
}
- return value.GetBool();
-}
-inline optional<float> toNumber(const JSValue& value) {
- if (!value.IsNumber()) {
- return {};
+ static optional<bool> toBool(const JSValue* value) {
+ if (!value->IsBool()) {
+ return {};
+ }
+ return value->GetBool();
}
- return value.GetDouble();
-}
-inline optional<double> toDouble(const JSValue& value) {
- if (!value.IsNumber()) {
- return {};
+ static optional<float> toNumber(const JSValue* value) {
+ if (!value->IsNumber()) {
+ return {};
+ }
+ return value->GetDouble();
}
- return value.GetDouble();
-}
-inline optional<std::string> toString(const JSValue& value) {
- if (!value.IsString()) {
- return {};
+ static optional<double> toDouble(const JSValue* value) {
+ if (!value->IsNumber()) {
+ return {};
+ }
+ return value->GetDouble();
+ }
+
+ static optional<std::string> toString(const JSValue* value) {
+ if (!value->IsString()) {
+ return {};
+ }
+ return {{ value->GetString(), value->GetStringLength() }};
}
- return {{ value.GetString(), value.GetStringLength() }};
-}
-inline optional<Value> toValue(const JSValue& value) {
- switch (value.GetType()) {
- case rapidjson::kNullType:
- case rapidjson::kFalseType:
- return { false };
+ static optional<Value> toValue(const JSValue* value) {
+ switch (value->GetType()) {
+ case rapidjson::kNullType:
+ case rapidjson::kFalseType:
+ return { false };
- case rapidjson::kTrueType:
- return { true };
+ case rapidjson::kTrueType:
+ return { true };
- case rapidjson::kStringType:
- return { std::string { value.GetString(), value.GetStringLength() } };
+ case rapidjson::kStringType:
+ return { std::string { value->GetString(), value->GetStringLength() } };
- case rapidjson::kNumberType:
- if (value.IsUint64()) return { value.GetUint64() };
- if (value.IsInt64()) return { value.GetInt64() };
- return { value.GetDouble() };
+ case rapidjson::kNumberType:
+ if (value->IsUint64()) return { value->GetUint64() };
+ if (value->IsInt64()) return { value->GetInt64() };
+ return { value->GetDouble() };
- default:
+ default:
+ return {};
+ }
+ }
+
+ static optional<GeoJSON> toGeoJSON(const JSValue* value, Error& error) {
+ try {
+ return mapbox::geojson::convert(*value);
+ } catch (const std::exception& ex) {
+ error = { ex.what() };
return {};
+ }
}
+};
+
+template <class T, class...Args>
+optional<T> convert(const JSValue& value, Error& error, Args&&...args) {
+ return convert<T>(Convertible(&value), error, std::forward<Args>(args)...);
}
} // namespace conversion
} // namespace style
} // namespace mbgl
+
diff --git a/src/mbgl/style/sources/custom_geometry_source.cpp b/src/mbgl/style/sources/custom_geometry_source.cpp
new file mode 100644
index 0000000000..b37490a5ce
--- /dev/null
+++ b/src/mbgl/style/sources/custom_geometry_source.cpp
@@ -0,0 +1,45 @@
+#include <mbgl/style/sources/custom_geometry_source.hpp>
+#include <mbgl/style/custom_tile_loader.hpp>
+#include <mbgl/style/sources/custom_geometry_source_impl.hpp>
+#include <mbgl/actor/actor.hpp>
+#include <mbgl/actor/scheduler.hpp>
+#include <mbgl/tile/tile_id.hpp>
+#include <mbgl/util/shared_thread_pool.hpp>
+#include <tuple>
+#include <map>
+
+namespace mbgl {
+namespace style {
+
+CustomGeometrySource::CustomGeometrySource(std::string id,
+ const CustomGeometrySource::Options options)
+ : Source(makeMutable<CustomGeometrySource::Impl>(std::move(id), options)),
+ loader(std::make_unique<Actor<CustomTileLoader>>(*sharedThreadPool(), options.fetchTileFunction, options.cancelTileFunction)) {
+}
+
+CustomGeometrySource::~CustomGeometrySource() = default;
+
+const CustomGeometrySource::Impl& CustomGeometrySource::impl() const {
+ return static_cast<const CustomGeometrySource::Impl&>(*baseImpl);
+}
+
+void CustomGeometrySource::loadDescription(FileSource&) {
+ baseImpl = makeMutable<CustomGeometrySource::Impl>(impl(), loader->self());
+ loaded = true;
+}
+
+void CustomGeometrySource::setTileData(const CanonicalTileID& tileID,
+ const GeoJSON& data) {
+ loader->invoke(&CustomTileLoader::setTileData, tileID, data);
+}
+
+void CustomGeometrySource::invalidateTile(const CanonicalTileID& tileID) {
+ loader->invoke(&CustomTileLoader::invalidateTile, tileID);
+}
+
+void CustomGeometrySource::invalidateRegion(const LatLngBounds& bounds) {
+ loader->invoke(&CustomTileLoader::invalidateRegion, bounds, impl().getZoomRange());
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/sources/custom_geometry_source_impl.cpp b/src/mbgl/style/sources/custom_geometry_source_impl.cpp
new file mode 100644
index 0000000000..67d52bdc24
--- /dev/null
+++ b/src/mbgl/style/sources/custom_geometry_source_impl.cpp
@@ -0,0 +1,40 @@
+#include <mbgl/style/sources/custom_geometry_source_impl.hpp>
+#include <mbgl/style/source_observer.hpp>
+
+namespace mbgl {
+namespace style {
+
+CustomGeometrySource::Impl::Impl(std::string id_,
+ const CustomGeometrySource::Options options)
+ : Source::Impl(SourceType::CustomVector, std::move(id_)),
+ tileOptions(options.tileOptions),
+ zoomRange(options.zoomRange),
+ loaderRef({}) {
+}
+
+CustomGeometrySource::Impl::Impl(const Impl& impl, ActorRef<CustomTileLoader> loaderRef_)
+ : Source::Impl(impl),
+ tileOptions(impl.tileOptions),
+ zoomRange(impl.zoomRange),
+ loaderRef(loaderRef_){
+
+}
+
+optional<std::string> CustomGeometrySource::Impl::getAttribution() const {
+ return {};
+}
+
+CustomGeometrySource::TileOptions CustomGeometrySource::Impl::getTileOptions() const {
+ return tileOptions;
+}
+
+Range<uint8_t> CustomGeometrySource::Impl::getZoomRange() const {
+ return zoomRange;
+}
+
+optional<ActorRef<CustomTileLoader>> CustomGeometrySource::Impl::getTileLoader() const {
+ return loaderRef;
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/sources/custom_geometry_source_impl.hpp b/src/mbgl/style/sources/custom_geometry_source_impl.hpp
new file mode 100644
index 0000000000..ce7187202d
--- /dev/null
+++ b/src/mbgl/style/sources/custom_geometry_source_impl.hpp
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <mbgl/style/source_impl.hpp>
+#include <mbgl/style/sources/custom_geometry_source.hpp>
+#include <mbgl/style/custom_tile_loader.hpp>
+#include <mbgl/actor/actor_ref.hpp>
+
+namespace mbgl {
+namespace style {
+
+class CustomGeometrySource::Impl : public Source::Impl {
+public:
+ Impl(std::string id, CustomGeometrySource::Options options);
+ Impl(const Impl&, ActorRef<CustomTileLoader>);
+
+ optional<std::string> getAttribution() const final;
+
+ CustomGeometrySource::TileOptions getTileOptions() const;
+ Range<uint8_t> getZoomRange() const;
+ optional<ActorRef<CustomTileLoader>> getTileLoader() const;
+
+private:
+ CustomGeometrySource::TileOptions tileOptions;
+ Range<uint8_t> zoomRange;
+ optional<ActorRef<CustomTileLoader>> loaderRef;
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/types.cpp b/src/mbgl/style/types.cpp
index 0a1781e01b..cd5e597fc0 100644
--- a/src/mbgl/style/types.cpp
+++ b/src/mbgl/style/types.cpp
@@ -12,6 +12,7 @@ MBGL_DEFINE_ENUM(SourceType, {
{ SourceType::Video, "video" },
{ SourceType::Annotations, "annotations" },
{ SourceType::Image, "image" },
+ { SourceType::CustomVector, "customvector" }
});
MBGL_DEFINE_ENUM(VisibilityType, {
diff --git a/src/mbgl/text/collision_feature.cpp b/src/mbgl/text/collision_feature.cpp
index 3eb08da8d1..6d6f2aabc7 100644
--- a/src/mbgl/text/collision_feature.cpp
+++ b/src/mbgl/text/collision_feature.cpp
@@ -13,8 +13,9 @@ CollisionFeature::CollisionFeature(const GeometryCoordinates& line,
const float padding,
const style::SymbolPlacementType placement,
IndexedSubfeature indexedFeature_,
- const AlignmentType alignment)
- : indexedFeature(std::move(indexedFeature_)) {
+ const float overscaling)
+ : indexedFeature(std::move(indexedFeature_))
+ , alongLine(placement == style::SymbolPlacementType::Line) {
if (top == 0 && bottom == 0 && left == 0 && right == 0) return;
const float y1 = top * boxScale - padding;
@@ -22,7 +23,7 @@ CollisionFeature::CollisionFeature(const GeometryCoordinates& line,
const float x1 = left * boxScale - padding;
const float x2 = right * boxScale + padding;
- if (placement == style::SymbolPlacementType::Line) {
+ if (alongLine) {
float height = y2 - y1;
const double length = x2 - x1;
@@ -31,29 +32,26 @@ CollisionFeature::CollisionFeature(const GeometryCoordinates& line,
height = std::max(10.0f * boxScale, height);
GeometryCoordinate anchorPoint = convertPoint<int16_t>(anchor.point);
-
- if (alignment == AlignmentType::Straight) {
- // used for icon labels that are aligned with the line, but don't curve along it
- const GeometryCoordinate vector = convertPoint<int16_t>(util::unit(convertPoint<double>(line[anchor.segment + 1] - line[anchor.segment])) * length);
- const GeometryCoordinates newLine({ anchorPoint - vector, anchorPoint + vector });
- bboxifyLabel(newLine, anchorPoint, 0, length, height);
- } else {
- // used for text labels that curve along a line
- bboxifyLabel(line, anchorPoint, anchor.segment, length, height);
- }
+ bboxifyLabel(line, anchorPoint, anchor.segment, length, height, overscaling);
} else {
- boxes.emplace_back(anchor.point, Point<float>{ 0, 0 }, x1, y1, x2, y2, std::numeric_limits<float>::infinity());
+ boxes.emplace_back(anchor.point, Point<float>{ 0, 0 }, x1, y1, x2, y2);
}
}
void CollisionFeature::bboxifyLabel(const GeometryCoordinates& line, GeometryCoordinate& anchorPoint,
- const int segment, const float labelLength, const float boxSize) {
+ const int segment, const float labelLength, const float boxSize, const float overscaling) {
const float step = boxSize / 2;
const int nBoxes = std::floor(labelLength / step);
- // We calculate line collision boxes out to 300% of what would normally be our
+ // We calculate line collision circles out to 300% of what would normally be our
// max size, to allow collision detection to work on labels that expand as
// they move into the distance
- const int nPitchPaddingBoxes = std::floor(nBoxes / 2);
+ // Vertically oriented labels in the distant field can extend past this padding
+ // This is a noticeable problem in overscaled tiles where the pitch 0-based
+ // 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 * std::log(overscaling) / std::log(2);
+ 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
// box is at the edge of the label.
@@ -124,47 +122,18 @@ void CollisionFeature::bboxifyLabel(const GeometryCoordinates& line, GeometryCoo
p0.x + segmentBoxDistance / segmentLength * (p1.x - p0.x),
p0.y + segmentBoxDistance / segmentLength * (p1.y - p0.y)
};
-
- // Distance from label anchor point to inner (towards center) edge of this box
- // The tricky thing here is that box positioning doesn't change with scale,
- // but box size does change with scale.
- // Technically, distanceToInnerEdge should be:
- // Math.max(Math.abs(boxDistanceToAnchor - firstBoxOffset) - (step / scale), 0);
- // But using that formula would make solving for maxScale more difficult, so we
- // approximate with scale=2.
- // This makes our calculation spot-on at scale=2, and on the conservative side for
- // lower scales
- const float distanceToInnerEdge = std::max(std::fabs(boxDistanceToAnchor - firstBoxOffset) - step / 2, 0.0f);
- float maxScale = util::division(labelLength / 2, distanceToInnerEdge, std::numeric_limits<float>::infinity());
-
- // The box maxScale calculations are designed to be conservative on collisions in the scale range
- // [1,2]. At scale=1, each box has 50% overlap, and at scale=2, the boxes are lined up edge
- // to edge (beyond scale 2, gaps start to appear, which could potentially allow missed collisions).
- // We add "pitch padding" boxes to the left and right to handle effective underzooming
- // (scale < 1) when labels are in the distance. The overlap approximation could cause us to use
- // these boxes when the scale is greater than 1, but we prevent that because we know
- // they're only necessary for scales less than one.
- // This preserves the pre-pitch-padding behavior for unpitched maps.
- if (i < 0 || i >= nBoxes) {
- maxScale = std::min(maxScale, 0.99f);
- }
-
- boxes.emplace_back(boxAnchor, boxAnchor - convertPoint<float>(anchorPoint), -boxSize / 2, -boxSize / 2, boxSize / 2, boxSize / 2, maxScale);
+
+ // If the box is within boxSize of the anchor, force the box to be used
+ // (so even 0-width labels use at least one box)
+ // Otherwise, the .8 multiplication gives us a little bit of conservative
+ // padding in choosing which boxes to use (see CollisionIndex#placedCollisionCircles)
+ const float paddedAnchorDistance = std::abs(boxDistanceToAnchor - firstBoxOffset) < step ?
+ 0 :
+ (boxDistanceToAnchor - firstBoxOffset) * 0.8;
+
+ boxes.emplace_back(boxAnchor, boxAnchor - convertPoint<float>(anchorPoint), -boxSize / 2, -boxSize / 2, boxSize / 2, boxSize / 2, paddedAnchorDistance, boxSize / 2);
}
}
-float CollisionBox::adjustedMaxScale(const std::array<float, 4>& rotationMatrix, const float yStretch) const {
- // When the map is pitched the distance covered by a line changes.
- // Adjust the max scale by (approximatePitchedLength / approximateRegularLength)
- // to compensate for this.
- const Point<float> rotatedOffset = util::matrixMultiply(rotationMatrix, offset);
- const float xSqr = rotatedOffset.x * rotatedOffset.x;
- const float ySqr = rotatedOffset.y * rotatedOffset.y;
- const float yStretchSqr = ySqr * yStretch * yStretch;
- const float adjustmentFactor = xSqr + ySqr != 0 ?
- std::sqrt((xSqr + yStretchSqr) / (xSqr + ySqr)) :
- 1.0f;
- return maxScale * adjustmentFactor;
-}
} // namespace mbgl
diff --git a/src/mbgl/text/collision_feature.hpp b/src/mbgl/text/collision_feature.hpp
index 3b6e461a26..df1b12819c 100644
--- a/src/mbgl/text/collision_feature.hpp
+++ b/src/mbgl/text/collision_feature.hpp
@@ -11,10 +11,8 @@ namespace mbgl {
class CollisionBox {
public:
- CollisionBox(Point<float> _anchor, Point<float> _offset, float _x1, float _y1, float _x2, float _y2, float _maxScale) :
- anchor(std::move(_anchor)), offset(_offset), x1(_x1), y1(_y1), x2(_x2), y2(_y2), maxScale(_maxScale) {}
-
- float adjustedMaxScale(const std::array<float, 4>& rotationMatrix, const float yStretch) const;
+ CollisionBox(Point<float> _anchor, Point<float> _offset, float _x1, float _y1, float _x2, float _y2, float _signedDistanceFromAnchor = 0, float _radius = 0) :
+ anchor(std::move(_anchor)), offset(_offset), x1(_x1), y1(_y1), x2(_x2), y2(_y2), used(true), signedDistanceFromAnchor(_signedDistanceFromAnchor), radius(_radius) {}
// the box is centered around the anchor point
Point<float> anchor;
@@ -28,20 +26,23 @@ public:
float x2;
float y2;
- // the box is only valid for scales < maxScale.
- // The box does not block other boxes at scales >= maxScale;
- float maxScale;
+ // Projected box geometry: generated/updated at placement time
+ float px1;
+ float py1;
+ float px2;
+ float py2;
+
+ // Projected circle geometry: generated/updated at placement time
+ float px;
+ float py;
+ bool used;
- // the scale at which the label can first be shown
- float placementScale = 0.0f;
+ float signedDistanceFromAnchor;
+ float radius;
};
class CollisionFeature {
public:
- enum class AlignmentType : bool {
- Straight = false,
- Curved
- };
// for text
CollisionFeature(const GeometryCoordinates& line,
@@ -50,23 +51,31 @@ public:
const float boxScale,
const float padding,
const style::SymbolPlacementType placement,
- const IndexedSubfeature& indexedFeature_)
- : CollisionFeature(line, anchor, shapedText.top, shapedText.bottom, shapedText.left, shapedText.right, boxScale, padding, placement, indexedFeature_, AlignmentType::Curved) {}
+ const IndexedSubfeature& indexedFeature_,
+ const float overscaling)
+ : CollisionFeature(line, anchor, shapedText.top, shapedText.bottom, shapedText.left, shapedText.right, boxScale, padding, placement, indexedFeature_, overscaling) {}
// for icons
+ // Icons collision features are always SymbolPlacementType::Point, which means the collision feature
+ // will be viewport-rotation-aligned even if the icon is map-rotation-aligned (e.g. `icon-rotation-alignment: map`
+ // _or_ `symbol-placement: line`). We're relying on most icons being "close enough" to square that having
+ // incorrect rotation alignment doesn't throw off collision detection too much.
+ // See: https://github.com/mapbox/mapbox-gl-js/issues/4861
CollisionFeature(const GeometryCoordinates& line,
const Anchor& anchor,
optional<PositionedIcon> shapedIcon,
const float boxScale,
const float padding,
- const style::SymbolPlacementType placement,
const IndexedSubfeature& indexedFeature_)
: CollisionFeature(line, anchor,
(shapedIcon ? shapedIcon->top() : 0),
(shapedIcon ? shapedIcon->bottom() : 0),
(shapedIcon ? shapedIcon->left() : 0),
(shapedIcon ? shapedIcon->right() : 0),
- boxScale, padding, placement, indexedFeature_, AlignmentType::Straight) {}
+ boxScale,
+ padding,
+ style::SymbolPlacementType::Point,
+ indexedFeature_, 1) {}
CollisionFeature(const GeometryCoordinates& line,
const Anchor&,
@@ -78,14 +87,15 @@ public:
const float padding,
const style::SymbolPlacementType,
IndexedSubfeature,
- const AlignmentType);
+ const float overscaling);
std::vector<CollisionBox> boxes;
IndexedSubfeature indexedFeature;
+ bool alongLine;
private:
void bboxifyLabel(const GeometryCoordinates& line, GeometryCoordinate& anchorPoint,
- const int segment, const float length, const float height);
+ const int segment, const float length, const float height, const float overscaling);
};
} // namespace mbgl
diff --git a/src/mbgl/text/collision_index.cpp b/src/mbgl/text/collision_index.cpp
new file mode 100644
index 0000000000..8014efe6c7
--- /dev/null
+++ b/src/mbgl/text/collision_index.cpp
@@ -0,0 +1,359 @@
+#include <mbgl/text/collision_index.hpp>
+#include <mbgl/layout/symbol_instance.hpp>
+#include <mbgl/geometry/feature_index.hpp>
+#include <mbgl/math/log2.hpp>
+#include <mbgl/util/constants.hpp>
+#include <mbgl/util/math.hpp>
+#include <mbgl/math/minmax.hpp>
+#include <mbgl/util/intersection_tests.hpp>
+#include <mbgl/layout/symbol_projection.hpp>
+
+#include <mapbox/geometry/envelope.hpp>
+
+#include <mbgl/renderer/buckets/symbol_bucket.hpp> // For PlacedSymbol: pull out to another location
+
+#include <cmath>
+
+namespace mbgl {
+
+// When a symbol crosses the edge that causes it to be included in
+// collision detection, it will cause changes in the symbols around
+// it. This constant specifies how many pixels to pad the edge of
+// the viewport for collision detection so that the bulk of the changes
+// occur offscreen. Making this constant greater increases label
+// stability, but it's expensive.
+static const float viewportPadding = 100;
+
+CollisionIndex::CollisionIndex(const TransformState& transformState_)
+ : transformState(transformState_)
+ , collisionGrid(transformState.getSize().width + 2 * viewportPadding, transformState.getSize().height + 2 * viewportPadding, 25)
+ , ignoredGrid(transformState.getSize().width + 2 * viewportPadding, transformState.getSize().height + 2 * viewportPadding, 25)
+ , screenRightBoundary(transformState.getSize().width + viewportPadding)
+ , screenBottomBoundary(transformState.getSize().height + viewportPadding)
+ , gridRightBoundary(transformState.getSize().width + 2 * viewportPadding)
+ , gridBottomBoundary(transformState.getSize().height + 2 * viewportPadding)
+ , pitchFactor(std::cos(transformState.getPitch()) * transformState.getCameraToCenterDistance())
+{}
+
+float CollisionIndex::approximateTileDistance(const TileDistance& tileDistance, const float lastSegmentAngle, const float pixelsToTileUnits, const float cameraToAnchorDistance, const bool pitchWithMap) {
+ // This is a quick and dirty solution for chosing which collision circles to use (since collision circles are
+ // laid out in tile units). Ideally, I think we should generate collision circles on the fly in viewport coordinates
+ // at the time we do collision detection.
+
+ // incidenceStretch is the ratio of how much y space a label takes up on a tile while drawn perpendicular to the viewport vs
+ // how much space it would take up if it were drawn flat on the tile
+ // Using law of sines, camera_to_anchor/sin(ground_angle) = camera_to_center/sin(incidence_angle)
+ // Incidence angle 90 -> head on, sin(incidence_angle) = 1, no stretch
+ // Incidence angle 1 -> very oblique, sin(incidence_angle) =~ 0, lots of stretch
+ // ground_angle = u_pitch + PI/2 -> sin(ground_angle) = cos(u_pitch)
+ // incidenceStretch = 1 / sin(incidenceAngle)
+
+ const float incidenceStretch = pitchWithMap ? 1 : cameraToAnchorDistance / pitchFactor;
+ const float lastSegmentTile = tileDistance.lastSegmentViewportDistance * pixelsToTileUnits;
+ return tileDistance.prevTileDistance +
+ lastSegmentTile +
+ (incidenceStretch - 1) * lastSegmentTile * std::abs(std::sin(lastSegmentAngle));
+}
+
+bool CollisionIndex::isOffscreen(const CollisionBox& box) const {
+ return box.px2 < viewportPadding || box.px1 >= screenRightBoundary || box.py2 < viewportPadding || box.py1 >= screenBottomBoundary;
+}
+
+bool CollisionIndex::isInsideGrid(const CollisionBox& box) const {
+ return box.px2 >= 0 && box.px1 < gridRightBoundary && box.py2 >= 0 && box.py1 < gridBottomBoundary;
+}
+
+
+std::pair<bool,bool> CollisionIndex::placeFeature(CollisionFeature& feature,
+ const mat4& posMatrix,
+ const mat4& labelPlaneMatrix,
+ const float textPixelRatio,
+ PlacedSymbol& symbol,
+ const float scale,
+ const float fontSize,
+ const bool allowOverlap,
+ const bool pitchWithMap,
+ const bool collisionDebug) {
+ if (!feature.alongLine) {
+ CollisionBox& box = feature.boxes.front();
+ const auto projectedPoint = projectAndGetPerspectiveRatio(posMatrix, box.anchor);
+ const float tileToViewport = textPixelRatio * projectedPoint.second;
+ box.px1 = box.x1 / tileToViewport + projectedPoint.first.x;
+ box.py1 = box.y1 / tileToViewport + projectedPoint.first.y;
+ box.px2 = box.x2 / tileToViewport + projectedPoint.first.x;
+ box.py2 = box.y2 / tileToViewport + projectedPoint.first.y;
+
+ if (!isInsideGrid(box) ||
+ (!allowOverlap && collisionGrid.hitTest({{ box.px1, box.py1 }, { box.px2, box.py2 }}))) {
+ return { false, false };
+ }
+
+ return {true, isOffscreen(box)};
+ } else {
+ return placeLineFeature(feature, posMatrix, labelPlaneMatrix, textPixelRatio, symbol, scale, fontSize, allowOverlap, pitchWithMap, collisionDebug);
+ }
+}
+
+std::pair<bool,bool> CollisionIndex::placeLineFeature(CollisionFeature& feature,
+ const mat4& posMatrix,
+ const mat4& labelPlaneMatrix,
+ const float textPixelRatio,
+ PlacedSymbol& symbol,
+ const float scale,
+ const float fontSize,
+ const bool allowOverlap,
+ const bool pitchWithMap,
+ const bool collisionDebug) {
+
+ const auto tileUnitAnchorPoint = symbol.anchorPoint;
+ const auto projectedAnchor = projectAnchor(posMatrix, tileUnitAnchorPoint);
+
+ const float fontScale = fontSize / 24;
+ const float lineOffsetX = symbol.lineOffset[0] * fontSize;
+ const float lineOffsetY = symbol.lineOffset[1] * fontSize;
+
+ const auto labelPlaneAnchorPoint = project(tileUnitAnchorPoint, labelPlaneMatrix).first;
+
+ const auto firstAndLastGlyph = placeFirstAndLastGlyph(
+ fontScale,
+ lineOffsetX,
+ lineOffsetY,
+ /*flip*/ false,
+ labelPlaneAnchorPoint,
+ tileUnitAnchorPoint,
+ symbol,
+ labelPlaneMatrix,
+ /*return tile distance*/ true);
+
+ bool collisionDetected = false;
+ bool inGrid = false;
+ bool entirelyOffscreen = true;
+
+ const auto tileToViewport = projectedAnchor.first * textPixelRatio;
+ // equivalent to pixel_to_tile_units
+ const auto pixelsToTileUnits = tileToViewport / scale;
+
+ float firstTileDistance = 0, lastTileDistance = 0;
+ if (firstAndLastGlyph) {
+ firstTileDistance = approximateTileDistance(*(firstAndLastGlyph->first.tileDistance), firstAndLastGlyph->first.angle, pixelsToTileUnits, projectedAnchor.second, pitchWithMap);
+ lastTileDistance = approximateTileDistance(*(firstAndLastGlyph->second.tileDistance), firstAndLastGlyph->second.angle, pixelsToTileUnits, projectedAnchor.second, pitchWithMap);
+ }
+
+ bool atLeastOneCirclePlaced = false;
+ for (size_t i = 0; i < feature.boxes.size(); i++) {
+ CollisionBox& circle = feature.boxes[i];
+ const float boxSignedDistanceFromAnchor = circle.signedDistanceFromAnchor;
+ if (!firstAndLastGlyph ||
+ (boxSignedDistanceFromAnchor < -firstTileDistance) ||
+ (boxSignedDistanceFromAnchor > lastTileDistance)) {
+ // The label either doesn't fit on its line or we
+ // don't need to use this circle because the label
+ // doesn't extend this far. Either way, mark the circle unused.
+ circle.used = false;
+ continue;
+ }
+
+ const auto projectedPoint = projectPoint(posMatrix, circle.anchor);
+ const float tileUnitRadius = (circle.x2 - circle.x1) / 2;
+ const float radius = tileUnitRadius / tileToViewport;
+
+ if (atLeastOneCirclePlaced) {
+ const CollisionBox& previousCircle = feature.boxes[i - 1];
+ const float dx = projectedPoint.x - previousCircle.px;
+ const float dy = projectedPoint.y - previousCircle.py;
+ // The circle edges touch when the distance between their centers is 2x the radius
+ // When the distance is 1x the radius, they're doubled up, and we could remove
+ // every other circle while keeping them all in touch.
+ // We actually start removing circles when the distance is √2x the radius:
+ // thinning the number of circles as much as possible is a major performance win,
+ // and the small gaps introduced don't make a very noticeable difference.
+ const bool placedTooDensely = radius * radius * 2 > dx * dx + dy * dy;
+ if (placedTooDensely) {
+ const bool atLeastOneMoreCircle = (i + 1) < feature.boxes.size();
+ if (atLeastOneMoreCircle) {
+ const CollisionBox& nextCircle = feature.boxes[i + 1];
+ const float nextBoxDistanceFromAnchor = nextCircle.signedDistanceFromAnchor;
+ if ((nextBoxDistanceFromAnchor > -firstTileDistance) &&
+ (nextBoxDistanceFromAnchor < lastTileDistance)) {
+ // Hide significantly overlapping circles, unless this is the last one we can
+ // use, in which case we want to keep it in place even if it's tightly packed
+ // with the one before it.
+ circle.used = false;
+ continue;
+ }
+ }
+ }
+ }
+
+ atLeastOneCirclePlaced = true;
+ circle.px1 = projectedPoint.x - radius;
+ circle.px2 = projectedPoint.x + radius;
+ circle.py1 = projectedPoint.y - radius;
+ circle.py2 = projectedPoint.y + radius;
+
+ circle.used = true;
+
+ circle.px = projectedPoint.x;
+ circle.py = projectedPoint.y;
+ circle.radius = radius;
+
+ entirelyOffscreen &= isOffscreen(circle);
+ inGrid |= isInsideGrid(circle);
+
+ if (!allowOverlap) {
+ if (collisionGrid.hitTest({{circle.px, circle.py}, circle.radius})) {
+ if (!collisionDebug) {
+ return {false, false};
+ } else {
+ // Don't early exit if we're showing the debug circles because we still want to calculate
+ // which circles are in use
+ collisionDetected = true;
+ }
+ }
+ }
+ }
+
+ return {!collisionDetected && firstAndLastGlyph && inGrid, entirelyOffscreen};
+}
+
+
+void CollisionIndex::insertFeature(CollisionFeature& feature, bool ignorePlacement) {
+ if (feature.alongLine) {
+ for (auto& circle : feature.boxes) {
+ if (!circle.used) {
+ continue;
+ }
+
+ if (ignorePlacement) {
+ ignoredGrid.insert(IndexedSubfeature(feature.indexedFeature), {{ circle.px, circle.py }, circle.radius});
+ } else {
+ collisionGrid.insert(IndexedSubfeature(feature.indexedFeature), {{ circle.px, circle.py }, circle.radius});
+ }
+ }
+ } else {
+ assert(feature.boxes.size() == 1);
+ auto& box = feature.boxes[0];
+ if (ignorePlacement) {
+ ignoredGrid.insert(IndexedSubfeature(feature.indexedFeature), {{ box.px1, box.py1 }, { box.px2, box.py2 }});
+ } else {
+ collisionGrid.insert(IndexedSubfeature(feature.indexedFeature), {{ box.px1, box.py1 }, { box.px2, box.py2 }});
+ }
+ }
+}
+
+bool polygonIntersectsBox(const LineString<float>& polygon, const GridIndex<IndexedSubfeature>::BBox& bbox) {
+ // This is just a wrapper that allows us to use the integer-based util::polygonIntersectsPolygon
+ // Conversion limits our query accuracy to single-pixel resolution
+ GeometryCoordinates integerPolygon;
+ for (const auto& point : polygon) {
+ integerPolygon.push_back(convertPoint<int16_t>(point));
+ }
+ int16_t minX1 = bbox.min.x;
+ int16_t maxY1 = bbox.max.y;
+ int16_t minY1 = bbox.min.y;
+ int16_t maxX1 = bbox.max.x;
+
+ auto bboxPoints = GeometryCoordinates {
+ { minX1, minY1 }, { maxX1, minY1 }, { maxX1, maxY1 }, { minX1, maxY1 }
+ };
+
+ return util::polygonIntersectsPolygon(integerPolygon, bboxPoints);
+}
+
+std::vector<IndexedSubfeature> CollisionIndex::queryRenderedSymbols(const GeometryCoordinates& queryGeometry, const UnwrappedTileID& tileID, const std::string& sourceID) const {
+ std::vector<IndexedSubfeature> result;
+ if (queryGeometry.empty() || (collisionGrid.empty() && ignoredGrid.empty())) {
+ return result;
+ }
+
+ mat4 posMatrix;
+ mat4 projMatrix;
+ transformState.getProjMatrix(projMatrix);
+ transformState.matrixFor(posMatrix, tileID);
+ matrix::multiply(posMatrix, projMatrix, posMatrix);
+
+ // queryGeometry is specified in integer tile units, but in projecting we switch to float pixels
+ LineString<float> projectedQuery;
+ for (const auto& point : queryGeometry) {
+ auto projected = projectPoint(posMatrix, convertPoint<float>(point));
+ projectedQuery.push_back(projected);
+ }
+
+ auto envelope = mapbox::geometry::envelope(projectedQuery);
+
+ using QueryResult = std::pair<IndexedSubfeature, GridIndex<IndexedSubfeature>::BBox>;
+
+ std::vector<QueryResult> thisTileFeatures;
+ std::vector<QueryResult> features = collisionGrid.queryWithBoxes(envelope);
+
+ for (auto& queryResult : features) {
+ auto& feature = queryResult.first;
+ if (feature.sourceID == sourceID && feature.tileID == tileID.canonical) {
+ // We only have to filter on the canonical ID because even if the feature is showing multiple times
+ // we treat it as one feature.
+ thisTileFeatures.push_back(queryResult);
+ }
+ }
+
+ std::vector<QueryResult> ignoredFeatures = ignoredGrid.queryWithBoxes(envelope);
+ for (auto& queryResult : ignoredFeatures) {
+ auto& feature = queryResult.first;
+ if (feature.sourceID == sourceID && feature.tileID == tileID.canonical) {
+ thisTileFeatures.push_back(queryResult);
+ }
+ }
+
+ std::unordered_map<std::string, std::unordered_map<std::string, std::unordered_set<std::size_t>>> sourceLayerFeatures;
+ for (auto& queryResult : thisTileFeatures) {
+ auto& feature = queryResult.first;
+ auto& bbox = queryResult.second;
+
+ // Skip already seen features.
+ auto& seenFeatures = sourceLayerFeatures[feature.sourceLayerName][feature.bucketName];
+ if (seenFeatures.find(feature.index) != seenFeatures.end())
+ continue;
+
+ seenFeatures.insert(feature.index);
+
+ if (!polygonIntersectsBox(projectedQuery, bbox)) {
+ continue;
+ }
+
+ result.push_back(feature);
+ }
+
+ return result;
+
+}
+
+std::pair<float,float> CollisionIndex::projectAnchor(const mat4& posMatrix, const Point<float>& point) const {
+ vec4 p = {{ point.x, point.y, 0, 1 }};
+ matrix::transformMat4(p, p, posMatrix);
+ return std::make_pair(
+ 0.5 + 0.5 * (p[3] / transformState.getCameraToCenterDistance()),
+ p[3]
+ );
+}
+
+std::pair<Point<float>,float> CollisionIndex::projectAndGetPerspectiveRatio(const mat4& posMatrix, const Point<float>& point) const {
+ vec4 p = {{ point.x, point.y, 0, 1 }};
+ matrix::transformMat4(p, p, posMatrix);
+ return std::make_pair(
+ Point<float>(
+ (((p[0] / p[3] + 1) / 2) * transformState.getSize().width) + viewportPadding,
+ (((-p[1] / p[3] + 1) / 2) * transformState.getSize().height) + viewportPadding
+ ),
+ 0.5 + 0.5 * (p[3] / transformState.getCameraToCenterDistance())
+ );
+}
+
+Point<float> CollisionIndex::projectPoint(const mat4& posMatrix, const Point<float>& point) const {
+ vec4 p = {{ point.x, point.y, 0, 1 }};
+ matrix::transformMat4(p, p, posMatrix);
+ return Point<float>(
+ (((p[0] / p[3] + 1) / 2) * transformState.getSize().width) + viewportPadding,
+ (((-p[1] / p[3] + 1) / 2) * transformState.getSize().height) + viewportPadding
+ );
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/text/collision_index.hpp b/src/mbgl/text/collision_index.hpp
new file mode 100644
index 0000000000..8653c1d76c
--- /dev/null
+++ b/src/mbgl/text/collision_index.hpp
@@ -0,0 +1,70 @@
+#pragma once
+
+#include <mbgl/geometry/feature_index.hpp>
+#include <mbgl/text/collision_feature.hpp>
+#include <mbgl/util/grid_index.hpp>
+#include <mbgl/map/transform_state.hpp>
+
+namespace mbgl {
+
+class PlacedSymbol;
+
+struct TileDistance;
+
+class CollisionIndex {
+public:
+ using CollisionGrid = GridIndex<IndexedSubfeature>;
+
+ explicit CollisionIndex(const TransformState&);
+
+ std::pair<bool,bool> placeFeature(CollisionFeature& feature,
+ const mat4& posMatrix,
+ const mat4& labelPlaneMatrix,
+ const float textPixelRatio,
+ PlacedSymbol& symbol,
+ const float scale,
+ const float fontSize,
+ const bool allowOverlap,
+ const bool pitchWithMap,
+ const bool collisionDebug);
+
+ void insertFeature(CollisionFeature& feature, bool ignorePlacement);
+
+ std::vector<IndexedSubfeature> queryRenderedSymbols(const GeometryCoordinates&, const UnwrappedTileID& tileID, const std::string& sourceID) const;
+
+
+private:
+ bool isOffscreen(const CollisionBox&) const;
+ bool isInsideGrid(const CollisionBox&) const;
+
+ std::pair<bool,bool> placeLineFeature(CollisionFeature& feature,
+ const mat4& posMatrix,
+ const mat4& labelPlaneMatrix,
+ const float textPixelRatio,
+ PlacedSymbol& symbol,
+ const float scale,
+ const float fontSize,
+ const bool allowOverlap,
+ const bool pitchWithMap,
+ const bool collisionDebug);
+
+ float approximateTileDistance(const TileDistance& tileDistance, const float lastSegmentAngle, const float pixelsToTileUnits, const float cameraToAnchorDistance, const bool pitchWithMap);
+
+ std::pair<float,float> projectAnchor(const mat4& posMatrix, const Point<float>& point) const;
+ std::pair<Point<float>,float> projectAndGetPerspectiveRatio(const mat4& posMatrix, const Point<float>& point) const;
+ Point<float> projectPoint(const mat4& posMatrix, const Point<float>& point) const;
+
+ const TransformState transformState;
+
+ CollisionGrid collisionGrid;
+ CollisionGrid ignoredGrid;
+
+ const float screenRightBoundary;
+ const float screenBottomBoundary;
+ const float gridRightBoundary;
+ const float gridBottomBoundary;
+
+ const float pitchFactor;
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/text/collision_tile.cpp b/src/mbgl/text/collision_tile.cpp
deleted file mode 100644
index cc9b602f08..0000000000
--- a/src/mbgl/text/collision_tile.cpp
+++ /dev/null
@@ -1,267 +0,0 @@
-#include <mbgl/text/collision_tile.hpp>
-#include <mbgl/geometry/feature_index.hpp>
-#include <mbgl/math/log2.hpp>
-#include <mbgl/util/constants.hpp>
-#include <mbgl/util/math.hpp>
-#include <mbgl/math/minmax.hpp>
-#include <mbgl/util/intersection_tests.hpp>
-
-#include <mapbox/geometry/envelope.hpp>
-#include <mapbox/geometry/multi_point.hpp>
-
-#include <cmath>
-
-namespace mbgl {
-
-CollisionTile::CollisionTile(PlacementConfig config_) : config(std::move(config_)) {
- // Compute the transformation matrix.
- const float angle_sin = std::sin(config.angle);
- const float angle_cos = std::cos(config.angle);
- rotationMatrix = { { angle_cos, -angle_sin, angle_sin, angle_cos } };
- reverseRotationMatrix = { { angle_cos, angle_sin, -angle_sin, angle_cos } };
-
- perspectiveRatio =
- 1.0f +
- 0.5f * (util::division(config.cameraToTileDistance, config.cameraToCenterDistance, 1.0f) -
- 1.0f);
-
- minScale /= perspectiveRatio;
- maxScale /= perspectiveRatio;
-
- // We can only approximate here based on the y position of the tile
- // The shaders calculate a more accurate "incidence_stretch"
- // at render time to calculate an effective scale for collision
- // purposes, but we still want to use the yStretch approximation
- // here because we can't adjust the aspect ratio of the collision
- // boxes at render time.
- yStretch = util::max(
- 1.0f, util::division(config.cameraToTileDistance,
- config.cameraToCenterDistance * std::cos(config.pitch), 1.0f));
-}
-
-float CollisionTile::findPlacementScale(const Point<float>& anchor, const CollisionBox& box, const float boxMaxScale, const Point<float>& blockingAnchor, const CollisionBox& blocking) {
- float minPlacementScale = minScale;
-
- // Find the lowest scale at which the two boxes can fit side by side without overlapping.
- // Original algorithm:
-
- const float s1 = util::division(blocking.x1 - box.x2, anchor.x - blockingAnchor.x,
- 1.0f); // scale at which new box is to the left of old box
- const float s2 = util::division(blocking.x2 - box.x1, anchor.x - blockingAnchor.x,
- 1.0f); // scale at which new box is to the right of old box
- const float s3 = util::division((blocking.y1 - box.y2) * yStretch, anchor.y - blockingAnchor.y,
- 1.0f); // scale at which new box is to the top of old box
- const float s4 = util::division((blocking.y2 - box.y1) * yStretch, anchor.y - blockingAnchor.y,
- 1.0f); // scale at which new box is to the bottom of old box
-
- float collisionFreeScale = util::min(util::max(s1, s2), util::max(s3, s4));
-
- if (collisionFreeScale > blocking.maxScale) {
- // After a box's maxScale the label has shrunk enough that the box is no longer needed to cover it,
- // so unblock the new box at the scale that the old box disappears.
- collisionFreeScale = blocking.maxScale;
- }
-
- if (collisionFreeScale > boxMaxScale) {
- // If the box can only be shown after it is visible, then the box can never be shown.
- // But the label can be shown after this box is not visible.
- collisionFreeScale = boxMaxScale;
- }
-
- if (collisionFreeScale > minPlacementScale &&
- collisionFreeScale >= blocking.placementScale) {
- // If this collision occurs at a lower scale than previously found collisions
- // and the collision occurs while the other label is visible
-
- // this this is the lowest scale at which the label won't collide with anything
- minPlacementScale = collisionFreeScale;
- }
-
- return minPlacementScale;
-}
-
-float CollisionTile::placeFeature(const CollisionFeature& feature, bool allowOverlap, bool avoidEdges) {
- static const float infinity = std::numeric_limits<float>::infinity();
- static const std::array<CollisionBox, 4> edges {{
- // left
- CollisionBox(Point<float>(0, 0), { 0, 0 }, 0, -infinity, 0, infinity, infinity),
- // right
- CollisionBox(Point<float>(util::EXTENT, 0), { 0, 0 }, 0, -infinity, 0, infinity, infinity),
- // top
- CollisionBox(Point<float>(0, 0), { 0, 0 }, -infinity, 0, infinity, 0, infinity),
- // bottom
- CollisionBox(Point<float>(0, util::EXTENT), { 0, 0 }, -infinity, 0, infinity, 0, infinity)
- }};
-
- float minPlacementScale = minScale;
-
- for (auto& box : feature.boxes) {
- const auto anchor = util::matrixMultiply(rotationMatrix, box.anchor);
-
- const float boxMaxScale = box.adjustedMaxScale(rotationMatrix, yStretch);
-
- if (!allowOverlap) {
- for (auto it = tree.qbegin(bgi::intersects(getTreeBox(anchor, box))); it != tree.qend(); ++it) {
- const CollisionBox& blocking = std::get<1>(*it);
- Point<float> blockingAnchor = util::matrixMultiply(rotationMatrix, blocking.anchor);
-
- minPlacementScale = util::max(minPlacementScale, findPlacementScale(anchor, box, boxMaxScale, blockingAnchor, blocking));
- if (minPlacementScale >= maxScale) return minPlacementScale;
- }
- }
-
- if (avoidEdges) {
- const Point<float> rtl = util::matrixMultiply(reverseRotationMatrix, { box.x1, box.y1 });
- const Point<float> rtr = util::matrixMultiply(reverseRotationMatrix, { box.x2, box.y1 });
- const Point<float> rbl = util::matrixMultiply(reverseRotationMatrix, { box.x1, box.y2 });
- const Point<float> rbr = util::matrixMultiply(reverseRotationMatrix, { box.x2, box.y2 });
- CollisionBox rotatedBox(box.anchor,
- box.offset,
- util::min(rtl.x, rtr.x, rbl.x, rbr.x),
- util::min(rtl.y, rtr.y, rbl.y, rbr.y),
- util::max(rtl.x, rtr.x, rbl.x, rbr.x),
- util::max(rtl.y, rtr.y, rbl.y, rbr.y),
- boxMaxScale);
-
- for (auto& blocking : edges) {
- minPlacementScale = util::max(minPlacementScale, findPlacementScale(box.anchor, rotatedBox, boxMaxScale, blocking.anchor, blocking));
- if (minPlacementScale >= maxScale) return minPlacementScale;
- }
- }
- }
-
- return minPlacementScale;
-}
-
-void CollisionTile::insertFeature(CollisionFeature& feature, float minPlacementScale, bool ignorePlacement) {
- for (auto& box : feature.boxes) {
- box.placementScale = minPlacementScale;
- }
-
- if (minPlacementScale < maxScale) {
- std::vector<CollisionTreeBox> treeBoxes;
- for (auto& box : feature.boxes) {
- CollisionBox adjustedBox = box;
- box.maxScale = box.adjustedMaxScale(rotationMatrix, yStretch);
- treeBoxes.emplace_back(getTreeBox(util::matrixMultiply(rotationMatrix, box.anchor), box), std::move(adjustedBox), feature.indexedFeature);
- }
- if (ignorePlacement) {
- ignoredTree.insert(treeBoxes.begin(), treeBoxes.end());
- } else {
- tree.insert(treeBoxes.begin(), treeBoxes.end());
- }
- }
-
-}
-
-// +---------------------------+ As you zoom, the size of the symbol changes
-// |(x1,y1) | | relative to the tile e.g. when zooming in,
-// | | | the symbol gets smaller relative to the tile.
-// | (x1',y1') v |
-// | +-------+-------+ | The boxes inserted into the tree represents
-// | | | | | the bounds at the integer zoom level (where
-// | | | | | the symbol is biggest relative to the tile).
-// | | | | |
-// |---->+-------+-------+<----| This happens because placement is updated
-// | | |(xa,ya)| | once every new integer zoom level e.g.
-// | | | | | std::floor(oldZoom) != std::floor(newZoom).
-// | | | | |
-// | +-------+-------+ | Thus, they don't represent the exact bounds
-// | ^ (x2',y2') | of the symbol at the current zoom level. For
-// | | | calculating the bounds at current zoom level
-// | | (x2,y2)| we must unscale the box using its center as
-// +---------------------------+ transform origin.
-Box CollisionTile::getTreeBox(const Point<float>& anchor, const CollisionBox& box, const float scale) {
- assert(box.x1 <= box.x2 && box.y1 <= box.y2);
- return Box{
- // When the 'perspectiveRatio' is high, we're effectively underzooming
- // the tile because it's in the distance.
- // In order to detect collisions that only happen while underzoomed,
- // we have to query a larger portion of the grid.
- // This extra work is offset by having a lower 'maxScale' bound
- // Note that this adjustment ONLY affects the bounding boxes
- // in the grid. It doesn't affect the boxes used for the
- // minPlacementScale calculations.
- CollisionPoint{
- anchor.x + box.x1 / scale * perspectiveRatio,
- anchor.y + box.y1 / scale * yStretch * perspectiveRatio,
- },
- CollisionPoint{
- anchor.x + box.x2 / scale * perspectiveRatio,
- anchor.y + box.y2 / scale * yStretch * perspectiveRatio
- }
- };
-}
-
-std::vector<IndexedSubfeature> CollisionTile::queryRenderedSymbols(const GeometryCoordinates& queryGeometry, float scale) const {
- std::vector<IndexedSubfeature> result;
- if (queryGeometry.empty() || (tree.empty() && ignoredTree.empty())) {
- return result;
- }
-
- // Generate a rotated geometry out of the original query geometry.
- // Scale has already been handled by the prior conversions.
- GeometryCoordinates polygon;
- for (const auto& point : queryGeometry) {
- auto rotated = util::matrixMultiply(rotationMatrix, convertPoint<float>(point));
- polygon.push_back(convertPoint<int16_t>(rotated));
- }
-
- // Predicate for ruling out already seen features.
- std::unordered_map<std::string, std::unordered_set<std::size_t>> sourceLayerFeatures;
- auto seenFeature = [&] (const CollisionTreeBox& treeBox) -> bool {
- const IndexedSubfeature& feature = std::get<2>(treeBox);
- const auto& seenFeatures = sourceLayerFeatures[feature.sourceLayerName];
- return seenFeatures.find(feature.index) == seenFeatures.end();
- };
-
- // "perspectiveRatio" is a tile-based approximation of how much larger symbols will
- // be in the distance. It won't line up exactly with the actually rendered symbols
- // Being exact would require running the collision detection logic in symbol_sdf.vertex
- // in the CPU
- const float perspectiveScale = scale / perspectiveRatio;
-
- // Account for the rounding done when updating symbol shader variables.
- const float roundedScale = std::pow(2.0f, std::ceil(util::log2(perspectiveScale) * 10.0f) / 10.0f);
-
- // Check if feature is rendered (collision free) at current scale.
- auto visibleAtScale = [&] (const CollisionTreeBox& treeBox) -> bool {
- const CollisionBox& box = std::get<1>(treeBox);
- return roundedScale >= box.placementScale && roundedScale <= box.adjustedMaxScale(rotationMatrix, yStretch);
- };
-
- // Check if query polygon intersects with the feature box at current scale.
- auto intersectsAtScale = [&] (const CollisionTreeBox& treeBox) -> bool {
- const CollisionBox& collisionBox = std::get<1>(treeBox);
- const auto anchor = util::matrixMultiply(rotationMatrix, collisionBox.anchor);
-
- const int16_t x1 = anchor.x + (collisionBox.x1 / perspectiveScale);
- const int16_t y1 = anchor.y + (collisionBox.y1 / perspectiveScale) * yStretch;
- const int16_t x2 = anchor.x + (collisionBox.x2 / perspectiveScale);
- const int16_t y2 = anchor.y + (collisionBox.y2 / perspectiveScale) * yStretch;
- auto bbox = GeometryCoordinates {
- { x1, y1 }, { x2, y1 }, { x2, y2 }, { x1, y2 }
- };
- return util::polygonIntersectsPolygon(polygon, bbox);
- };
-
- auto predicates = bgi::satisfies(seenFeature)
- && bgi::satisfies(visibleAtScale)
- && bgi::satisfies(intersectsAtScale);
-
- auto queryTree = [&](const auto& tree_) {
- for (auto it = tree_.qbegin(predicates); it != tree_.qend(); ++it) {
- const IndexedSubfeature& feature = std::get<2>(*it);
- auto& seenFeatures = sourceLayerFeatures[feature.sourceLayerName];
- seenFeatures.insert(feature.index);
- result.push_back(feature);
- }
- };
-
- queryTree(tree);
- queryTree(ignoredTree);
-
- return result;
-}
-
-} // namespace mbgl
diff --git a/src/mbgl/text/collision_tile.hpp b/src/mbgl/text/collision_tile.hpp
deleted file mode 100644
index 9868266aa2..0000000000
--- a/src/mbgl/text/collision_tile.hpp
+++ /dev/null
@@ -1,71 +0,0 @@
-#pragma once
-
-#include <mbgl/text/collision_feature.hpp>
-#include <mbgl/text/placement_config.hpp>
-#include <mbgl/tile/geometry_tile_data.hpp>
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-function"
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-#pragma GCC diagnostic ignored "-Wunused-variable"
-#pragma GCC diagnostic ignored "-Wshadow"
-#ifdef __clang__
-#pragma GCC diagnostic ignored "-Wunknown-pragmas"
-#endif
-#pragma GCC diagnostic ignored "-Wpragmas"
-#pragma GCC diagnostic ignored "-Wdeprecated-register"
-#pragma GCC diagnostic ignored "-Wshorten-64-to-32"
-#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
-#ifndef __clang__
-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
-#pragma GCC diagnostic ignored "-Wmisleading-indentation"
-#endif
-#include <boost/geometry.hpp>
-#include <boost/geometry/geometries/point.hpp>
-#include <boost/geometry/geometries/box.hpp>
-#include <boost/geometry/index/rtree.hpp>
-#pragma GCC diagnostic pop
-
-namespace mbgl {
-
-namespace bg = boost::geometry;
-namespace bgm = bg::model;
-namespace bgi = bg::index;
-using CollisionPoint = bgm::point<float, 2, bg::cs::cartesian>;
-using Box = bgm::box<CollisionPoint>;
-using CollisionTreeBox = std::tuple<Box, CollisionBox, IndexedSubfeature>;
-using Tree = bgi::rtree<CollisionTreeBox, bgi::linear<16, 4>>;
-
-class IndexedSubfeature;
-
-class CollisionTile {
-public:
- explicit CollisionTile(PlacementConfig);
-
- float placeFeature(const CollisionFeature&, bool allowOverlap, bool avoidEdges);
- void insertFeature(CollisionFeature&, float minPlacementScale, bool ignorePlacement);
-
- std::vector<IndexedSubfeature> queryRenderedSymbols(const GeometryCoordinates&, float scale) const;
-
- const PlacementConfig config;
-
- float minScale = 0.5f;
- float maxScale = 2.0f;
- float yStretch;
-
- std::array<float, 4> rotationMatrix;
- std::array<float, 4> reverseRotationMatrix;
-
-private:
- float findPlacementScale(
- const Point<float>& anchor, const CollisionBox& box, const float boxMaxScale,
- const Point<float>& blockingAnchor, const CollisionBox& blocking);
- Box getTreeBox(const Point<float>& anchor, const CollisionBox& box, const float scale = 1.0);
-
- Tree tree;
- Tree ignoredTree;
-
- float perspectiveRatio;
-};
-
-} // namespace mbgl
diff --git a/src/mbgl/text/cross_tile_symbol_index.cpp b/src/mbgl/text/cross_tile_symbol_index.cpp
new file mode 100644
index 0000000000..177615857f
--- /dev/null
+++ b/src/mbgl/text/cross_tile_symbol_index.cpp
@@ -0,0 +1,165 @@
+#include <mbgl/text/cross_tile_symbol_index.hpp>
+#include <mbgl/layout/symbol_instance.hpp>
+#include <mbgl/renderer/buckets/symbol_bucket.hpp>
+#include <mbgl/renderer/render_tile.hpp>
+#include <mbgl/tile/tile.hpp>
+
+namespace mbgl {
+
+
+TileLayerIndex::TileLayerIndex(OverscaledTileID coord_, std::vector<SymbolInstance>& symbolInstances, uint32_t bucketInstanceId_)
+ : coord(coord_), bucketInstanceId(bucketInstanceId_) {
+ for (SymbolInstance& symbolInstance : symbolInstances) {
+ indexedSymbolInstances[symbolInstance.key].emplace_back(symbolInstance.crossTileID, getScaledCoordinates(symbolInstance, coord));
+ }
+ }
+
+Point<int64_t> TileLayerIndex::getScaledCoordinates(SymbolInstance& symbolInstance, const OverscaledTileID& childTileCoord) {
+ // Round anchor positions to roughly 4 pixel grid
+ const double roundingFactor = 512.0 / util::EXTENT / 2.0;
+ const double scale = roundingFactor / std::pow(2, childTileCoord.canonical.z - coord.canonical.z);
+ return {
+ static_cast<int64_t>(std::floor((childTileCoord.canonical.x * util::EXTENT + symbolInstance.anchor.point.x) * scale)),
+ static_cast<int64_t>(std::floor((childTileCoord.canonical.y * util::EXTENT + symbolInstance.anchor.point.y) * scale))
+ };
+}
+
+void TileLayerIndex::findMatches(std::vector<SymbolInstance>& symbolInstances, const OverscaledTileID& newCoord) {
+ float tolerance = coord.canonical.z < newCoord.canonical.z ? 1 : std::pow(2, coord.canonical.z - newCoord.canonical.z);
+
+ for (auto& symbolInstance : symbolInstances) {
+ if (symbolInstance.crossTileID) {
+ // already has a match, skip
+ continue;
+ }
+
+ auto it = indexedSymbolInstances.find(symbolInstance.key);
+ if (it == indexedSymbolInstances.end()) {
+ // No symbol with this key in this bucket
+ continue;
+ }
+
+ auto scaledSymbolCoord = getScaledCoordinates(symbolInstance, newCoord);
+
+ for (IndexedSymbolInstance& thisTileSymbol: it->second) {
+ // Return any symbol with the same keys whose coordinates are within 1
+ // grid unit. (with a 4px grid, this covers a 12px by 12px area)
+ if (std::abs(thisTileSymbol.coord.x - scaledSymbolCoord.x) <= tolerance &&
+ std::abs(thisTileSymbol.coord.y - scaledSymbolCoord.y) <= tolerance) {
+
+ symbolInstance.crossTileID = thisTileSymbol.crossTileID;
+ break;
+ }
+ }
+ }
+}
+
+CrossTileSymbolLayerIndex::CrossTileSymbolLayerIndex() {
+}
+
+void CrossTileSymbolLayerIndex::addBucket(const OverscaledTileID& coord, SymbolBucket& bucket, uint32_t& maxCrossTileID) {
+ if (bucket.bucketInstanceId) return;
+ bucket.bucketInstanceId = ++maxBucketInstanceId;
+
+ uint8_t minZoom = 25;
+ uint8_t maxZoom = 0;
+ for (auto& it : indexes) {
+ auto z = it.first;
+ minZoom = std::min(minZoom, z);
+ maxZoom = std::max(maxZoom, z);
+ }
+
+
+ // make all higher-res child tiles block duplicate labels in this tile
+ for (auto z = maxZoom; z > coord.overscaledZ; z--) {
+ auto zoomIndexes = indexes.find(z);
+ if (zoomIndexes != indexes.end()) {
+ for (auto& childIndex : zoomIndexes->second) {
+ if (!childIndex.second.coord.isChildOf(coord)) {
+ continue;
+ }
+ childIndex.second.findMatches(bucket.symbolInstances, coord);
+ }
+ }
+ if (z == 0) {
+ break;
+ }
+ }
+
+ // make this tile block duplicate labels in lower-res parent tiles
+ for (auto z = coord.overscaledZ; z >= minZoom; z--) {
+ auto parentCoord = coord.scaledTo(z);
+ auto zoomIndexes = indexes.find(z);
+ if (zoomIndexes != indexes.end()) {
+ auto parentIndex = zoomIndexes->second.find(parentCoord);
+ if (parentIndex != zoomIndexes->second.end()) {
+ parentIndex->second.findMatches(bucket.symbolInstances, coord);
+ }
+ }
+ if (z == 0) {
+ break;
+ }
+ }
+
+ for (auto& symbolInstance : bucket.symbolInstances) {
+ if (!symbolInstance.crossTileID) {
+ // symbol did not match any known symbol, assign a new id
+ symbolInstance.crossTileID = ++maxCrossTileID;
+ }
+ }
+
+ indexes[coord.overscaledZ].emplace(coord, TileLayerIndex(coord, bucket.symbolInstances, bucket.bucketInstanceId));
+}
+
+bool CrossTileSymbolLayerIndex::removeStaleBuckets(const std::unordered_set<uint32_t>& currentIDs) {
+ bool tilesChanged = false;
+ for (auto& zoomIndexes : indexes) {
+ for (auto it = zoomIndexes.second.begin(); it != zoomIndexes.second.end();) {
+ if (!currentIDs.count(it->second.bucketInstanceId)) {
+ it = zoomIndexes.second.erase(it);
+ tilesChanged = true;
+ } else {
+ ++it;
+ }
+ }
+ }
+ return tilesChanged;
+}
+
+CrossTileSymbolIndex::CrossTileSymbolIndex() {}
+
+bool CrossTileSymbolIndex::addLayer(RenderSymbolLayer& symbolLayer) {
+
+ auto& layerIndex = layerIndexes[symbolLayer.getID()];
+
+ bool symbolBucketsChanged = false;
+ std::unordered_set<uint32_t> currentBucketIDs;
+
+ for (RenderTile& renderTile : symbolLayer.renderTiles) {
+ if (!renderTile.tile.isRenderable()) {
+ continue;
+ }
+
+ auto bucket = renderTile.tile.getBucket(*symbolLayer.baseImpl);
+ assert(dynamic_cast<SymbolBucket*>(bucket));
+ SymbolBucket& symbolBucket = *reinterpret_cast<SymbolBucket*>(bucket);
+
+ if (!symbolBucket.bucketInstanceId) {
+ symbolBucketsChanged = true;
+ }
+ layerIndex.addBucket(renderTile.tile.id, symbolBucket, maxCrossTileID);
+ currentBucketIDs.insert(symbolBucket.bucketInstanceId);
+ }
+
+ if (layerIndex.removeStaleBuckets(currentBucketIDs)) {
+ symbolBucketsChanged = true;
+ }
+ return symbolBucketsChanged;
+}
+
+void CrossTileSymbolIndex::reset() {
+ layerIndexes.clear();
+}
+
+} // namespace mbgl
+
diff --git a/src/mbgl/text/cross_tile_symbol_index.hpp b/src/mbgl/text/cross_tile_symbol_index.hpp
new file mode 100644
index 0000000000..c67cd37e00
--- /dev/null
+++ b/src/mbgl/text/cross_tile_symbol_index.hpp
@@ -0,0 +1,64 @@
+#pragma once
+
+#include <mbgl/tile/tile_id.hpp>
+#include <mbgl/util/geometry.hpp>
+#include <mbgl/util/constants.hpp>
+#include <mbgl/util/optional.hpp>
+
+#include <map>
+#include <vector>
+#include <string>
+#include <memory>
+#include <unordered_set>
+
+namespace mbgl {
+
+class SymbolInstance;
+class RenderSymbolLayer;
+class SymbolBucket;
+
+class IndexedSymbolInstance {
+public:
+ IndexedSymbolInstance(uint32_t crossTileID_, Point<int64_t> coord_)
+ : crossTileID(crossTileID_), coord(coord_)
+ {}
+
+ uint32_t crossTileID;
+ Point<int64_t> coord;
+};
+
+class TileLayerIndex {
+public:
+ TileLayerIndex(OverscaledTileID coord, std::vector<SymbolInstance>&, uint32_t bucketInstanceId);
+
+ Point<int64_t> getScaledCoordinates(SymbolInstance&, const OverscaledTileID&);
+ void findMatches(std::vector<SymbolInstance>&, const OverscaledTileID&);
+
+ OverscaledTileID coord;
+ uint32_t bucketInstanceId;
+ std::map<std::u16string,std::vector<IndexedSymbolInstance>> indexedSymbolInstances;
+};
+
+class CrossTileSymbolLayerIndex {
+public:
+ CrossTileSymbolLayerIndex();
+ void addBucket(const OverscaledTileID&, SymbolBucket&, uint32_t& maxCrossTileID);
+ bool removeStaleBuckets(const std::unordered_set<uint32_t>& currentIDs);
+private:
+ std::map<uint8_t,std::map<OverscaledTileID,TileLayerIndex>> indexes;
+ uint32_t maxBucketInstanceId = 0;
+};
+
+class CrossTileSymbolIndex {
+public:
+ CrossTileSymbolIndex();
+
+ bool addLayer(RenderSymbolLayer&);
+
+ void reset();
+private:
+ std::map<std::string, CrossTileSymbolLayerIndex> layerIndexes;
+ uint32_t maxCrossTileID = 0;
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/text/glyph.hpp b/src/mbgl/text/glyph.hpp
index 6cccb72ebe..08ff82a20a 100644
--- a/src/mbgl/text/glyph.hpp
+++ b/src/mbgl/text/glyph.hpp
@@ -75,10 +75,10 @@ class Shaping {
explicit Shaping(float x, float y, WritingModeType writingMode_)
: top(y), bottom(y), left(x), right(x), writingMode(writingMode_) {}
std::vector<PositionedGlyph> positionedGlyphs;
- int32_t top = 0;
- int32_t bottom = 0;
- int32_t left = 0;
- int32_t right = 0;
+ float top = 0;
+ float bottom = 0;
+ float left = 0;
+ float right = 0;
WritingModeType writingMode;
explicit operator bool() const { return !positionedGlyphs.empty(); }
diff --git a/src/mbgl/text/glyph_manager.cpp b/src/mbgl/text/glyph_manager.cpp
index 59b019b547..3130418908 100644
--- a/src/mbgl/text/glyph_manager.cpp
+++ b/src/mbgl/text/glyph_manager.cpp
@@ -44,8 +44,9 @@ void GlyphManager::getGlyphs(GlyphRequestor& requestor, GlyphDependencies glyphD
for (const auto& range : ranges) {
auto it = entry.ranges.find(range);
if (it == entry.ranges.end() || !it->second.parsed) {
- GlyphRequest& request = requestRange(entry, fontStack, range);
+ GlyphRequest& request = entry.ranges[range];
request.requestors[&requestor] = dependencies;
+ requestRange(request, fontStack, range);
}
}
}
@@ -63,17 +64,14 @@ Glyph GlyphManager::generateLocalSDF(const FontStack& fontStack, GlyphID glyphID
return local;
}
-GlyphManager::GlyphRequest& GlyphManager::requestRange(Entry& entry, const FontStack& fontStack, const GlyphRange& range) {
- GlyphRequest& request = entry.ranges[range];
+void GlyphManager::requestRange(GlyphRequest& request, const FontStack& fontStack, const GlyphRange& range) {
if (request.req) {
- return request;
+ return;
}
request.req = fileSource.request(Resource::glyphs(glyphURL, fontStack, range), [this, fontStack, range](Response res) {
processResponse(res, fontStack, range);
});
-
- return request;
}
void GlyphManager::processResponse(const Response& res, const FontStack& fontStack, const GlyphRange& range) {
diff --git a/src/mbgl/text/glyph_manager.hpp b/src/mbgl/text/glyph_manager.hpp
index ccc8d7e16e..84db2c4be5 100644
--- a/src/mbgl/text/glyph_manager.hpp
+++ b/src/mbgl/text/glyph_manager.hpp
@@ -61,7 +61,7 @@ private:
std::unordered_map<FontStack, Entry, FontStackHash> entries;
- GlyphRequest& requestRange(Entry&, const FontStack&, const GlyphRange&);
+ void requestRange(GlyphRequest&, const FontStack&, const GlyphRange&);
void processResponse(const Response&, const FontStack&, const GlyphRange&);
void notify(GlyphRequestor&, const GlyphDependencies&);
diff --git a/src/mbgl/text/placement.cpp b/src/mbgl/text/placement.cpp
new file mode 100644
index 0000000000..334748dda6
--- /dev/null
+++ b/src/mbgl/text/placement.cpp
@@ -0,0 +1,332 @@
+#include <mbgl/text/placement.hpp>
+#include <mbgl/renderer/render_layer.hpp>
+#include <mbgl/renderer/layers/render_symbol_layer.hpp>
+#include <mbgl/renderer/render_tile.hpp>
+#include <mbgl/tile/geometry_tile.hpp>
+#include <mbgl/renderer/buckets/symbol_bucket.hpp>
+#include <mbgl/renderer/bucket.hpp>
+
+namespace mbgl {
+
+OpacityState::OpacityState(bool placed_, bool offscreen)
+ : opacity((offscreen && placed_) ? 1 : 0)
+ , placed(placed_)
+{
+}
+
+OpacityState::OpacityState(const OpacityState& prevState, float increment, bool placed_) :
+ opacity(::fmax(0, ::fmin(1, prevState.opacity + (prevState.placed ? increment : -increment)))),
+ placed(placed_) {}
+
+bool OpacityState::isHidden() const {
+ return opacity == 0 && !placed;
+}
+
+JointOpacityState::JointOpacityState(bool placedIcon, bool placedText, bool offscreen) :
+ icon(OpacityState(placedIcon, offscreen)),
+ text(OpacityState(placedText, offscreen)) {}
+
+JointOpacityState::JointOpacityState(const JointOpacityState& prevOpacityState, float increment, bool placedIcon, bool placedText) :
+ icon(OpacityState(prevOpacityState.icon, increment, placedIcon)),
+ text(OpacityState(prevOpacityState.text, increment, placedText)) {}
+
+bool JointOpacityState::isHidden() const {
+ return icon.isHidden() && text.isHidden();
+}
+
+Placement::Placement(const TransformState& state_, MapMode mapMode_)
+ : collisionIndex(state_)
+ , state(state_)
+ , mapMode(mapMode_)
+ , recentUntil(TimePoint::min())
+{}
+
+void Placement::placeLayer(RenderSymbolLayer& symbolLayer, const mat4& projMatrix, bool showCollisionBoxes) {
+
+ std::unordered_set<uint32_t> seenCrossTileIDs;
+
+ for (RenderTile& renderTile : symbolLayer.renderTiles) {
+ if (!renderTile.tile.isRenderable()) {
+ continue;
+ }
+
+ auto bucket = renderTile.tile.getBucket(*symbolLayer.baseImpl);
+ assert(dynamic_cast<SymbolBucket*>(bucket));
+ SymbolBucket& symbolBucket = *reinterpret_cast<SymbolBucket*>(bucket);
+
+ auto& layout = symbolBucket.layout;
+
+ const float pixelsToTileUnits = renderTile.id.pixelsToTileUnits(1, state.getZoom());
+
+ const float scale = std::pow(2, state.getZoom() - renderTile.tile.id.overscaledZ);
+ const float textPixelRatio = util::EXTENT / (util::tileSize * renderTile.tile.id.overscaleFactor());
+
+ mat4 posMatrix;
+ state.matrixFor(posMatrix, renderTile.id);
+ matrix::multiply(posMatrix, projMatrix, posMatrix);
+
+ mat4 textLabelPlaneMatrix = getLabelPlaneMatrix(posMatrix,
+ layout.get<style::TextPitchAlignment>() == style::AlignmentType::Map,
+ layout.get<style::TextRotationAlignment>() == style::AlignmentType::Map,
+ state,
+ pixelsToTileUnits);
+
+ mat4 iconLabelPlaneMatrix = getLabelPlaneMatrix(posMatrix,
+ layout.get<style::IconPitchAlignment>() == style::AlignmentType::Map,
+ layout.get<style::IconRotationAlignment>() == style::AlignmentType::Map,
+ state,
+ pixelsToTileUnits);
+
+ placeLayerBucket(symbolBucket, posMatrix, textLabelPlaneMatrix, iconLabelPlaneMatrix, scale, textPixelRatio, showCollisionBoxes, seenCrossTileIDs, renderTile.tile.holdForFade());
+ }
+}
+
+void Placement::placeLayerBucket(
+ SymbolBucket& bucket,
+ const mat4& posMatrix,
+ const mat4& textLabelPlaneMatrix,
+ const mat4& iconLabelPlaneMatrix,
+ const float scale,
+ const float textPixelRatio,
+ const bool showCollisionBoxes,
+ std::unordered_set<uint32_t>& seenCrossTileIDs,
+ const bool holdingForFade) {
+
+ auto partiallyEvaluatedTextSize = bucket.textSizeBinder->evaluateForZoom(state.getZoom());
+ auto partiallyEvaluatedIconSize = bucket.iconSizeBinder->evaluateForZoom(state.getZoom());
+
+ const bool iconWithoutText = !bucket.hasTextData() || bucket.layout.get<style::TextOptional>();
+ const bool textWithoutIcon = !bucket.hasIconData() || bucket.layout.get<style::IconOptional>();
+
+ for (auto& symbolInstance : bucket.symbolInstances) {
+
+ if (seenCrossTileIDs.count(symbolInstance.crossTileID) == 0) {
+ if (holdingForFade) {
+ // Mark all symbols from this tile as "not placed", but don't add to seenCrossTileIDs, because we don't
+ // know yet if we have a duplicate in a parent tile that _should_ be placed.
+ placements.emplace(symbolInstance.crossTileID, JointPlacement(false, false, false));
+ continue;
+ }
+
+ bool placeText = false;
+ bool placeIcon = false;
+ bool offscreen = true;
+
+ if (symbolInstance.placedTextIndex) {
+ PlacedSymbol& placedSymbol = bucket.text.placedSymbols.at(*symbolInstance.placedTextIndex);
+ const float fontSize = evaluateSizeForFeature(partiallyEvaluatedTextSize, placedSymbol);
+
+ auto placed = collisionIndex.placeFeature(symbolInstance.textCollisionFeature,
+ posMatrix, textLabelPlaneMatrix, textPixelRatio,
+ placedSymbol, scale, fontSize,
+ bucket.layout.get<style::TextAllowOverlap>(),
+ bucket.layout.get<style::TextPitchAlignment>() == style::AlignmentType::Map,
+ showCollisionBoxes);
+ placeText = placed.first;
+ offscreen &= placed.second;
+ }
+
+ if (symbolInstance.placedIconIndex) {
+ PlacedSymbol& placedSymbol = bucket.icon.placedSymbols.at(*symbolInstance.placedIconIndex);
+ const float fontSize = evaluateSizeForFeature(partiallyEvaluatedIconSize, placedSymbol);
+
+ auto placed = collisionIndex.placeFeature(symbolInstance.iconCollisionFeature,
+ posMatrix, iconLabelPlaneMatrix, textPixelRatio,
+ placedSymbol, scale, fontSize,
+ bucket.layout.get<style::IconAllowOverlap>(),
+ bucket.layout.get<style::IconPitchAlignment>() == style::AlignmentType::Map,
+ showCollisionBoxes);
+ placeIcon = placed.first;
+ offscreen &= placed.second;
+ }
+
+ // combine placements for icon and text
+ if (!iconWithoutText && !textWithoutIcon) {
+ placeText = placeIcon = placeText && placeIcon;
+ } else if (!textWithoutIcon) {
+ placeText = placeText && placeIcon;
+ } else if (!iconWithoutText) {
+ placeIcon = placeText && placeIcon;
+ }
+
+ if (placeText) {
+ collisionIndex.insertFeature(symbolInstance.textCollisionFeature, bucket.layout.get<style::TextIgnorePlacement>());
+ }
+
+ if (placeIcon) {
+ collisionIndex.insertFeature(symbolInstance.iconCollisionFeature, bucket.layout.get<style::IconIgnorePlacement>());
+ }
+
+ assert(symbolInstance.crossTileID != 0);
+
+ if (placements.find(symbolInstance.crossTileID) != placements.end()) {
+ // If there's a previous placement with this ID, it comes from a tile that's fading out
+ // Erase it so that the placement result from the non-fading tile supersedes it
+ placements.erase(symbolInstance.crossTileID);
+ }
+
+ placements.emplace(symbolInstance.crossTileID, JointPlacement(placeText, placeIcon, offscreen));
+ seenCrossTileIDs.insert(symbolInstance.crossTileID);
+ }
+ }
+}
+
+bool Placement::commit(const Placement& prevPlacement, TimePoint now) {
+ commitTime = now;
+
+ bool placementChanged = false;
+
+ float increment = mapMode == MapMode::Continuous ?
+ std::chrono::duration<float>(commitTime - prevPlacement.commitTime) / Duration(std::chrono::milliseconds(300)) :
+ 1.0;
+
+ // add the opacities from the current placement, and copy their current values from the previous placement
+ for (auto& jointPlacement : placements) {
+ auto prevOpacity = prevPlacement.opacities.find(jointPlacement.first);
+ if (prevOpacity != prevPlacement.opacities.end()) {
+ opacities.emplace(jointPlacement.first, JointOpacityState(prevOpacity->second, increment, jointPlacement.second.icon, jointPlacement.second.text));
+ placementChanged = placementChanged ||
+ jointPlacement.second.icon != prevOpacity->second.icon.placed ||
+ jointPlacement.second.text != prevOpacity->second.text.placed;
+ } else {
+ opacities.emplace(jointPlacement.first, JointOpacityState(jointPlacement.second.icon, jointPlacement.second.text, jointPlacement.second.offscreen));
+ placementChanged = placementChanged || jointPlacement.second.icon || jointPlacement.second.text;
+ }
+ }
+
+ // copy and update values from the previous placement that aren't in the current placement but haven't finished fading
+ for (auto& prevOpacity : prevPlacement.opacities) {
+ if (opacities.find(prevOpacity.first) == opacities.end()) {
+ JointOpacityState jointOpacity(prevOpacity.second, increment, false, false);
+ if (!jointOpacity.isHidden()) {
+ opacities.emplace(prevOpacity.first, jointOpacity);
+ placementChanged = placementChanged || prevOpacity.second.icon.placed || prevOpacity.second.text.placed;
+ }
+ }
+ }
+
+ return placementChanged;
+}
+
+void Placement::updateLayerOpacities(RenderSymbolLayer& symbolLayer) {
+ std::set<uint32_t> seenCrossTileIDs;
+ for (RenderTile& renderTile : symbolLayer.renderTiles) {
+ if (!renderTile.tile.isRenderable()) {
+ continue;
+ }
+
+ auto bucket = renderTile.tile.getBucket(*symbolLayer.baseImpl);
+ assert(dynamic_cast<SymbolBucket*>(bucket));
+ SymbolBucket& symbolBucket = *reinterpret_cast<SymbolBucket*>(bucket);
+ updateBucketOpacities(symbolBucket, seenCrossTileIDs);
+ }
+}
+
+void Placement::updateBucketOpacities(SymbolBucket& bucket, std::set<uint32_t>& seenCrossTileIDs) {
+ if (bucket.hasTextData()) bucket.text.opacityVertices.clear();
+ if (bucket.hasIconData()) bucket.icon.opacityVertices.clear();
+ if (bucket.hasCollisionBoxData()) bucket.collisionBox.dynamicVertices.clear();
+ if (bucket.hasCollisionCircleData()) bucket.collisionCircle.dynamicVertices.clear();
+
+ for (SymbolInstance& symbolInstance : bucket.symbolInstances) {
+ auto opacityState = seenCrossTileIDs.count(symbolInstance.crossTileID) == 0 ?
+ getOpacity(symbolInstance.crossTileID) :
+ JointOpacityState(false, false, false);
+
+ seenCrossTileIDs.insert(symbolInstance.crossTileID);
+
+ if (symbolInstance.hasText) {
+ auto opacityVertex = SymbolOpacityAttributes::vertex(opacityState.text.placed, opacityState.text.opacity);
+ for (size_t i = 0; i < symbolInstance.horizontalGlyphQuads.size() * 4; i++) {
+ bucket.text.opacityVertices.emplace_back(opacityVertex);
+ }
+ for (size_t i = 0; i < symbolInstance.verticalGlyphQuads.size() * 4; i++) {
+ bucket.text.opacityVertices.emplace_back(opacityVertex);
+ }
+ if (symbolInstance.placedTextIndex) {
+ bucket.text.placedSymbols[*symbolInstance.placedTextIndex].hidden = opacityState.isHidden();
+ }
+ if (symbolInstance.placedVerticalTextIndex) {
+ bucket.text.placedSymbols[*symbolInstance.placedVerticalTextIndex].hidden = opacityState.isHidden();
+ }
+ }
+ if (symbolInstance.hasIcon) {
+ auto opacityVertex = SymbolOpacityAttributes::vertex(opacityState.icon.placed, opacityState.icon.opacity);
+ if (symbolInstance.iconQuad) {
+ bucket.icon.opacityVertices.emplace_back(opacityVertex);
+ bucket.icon.opacityVertices.emplace_back(opacityVertex);
+ bucket.icon.opacityVertices.emplace_back(opacityVertex);
+ bucket.icon.opacityVertices.emplace_back(opacityVertex);
+ }
+ if (symbolInstance.placedIconIndex) {
+ bucket.icon.placedSymbols[*symbolInstance.placedIconIndex].hidden = opacityState.isHidden();
+ }
+ }
+
+ auto updateCollisionBox = [&](const auto& feature, const bool placed) {
+ for (const CollisionBox& box : feature.boxes) {
+ if (feature.alongLine) {
+ auto dynamicVertex = CollisionBoxDynamicAttributes::vertex(placed, !box.used);
+ bucket.collisionCircle.dynamicVertices.emplace_back(dynamicVertex);
+ bucket.collisionCircle.dynamicVertices.emplace_back(dynamicVertex);
+ bucket.collisionCircle.dynamicVertices.emplace_back(dynamicVertex);
+ bucket.collisionCircle.dynamicVertices.emplace_back(dynamicVertex);
+ } else {
+ auto dynamicVertex = CollisionBoxDynamicAttributes::vertex(placed, false);
+ bucket.collisionBox.dynamicVertices.emplace_back(dynamicVertex);
+ bucket.collisionBox.dynamicVertices.emplace_back(dynamicVertex);
+ bucket.collisionBox.dynamicVertices.emplace_back(dynamicVertex);
+ bucket.collisionBox.dynamicVertices.emplace_back(dynamicVertex);
+ }
+ }
+ };
+ updateCollisionBox(symbolInstance.textCollisionFeature, opacityState.text.placed);
+ updateCollisionBox(symbolInstance.iconCollisionFeature, opacityState.icon.placed);
+ }
+
+ bucket.updateOpacity();
+ bucket.sortFeatures(state.getAngle());
+}
+
+JointOpacityState Placement::getOpacity(uint32_t crossTileSymbolID) const {
+ auto it = opacities.find(crossTileSymbolID);
+ if (it != opacities.end()) {
+ return it->second;
+ } else {
+ return JointOpacityState(false, false, false);
+ }
+
+}
+
+float Placement::symbolFadeChange(TimePoint now) const {
+ if (mapMode == MapMode::Continuous) {
+ return std::chrono::duration<float>(now - commitTime) / Duration(std::chrono::milliseconds(300));
+ } else {
+ return 1.0;
+ }
+}
+
+bool Placement::hasTransitions(TimePoint now) const {
+ return symbolFadeChange(now) < 1.0 || stale;
+}
+
+bool Placement::stillRecent(TimePoint now) const {
+ return mapMode == MapMode::Continuous && recentUntil > now;
+}
+void Placement::setRecent(TimePoint now) {
+ stale = false;
+ if (mapMode == MapMode::Continuous) {
+ // Only set in continuous mode because "now" isn't defined in still mode
+ recentUntil = now + Duration(std::chrono::milliseconds(300));
+ }
+}
+
+void Placement::setStale() {
+ stale = true;
+}
+
+const CollisionIndex& Placement::getCollisionIndex() const {
+ return collisionIndex;
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/text/placement.hpp b/src/mbgl/text/placement.hpp
new file mode 100644
index 0000000000..bcc20f15a4
--- /dev/null
+++ b/src/mbgl/text/placement.hpp
@@ -0,0 +1,91 @@
+#pragma once
+
+#include <string>
+#include <unordered_map>
+#include <mbgl/util/chrono.hpp>
+#include <mbgl/text/collision_index.hpp>
+#include <mbgl/layout/symbol_projection.hpp>
+#include <unordered_set>
+
+namespace mbgl {
+
+class RenderSymbolLayer;
+class SymbolBucket;
+
+class OpacityState {
+public:
+ OpacityState(bool placed, bool offscreen);
+ OpacityState(const OpacityState& prevOpacityState, float increment, bool placed);
+ bool isHidden() const;
+ float opacity;
+ bool placed;
+};
+
+class JointOpacityState {
+public:
+ JointOpacityState(bool placedIcon, bool placedText, bool offscreen);
+ JointOpacityState(const JointOpacityState& prevOpacityState, float increment, bool placedIcon, bool placedText);
+ bool isHidden() const;
+ OpacityState icon;
+ OpacityState text;
+};
+
+class JointPlacement {
+public:
+ JointPlacement(bool text_, bool icon_, bool offscreen_)
+ : text(text_), icon(icon_), offscreen(offscreen_)
+ {}
+
+ const bool text;
+ const bool icon;
+ // offscreen = outside viewport, but within CollisionIndex::viewportPadding px of the edge
+ // Because these symbols aren't onscreen yet, we can skip the "fade in" animation,
+ // and if a subsequent viewport change brings them into view, they'll be fully
+ // visible right away.
+ const bool offscreen;
+};
+
+class Placement {
+public:
+ Placement(const TransformState&, MapMode mapMode);
+ void placeLayer(RenderSymbolLayer&, const mat4&, bool showCollisionBoxes);
+ bool commit(const Placement& prevPlacement, TimePoint);
+ void updateLayerOpacities(RenderSymbolLayer&);
+ JointOpacityState getOpacity(uint32_t crossTileSymbolID) const;
+ float symbolFadeChange(TimePoint now) const;
+ bool hasTransitions(TimePoint now) const;
+
+ const CollisionIndex& getCollisionIndex() const;
+
+ bool stillRecent(TimePoint now) const;
+ void setRecent(TimePoint now);
+ void setStale();
+private:
+
+ void placeLayerBucket(
+ SymbolBucket&,
+ const mat4& posMatrix,
+ const mat4& textLabelPlaneMatrix,
+ const mat4& iconLabelPlaneMatrix,
+ const float scale,
+ const float pixelRatio,
+ const bool showCollisionBoxes,
+ std::unordered_set<uint32_t>& seenCrossTileIDs,
+ const bool holdingForFade);
+
+ void updateBucketOpacities(SymbolBucket&, std::set<uint32_t>&);
+
+ CollisionIndex collisionIndex;
+
+ TransformState state;
+ MapMode mapMode;
+ TimePoint commitTime;
+
+ std::unordered_map<uint32_t, JointPlacement> placements;
+ std::unordered_map<uint32_t, JointOpacityState> opacities;
+
+ TimePoint recentUntil;
+ bool stale = false;
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/text/placement_config.hpp b/src/mbgl/text/placement_config.hpp
deleted file mode 100644
index 48b24b5f41..0000000000
--- a/src/mbgl/text/placement_config.hpp
+++ /dev/null
@@ -1,33 +0,0 @@
-#pragma once
-
-#include <mbgl/util/constants.hpp>
-
-namespace mbgl {
-
-class PlacementConfig {
-public:
- PlacementConfig(float angle_ = 0, float pitch_ = 0, float cameraToCenterDistance_ = 0, float cameraToTileDistance_ = 0, bool debug_ = false)
- : angle(angle_), pitch(pitch_), cameraToCenterDistance(cameraToCenterDistance_), cameraToTileDistance(cameraToTileDistance_), debug(debug_) {
- }
-
- bool operator==(const PlacementConfig& rhs) const {
- return angle == rhs.angle &&
- pitch == rhs.pitch &&
- debug == rhs.debug &&
- ((pitch * util::RAD2DEG < 25) ||
- (cameraToCenterDistance == rhs.cameraToCenterDistance && cameraToTileDistance == rhs.cameraToTileDistance));
- }
-
- bool operator!=(const PlacementConfig& rhs) const {
- return !operator==(rhs);
- }
-
-public:
- float angle;
- float pitch;
- float cameraToCenterDistance;
- float cameraToTileDistance;
- bool debug;
-};
-
-} // namespace mbgl
diff --git a/src/mbgl/text/shaping.cpp b/src/mbgl/text/shaping.cpp
index 5d688ea539..a8232836b6 100644
--- a/src/mbgl/text/shaping.cpp
+++ b/src/mbgl/text/shaping.cpp
@@ -313,7 +313,7 @@ void shapeLines(Shaping& shaping,
align(shaping, justify, anchorAlign.horizontalAlign, anchorAlign.verticalAlign, maxLineLength,
lineHeight, lines.size());
- const uint32_t height = lines.size() * lineHeight;
+ const float height = lines.size() * lineHeight;
// Calculate the bounding box
shaping.top += -anchorAlign.verticalAlign * height;
diff --git a/src/mbgl/tile/custom_geometry_tile.cpp b/src/mbgl/tile/custom_geometry_tile.cpp
new file mode 100644
index 0000000000..7c8a85c4a4
--- /dev/null
+++ b/src/mbgl/tile/custom_geometry_tile.cpp
@@ -0,0 +1,91 @@
+#include <mbgl/tile/custom_geometry_tile.hpp>
+#include <mbgl/tile/geojson_tile_data.hpp>
+#include <mbgl/renderer/query.hpp>
+#include <mbgl/renderer/tile_parameters.hpp>
+#include <mbgl/actor/scheduler.hpp>
+#include <mbgl/style/filter_evaluator.hpp>
+#include <mbgl/util/string.hpp>
+#include <mbgl/tile/tile_observer.hpp>
+#include <mbgl/style/custom_tile_loader.hpp>
+
+#include <mapbox/geojsonvt.hpp>
+
+namespace mbgl {
+
+CustomGeometryTile::CustomGeometryTile(const OverscaledTileID& overscaledTileID,
+ std::string sourceID_,
+ const TileParameters& parameters,
+ const style::CustomGeometrySource::TileOptions options_,
+ ActorRef<style::CustomTileLoader> loader_)
+ : GeometryTile(overscaledTileID, sourceID_, parameters),
+ necessity(TileNecessity::Optional),
+ options(options_),
+ loader(loader_),
+ mailbox(std::make_shared<Mailbox>(*Scheduler::GetCurrent())),
+ actorRef(*this, mailbox) {
+}
+
+CustomGeometryTile::~CustomGeometryTile() {
+ loader.invoke(&style::CustomTileLoader::removeTile, id);
+}
+
+void CustomGeometryTile::setTileData(const GeoJSON& geoJSON) {
+
+ auto featureData = mapbox::geometry::feature_collection<int16_t>();
+ if (geoJSON.is<FeatureCollection>() && !geoJSON.get<FeatureCollection>().empty()) {
+ const double scale = util::EXTENT / options.tileSize;
+
+ mapbox::geojsonvt::TileOptions vtOptions;
+ vtOptions.extent = util::EXTENT;
+ vtOptions.buffer = ::round(scale * options.buffer);
+ vtOptions.tolerance = scale * options.tolerance;
+ featureData = mapbox::geojsonvt::geoJSONToTile(geoJSON, id.canonical.z, id.canonical.x, id.canonical.y, vtOptions).features;
+ } else {
+ setNecessity(TileNecessity::Optional);
+ }
+ setData(std::make_unique<GeoJSONTileData>(std::move(featureData)));
+}
+
+void CustomGeometryTile::invalidateTileData() {
+ stale = true;
+ observer->onTileChanged(*this);
+}
+
+//Fetching tile data for custom sources is assumed to be an expensive operation.
+// Only required tiles make fetchTile requests. Attempt to cancel a tile
+// that is no longer required.
+void CustomGeometryTile::setNecessity(TileNecessity newNecessity) {
+ if (newNecessity != necessity || stale ) {
+ necessity = newNecessity;
+ if (necessity == TileNecessity::Required) {
+ loader.invoke(&style::CustomTileLoader::fetchTile, id, actorRef);
+ stale = false;
+ } else if (!isRenderable()) {
+ loader.invoke(&style::CustomTileLoader::cancelTile, id);
+ }
+ }
+}
+
+void CustomGeometryTile::querySourceFeatures(
+ std::vector<Feature>& result,
+ const SourceQueryOptions& queryOptions) {
+
+ // Ignore the sourceLayer, there is only one
+ auto layer = getData()->getLayer({});
+
+ if (layer) {
+ auto featureCount = layer->featureCount();
+ for (std::size_t i = 0; i < featureCount; i++) {
+ auto feature = layer->getFeature(i);
+
+ // Apply filter, if any
+ if (queryOptions.filter && !(*queryOptions.filter)(*feature)) {
+ continue;
+ }
+
+ result.push_back(convertFeature(*feature, id.canonical));
+ }
+ }
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/tile/custom_geometry_tile.hpp b/src/mbgl/tile/custom_geometry_tile.hpp
new file mode 100644
index 0000000000..1df44e6b2a
--- /dev/null
+++ b/src/mbgl/tile/custom_geometry_tile.hpp
@@ -0,0 +1,44 @@
+#pragma once
+
+#include <mbgl/tile/geometry_tile.hpp>
+#include <mbgl/style/sources/custom_geometry_source.hpp>
+#include <mbgl/util/feature.hpp>
+#include <mbgl/util/geojson.hpp>
+#include <mbgl/actor/mailbox.hpp>
+
+namespace mbgl {
+
+class TileParameters;
+
+namespace style {
+class CustomTileLoader;
+} // namespace style
+
+class CustomGeometryTile: public GeometryTile {
+public:
+ CustomGeometryTile(const OverscaledTileID&,
+ std::string sourceID,
+ const TileParameters&,
+ const style::CustomGeometrySource::TileOptions,
+ ActorRef<style::CustomTileLoader> loader);
+ ~CustomGeometryTile() override;
+
+ void setTileData(const GeoJSON& data);
+ void invalidateTileData();
+
+ void setNecessity(TileNecessity) final;
+
+ void querySourceFeatures(
+ std::vector<Feature>& result,
+ const SourceQueryOptions&) override;
+
+private:
+ bool stale = true;
+ TileNecessity necessity;
+ const style::CustomGeometrySource::TileOptions options;
+ ActorRef<style::CustomTileLoader> loader;
+ std::shared_ptr<Mailbox> mailbox;
+ ActorRef<CustomGeometryTile> actorRef;
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp
index 8c018ce3aa..701e7cf2d6 100644
--- a/src/mbgl/tile/geometry_tile.cpp
+++ b/src/mbgl/tile/geometry_tile.cpp
@@ -15,7 +15,6 @@
#include <mbgl/renderer/image_atlas.hpp>
#include <mbgl/storage/file_source.hpp>
#include <mbgl/geometry/feature_index.hpp>
-#include <mbgl/text/collision_tile.hpp>
#include <mbgl/map/transform_state.hpp>
#include <mbgl/style/filter_evaluator.hpp>
#include <mbgl/util/logging.hpp>
@@ -33,7 +32,7 @@ using namespace style;
GeometryTile's 'correlationID' is used for ensuring the tile will be flagged
as non-pending only when the placement coming from the last operation (as in
- 'setData', 'setLayers', 'setPlacementConfig') occurs. This is important for
+ 'setData', 'setLayers', 'setShowCollisionBoxes') occurs. This is important for
still mode rendering as we want to render only when all layout and placement
operations are completed.
@@ -52,13 +51,15 @@ GeometryTile::GeometryTile(const OverscaledTileID& id_,
worker(parameters.workerScheduler,
ActorRef<GeometryTile>(*this, mailbox),
id_,
+ sourceID,
obsolete,
parameters.mode,
- parameters.pixelRatio),
+ parameters.pixelRatio,
+ parameters.debugOptions & MapDebugOptions::Collision),
glyphManager(parameters.glyphManager),
imageManager(parameters.imageManager),
- lastYStretch(1.0f),
- mode(parameters.mode) {
+ mode(parameters.mode),
+ showCollisionBoxes(parameters.debugOptions & MapDebugOptions::Collision) {
}
GeometryTile::~GeometryTile() {
@@ -89,25 +90,6 @@ void GeometryTile::setData(std::unique_ptr<const GeometryTileData> data_) {
worker.invoke(&GeometryTileWorker::setData, std::move(data_), correlationID);
}
-void GeometryTile::setPlacementConfig(const PlacementConfig& desiredConfig) {
- if (requestedConfig == desiredConfig) {
- return;
- }
-
- // Mark the tile as pending again if it was complete before to prevent signaling a complete
- // state despite pending parse operations.
- pending = true;
-
- ++correlationID;
- requestedConfig = desiredConfig;
- invokePlacement();
-}
-
-void GeometryTile::invokePlacement() {
- if (requestedConfig) {
- worker.invoke(&GeometryTileWorker::setPlacementConfig, *requestedConfig, correlationID);
- }
-}
void GeometryTile::setLayers(const std::vector<Immutable<Layer::Impl>>& layers) {
// Mark the tile as pending again if it was complete before to prevent signaling a complete
@@ -134,14 +116,22 @@ void GeometryTile::setLayers(const std::vector<Immutable<Layer::Impl>>& layers)
worker.invoke(&GeometryTileWorker::setLayers, std::move(impls), correlationID);
}
+void GeometryTile::setShowCollisionBoxes(const bool showCollisionBoxes_) {
+ if (showCollisionBoxes != showCollisionBoxes_) {
+ showCollisionBoxes = showCollisionBoxes_;
+ ++correlationID;
+ worker.invoke(&GeometryTileWorker::setShowCollisionBoxes, showCollisionBoxes, correlationID);
+ }
+}
+
void GeometryTile::onLayout(LayoutResult result, const uint64_t resultCorrelationID) {
- loaded = true;
- renderable = true;
+ // Don't mark ourselves loaded or renderable until the first successful placement
+ // TODO: Ideally we'd render this tile without symbols as long as this tile wasn't
+ // replacing a tile at a different zoom that _did_ have symbols.
(void)resultCorrelationID;
nonSymbolBuckets = std::move(result.nonSymbolBuckets);
featureIndex = std::move(result.featureIndex);
data = std::move(result.tileData);
- collisionTile.reset();
observer->onTileChanged(*this);
}
@@ -152,16 +142,13 @@ void GeometryTile::onPlacement(PlacementResult result, const uint64_t resultCorr
pending = false;
}
symbolBuckets = std::move(result.symbolBuckets);
- collisionTile = std::move(result.collisionTile);
if (result.glyphAtlasImage) {
glyphAtlasImage = std::move(*result.glyphAtlasImage);
}
if (result.iconAtlasImage) {
iconAtlasImage = std::move(*result.iconAtlasImage);
}
- if (collisionTile.get()) {
- lastYStretch = collisionTile->yStretch;
- }
+
observer->onTileChanged(*this);
}
@@ -231,7 +218,8 @@ void GeometryTile::queryRenderedFeatures(
const GeometryCoordinates& queryGeometry,
const TransformState& transformState,
const std::vector<const RenderLayer*>& layers,
- const RenderedQueryOptions& options) {
+ const RenderedQueryOptions& options,
+ const CollisionIndex& collisionIndex) {
if (!featureIndex || !data) return;
@@ -251,9 +239,10 @@ void GeometryTile::queryRenderedFeatures(
std::pow(2, transformState.getZoom() - id.overscaledZ),
options,
*data,
- id.canonical,
+ id.toUnwrapped(),
+ sourceID,
layers,
- collisionTile.get(),
+ collisionIndex,
additionalRadius);
}
@@ -293,11 +282,37 @@ void GeometryTile::querySourceFeatures(
}
}
-float GeometryTile::yStretch() const {
- // collisionTile gets reset in onLayout but we don't clear the symbolBuckets
- // until a new placement result comes along, so keep the yStretch value in
- // case we need to render them.
- return lastYStretch;
+void GeometryTile::resetCrossTileIDs() {
+ for (auto& bucket : symbolBuckets) {
+ auto symbolBucket = dynamic_cast<SymbolBucket*>(bucket.second.get());
+ if (symbolBucket && symbolBucket->bucketInstanceId) {
+ symbolBucket->bucketInstanceId = 0;
+ for (auto& symbolInstance : symbolBucket->symbolInstances) {
+ symbolInstance.crossTileID = 0;
+ }
+ }
+ }
+}
+
+bool GeometryTile::holdForFade() const {
+ return mode == MapMode::Continuous &&
+ (fadeState == FadeState::NeedsFirstPlacement || fadeState == FadeState::NeedsSecondPlacement);
+}
+
+void GeometryTile::markRenderedIdeal() {
+ fadeState = FadeState::Loaded;
+}
+void GeometryTile::markRenderedPreviously() {
+ if (fadeState == FadeState::Loaded) {
+ fadeState = FadeState::NeedsFirstPlacement;
+ }
+}
+void GeometryTile::performedFadePlacement() {
+ if (fadeState == FadeState::NeedsFirstPlacement) {
+ fadeState = FadeState::NeedsSecondPlacement;
+ } else if (fadeState == FadeState::NeedsSecondPlacement) {
+ fadeState = FadeState::CanRemove;
+ }
}
} // namespace mbgl
diff --git a/src/mbgl/tile/geometry_tile.hpp b/src/mbgl/tile/geometry_tile.hpp
index a478aad504..6f871819a4 100644
--- a/src/mbgl/tile/geometry_tile.hpp
+++ b/src/mbgl/tile/geometry_tile.hpp
@@ -4,8 +4,6 @@
#include <mbgl/tile/geometry_tile_worker.hpp>
#include <mbgl/renderer/image_manager.hpp>
#include <mbgl/text/glyph_manager.hpp>
-#include <mbgl/text/placement_config.hpp>
-#include <mbgl/text/collision_tile.hpp>
#include <mbgl/util/feature.hpp>
#include <mbgl/util/throttler.hpp>
#include <mbgl/actor/actor.hpp>
@@ -36,9 +34,9 @@ public:
void setError(std::exception_ptr);
void setData(std::unique_ptr<const GeometryTileData>);
- void setPlacementConfig(const PlacementConfig&) override;
void setLayers(const std::vector<Immutable<style::Layer::Impl>>&) override;
-
+ void setShowCollisionBoxes(const bool showCollisionBoxes) override;
+
void onGlyphsAvailable(GlyphMap) override;
void onImagesAvailable(ImageMap, uint64_t imageCorrelationID) override;
@@ -56,7 +54,8 @@ public:
const GeometryCoordinates& queryGeometry,
const TransformState&,
const std::vector<const RenderLayer*>& layers,
- const RenderedQueryOptions& options) override;
+ const RenderedQueryOptions& options,
+ const CollisionIndex& collisionIndex) override;
void querySourceFeatures(
std::vector<Feature>& result,
@@ -82,16 +81,13 @@ public:
class PlacementResult {
public:
std::unordered_map<std::string, std::shared_ptr<Bucket>> symbolBuckets;
- std::unique_ptr<CollisionTile> collisionTile;
optional<AlphaImage> glyphAtlasImage;
optional<PremultipliedImage> iconAtlasImage;
PlacementResult(std::unordered_map<std::string, std::shared_ptr<Bucket>> symbolBuckets_,
- std::unique_ptr<CollisionTile> collisionTile_,
optional<AlphaImage> glyphAtlasImage_,
optional<PremultipliedImage> iconAtlasImage_)
: symbolBuckets(std::move(symbolBuckets_)),
- collisionTile(std::move(collisionTile_)),
glyphAtlasImage(std::move(glyphAtlasImage_)),
iconAtlasImage(std::move(iconAtlasImage_)) {}
};
@@ -99,7 +95,12 @@ public:
void onError(std::exception_ptr, uint64_t correlationID);
- float yStretch() const override;
+ void resetCrossTileIDs() override;
+
+ bool holdForFade() const override;
+ void markRenderedIdeal() override;
+ void markRenderedPreviously() override;
+ void performedFadePlacement() override;
protected:
const GeometryTileData* getData() {
@@ -108,7 +109,6 @@ protected:
private:
void markObsolete();
- void invokePlacement();
const std::string sourceID;
@@ -122,7 +122,6 @@ private:
ImageManager& imageManager;
uint64_t correlationID = 0;
- optional<PlacementConfig> requestedConfig;
std::unordered_map<std::string, std::shared_ptr<Bucket>> nonSymbolBuckets;
std::unique_ptr<FeatureIndex> featureIndex;
@@ -132,11 +131,19 @@ private:
optional<PremultipliedImage> iconAtlasImage;
std::unordered_map<std::string, std::shared_ptr<Bucket>> symbolBuckets;
- std::unique_ptr<CollisionTile> collisionTile;
- float lastYStretch;
const MapMode mode;
+
+ bool showCollisionBoxes;
+
+ enum class FadeState {
+ Loaded,
+ NeedsFirstPlacement,
+ NeedsSecondPlacement,
+ CanRemove
+ };
+ FadeState fadeState = FadeState::Loaded;
public:
optional<gl::Texture> glyphAtlasTexture;
optional<gl::Texture> iconAtlasTexture;
diff --git a/src/mbgl/tile/geometry_tile_worker.cpp b/src/mbgl/tile/geometry_tile_worker.cpp
index 50429420c3..cf74bf3647 100644
--- a/src/mbgl/tile/geometry_tile_worker.cpp
+++ b/src/mbgl/tile/geometry_tile_worker.cpp
@@ -1,7 +1,6 @@
#include <mbgl/tile/geometry_tile_worker.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/tile/geometry_tile.hpp>
-#include <mbgl/text/collision_tile.hpp>
#include <mbgl/layout/symbol_layout.hpp>
#include <mbgl/renderer/bucket_parameters.hpp>
#include <mbgl/renderer/group_by_layout.hpp>
@@ -24,20 +23,36 @@ using namespace style;
GeometryTileWorker::GeometryTileWorker(ActorRef<GeometryTileWorker> self_,
ActorRef<GeometryTile> parent_,
OverscaledTileID id_,
+ const std::string& sourceID_,
const std::atomic<bool>& obsolete_,
const MapMode mode_,
- const float pixelRatio_)
+ const float pixelRatio_,
+ const bool showCollisionBoxes_)
: self(std::move(self_)),
parent(std::move(parent_)),
id(std::move(id_)),
+ sourceID(sourceID_),
obsolete(obsolete_),
mode(mode_),
- pixelRatio(pixelRatio_) {
+ pixelRatio(pixelRatio_),
+ showCollisionBoxes(showCollisionBoxes_) {
}
GeometryTileWorker::~GeometryTileWorker() = default;
/*
+ NOTE: The comments below are technically correct, but currently
+ conceptually misleading. The change to foreground label placement
+ means that:
+ (1) "placement" here is a misnomer: the remaining role of
+ "attemptPlacement" is symbol buffer generation
+ (2) Once a tile has completed layout, we will only run
+ "attemptPlacement" once
+ (3) Tiles won't be rendered until "attemptPlacement" has run once
+
+ TODO: Simplify GeometryTileWorker to fit its new role
+ https://github.com/mapbox/mapbox-gl-native/issues/10457
+
GeometryTileWorker is a state machine. This is its transition diagram.
States are indicated by [state], lines are transitions triggered by
messages, (parentheses) are actions taken on transition.
@@ -116,9 +131,9 @@ void GeometryTileWorker::setLayers(std::vector<Immutable<Layer::Impl>> layers_,
}
}
-void GeometryTileWorker::setPlacementConfig(PlacementConfig placementConfig_, uint64_t correlationID_) {
+void GeometryTileWorker::setShowCollisionBoxes(bool showCollisionBoxes_, uint64_t correlationID_) {
try {
- placementConfig = std::move(placementConfig_);
+ showCollisionBoxes = showCollisionBoxes_;
correlationID = correlationID_;
switch (state) {
@@ -372,7 +387,7 @@ bool GeometryTileWorker::hasPendingSymbolDependencies() const {
}
void GeometryTileWorker::attemptPlacement() {
- if (!data || !layers || !placementConfig || hasPendingSymbolDependencies()) {
+ if (!data || !layers || hasPendingSymbolDependencies()) {
return;
}
@@ -392,13 +407,13 @@ void GeometryTileWorker::attemptPlacement() {
}
symbolLayout->prepare(glyphMap, glyphAtlas.positions,
- imageMap, imageAtlas.positions);
+ imageMap, imageAtlas.positions,
+ id, sourceID);
}
symbolLayoutsNeedPreparation = false;
}
- auto collisionTile = std::make_unique<CollisionTile>(*placementConfig);
std::unordered_map<std::string, std::shared_ptr<Bucket>> buckets;
for (auto& symbolLayout : symbolLayouts) {
@@ -410,7 +425,7 @@ void GeometryTileWorker::attemptPlacement() {
continue;
}
- std::shared_ptr<Bucket> bucket = symbolLayout->place(*collisionTile);
+ std::shared_ptr<Bucket> bucket = symbolLayout->place(showCollisionBoxes);
for (const auto& pair : symbolLayout->layerPaintProperties) {
buckets.emplace(pair.first, bucket);
}
@@ -418,7 +433,6 @@ void GeometryTileWorker::attemptPlacement() {
parent.invoke(&GeometryTile::onPlacement, GeometryTile::PlacementResult {
std::move(buckets),
- std::move(collisionTile),
std::move(glyphAtlasImage),
std::move(iconAtlasImage),
}, correlationID);
diff --git a/src/mbgl/tile/geometry_tile_worker.hpp b/src/mbgl/tile/geometry_tile_worker.hpp
index 1425daa7a1..cc86248cec 100644
--- a/src/mbgl/tile/geometry_tile_worker.hpp
+++ b/src/mbgl/tile/geometry_tile_worker.hpp
@@ -4,7 +4,6 @@
#include <mbgl/tile/tile_id.hpp>
#include <mbgl/style/image_impl.hpp>
#include <mbgl/text/glyph.hpp>
-#include <mbgl/text/placement_config.hpp>
#include <mbgl/actor/actor_ref.hpp>
#include <mbgl/util/optional.hpp>
#include <mbgl/util/immutable.hpp>
@@ -28,14 +27,16 @@ public:
GeometryTileWorker(ActorRef<GeometryTileWorker> self,
ActorRef<GeometryTile> parent,
OverscaledTileID,
+ const std::string&,
const std::atomic<bool>&,
const MapMode,
- const float pixelRatio);
+ const float pixelRatio,
+ const bool showCollisionBoxes_);
~GeometryTileWorker();
void setLayers(std::vector<Immutable<style::Layer::Impl>>, uint64_t correlationID);
void setData(std::unique_ptr<const GeometryTileData>, uint64_t correlationID);
- void setPlacementConfig(PlacementConfig, uint64_t correlationID);
+ void setShowCollisionBoxes(bool showCollisionBoxes_, uint64_t correlationID_);
void onGlyphsAvailable(GlyphMap glyphs);
void onImagesAvailable(ImageMap images, uint64_t imageCorrelationID);
@@ -57,6 +58,7 @@ private:
ActorRef<GeometryTile> parent;
const OverscaledTileID id;
+ const std::string sourceID;
const std::atomic<bool>& obsolete;
const MapMode mode;
const float pixelRatio;
@@ -75,7 +77,6 @@ private:
// Outer optional indicates whether we've received it or not.
optional<std::vector<Immutable<style::Layer::Impl>>> layers;
optional<std::unique_ptr<const GeometryTileData>> data;
- optional<PlacementConfig> placementConfig;
bool symbolLayoutsNeedPreparation = false;
std::vector<std::unique_ptr<SymbolLayout>> symbolLayouts;
@@ -83,6 +84,8 @@ private:
ImageDependencies pendingImageDependencies;
GlyphMap glyphMap;
ImageMap imageMap;
+
+ bool showCollisionBoxes;
};
} // namespace mbgl
diff --git a/src/mbgl/tile/tile.cpp b/src/mbgl/tile/tile.cpp
index f36a472e72..85899a98cb 100644
--- a/src/mbgl/tile/tile.cpp
+++ b/src/mbgl/tile/tile.cpp
@@ -34,7 +34,8 @@ void Tile::queryRenderedFeatures(
const GeometryCoordinates&,
const TransformState&,
const std::vector<const RenderLayer*>&,
- const RenderedQueryOptions&) {}
+ const RenderedQueryOptions&,
+ const CollisionIndex&) {}
void Tile::querySourceFeatures(
std::vector<Feature>&,
diff --git a/src/mbgl/tile/tile.hpp b/src/mbgl/tile/tile.hpp
index 8be7c4d862..1186b74111 100644
--- a/src/mbgl/tile/tile.hpp
+++ b/src/mbgl/tile/tile.hpp
@@ -23,11 +23,12 @@ namespace mbgl {
class DebugBucket;
class TransformState;
class TileObserver;
-class PlacementConfig;
class RenderLayer;
class RenderedQueryOptions;
class SourceQueryOptions;
+class CollisionIndex;
+
namespace gl {
class Context;
} // namespace gl
@@ -47,7 +48,7 @@ public:
virtual void upload(gl::Context&) = 0;
virtual Bucket* getBucket(const style::Layer::Impl&) const = 0;
- virtual void setPlacementConfig(const PlacementConfig&) {}
+ virtual void setShowCollisionBoxes(const bool) {}
virtual void setLayers(const std::vector<Immutable<style::Layer::Impl>>&) {}
virtual void setMask(TileMask&&) {}
@@ -56,7 +57,8 @@ public:
const GeometryCoordinates& queryGeometry,
const TransformState&,
const std::vector<const RenderLayer*>&,
- const RenderedQueryOptions& options);
+ const RenderedQueryOptions& options,
+ const CollisionIndex&);
virtual void querySourceFeatures(
std::vector<Feature>& result,
@@ -92,6 +94,22 @@ public:
bool isComplete() const {
return loaded && !pending;
}
+
+ // "holdForFade" is used to keep tiles in the render tree after they're no longer
+ // ideal tiles in order to allow symbols to fade out
+ virtual bool holdForFade() const {
+ return false;
+ }
+ // Set whenever this tile is used as an ideal tile
+ virtual void markRenderedIdeal() {}
+ // Set when the tile is removed from the ideal render set but may still be held for fading
+ virtual void markRenderedPreviously() {}
+ // Placement operation performed while this tile is fading
+ // We hold onto a tile for two placements: fading starts with the first placement
+ // and will have time to finish by the second placement.
+ virtual void performedFadePlacement() {}
+
+ virtual void resetCrossTileIDs() {};
void dumpDebugLogs() const;
@@ -101,8 +119,6 @@ public:
// Contains the tile ID string for painting debug information.
std::unique_ptr<DebugBucket> debugBucket;
-
- virtual float yStretch() const { return 1.0f; }
protected:
bool triedOptional = false;
diff --git a/src/mbgl/util/grid_index.cpp b/src/mbgl/util/grid_index.cpp
index b3afd3fdc8..afd469501d 100644
--- a/src/mbgl/util/grid_index.cpp
+++ b/src/mbgl/util/grid_index.cpp
@@ -3,83 +3,301 @@
#include <mbgl/math/minmax.hpp>
#include <unordered_set>
+#include <cmath>
namespace mbgl {
template <class T>
-GridIndex<T>::GridIndex(int32_t extent_, int32_t n_, int32_t padding_) :
- extent(extent_),
- n(n_),
- padding(padding_),
- d(n + 2 * padding),
- scale(double(n) / double(extent)),
- min(-double(padding) / n * extent),
- max(extent + double(padding) / n * extent)
+GridIndex<T>::GridIndex(const float width_, const float height_, const int16_t cellSize_) :
+ width(width_),
+ height(height_),
+ xCellCount(std::ceil(width_ / cellSize_)),
+ yCellCount(std::ceil(height_ / cellSize_)),
+ xScale(xCellCount / width_),
+ yScale(yCellCount / height_)
{
- cells.resize(d * d);
+ boxCells.resize(xCellCount * yCellCount);
+ circleCells.resize(xCellCount * yCellCount);
}
template <class T>
void GridIndex<T>::insert(T&& t, const BBox& bbox) {
- size_t uid = elements.size();
+ size_t uid = boxElements.size();
- auto cx1 = convertToCellCoord(bbox.min.x);
- auto cy1 = convertToCellCoord(bbox.min.y);
- auto cx2 = convertToCellCoord(bbox.max.x);
- auto cy2 = convertToCellCoord(bbox.max.y);
+ auto cx1 = convertToXCellCoord(bbox.min.x);
+ auto cy1 = convertToYCellCoord(bbox.min.y);
+ auto cx2 = convertToXCellCoord(bbox.max.x);
+ auto cy2 = convertToYCellCoord(bbox.max.y);
- int32_t x, y, cellIndex;
+ int16_t x, y, cellIndex;
for (x = cx1; x <= cx2; ++x) {
for (y = cy1; y <= cy2; ++y) {
- cellIndex = d * y + x;
- cells[cellIndex].push_back(uid);
+ cellIndex = xCellCount * y + x;
+ boxCells[cellIndex].push_back(uid);
}
}
- elements.emplace_back(t, bbox);
+ boxElements.emplace_back(t, bbox);
+}
+
+template <class T>
+void GridIndex<T>::insert(T&& t, const BCircle& bcircle) {
+ size_t uid = circleElements.size();
+
+ auto cx1 = convertToXCellCoord(bcircle.center.x - bcircle.radius);
+ auto cy1 = convertToYCellCoord(bcircle.center.y - bcircle.radius);
+ auto cx2 = convertToXCellCoord(bcircle.center.x + bcircle.radius);
+ auto cy2 = convertToYCellCoord(bcircle.center.y + bcircle.radius);
+
+ int16_t x, y, cellIndex;
+ for (x = cx1; x <= cx2; ++x) {
+ for (y = cy1; y <= cy2; ++y) {
+ cellIndex = xCellCount * y + x;
+ circleCells[cellIndex].push_back(uid);
+ }
+ }
+
+ circleElements.emplace_back(t, bcircle);
}
template <class T>
std::vector<T> GridIndex<T>::query(const BBox& queryBBox) const {
std::vector<T> result;
- std::unordered_set<size_t> seenUids;
+ query(queryBBox, [&](const T& t, const BBox&) -> bool {
+ result.push_back(t);
+ return false;
+ });
+ return result;
+}
+
+template <class T>
+std::vector<std::pair<T, typename GridIndex<T>::BBox>> GridIndex<T>::queryWithBoxes(const BBox& queryBBox) const {
+ std::vector<std::pair<T, BBox>> result;
+ query(queryBBox, [&](const T& t, const BBox& bbox) -> bool {
+ result.push_back(std::make_pair(t, bbox));
+ return false;
+ });
+ return result;
+}
+
+template <class T>
+bool GridIndex<T>::hitTest(const BBox& queryBBox) const {
+ bool hit = false;
+ query(queryBBox, [&](const T&, const BBox&) -> bool {
+ hit = true;
+ return true;
+ });
+ return hit;
+}
+
+template <class T>
+bool GridIndex<T>::hitTest(const BCircle& queryBCircle) const {
+ bool hit = false;
+ query(queryBCircle, [&](const T&, const BBox&) -> bool {
+ hit = true;
+ return true;
+ });
+ return hit;
+}
- auto cx1 = convertToCellCoord(queryBBox.min.x);
- auto cy1 = convertToCellCoord(queryBBox.min.y);
- auto cx2 = convertToCellCoord(queryBBox.max.x);
- auto cy2 = convertToCellCoord(queryBBox.max.y);
+template <class T>
+bool GridIndex<T>::noIntersection(const BBox& queryBBox) const {
+ return queryBBox.max.x < 0 || queryBBox.min.x >= width || queryBBox.max.y < 0 || queryBBox.min.y >= height;
+}
+
+template <class T>
+bool GridIndex<T>::completeIntersection(const BBox& queryBBox) const {
+ return queryBBox.min.x <= 0 && queryBBox.min.y <= 0 && width <= queryBBox.max.x && height <= queryBBox.max.y;
+}
+
+template <class T>
+typename GridIndex<T>::BBox GridIndex<T>::convertToBox(const BCircle& circle) const {
+ return BBox{{circle.center.x - circle.radius, circle.center.y - circle.radius},
+ {circle.center.x + circle.radius, circle.center.y + circle.radius}};
+}
+
+template <class T>
+void GridIndex<T>::query(const BBox& queryBBox, std::function<bool (const T&, const BBox&)> resultFn) const {
+ std::unordered_set<size_t> seenBoxes;
+ std::unordered_set<size_t> seenCircles;
+
+ if (noIntersection(queryBBox)) {
+ return;
+ } else if (completeIntersection(queryBBox)) {
+ for (auto& element : boxElements) {
+ if (resultFn(element.first, element.second)) {
+ return;
+ }
+ }
+ for (auto& element : circleElements) {
+ if (resultFn(element.first, convertToBox(element.second))) {
+ return;
+ }
+ }
+ return;
+ }
+
+ auto cx1 = convertToXCellCoord(queryBBox.min.x);
+ auto cy1 = convertToYCellCoord(queryBBox.min.y);
+ auto cx2 = convertToXCellCoord(queryBBox.max.x);
+ auto cy2 = convertToYCellCoord(queryBBox.max.y);
- int32_t x, y, cellIndex;
+ int16_t x, y, cellIndex;
for (x = cx1; x <= cx2; ++x) {
for (y = cy1; y <= cy2; ++y) {
- cellIndex = d * y + x;
- for (auto uid : cells[cellIndex]) {
- if (seenUids.count(uid) == 0) {
- seenUids.insert(uid);
+ cellIndex = xCellCount * y + x;
+ // Look up other boxes
+ for (auto uid : boxCells[cellIndex]) {
+ if (seenBoxes.count(uid) == 0) {
+ seenBoxes.insert(uid);
- auto& pair = elements.at(uid);
+ auto& pair = boxElements.at(uid);
auto& bbox = pair.second;
- if (queryBBox.min.x <= bbox.max.x &&
- queryBBox.min.y <= bbox.max.y &&
- queryBBox.max.x >= bbox.min.x &&
- queryBBox.max.y >= bbox.min.y) {
+ if (boxesCollide(queryBBox, bbox)) {
+ if (resultFn(pair.first, bbox)) {
+ return;
+ }
+ }
+ }
+ }
+
+ // Look up circles
+ for (auto uid : circleCells[cellIndex]) {
+ if (seenCircles.count(uid) == 0) {
+ seenCircles.insert(uid);
- result.push_back(pair.first);
+ auto& pair = circleElements.at(uid);
+ auto& bcircle = pair.second;
+ if (circleAndBoxCollide(bcircle, queryBBox)) {
+ if (resultFn(pair.first, convertToBox(bcircle))) {
+ return;
+ }
}
}
}
}
}
+}
- return result;
+template <class T>
+void GridIndex<T>::query(const BCircle& queryBCircle, std::function<bool (const T&, const BBox&)> resultFn) const {
+ std::unordered_set<size_t> seenBoxes;
+ std::unordered_set<size_t> seenCircles;
+
+ BBox queryBBox = convertToBox(queryBCircle);
+ if (noIntersection(queryBBox)) {
+ return;
+ } else if (completeIntersection(queryBBox)) {
+ for (auto& element : boxElements) {
+ if (resultFn(element.first, element.second)) {
+ return;
+ }
+ }
+ for (auto& element : circleElements) {
+ if (resultFn(element.first, convertToBox(element.second))) {
+ return;
+ }
+ }
+ }
+
+ auto cx1 = convertToXCellCoord(queryBCircle.center.x - queryBCircle.radius);
+ auto cy1 = convertToYCellCoord(queryBCircle.center.y - queryBCircle.radius);
+ auto cx2 = convertToXCellCoord(queryBCircle.center.x + queryBCircle.radius);
+ auto cy2 = convertToYCellCoord(queryBCircle.center.y + queryBCircle.radius);
+
+ int16_t x, y, cellIndex;
+ for (x = cx1; x <= cx2; ++x) {
+ for (y = cy1; y <= cy2; ++y) {
+ cellIndex = xCellCount * y + x;
+ // Look up boxes
+ for (auto uid : boxCells[cellIndex]) {
+ if (seenBoxes.count(uid) == 0) {
+ seenBoxes.insert(uid);
+
+ auto& pair = boxElements.at(uid);
+ auto& bbox = pair.second;
+ if (circleAndBoxCollide(queryBCircle, bbox)) {
+ if (resultFn(pair.first, bbox)) {
+ return;
+ }
+ }
+ }
+ }
+
+ // Look up other circles
+ for (auto uid : circleCells[cellIndex]) {
+ if (seenCircles.count(uid) == 0) {
+ seenCircles.insert(uid);
+
+ auto& pair = circleElements.at(uid);
+ auto& bcircle = pair.second;
+ if (circlesCollide(queryBCircle, bcircle)) {
+ if (resultFn(pair.first, convertToBox(bcircle))) {
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
}
+template <class T>
+int16_t GridIndex<T>::convertToXCellCoord(const float x) const {
+ return util::max(0.0, util::min(xCellCount - 1.0, std::floor(x * xScale)));
+}
+
+template <class T>
+int16_t GridIndex<T>::convertToYCellCoord(const float y) const {
+ return util::max(0.0, util::min(yCellCount - 1.0, std::floor(y * yScale)));
+}
template <class T>
-int32_t GridIndex<T>::convertToCellCoord(int32_t x) const {
- return util::max(0.0, util::min(d - 1.0, std::floor(x * scale) + padding));
+bool GridIndex<T>::boxesCollide(const BBox& first, const BBox& second) const {
+ return first.min.x <= second.max.x &&
+ first.min.y <= second.max.y &&
+ first.max.x >= second.min.x &&
+ first.max.y >= second.min.y;
}
+template <class T>
+bool GridIndex<T>::circlesCollide(const BCircle& first, const BCircle& second) const {
+ auto dx = second.center.x - first.center.x;
+ auto dy = second.center.y - first.center.y;
+ auto bothRadii = first.radius + second.radius;
+ return (bothRadii * bothRadii) > (dx * dx + dy * dy);
+}
+
+template <class T>
+bool GridIndex<T>::circleAndBoxCollide(const BCircle& circle, const BBox& box) const {
+ auto halfRectWidth = (box.max.x - box.min.x) / 2;
+ auto distX = std::abs(circle.center.x - (box.min.x + halfRectWidth));
+ if (distX > (halfRectWidth + circle.radius)) {
+ return false;
+ }
+
+ auto halfRectHeight = (box.max.y - box.min.y) / 2;
+ auto distY = std::abs(circle.center.y - (box.min.y + halfRectHeight));
+ if (distY > (halfRectHeight + circle.radius)) {
+ return false;
+ }
+
+ if (distX <= halfRectWidth || distY <= halfRectHeight) {
+ return true;
+ }
+
+ auto dx = distX - halfRectWidth;
+ auto dy = distY - halfRectHeight;
+ return (dx * dx + dy * dy) <= (circle.radius * circle.radius);
+}
+
+template <class T>
+bool GridIndex<T>::empty() const {
+ return boxElements.empty() && circleElements.empty();
+}
+
+
template class GridIndex<IndexedSubfeature>;
+
} // namespace mbgl
diff --git a/src/mbgl/util/grid_index.hpp b/src/mbgl/util/grid_index.hpp
index 8ef8fb35b7..6ef2966bee 100644
--- a/src/mbgl/util/grid_index.hpp
+++ b/src/mbgl/util/grid_index.hpp
@@ -6,32 +6,100 @@
#include <cstdint>
#include <cstddef>
#include <vector>
+#include <functional>
namespace mbgl {
+namespace geometry {
+
+template <typename T>
+struct circle
+{
+ using point_type = mapbox::geometry::point<T>;
+
+ constexpr circle(point_type const& center_, T const& radius_)
+ : center(center_), radius(radius_)
+ {}
+
+ point_type center;
+ T radius;
+};
+
+template <typename T>
+constexpr bool operator==(circle<T> const& lhs, circle<T> const& rhs)
+{
+ return lhs.center == rhs.center && lhs.radius == rhs.radius;
+}
+
+template <typename T>
+constexpr bool operator!=(circle<T> const& lhs, circle<T> const& rhs)
+{
+ return lhs.center != rhs.center || lhs.radius != rhs.radius;
+}
+
+} // namespace geometry
+
+
+/*
+ GridIndex is a data structure for testing the intersection of
+ circles and rectangles in a 2d plane.
+ It is optimized for rapid insertion and querying.
+ GridIndex splits the plane into a set of "cells" and keeps track
+ of which geometries intersect with each cell. At query time,
+ full geometry comparisons are only done for items that share
+ at least one cell. As long as the geometries are relatively
+ uniformly distributed across the plane, this greatly reduces
+ the number of comparisons necessary.
+*/
+
template <class T>
class GridIndex {
public:
- GridIndex(int32_t extent_, int32_t n_, int32_t padding_);
- using BBox = mapbox::geometry::box<int16_t>;
+ GridIndex(const float width_, const float height_, const int16_t cellSize_);
+
+ using BBox = mapbox::geometry::box<float>;
+ using BCircle = geometry::circle<float>;
void insert(T&& t, const BBox&);
+ void insert(T&& t, const BCircle&);
+
std::vector<T> query(const BBox&) const;
+ std::vector<std::pair<T,BBox>> queryWithBoxes(const BBox&) const;
+
+ bool hitTest(const BBox&) const;
+ bool hitTest(const BCircle&) const;
+
+ bool empty() const;
private:
- int32_t convertToCellCoord(int32_t x) const;
-
- const int32_t extent;
- const int32_t n;
- const int32_t padding;
- const int32_t d;
- const double scale;
- const int32_t min;
- const int32_t max;
-
- std::vector<std::pair<T, BBox>> elements;
- std::vector<std::vector<size_t>> cells;
+ bool noIntersection(const BBox& queryBBox) const;
+ bool completeIntersection(const BBox& queryBBox) const;
+ BBox convertToBox(const BCircle& circle) const;
+
+ void query(const BBox&, std::function<bool (const T&, const BBox&)>) const;
+ void query(const BCircle&, std::function<bool (const T&, const BBox&)>) const;
+
+ int16_t convertToXCellCoord(const float x) const;
+ int16_t convertToYCellCoord(const float y) const;
+
+ bool boxesCollide(const BBox&, const BBox&) const;
+ bool circlesCollide(const BCircle&, const BCircle&) const;
+ bool circleAndBoxCollide(const BCircle&, const BBox&) const;
+
+ const float width;
+ const float height;
+
+ const int16_t xCellCount;
+ const int16_t yCellCount;
+ const double xScale;
+ const double yScale;
+
+ std::vector<std::pair<T, BBox>> boxElements;
+ std::vector<std::pair<T, BCircle>> circleElements;
+
+ std::vector<std::vector<size_t>> boxCells;
+ std::vector<std::vector<size_t>> circleCells;
};
diff --git a/src/mbgl/util/mapbox.cpp b/src/mbgl/util/mapbox.cpp
index 8cbc85d492..802b527a26 100644
--- a/src/mbgl/util/mapbox.cpp
+++ b/src/mbgl/util/mapbox.cpp
@@ -114,7 +114,7 @@ std::string normalizeTileURL(const std::string& baseURL,
}
std::string
-canonicalizeTileURL(const std::string& str, const SourceType type, const uint16_t tileSize) {
+canonicalizeTileURL(const std::string& str, const style::SourceType type, const uint16_t tileSize) {
const char* version = "/v4/";
const size_t versionLen = strlen(version);
@@ -133,7 +133,7 @@ canonicalizeTileURL(const std::string& str, const SourceType type, const uint16_
std::string result = "mapbox://tiles/";
result.append(str, path.directory.first + versionLen, path.directory.second - versionLen);
result.append(str, path.filename.first, path.filename.second);
- if (type == SourceType::Raster) {
+ if (type == style::SourceType::Raster) {
result += tileSize == util::tileSize ? "@2x" : "{ratio}";
}
@@ -171,7 +171,7 @@ canonicalizeTileURL(const std::string& str, const SourceType type, const uint16_
return result;
}
-void canonicalizeTileset(Tileset& tileset, const std::string& sourceURL, SourceType type, uint16_t tileSize) {
+void canonicalizeTileset(Tileset& tileset, const std::string& sourceURL, style::SourceType type, uint16_t tileSize) {
// TODO: Remove this hack by delivering proper URLs in the TileJSON to begin with.
if (isMapboxURL(sourceURL)) {
for (auto& url : tileset.tiles) {
diff --git a/src/mbgl/util/mapbox.hpp b/src/mbgl/util/mapbox.hpp
index f3dfdd0b01..aa128f2667 100644
--- a/src/mbgl/util/mapbox.hpp
+++ b/src/mbgl/util/mapbox.hpp
@@ -19,10 +19,10 @@ std::string normalizeGlyphsURL(const std::string& baseURL, const std::string& ur
std::string normalizeTileURL(const std::string& baseURL, const std::string& url, const std::string& accessToken);
// Return a "mapbox://tiles/..." URL (suitable for normalizeTileURL) for the given Mapbox tile URL.
-std::string canonicalizeTileURL(const std::string& url, SourceType, uint16_t tileSize);
+std::string canonicalizeTileURL(const std::string& url, style::SourceType, uint16_t tileSize);
// Replace URL templates with "mapbox://tiles/..." URLs (suitable for normalizeTileURL).
-void canonicalizeTileset(Tileset&, const std::string& url, SourceType, uint16_t tileSize);
+void canonicalizeTileset(Tileset&, const std::string& url, style::SourceType, uint16_t tileSize);
extern const uint64_t DEFAULT_OFFLINE_TILE_COUNT_LIMIT;
diff --git a/src/mbgl/util/tile_cover.cpp b/src/mbgl/util/tile_cover.cpp
index a5a1b1d70c..39b562d811 100644
--- a/src/mbgl/util/tile_cover.cpp
+++ b/src/mbgl/util/tile_cover.cpp
@@ -126,9 +126,9 @@ std::vector<UnwrappedTileID> tileCover(const Point<double>& tl,
} // namespace
-int32_t coveringZoomLevel(double zoom, SourceType type, uint16_t size) {
+int32_t coveringZoomLevel(double zoom, style::SourceType type, uint16_t size) {
zoom += std::log(util::tileSize / size) / std::log(2);
- if (type == SourceType::Raster || type == SourceType::Video) {
+ if (type == style::SourceType::Raster || type == style::SourceType::Video) {
return ::round(zoom);
} else {
return std::floor(zoom);
@@ -182,10 +182,10 @@ uint64_t tileCount(const LatLngBounds& bounds, uint8_t zoom, uint16_t tileSize_)
auto y1 = floor(sw.y/ tileSize_);
auto y2 = floor((ne.y - 1) / tileSize_);
- auto minX = std::fmax(std::min(x1, x2), 0);
+ auto minX = ::fmax(std::min(x1, x2), 0);
auto maxX = std::max(x1, x2);
auto minY = (std::pow(2, zoom) - 1) - std::max(y1, y2);
- auto maxY = (std::pow(2, zoom) - 1) - std::fmax(std::min(y1, y2), 0);
+ auto maxY = (std::pow(2, zoom) - 1) - ::fmax(std::min(y1, y2), 0);
return (maxX - minX + 1) * (maxY - minY + 1);
}
diff --git a/src/mbgl/util/tile_cover.hpp b/src/mbgl/util/tile_cover.hpp
index 3c7a4ee44a..b2098b59b8 100644
--- a/src/mbgl/util/tile_cover.hpp
+++ b/src/mbgl/util/tile_cover.hpp
@@ -13,7 +13,7 @@ class LatLngBounds;
namespace util {
-int32_t coveringZoomLevel(double z, SourceType type, uint16_t tileSize);
+int32_t coveringZoomLevel(double z, style::SourceType type, uint16_t tileSize);
std::vector<UnwrappedTileID> tileCover(const TransformState&, int32_t z);
std::vector<UnwrappedTileID> tileCover(const LatLngBounds&, int32_t z);
diff --git a/src/parsedate/parsedate.c b/src/parsedate/parsedate.c
index 46acceed75..7228c4edbc 100644
--- a/src/parsedate/parsedate.c
+++ b/src/parsedate/parsedate.c
@@ -418,7 +418,7 @@ static time_t my_timegm(struct my_tm *tm)
{
static const int month_days_cumulative [12] =
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
- int month, year, leap_days;
+ int month_, year, leap_days;
if(tm->tm_year < 70)
/* we don't support years before 1970 as they will cause this function
@@ -426,14 +426,14 @@ static time_t my_timegm(struct my_tm *tm)
return -1;
year = tm->tm_year + 1900;
- month = tm->tm_mon;
- if(month < 0) {
- year += (11 - month) / 12;
- month = 11 - (11 - month) % 12;
+ month_ = tm->tm_mon;
+ if(month_ < 0) {
+ year += (11 - month_) / 12;
+ month_ = 11 - (11 - month_) % 12;
}
- else if(month >= 12) {
- year -= month / 12;
- month = month % 12;
+ else if(month_ >= 12) {
+ year -= month_ / 12;
+ month_ = month_ % 12;
}
leap_days = year - (tm->tm_mon <= 1);
@@ -441,7 +441,7 @@ static time_t my_timegm(struct my_tm *tm)
- (1969 / 4) + (1969 / 100) - (1969 / 400));
return ((((time_t) (year - 1970) * 365
- + leap_days + month_days_cumulative [month] + tm->tm_mday - 1) * 24
+ + leap_days + month_days_cumulative [month_] + tm->tm_mday - 1) * 24
+ tm->tm_hour) * 60 + tm->tm_min) * 60 + tm->tm_sec;
}
diff --git a/test/api/annotations.test.cpp b/test/api/annotations.test.cpp
index b777615b4c..07257851ac 100644
--- a/test/api/annotations.test.cpp
+++ b/test/api/annotations.test.cpp
@@ -32,7 +32,7 @@ public:
float pixelRatio { 1 };
HeadlessFrontend frontend { pixelRatio, fileSource, threadPool };
Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, fileSource,
- threadPool, MapMode::Still };
+ threadPool, MapMode::Static};
void checkRendering(const char * name) {
test::checkImage(std::string("test/fixtures/annotations/") + name,
@@ -366,8 +366,8 @@ TEST(Annotations, QueryFractionalZoomLevels) {
test.map.addAnnotationImage(namedMarker("default_marker"));
std::vector<mbgl::AnnotationID> ids;
- for (int longitude = 0; longitude < 10; ++longitude) {
- for (int latitude = 0; latitude < 10; ++latitude) {
+ for (int longitude = 0; longitude < 10; longitude += 2) {
+ for (int latitude = 0; latitude < 10; latitude += 2) {
ids.push_back(test.map.addAnnotation(SymbolAnnotation { { double(latitude), double(longitude) }, "default_marker" }));
}
}
@@ -399,8 +399,8 @@ TEST(Annotations, VisibleFeatures) {
test.map.setLatLngZoom({ 5, 5 }, 3);
std::vector<mbgl::AnnotationID> ids;
- for (int longitude = 0; longitude < 10; ++longitude) {
- for (int latitude = 0; latitude <= 10; ++latitude) {
+ for (int longitude = 0; longitude < 10; longitude += 2) {
+ for (int latitude = 0; latitude <= 10; latitude += 2) {
ids.push_back(test.map.addAnnotation(SymbolAnnotation { { double(latitude), double(longitude) }, "default_marker" }));
}
}
diff --git a/test/api/api_misuse.test.cpp b/test/api/api_misuse.test.cpp
index 690c1548e5..363958451b 100644
--- a/test/api/api_misuse.test.cpp
+++ b/test/api/api_misuse.test.cpp
@@ -27,7 +27,7 @@ TEST(API, RenderWithoutCallback) {
HeadlessFrontend frontend { pixelRatio, fileSource, threadPool };
auto map = std::make_unique<Map>(frontend, MapObserver::nullObserver(), frontend.getSize(),
- pixelRatio, fileSource, threadPool, MapMode::Still);
+ pixelRatio, fileSource, threadPool, MapMode::Static);
map->renderStill(nullptr);
// Force Map thread to join.
diff --git a/test/api/custom_geometry_source.test.cpp b/test/api/custom_geometry_source.test.cpp
new file mode 100644
index 0000000000..83d1543a0a
--- /dev/null
+++ b/test/api/custom_geometry_source.test.cpp
@@ -0,0 +1,71 @@
+#include <mbgl/test/util.hpp>
+
+#include <mbgl/gl/gl.hpp>
+#include <mbgl/map/map.hpp>
+#include <mbgl/util/shared_thread_pool.hpp>
+#include <mbgl/storage/default_file_source.hpp>
+#include <mbgl/gl/headless_frontend.hpp>
+#include <mbgl/style/style.hpp>
+#include <mbgl/style/sources/custom_geometry_source.hpp>
+#include <mbgl/style/layers/fill_layer.hpp>
+#include <mbgl/style/layers/line_layer.hpp>
+#include <mbgl/util/geojson.hpp>
+#include <mbgl/util/io.hpp>
+#include <mbgl/util/mat4.hpp>
+#include <mbgl/util/run_loop.hpp>
+
+using namespace mbgl;
+using namespace mbgl::style;
+
+TEST(CustomGeometrySource, Grid) {
+ util::RunLoop loop;
+
+ DefaultFileSource fileSource(":memory:", "test/fixtures/api/assets");
+ auto threadPool = sharedThreadPool();
+ float pixelRatio { 1 };
+ HeadlessFrontend frontend { pixelRatio, fileSource, *threadPool };
+ Map map(frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, fileSource,
+ *threadPool, MapMode::Static);
+ map.getStyle().loadJSON(util::read_file("test/fixtures/api/water.json"));
+ map.setLatLngZoom({ 37.8, -122.5 }, 10);
+
+ CustomGeometrySource::Options options;
+ options.fetchTileFunction = [&map](const mbgl::CanonicalTileID& tileID) {
+ double gridSpacing = 0.1;
+ FeatureCollection features;
+ const LatLngBounds bounds(tileID);
+ for (double y = ceil(bounds.north() / gridSpacing) * gridSpacing; y >= floor(bounds.south() / gridSpacing) * gridSpacing; y -= gridSpacing) {
+
+ mapbox::geojson::line_string gridLine;
+ gridLine.emplace_back(bounds.west(), y);
+ gridLine.emplace_back(bounds.east(), y);
+
+ features.emplace_back(gridLine);
+ }
+
+ for (double x = floor(bounds.west() / gridSpacing) * gridSpacing; x <= ceil(bounds.east() / gridSpacing) * gridSpacing; x += gridSpacing) {
+ mapbox::geojson::line_string gridLine;
+ gridLine.emplace_back(x, bounds.south());
+ gridLine.emplace_back(x, bounds.north());
+
+ features.emplace_back(gridLine);
+ }
+ auto source = static_cast<CustomGeometrySource *>(map.getStyle().getSource("custom"));
+ if (source) {
+ source->setTileData(tileID, features);
+ }
+ };
+
+ map.getStyle().addSource(std::make_unique<CustomGeometrySource>("custom", options));
+
+ auto fillLayer = std::make_unique<FillLayer>("landcover", "mapbox");
+ fillLayer->setSourceLayer("landcover");
+ fillLayer->setFillColor(Color{ 1.0, 1.0, 0.0, 1.0 });
+ map.getStyle().addLayer(std::move(fillLayer));
+
+ auto layer = std::make_unique<LineLayer>("grid", "custom");
+ layer->setLineColor(Color{ 1.0, 1.0, 1.0, 1.0 });
+ map.getStyle().addLayer(std::move(layer));
+
+ test::checkImage("test/fixtures/custom_geometry_source/grid", frontend.render(map), 0.0006, 0.1);
+}
diff --git a/test/api/custom_layer.test.cpp b/test/api/custom_layer.test.cpp
index 1c514aeca2..eb1d7e0d3a 100644
--- a/test/api/custom_layer.test.cpp
+++ b/test/api/custom_layer.test.cpp
@@ -90,7 +90,7 @@ TEST(CustomLayer, Basic) {
float pixelRatio { 1 };
HeadlessFrontend frontend { pixelRatio, fileSource, threadPool };
Map map(frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, fileSource,
- threadPool, MapMode::Still);
+ threadPool, MapMode::Static);
map.getStyle().loadJSON(util::read_file("test/fixtures/api/water.json"));
map.setLatLngZoom({ 37.8, -122.5 }, 10);
map.getStyle().addLayer(std::make_unique<CustomLayer>(
diff --git a/test/api/query.test.cpp b/test/api/query.test.cpp
index 3f3825eb72..c67ff9064c 100644
--- a/test/api/query.test.cpp
+++ b/test/api/query.test.cpp
@@ -32,7 +32,7 @@ public:
float pixelRatio { 1 };
HeadlessFrontend frontend { pixelRatio, fileSource, threadPool };
Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, fileSource,
- threadPool, MapMode::Still };
+ threadPool, MapMode::Static};
};
} // end namespace
diff --git a/test/api/recycle_map.cpp b/test/api/recycle_map.cpp
index 8cd622fe79..ca6abac8c1 100644
--- a/test/api/recycle_map.cpp
+++ b/test/api/recycle_map.cpp
@@ -29,7 +29,7 @@ TEST(API, RecycleMapUpdateImages) {
HeadlessFrontend frontend { pixelRatio, fileSource, threadPool };
auto map = std::make_unique<Map>(frontend, MapObserver::nullObserver(), frontend.getSize(),
- pixelRatio, fileSource, threadPool, MapMode::Still);
+ pixelRatio, fileSource, threadPool, MapMode::Static);
EXPECT_TRUE(map);
diff --git a/test/api/zoom_history.cpp b/test/api/zoom_history.cpp
index 1b1159bf52..df9b6ff2a3 100644
--- a/test/api/zoom_history.cpp
+++ b/test/api/zoom_history.cpp
@@ -30,7 +30,7 @@ TEST(API, ZoomHistory) {
HeadlessFrontend frontend { pixelRatio, fileSource, threadPool };
auto map = std::make_unique<Map>(frontend, MapObserver::nullObserver(), frontend.getSize(),
- pixelRatio, fileSource, threadPool, MapMode::Still);
+ pixelRatio, fileSource, threadPool, MapMode::Static);
EXPECT_TRUE(map);
diff --git a/test/fixtures/annotations/debug_sparse/expected.png b/test/fixtures/annotations/debug_sparse/expected.png
index 3c1ad1599c..493928998d 100644
--- a/test/fixtures/annotations/debug_sparse/expected.png
+++ b/test/fixtures/annotations/debug_sparse/expected.png
Binary files differ
diff --git a/test/fixtures/api/query_style.json b/test/fixtures/api/query_style.json
index 2e499c383d..fd147f7899 100644
--- a/test/fixtures/api/query_style.json
+++ b/test/fixtures/api/query_style.json
@@ -67,7 +67,8 @@
"type": "symbol",
"source": "source1",
"layout": {
- "icon-image": "test-icon"
+ "icon-image": "test-icon",
+ "icon-allow-overlap": true
}
},
{
@@ -75,7 +76,8 @@
"type": "symbol",
"source": "source2",
"layout": {
- "icon-image": "test-icon"
+ "icon-image": "test-icon",
+ "icon-allow-overlap": true
}
},
{
@@ -83,7 +85,8 @@
"type": "symbol",
"source": "source3",
"layout": {
- "icon-image": "test-icon"
+ "icon-image": "test-icon",
+ "icon-allow-overlap": true
}
},
{
@@ -91,7 +94,8 @@
"type": "symbol",
"source": "source4",
"layout": {
- "icon-image": "test-icon"
+ "icon-image": "test-icon",
+ "icon-allow-overlap": true
}
}
]
diff --git a/test/fixtures/custom_geometry_source/grid/expected.png b/test/fixtures/custom_geometry_source/grid/expected.png
new file mode 100644
index 0000000000..628a3b11fb
--- /dev/null
+++ b/test/fixtures/custom_geometry_source/grid/expected.png
Binary files differ
diff --git a/test/fixtures/expression_equality/acos.a.json b/test/fixtures/expression_equality/acos.a.json
new file mode 100644
index 0000000000..1e9bb752ca
--- /dev/null
+++ b/test/fixtures/expression_equality/acos.a.json
@@ -0,0 +1,4 @@
+[
+ "acos",
+ 0.5
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/acos.b.json b/test/fixtures/expression_equality/acos.b.json
new file mode 100644
index 0000000000..54e035cb7e
--- /dev/null
+++ b/test/fixtures/expression_equality/acos.b.json
@@ -0,0 +1,4 @@
+[
+ "acos",
+ 1.5
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/all.a.json b/test/fixtures/expression_equality/all.a.json
new file mode 100644
index 0000000000..ec7154b7b9
--- /dev/null
+++ b/test/fixtures/expression_equality/all.a.json
@@ -0,0 +1,17 @@
+[
+ "all",
+ [
+ "boolean",
+ [
+ "get",
+ "x"
+ ]
+ ],
+ [
+ "boolean",
+ [
+ "get",
+ "y"
+ ]
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/all.b.json b/test/fixtures/expression_equality/all.b.json
new file mode 100644
index 0000000000..8eab839bb0
--- /dev/null
+++ b/test/fixtures/expression_equality/all.b.json
@@ -0,0 +1,17 @@
+[
+ "all",
+ [
+ "boolean",
+ [
+ "get",
+ "x"
+ ]
+ ],
+ [
+ "boolean",
+ [
+ "get",
+ "y_other"
+ ]
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/any.a.json b/test/fixtures/expression_equality/any.a.json
new file mode 100644
index 0000000000..3f044c1f79
--- /dev/null
+++ b/test/fixtures/expression_equality/any.a.json
@@ -0,0 +1,17 @@
+[
+ "any",
+ [
+ "boolean",
+ [
+ "get",
+ "x"
+ ]
+ ],
+ [
+ "boolean",
+ [
+ "get",
+ "y"
+ ]
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/any.b.json b/test/fixtures/expression_equality/any.b.json
new file mode 100644
index 0000000000..720662751f
--- /dev/null
+++ b/test/fixtures/expression_equality/any.b.json
@@ -0,0 +1,17 @@
+[
+ "any",
+ [
+ "boolean",
+ [
+ "get",
+ "x"
+ ]
+ ],
+ [
+ "boolean",
+ [
+ "get",
+ "y_other"
+ ]
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/array.a.json b/test/fixtures/expression_equality/array.a.json
new file mode 100644
index 0000000000..3c31303ca3
--- /dev/null
+++ b/test/fixtures/expression_equality/array.a.json
@@ -0,0 +1,11 @@
+[
+ "array",
+ [
+ "literal",
+ [
+ 1,
+ 2,
+ 3
+ ]
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/array.b.json b/test/fixtures/expression_equality/array.b.json
new file mode 100644
index 0000000000..7606794d56
--- /dev/null
+++ b/test/fixtures/expression_equality/array.b.json
@@ -0,0 +1,11 @@
+[
+ "array",
+ [
+ "literal",
+ [
+ 1,
+ 2,
+ 4
+ ]
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/asin.a.json b/test/fixtures/expression_equality/asin.a.json
new file mode 100644
index 0000000000..3cd730ccbf
--- /dev/null
+++ b/test/fixtures/expression_equality/asin.a.json
@@ -0,0 +1,4 @@
+[
+ "asin",
+ 0.5
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/asin.b.json b/test/fixtures/expression_equality/asin.b.json
new file mode 100644
index 0000000000..2c862c8cbe
--- /dev/null
+++ b/test/fixtures/expression_equality/asin.b.json
@@ -0,0 +1,4 @@
+[
+ "asin",
+ 1.5
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/at.a.json b/test/fixtures/expression_equality/at.a.json
new file mode 100644
index 0000000000..c69b0d933b
--- /dev/null
+++ b/test/fixtures/expression_equality/at.a.json
@@ -0,0 +1,20 @@
+[
+ "number",
+ [
+ "at",
+ [
+ "number",
+ [
+ "get",
+ "i"
+ ]
+ ],
+ [
+ "array",
+ [
+ "get",
+ "arr"
+ ]
+ ]
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/at.b.json b/test/fixtures/expression_equality/at.b.json
new file mode 100644
index 0000000000..6e19c28606
--- /dev/null
+++ b/test/fixtures/expression_equality/at.b.json
@@ -0,0 +1,20 @@
+[
+ "number",
+ [
+ "at",
+ [
+ "number",
+ [
+ "get",
+ "i"
+ ]
+ ],
+ [
+ "array",
+ [
+ "get",
+ "arr_other"
+ ]
+ ]
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/atan.a.json b/test/fixtures/expression_equality/atan.a.json
new file mode 100644
index 0000000000..b76406bc44
--- /dev/null
+++ b/test/fixtures/expression_equality/atan.a.json
@@ -0,0 +1,4 @@
+[
+ "atan",
+ 1
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/atan.b.json b/test/fixtures/expression_equality/atan.b.json
new file mode 100644
index 0000000000..aafbbb0594
--- /dev/null
+++ b/test/fixtures/expression_equality/atan.b.json
@@ -0,0 +1,4 @@
+[
+ "atan",
+ 2
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/boolean.a.json b/test/fixtures/expression_equality/boolean.a.json
new file mode 100644
index 0000000000..1230a2a926
--- /dev/null
+++ b/test/fixtures/expression_equality/boolean.a.json
@@ -0,0 +1,7 @@
+[
+ "boolean",
+ [
+ "get",
+ "x"
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/boolean.b.json b/test/fixtures/expression_equality/boolean.b.json
new file mode 100644
index 0000000000..1ae91ef60c
--- /dev/null
+++ b/test/fixtures/expression_equality/boolean.b.json
@@ -0,0 +1,7 @@
+[
+ "boolean",
+ [
+ "get",
+ "x_other"
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/case.a.json b/test/fixtures/expression_equality/case.a.json
new file mode 100644
index 0000000000..84049294f5
--- /dev/null
+++ b/test/fixtures/expression_equality/case.a.json
@@ -0,0 +1,14 @@
+[
+ "case",
+ [
+ "get",
+ "x"
+ ],
+ "x",
+ [
+ "get",
+ "y"
+ ],
+ "y",
+ "otherwise"
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/case.b.json b/test/fixtures/expression_equality/case.b.json
new file mode 100644
index 0000000000..038806043f
--- /dev/null
+++ b/test/fixtures/expression_equality/case.b.json
@@ -0,0 +1,14 @@
+[
+ "case",
+ [
+ "get",
+ "x"
+ ],
+ "x",
+ [
+ "get",
+ "y"
+ ],
+ "y",
+ "otherwise_other"
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/coalesce.a.json b/test/fixtures/expression_equality/coalesce.a.json
new file mode 100644
index 0000000000..8fae579e7c
--- /dev/null
+++ b/test/fixtures/expression_equality/coalesce.a.json
@@ -0,0 +1,16 @@
+[
+ "coalesce",
+ [
+ "get",
+ "x"
+ ],
+ [
+ "get",
+ "y"
+ ],
+ [
+ "get",
+ "z"
+ ],
+ 0
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/coalesce.b.json b/test/fixtures/expression_equality/coalesce.b.json
new file mode 100644
index 0000000000..4e0af8baa0
--- /dev/null
+++ b/test/fixtures/expression_equality/coalesce.b.json
@@ -0,0 +1,16 @@
+[
+ "coalesce",
+ [
+ "get",
+ "x"
+ ],
+ [
+ "get",
+ "y"
+ ],
+ [
+ "get",
+ "z"
+ ],
+ 1
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/concat.a.json b/test/fixtures/expression_equality/concat.a.json
new file mode 100644
index 0000000000..08c95d7f49
--- /dev/null
+++ b/test/fixtures/expression_equality/concat.a.json
@@ -0,0 +1,6 @@
+[
+ "concat",
+ "a",
+ "b",
+ "c"
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/concat.b.json b/test/fixtures/expression_equality/concat.b.json
new file mode 100644
index 0000000000..e3396d4fc0
--- /dev/null
+++ b/test/fixtures/expression_equality/concat.b.json
@@ -0,0 +1,6 @@
+[
+ "concat",
+ "a",
+ "b",
+ "c_other"
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/cos.a.json b/test/fixtures/expression_equality/cos.a.json
new file mode 100644
index 0000000000..e41430de53
--- /dev/null
+++ b/test/fixtures/expression_equality/cos.a.json
@@ -0,0 +1,4 @@
+[
+ "cos",
+ 0
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/cos.b.json b/test/fixtures/expression_equality/cos.b.json
new file mode 100644
index 0000000000..5ba4424dae
--- /dev/null
+++ b/test/fixtures/expression_equality/cos.b.json
@@ -0,0 +1,4 @@
+[
+ "cos",
+ 1
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/divide.a.json b/test/fixtures/expression_equality/divide.a.json
new file mode 100644
index 0000000000..40a67a871c
--- /dev/null
+++ b/test/fixtures/expression_equality/divide.a.json
@@ -0,0 +1,5 @@
+[
+ "/",
+ 10,
+ 5
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/divide.b.json b/test/fixtures/expression_equality/divide.b.json
new file mode 100644
index 0000000000..e3f7b155b2
--- /dev/null
+++ b/test/fixtures/expression_equality/divide.b.json
@@ -0,0 +1,5 @@
+[
+ "/",
+ 10,
+ 6
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/downcase.a.json b/test/fixtures/expression_equality/downcase.a.json
new file mode 100644
index 0000000000..ca367218c4
--- /dev/null
+++ b/test/fixtures/expression_equality/downcase.a.json
@@ -0,0 +1,4 @@
+[
+ "downcase",
+ "StRiNg"
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/downcase.b.json b/test/fixtures/expression_equality/downcase.b.json
new file mode 100644
index 0000000000..fd9ea9881d
--- /dev/null
+++ b/test/fixtures/expression_equality/downcase.b.json
@@ -0,0 +1,4 @@
+[
+ "downcase",
+ "StRiNg_other"
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/get.a.json b/test/fixtures/expression_equality/get.a.json
new file mode 100644
index 0000000000..57c3df48e7
--- /dev/null
+++ b/test/fixtures/expression_equality/get.a.json
@@ -0,0 +1,7 @@
+[
+ "number",
+ [
+ "get",
+ "x"
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/get.b.json b/test/fixtures/expression_equality/get.b.json
new file mode 100644
index 0000000000..d1843362d3
--- /dev/null
+++ b/test/fixtures/expression_equality/get.b.json
@@ -0,0 +1,7 @@
+[
+ "number",
+ [
+ "get",
+ "x_other"
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/has.a.json b/test/fixtures/expression_equality/has.a.json
new file mode 100644
index 0000000000..8326754107
--- /dev/null
+++ b/test/fixtures/expression_equality/has.a.json
@@ -0,0 +1,4 @@
+[
+ "has",
+ "x"
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/has.b.json b/test/fixtures/expression_equality/has.b.json
new file mode 100644
index 0000000000..20b6072303
--- /dev/null
+++ b/test/fixtures/expression_equality/has.b.json
@@ -0,0 +1,4 @@
+[
+ "has",
+ "x_other"
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/heatmap-density.a.json b/test/fixtures/expression_equality/heatmap-density.a.json
new file mode 100644
index 0000000000..90bd396f54
--- /dev/null
+++ b/test/fixtures/expression_equality/heatmap-density.a.json
@@ -0,0 +1,23 @@
+[
+ "interpolate",
+ [
+ "linear"
+ ],
+ [
+ "heatmap-density"
+ ],
+ 0,
+ [
+ "rgb",
+ 0,
+ 0,
+ 255
+ ],
+ 1,
+ [
+ "rgb",
+ 255,
+ 0,
+ 0
+ ]
+]
diff --git a/test/fixtures/expression_equality/heatmap-density.b.json b/test/fixtures/expression_equality/heatmap-density.b.json
new file mode 100644
index 0000000000..bce8ab03a1
--- /dev/null
+++ b/test/fixtures/expression_equality/heatmap-density.b.json
@@ -0,0 +1,23 @@
+[
+ "interpolate",
+ [
+ "linear"
+ ],
+ [
+ "heatmap-density"
+ ],
+ 0,
+ [
+ "rgb",
+ 0,
+ 0,
+ 255
+ ],
+ 1,
+ [
+ "rgb",
+ 255,
+ 255,
+ 255
+ ]
+]
diff --git a/test/fixtures/expression_equality/let.a.json b/test/fixtures/expression_equality/let.a.json
new file mode 100644
index 0000000000..fb24e50cfb
--- /dev/null
+++ b/test/fixtures/expression_equality/let.a.json
@@ -0,0 +1,25 @@
+[
+ "let",
+ "a",
+ 1,
+ "b",
+ 2,
+ [
+ "+",
+ [
+ "+",
+ [
+ "var",
+ "a"
+ ],
+ [
+ "var",
+ "b"
+ ]
+ ],
+ [
+ "var",
+ "a"
+ ]
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/let.b.json b/test/fixtures/expression_equality/let.b.json
new file mode 100644
index 0000000000..26813cb6ff
--- /dev/null
+++ b/test/fixtures/expression_equality/let.b.json
@@ -0,0 +1,25 @@
+[
+ "let",
+ "a",
+ 1,
+ "b",
+ 3,
+ [
+ "+",
+ [
+ "+",
+ [
+ "var",
+ "a"
+ ],
+ [
+ "var",
+ "b"
+ ]
+ ],
+ [
+ "var",
+ "b"
+ ]
+ ]
+]
diff --git a/test/fixtures/expression_equality/ln.a.json b/test/fixtures/expression_equality/ln.a.json
new file mode 100644
index 0000000000..30d80f36ae
--- /dev/null
+++ b/test/fixtures/expression_equality/ln.a.json
@@ -0,0 +1,4 @@
+[
+ "ln",
+ 2
+]
diff --git a/test/fixtures/expression_equality/ln.b.json b/test/fixtures/expression_equality/ln.b.json
new file mode 100644
index 0000000000..9bc04ad586
--- /dev/null
+++ b/test/fixtures/expression_equality/ln.b.json
@@ -0,0 +1,6 @@
+[
+ "ln",
+ [
+ "e"
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/log10.a.json b/test/fixtures/expression_equality/log10.a.json
new file mode 100644
index 0000000000..32e4c18807
--- /dev/null
+++ b/test/fixtures/expression_equality/log10.a.json
@@ -0,0 +1,4 @@
+[
+ "log10",
+ 100
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/log10.b.json b/test/fixtures/expression_equality/log10.b.json
new file mode 100644
index 0000000000..8f32c204f9
--- /dev/null
+++ b/test/fixtures/expression_equality/log10.b.json
@@ -0,0 +1,4 @@
+[
+ "log10",
+ 101
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/log2.a.json b/test/fixtures/expression_equality/log2.a.json
new file mode 100644
index 0000000000..95cdc15373
--- /dev/null
+++ b/test/fixtures/expression_equality/log2.a.json
@@ -0,0 +1,4 @@
+[
+ "log2",
+ 1024
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/log2.b.json b/test/fixtures/expression_equality/log2.b.json
new file mode 100644
index 0000000000..2fffaeb32a
--- /dev/null
+++ b/test/fixtures/expression_equality/log2.b.json
@@ -0,0 +1,4 @@
+[
+ "log2",
+ 1025
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/match.a.json b/test/fixtures/expression_equality/match.a.json
new file mode 100644
index 0000000000..ba8afc4126
--- /dev/null
+++ b/test/fixtures/expression_equality/match.a.json
@@ -0,0 +1,12 @@
+[
+ "match",
+ [
+ "get",
+ "x"
+ ],
+ "a",
+ "Apple",
+ "b",
+ "Banana",
+ "Kumquat"
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/match.b.json b/test/fixtures/expression_equality/match.b.json
new file mode 100644
index 0000000000..2404b8e2e7
--- /dev/null
+++ b/test/fixtures/expression_equality/match.b.json
@@ -0,0 +1,12 @@
+[
+ "match",
+ [
+ "get",
+ "x"
+ ],
+ "a",
+ "Apple",
+ "b",
+ "Banana",
+ "Kumquat_other"
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/max.a.json b/test/fixtures/expression_equality/max.a.json
new file mode 100644
index 0000000000..09a8f82bd7
--- /dev/null
+++ b/test/fixtures/expression_equality/max.a.json
@@ -0,0 +1,6 @@
+[
+ "max",
+ 0,
+ -1,
+ 100
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/max.b.json b/test/fixtures/expression_equality/max.b.json
new file mode 100644
index 0000000000..1b0beb20d6
--- /dev/null
+++ b/test/fixtures/expression_equality/max.b.json
@@ -0,0 +1,6 @@
+[
+ "max",
+ 0,
+ -1,
+ 101
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/min.a.json b/test/fixtures/expression_equality/min.a.json
new file mode 100644
index 0000000000..38cc90f1cd
--- /dev/null
+++ b/test/fixtures/expression_equality/min.a.json
@@ -0,0 +1,5 @@
+[
+ "min",
+ ["get", "x"],
+ 0
+]
diff --git a/test/fixtures/expression_equality/min.b.json b/test/fixtures/expression_equality/min.b.json
new file mode 100644
index 0000000000..84a5f66842
--- /dev/null
+++ b/test/fixtures/expression_equality/min.b.json
@@ -0,0 +1,5 @@
+[
+ "min",
+ ["get", "x"],
+ 1
+]
diff --git a/test/fixtures/expression_equality/minus.a.json b/test/fixtures/expression_equality/minus.a.json
new file mode 100644
index 0000000000..9eb4f954e7
--- /dev/null
+++ b/test/fixtures/expression_equality/minus.a.json
@@ -0,0 +1,5 @@
+[
+ "-",
+ 5,
+ 7
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/minus.b.json b/test/fixtures/expression_equality/minus.b.json
new file mode 100644
index 0000000000..87042b98ef
--- /dev/null
+++ b/test/fixtures/expression_equality/minus.b.json
@@ -0,0 +1,5 @@
+[
+ "-",
+ 5,
+ 8
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/mod.a.json b/test/fixtures/expression_equality/mod.a.json
new file mode 100644
index 0000000000..8439bafcd1
--- /dev/null
+++ b/test/fixtures/expression_equality/mod.a.json
@@ -0,0 +1,5 @@
+[
+ "%",
+ 18,
+ 12
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/mod.b.json b/test/fixtures/expression_equality/mod.b.json
new file mode 100644
index 0000000000..362e1721c1
--- /dev/null
+++ b/test/fixtures/expression_equality/mod.b.json
@@ -0,0 +1,5 @@
+[
+ "%",
+ 18,
+ 13
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/not.a.json b/test/fixtures/expression_equality/not.a.json
new file mode 100644
index 0000000000..b5f03e0ac0
--- /dev/null
+++ b/test/fixtures/expression_equality/not.a.json
@@ -0,0 +1,10 @@
+[
+ "!",
+ [
+ "boolean",
+ [
+ "get",
+ "x"
+ ]
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/not.b.json b/test/fixtures/expression_equality/not.b.json
new file mode 100644
index 0000000000..a4d77adf2e
--- /dev/null
+++ b/test/fixtures/expression_equality/not.b.json
@@ -0,0 +1,10 @@
+[
+ "!",
+ [
+ "boolean",
+ [
+ "get",
+ "x_other"
+ ]
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/number.a.json b/test/fixtures/expression_equality/number.a.json
new file mode 100644
index 0000000000..57c3df48e7
--- /dev/null
+++ b/test/fixtures/expression_equality/number.a.json
@@ -0,0 +1,7 @@
+[
+ "number",
+ [
+ "get",
+ "x"
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/number.b.json b/test/fixtures/expression_equality/number.b.json
new file mode 100644
index 0000000000..d1843362d3
--- /dev/null
+++ b/test/fixtures/expression_equality/number.b.json
@@ -0,0 +1,7 @@
+[
+ "number",
+ [
+ "get",
+ "x_other"
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/object.a.json b/test/fixtures/expression_equality/object.a.json
new file mode 100644
index 0000000000..7551cfdbb2
--- /dev/null
+++ b/test/fixtures/expression_equality/object.a.json
@@ -0,0 +1,7 @@
+[
+ "object",
+ [
+ "get",
+ "x"
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/object.b.json b/test/fixtures/expression_equality/object.b.json
new file mode 100644
index 0000000000..8444d40c0e
--- /dev/null
+++ b/test/fixtures/expression_equality/object.b.json
@@ -0,0 +1,7 @@
+[
+ "object",
+ [
+ "get",
+ "x_other"
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/plus.a.json b/test/fixtures/expression_equality/plus.a.json
new file mode 100644
index 0000000000..a00c4409fa
--- /dev/null
+++ b/test/fixtures/expression_equality/plus.a.json
@@ -0,0 +1,7 @@
+[
+ "+",
+ 1,
+ 2,
+ 3,
+ 4
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/plus.b.json b/test/fixtures/expression_equality/plus.b.json
new file mode 100644
index 0000000000..87c071123f
--- /dev/null
+++ b/test/fixtures/expression_equality/plus.b.json
@@ -0,0 +1,7 @@
+[
+ "+",
+ 1,
+ 2,
+ 3,
+ 5
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/pow.a.json b/test/fixtures/expression_equality/pow.a.json
new file mode 100644
index 0000000000..c1a1e67f86
--- /dev/null
+++ b/test/fixtures/expression_equality/pow.a.json
@@ -0,0 +1,11 @@
+[
+ "^",
+ 4,
+ [
+ "number",
+ [
+ "get",
+ "x"
+ ]
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/pow.b.json b/test/fixtures/expression_equality/pow.b.json
new file mode 100644
index 0000000000..ca5331b92a
--- /dev/null
+++ b/test/fixtures/expression_equality/pow.b.json
@@ -0,0 +1,11 @@
+[
+ "^",
+ 4,
+ [
+ "number",
+ [
+ "get",
+ "x_other"
+ ]
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/rgb.a.json b/test/fixtures/expression_equality/rgb.a.json
new file mode 100644
index 0000000000..ce6c5e5dd0
--- /dev/null
+++ b/test/fixtures/expression_equality/rgb.a.json
@@ -0,0 +1,6 @@
+[
+ "rgb",
+ 0,
+ 0,
+ 255
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/rgb.b.json b/test/fixtures/expression_equality/rgb.b.json
new file mode 100644
index 0000000000..577c19748b
--- /dev/null
+++ b/test/fixtures/expression_equality/rgb.b.json
@@ -0,0 +1,6 @@
+[
+ "rgb",
+ 0,
+ 0,
+ 0
+]
diff --git a/test/fixtures/expression_equality/rgba.a.json b/test/fixtures/expression_equality/rgba.a.json
new file mode 100644
index 0000000000..e8ad7326c1
--- /dev/null
+++ b/test/fixtures/expression_equality/rgba.a.json
@@ -0,0 +1,7 @@
+[
+ "rgba",
+ 0,
+ 0,
+ 255,
+ 1
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/rgba.b.json b/test/fixtures/expression_equality/rgba.b.json
new file mode 100644
index 0000000000..81d442eaae
--- /dev/null
+++ b/test/fixtures/expression_equality/rgba.b.json
@@ -0,0 +1,7 @@
+[
+ "rgba",
+ 0,
+ 0,
+ 255,
+ 0.5
+]
diff --git a/test/fixtures/expression_equality/sin.a.json b/test/fixtures/expression_equality/sin.a.json
new file mode 100644
index 0000000000..0f7ae2966f
--- /dev/null
+++ b/test/fixtures/expression_equality/sin.a.json
@@ -0,0 +1,4 @@
+[
+ "sin",
+ 0
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/sin.b.json b/test/fixtures/expression_equality/sin.b.json
new file mode 100644
index 0000000000..90f309b80f
--- /dev/null
+++ b/test/fixtures/expression_equality/sin.b.json
@@ -0,0 +1,4 @@
+[
+ "sin",
+ 1
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/sqrt.a.json b/test/fixtures/expression_equality/sqrt.a.json
new file mode 100644
index 0000000000..56dd85bc1a
--- /dev/null
+++ b/test/fixtures/expression_equality/sqrt.a.json
@@ -0,0 +1,7 @@
+[
+ "sqrt",
+ [
+ "get",
+ "x"
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/sqrt.b.json b/test/fixtures/expression_equality/sqrt.b.json
new file mode 100644
index 0000000000..ab05d5084c
--- /dev/null
+++ b/test/fixtures/expression_equality/sqrt.b.json
@@ -0,0 +1,7 @@
+[
+ "sqrt",
+ [
+ "get",
+ "x_other"
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/step.a.json b/test/fixtures/expression_equality/step.a.json
new file mode 100644
index 0000000000..4fee85cd03
--- /dev/null
+++ b/test/fixtures/expression_equality/step.a.json
@@ -0,0 +1,18 @@
+[
+ "number",
+ [
+ "step",
+ [
+ "number",
+ [
+ "get",
+ "x"
+ ]
+ ],
+ 11,
+ 0,
+ 111,
+ 1,
+ 1111
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/step.b.json b/test/fixtures/expression_equality/step.b.json
new file mode 100644
index 0000000000..0a591a84df
--- /dev/null
+++ b/test/fixtures/expression_equality/step.b.json
@@ -0,0 +1,18 @@
+[
+ "number",
+ [
+ "step",
+ [
+ "number",
+ [
+ "get",
+ "x"
+ ]
+ ],
+ 11,
+ 0,
+ 111,
+ 1,
+ 1112
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/string.a.json b/test/fixtures/expression_equality/string.a.json
new file mode 100644
index 0000000000..a79344f338
--- /dev/null
+++ b/test/fixtures/expression_equality/string.a.json
@@ -0,0 +1,7 @@
+[
+ "string",
+ [
+ "get",
+ "x"
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/string.b.json b/test/fixtures/expression_equality/string.b.json
new file mode 100644
index 0000000000..6f77f3c3cf
--- /dev/null
+++ b/test/fixtures/expression_equality/string.b.json
@@ -0,0 +1,7 @@
+[
+ "string",
+ [
+ "get",
+ "x_other"
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/tan.a.json b/test/fixtures/expression_equality/tan.a.json
new file mode 100644
index 0000000000..c78e47e492
--- /dev/null
+++ b/test/fixtures/expression_equality/tan.a.json
@@ -0,0 +1,4 @@
+[
+ "tan",
+ 0.7853981633974483
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/tan.b.json b/test/fixtures/expression_equality/tan.b.json
new file mode 100644
index 0000000000..c22e64cf8a
--- /dev/null
+++ b/test/fixtures/expression_equality/tan.b.json
@@ -0,0 +1,4 @@
+[
+ "tan",
+ 1.7853981633974483
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/times.a.json b/test/fixtures/expression_equality/times.a.json
new file mode 100644
index 0000000000..ce6d9b46e0
--- /dev/null
+++ b/test/fixtures/expression_equality/times.a.json
@@ -0,0 +1,7 @@
+[
+ "*",
+ 3,
+ 2,
+ 0.5,
+ 2
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/times.b.json b/test/fixtures/expression_equality/times.b.json
new file mode 100644
index 0000000000..147e011172
--- /dev/null
+++ b/test/fixtures/expression_equality/times.b.json
@@ -0,0 +1,7 @@
+[
+ "*",
+ 3,
+ 2,
+ 0.5,
+ 3
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/to-boolean.a.json b/test/fixtures/expression_equality/to-boolean.a.json
new file mode 100644
index 0000000000..ccf48149ec
--- /dev/null
+++ b/test/fixtures/expression_equality/to-boolean.a.json
@@ -0,0 +1,7 @@
+[
+ "to-boolean",
+ [
+ "get",
+ "x"
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/to-boolean.b.json b/test/fixtures/expression_equality/to-boolean.b.json
new file mode 100644
index 0000000000..7896261241
--- /dev/null
+++ b/test/fixtures/expression_equality/to-boolean.b.json
@@ -0,0 +1,7 @@
+[
+ "to-boolean",
+ [
+ "get",
+ "x_other"
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/to-color.a.json b/test/fixtures/expression_equality/to-color.a.json
new file mode 100644
index 0000000000..de9ab59eec
--- /dev/null
+++ b/test/fixtures/expression_equality/to-color.a.json
@@ -0,0 +1,7 @@
+[
+ "to-color",
+ [
+ "get",
+ "x"
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/to-color.b.json b/test/fixtures/expression_equality/to-color.b.json
new file mode 100644
index 0000000000..c0566ef6a7
--- /dev/null
+++ b/test/fixtures/expression_equality/to-color.b.json
@@ -0,0 +1,7 @@
+[
+ "to-color",
+ [
+ "get",
+ "x_other"
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/to-number.a.json b/test/fixtures/expression_equality/to-number.a.json
new file mode 100644
index 0000000000..65b2df5014
--- /dev/null
+++ b/test/fixtures/expression_equality/to-number.a.json
@@ -0,0 +1,7 @@
+[
+ "to-number",
+ [
+ "get",
+ "x"
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/to-number.b.json b/test/fixtures/expression_equality/to-number.b.json
new file mode 100644
index 0000000000..b38dc5a455
--- /dev/null
+++ b/test/fixtures/expression_equality/to-number.b.json
@@ -0,0 +1,7 @@
+[
+ "to-number",
+ [
+ "get",
+ "x_other"
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/to-string.a.json b/test/fixtures/expression_equality/to-string.a.json
new file mode 100644
index 0000000000..66f9a9caa1
--- /dev/null
+++ b/test/fixtures/expression_equality/to-string.a.json
@@ -0,0 +1,7 @@
+[
+ "to-string",
+ [
+ "get",
+ "x"
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/to-string.b.json b/test/fixtures/expression_equality/to-string.b.json
new file mode 100644
index 0000000000..977a9d7769
--- /dev/null
+++ b/test/fixtures/expression_equality/to-string.b.json
@@ -0,0 +1,7 @@
+[
+ "to-string",
+ [
+ "get",
+ "x_other"
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/typeof.a.json b/test/fixtures/expression_equality/typeof.a.json
new file mode 100644
index 0000000000..7843ff8c7f
--- /dev/null
+++ b/test/fixtures/expression_equality/typeof.a.json
@@ -0,0 +1,7 @@
+[
+ "typeof",
+ [
+ "get",
+ "x"
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/typeof.b.json b/test/fixtures/expression_equality/typeof.b.json
new file mode 100644
index 0000000000..412482347a
--- /dev/null
+++ b/test/fixtures/expression_equality/typeof.b.json
@@ -0,0 +1,7 @@
+[
+ "typeof",
+ [
+ "get",
+ "x_other"
+ ]
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/upcase.a.json b/test/fixtures/expression_equality/upcase.a.json
new file mode 100644
index 0000000000..d12ca7b08d
--- /dev/null
+++ b/test/fixtures/expression_equality/upcase.a.json
@@ -0,0 +1,4 @@
+[
+ "upcase",
+ "string"
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/upcase.b.json b/test/fixtures/expression_equality/upcase.b.json
new file mode 100644
index 0000000000..ddeeb0300c
--- /dev/null
+++ b/test/fixtures/expression_equality/upcase.b.json
@@ -0,0 +1,4 @@
+[
+ "upcase",
+ "string_other"
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/zoom.a.json b/test/fixtures/expression_equality/zoom.a.json
new file mode 100644
index 0000000000..fc675721ab
--- /dev/null
+++ b/test/fixtures/expression_equality/zoom.a.json
@@ -0,0 +1,13 @@
+[
+ "interpolate",
+ [
+ "linear"
+ ],
+ [
+ "zoom"
+ ],
+ 0,
+ 0,
+ 30,
+ 30
+] \ No newline at end of file
diff --git a/test/fixtures/expression_equality/zoom.b.json b/test/fixtures/expression_equality/zoom.b.json
new file mode 100644
index 0000000000..6314858a5e
--- /dev/null
+++ b/test/fixtures/expression_equality/zoom.b.json
@@ -0,0 +1,13 @@
+[
+ "interpolate",
+ [
+ "linear"
+ ],
+ [
+ "zoom"
+ ],
+ 0,
+ 0,
+ 30,
+ 31
+] \ No newline at end of file
diff --git a/test/fixtures/local_glyphs/droid/expected.png b/test/fixtures/local_glyphs/droid/expected.png
new file mode 100644
index 0000000000..c0ba43bf11
--- /dev/null
+++ b/test/fixtures/local_glyphs/droid/expected.png
Binary files differ
diff --git a/test/fixtures/local_glyphs/mixed.json b/test/fixtures/local_glyphs/mixed.json
new file mode 100644
index 0000000000..e07d429753
--- /dev/null
+++ b/test/fixtures/local_glyphs/mixed.json
@@ -0,0 +1,196 @@
+{
+ "version": 8,
+ "zoom": 0,
+ "center": [-14.41400, 39.09187],
+ "sources": {
+ "mapbox": {
+ "type": "geojson",
+ "data": {
+ "type": "FeatureCollection",
+ "features": [
+ {
+ "type": "Feature",
+ "properties": {
+ "name": "身什戰 1"
+ },
+ "geometry": {
+ "type": "LineString",
+ "coordinates": [
+ [
+ -14.4195556640625,
+ 39.091699613104595
+ ],
+ [
+ 102.3046875,
+ 39.36827914916014
+ ]
+ ]
+ }
+ },
+ {
+ "type": "Feature",
+ "properties": {
+ "name": "two 身什戰"
+ },
+ "geometry": {
+ "type": "LineString",
+ "coordinates": [
+ [
+ -14.403076171875,
+ 39.10022600175347
+ ],
+ [
+ 103.35937499999999,
+ 65.80277639340238
+ ]
+ ]
+ }
+ },
+ {
+ "type": "Feature",
+ "properties": {
+ "name": "身什戰33"
+ },
+ "geometry": {
+ "type": "LineString",
+ "coordinates": [
+ [
+ -14.414062499999998,
+ 39.091699613104595
+ ],
+ [
+ -14.765625,
+ 82.21421714106776
+ ]
+ ]
+ }
+ },
+ {
+ "type": "Feature",
+ "properties": {
+ "name": "身什戰"
+ },
+ "geometry": {
+ "type": "LineString",
+ "coordinates": [
+ [
+ -14.408569335937498,
+ 39.091699613104595
+ ],
+ [
+ -130.78125,
+ 39.095962936305476
+ ]
+ ]
+ }
+ },
+ {
+ "type": "Feature",
+ "properties": {
+ "name": "身什戰 five"
+ },
+ "geometry": {
+ "type": "LineString",
+ "coordinates": [
+ [
+ -14.414062499999998,
+ 39.095962936305476
+ ],
+ [
+ -16.5234375,
+ -58.81374171570779
+ ]
+ ]
+ }
+ },
+ {
+ "type": "Feature",
+ "properties": {
+ "name": "six 身什戰"
+ },
+ "geometry": {
+ "type": "LineString",
+ "coordinates": [
+ [
+ -14.4195556640625,
+ 39.10022600175347
+ ],
+ [
+ -130.4296875,
+ 64.47279382008166
+ ]
+ ]
+ }
+ },
+ {
+ "type": "Feature",
+ "properties": {
+ "name": "身什戰 seven"
+ },
+ "geometry": {
+ "type": "LineString",
+ "coordinates": [
+ [
+ -14.4195556640625,
+ 39.0831721934762
+ ],
+ [
+ 33.75,
+ 81.87364125482827
+ ]
+ ]
+ }
+ },
+ {
+ "type": "Feature",
+ "properties": {
+ "name": "eight 身什戰"
+ },
+ "geometry": {
+ "type": "LineString",
+ "coordinates": [
+ [
+ -14.447021484374998,
+ 39.104488809440475
+ ],
+ [
+ -66.4453125,
+ 82.26169873683153
+ ]
+ ]
+ }
+ }
+ ]
+ }
+ }
+ },
+ "glyphs": "local://glyphs/{fontstack}/{range}.pbf",
+ "layers": [
+ {
+ "id": "background",
+ "type": "background",
+ "paint": {
+ "background-color": "white"
+ }
+ },
+ {
+ "id": "lines-symbol",
+ "type": "symbol",
+ "source": "mapbox",
+ "layout": {
+ "text-field": "{name}",
+ "symbol-placement": "line",
+ "symbol-spacing": 150,
+ "text-allow-overlap": true,
+ "text-font": [ "NotoCJK" ]
+ }
+ }, {
+ "id": "lines",
+ "type": "line",
+ "source": "mapbox",
+ "paint": {
+ "line-opacity": 0.25
+ }
+ }
+ ]
+}
diff --git a/test/fixtures/local_glyphs/no_local/expected.png b/test/fixtures/local_glyphs/no_local/expected.png
new file mode 100644
index 0000000000..c7b1b828ee
--- /dev/null
+++ b/test/fixtures/local_glyphs/no_local/expected.png
Binary files differ
diff --git a/test/fixtures/local_glyphs/ping_fang/expected.png b/test/fixtures/local_glyphs/ping_fang/expected.png
new file mode 100644
index 0000000000..c0ba43bf11
--- /dev/null
+++ b/test/fixtures/local_glyphs/ping_fang/expected.png
Binary files differ
diff --git a/test/fixtures/map/offline/expected.png b/test/fixtures/map/offline/expected.png
index 973c4102da..0005137ae3 100644
--- a/test/fixtures/map/offline/expected.png
+++ b/test/fixtures/map/offline/expected.png
Binary files differ
diff --git a/test/fixtures/shared_context/expected.png b/test/fixtures/shared_context/expected.png
new file mode 100644
index 0000000000..3b3fd0e315
--- /dev/null
+++ b/test/fixtures/shared_context/expected.png
Binary files differ
diff --git a/test/fixtures/style_parser/expressions.info.json b/test/fixtures/style_parser/expressions.info.json
new file mode 100644
index 0000000000..9e1765ecd0
--- /dev/null
+++ b/test/fixtures/style_parser/expressions.info.json
@@ -0,0 +1,12 @@
+{
+ "default": {
+ "log": [
+ [1, "WARNING", "ParseStyle", "Expected color but found number instead."],
+ [1, "WARNING", "ParseStyle", "[2]: Expected number but found string instead."],
+ [1, "WARNING", "ParseStyle", "\"zoom\" expression may only be used as input to a top-level \"step\" or \"interpolate\" expression."],
+ [1, "WARNING", "ParseStyle", "value must be a string"],
+ [1, "WARNING", "ParseStyle", "property expressions not supported"],
+ [1, "WARNING", "ParseStyle", "Type array<number> is not interpolatable."]
+ ]
+ }
+}
diff --git a/test/fixtures/style_parser/expressions.style.json b/test/fixtures/style_parser/expressions.style.json
new file mode 100644
index 0000000000..b9b4aeac7f
--- /dev/null
+++ b/test/fixtures/style_parser/expressions.style.json
@@ -0,0 +1,74 @@
+{
+ "version": 8,
+ "sources": {
+ "source": {
+ "type": "vector",
+ "url": "mapbox://mapbox.mapbox-streets-v5"
+ }
+ },
+ "layers": [
+ {
+ "id": "valid expression",
+ "type": "fill",
+ "source": "source",
+ "source-layer": "layer",
+ "paint": {
+ "fill-color": ["rgba", 10, ["number", ["get", "x"]], 30, 1]
+ }
+ },
+ {
+ "id": "invalid expression type - color",
+ "type": "fill",
+ "source": "source",
+ "source-layer": "layer",
+ "paint": {
+ "fill-color": ["pi"]
+ }
+ },
+ {
+ "id": "invalid expression - fails type checking",
+ "type": "fill",
+ "source": "source",
+ "source-layer": "layer",
+ "paint": {
+ "fill-color": ["rgba", 1, "should be a number", 0, 1]
+ }
+ },
+ {
+ "id": "invalid expression - nested zoom expression",
+ "type": "fill",
+ "source": "source",
+ "source-layer": "layer",
+ "paint": {
+ "fill-opacity": ["+", 0.5, ["interpolate", ["linear"], ["zoom"], 0, 0, 1, 1]]
+ }
+ },
+ {
+ "id": "invalid expression - not allowed in visibility",
+ "type": "fill",
+ "source": "source",
+ "source-layer": "layer",
+ "layout": {
+ "visibility": ["literal", true]
+ }
+ },
+ {
+ "id": "invalid expression - not a DDS property",
+ "type": "fill-extrusion",
+ "source": "source",
+ "source-layer": "layer",
+ "paint": {
+ "fill-extrusion-opacity": ["get", "opacity"]
+ }
+ },
+ {
+ "id": "invalid expression - line-dasharray must use step interpolation",
+ "type": "line",
+ "source": "source",
+ "source-layer": "layer",
+ "paint": {
+ "line-dasharray": ["interpolate", ["linear"], ["zoom"], 0, ["literal", [1, 2]], 1, ["literal", [3, 4]]]
+ }
+ }
+ ]
+}
diff --git a/test/gl/bucket.test.cpp b/test/gl/bucket.test.cpp
index 5f9626bc99..8393fd130d 100644
--- a/test/gl/bucket.test.cpp
+++ b/test/gl/bucket.test.cpp
@@ -1,6 +1,7 @@
#include <mbgl/test/util.hpp>
#include <mbgl/test/stub_geometry_tile_feature.hpp>
+#include <mbgl/renderer/backend_scope.hpp>
#include <mbgl/renderer/buckets/circle_bucket.hpp>
#include <mbgl/renderer/buckets/fill_bucket.hpp>
#include <mbgl/renderer/buckets/line_bucket.hpp>
@@ -9,6 +10,7 @@
#include <mbgl/renderer/bucket_parameters.hpp>
#include <mbgl/style/layers/symbol_layer_properties.hpp>
#include <mbgl/gl/context.hpp>
+#include <mbgl/gl/headless_backend.hpp>
#include <mbgl/map/mode.hpp>
@@ -41,8 +43,11 @@ PropertyMap properties;
} // namespace
TEST(Buckets, CircleBucket) {
+ HeadlessBackend backend({ 512, 256 });
+ BackendScope scope { backend };
+
gl::Context context;
- CircleBucket bucket { { {0, 0, 0}, MapMode::Still, 1.0 }, {} };
+ CircleBucket bucket { { {0, 0, 0}, MapMode::Static, 1.0 }, {} };
ASSERT_FALSE(bucket.hasData());
ASSERT_FALSE(bucket.needsUpload());
@@ -57,8 +62,11 @@ TEST(Buckets, CircleBucket) {
}
TEST(Buckets, FillBucket) {
+ HeadlessBackend backend({ 512, 256 });
+ BackendScope scope { backend };
+
gl::Context context;
- FillBucket bucket { { {0, 0, 0}, MapMode::Still, 1.0 }, {} };
+ FillBucket bucket { { {0, 0, 0}, MapMode::Static, 1.0 }, {} };
ASSERT_FALSE(bucket.hasData());
ASSERT_FALSE(bucket.needsUpload());
@@ -72,8 +80,11 @@ TEST(Buckets, FillBucket) {
}
TEST(Buckets, LineBucket) {
+ HeadlessBackend backend({ 512, 256 });
+ BackendScope scope { backend };
+
gl::Context context;
- LineBucket bucket { { {0, 0, 0}, MapMode::Still, 1.0 }, {}, {} };
+ LineBucket bucket { { {0, 0, 0}, MapMode::Static, 1.0 }, {}, {} };
ASSERT_FALSE(bucket.hasData());
ASSERT_FALSE(bucket.needsUpload());
@@ -92,12 +103,17 @@ TEST(Buckets, LineBucket) {
}
TEST(Buckets, SymbolBucket) {
+ HeadlessBackend backend({ 512, 256 });
+ BackendScope scope { backend };
+
style::SymbolLayoutProperties::PossiblyEvaluated layout;
bool sdfIcons = false;
bool iconsNeedLinear = false;
+ bool sortFeaturesByY = false;
+ std::vector<SymbolInstance> symbolInstances;
gl::Context context;
- SymbolBucket bucket { layout, {}, 16.0f, 1.0f, 0, sdfIcons, iconsNeedLinear };
+ SymbolBucket bucket { layout, {}, 16.0f, 1.0f, 0, sdfIcons, iconsNeedLinear, sortFeaturesByY, std::move(symbolInstances) };
ASSERT_FALSE(bucket.hasIconData());
ASSERT_FALSE(bucket.hasTextData());
ASSERT_FALSE(bucket.hasCollisionBoxData());
@@ -120,6 +136,9 @@ TEST(Buckets, SymbolBucket) {
}
TEST(Buckets, RasterBucket) {
+ HeadlessBackend backend({ 512, 256 });
+ BackendScope scope { backend };
+
gl::Context context;
PremultipliedImage rgba({ 1, 1 });
diff --git a/test/gl/context.test.cpp b/test/gl/context.test.cpp
new file mode 100644
index 0000000000..179ce5de53
--- /dev/null
+++ b/test/gl/context.test.cpp
@@ -0,0 +1,114 @@
+#include <mbgl/test/util.hpp>
+
+#include <mbgl/gl/gl.hpp>
+#include <mbgl/gl/context.hpp>
+#include <mbgl/map/map.hpp>
+#include <mbgl/util/default_thread_pool.hpp>
+#include <mbgl/storage/default_file_source.hpp>
+#include <mbgl/gl/headless_frontend.hpp>
+#include <mbgl/style/style.hpp>
+#include <mbgl/style/layers/custom_layer.hpp>
+#include <mbgl/style/layers/fill_layer.hpp>
+#include <mbgl/style/layers/background_layer.hpp>
+#include <mbgl/util/io.hpp>
+#include <mbgl/util/mat4.hpp>
+#include <mbgl/util/run_loop.hpp>
+
+using namespace mbgl;
+using namespace mbgl::style;
+
+static const GLchar* vertexShaderSource = R"MBGL_SHADER(
+#ifdef GL_ES
+precision mediump float;
+#endif
+attribute vec2 a_pos;
+void main() {
+ gl_Position = vec4(a_pos, 0, 1);
+}
+)MBGL_SHADER";
+
+static const GLchar* fragmentShaderSource = R"MBGL_SHADER(
+#ifdef GL_ES
+precision mediump float;
+#endif
+void main() {
+ gl_FragColor = vec4(0, 1, 0, 1);
+}
+)MBGL_SHADER";
+
+struct Shader {
+ Shader(const GLchar* vertex, const GLchar* fragment) {
+ program = MBGL_CHECK_ERROR(glCreateProgram());
+ vertexShader = MBGL_CHECK_ERROR(glCreateShader(GL_VERTEX_SHADER));
+ fragmentShader = MBGL_CHECK_ERROR(glCreateShader(GL_FRAGMENT_SHADER));
+ MBGL_CHECK_ERROR(glShaderSource(vertexShader, 1, &vertex, nullptr));
+ MBGL_CHECK_ERROR(glCompileShader(vertexShader));
+ MBGL_CHECK_ERROR(glAttachShader(program, vertexShader));
+ MBGL_CHECK_ERROR(glShaderSource(fragmentShader, 1, &fragment, nullptr));
+ MBGL_CHECK_ERROR(glCompileShader(fragmentShader));
+ MBGL_CHECK_ERROR(glAttachShader(program, fragmentShader));
+ MBGL_CHECK_ERROR(glLinkProgram(program));
+ a_pos = MBGL_CHECK_ERROR(glGetAttribLocation(program, "a_pos"));
+ }
+
+ ~Shader() {
+ MBGL_CHECK_ERROR(glDetachShader(program, vertexShader));
+ MBGL_CHECK_ERROR(glDetachShader(program, fragmentShader));
+ MBGL_CHECK_ERROR(glDeleteShader(vertexShader));
+ MBGL_CHECK_ERROR(glDeleteShader(fragmentShader));
+ MBGL_CHECK_ERROR(glDeleteProgram(program));
+ }
+
+ GLuint program = 0;
+ GLuint vertexShader = 0;
+ GLuint fragmentShader = 0;
+ GLuint a_pos = 0;
+};
+
+struct Buffer {
+ Buffer(std::vector<GLfloat> data) {
+ MBGL_CHECK_ERROR(glGenBuffers(1, &buffer));
+ MBGL_CHECK_ERROR(glBindBuffer(GL_ARRAY_BUFFER, buffer));
+ MBGL_CHECK_ERROR(glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(GLfloat), data.data(),
+ GL_STATIC_DRAW));
+ }
+
+ ~Buffer() {
+ MBGL_CHECK_ERROR(glDeleteBuffers(1, &buffer));
+ }
+
+ GLuint buffer = 0;
+};
+
+TEST(GLContextMode, Shared) {
+ util::RunLoop loop;
+
+ DefaultFileSource fileSource(":memory:", "test/fixtures/api/assets");
+ ThreadPool threadPool(4);
+ float pixelRatio { 1 };
+
+ HeadlessFrontend frontend { pixelRatio, fileSource, threadPool, {}, GLContextMode::Shared };
+
+ Map map(frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, fileSource, threadPool, MapMode::Static);
+ map.getStyle().loadJSON(util::read_file("test/fixtures/api/water.json"));
+ map.setLatLngZoom({ 37.8, -122.5 }, 10);
+
+ // Set transparent background layer.
+ map.getStyle().getLayer("background")->as<BackgroundLayer>()->setBackgroundColor( { { 1.0f, 0.0f, 0.0f, 0.5f } } );
+
+ {
+ // Custom rendering outside of GL Native render loop.
+ BackendScope scope { *frontend.getBackend() };
+ frontend.getBackend()->bind();
+
+ Shader paintShader(vertexShaderSource, fragmentShaderSource);
+ Buffer triangleBuffer({ 0, 0.5, 0.5, -0.5, -0.5, -0.5 });
+ MBGL_CHECK_ERROR(glUseProgram(paintShader.program));
+ MBGL_CHECK_ERROR(glBindBuffer(GL_ARRAY_BUFFER, triangleBuffer.buffer));
+ MBGL_CHECK_ERROR(glEnableVertexAttribArray(paintShader.a_pos));
+ MBGL_CHECK_ERROR(glVertexAttribPointer(paintShader.a_pos, 2, GL_FLOAT, GL_FALSE, 0, nullptr));
+ MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, 3));
+ }
+
+ test::checkImage("test/fixtures/shared_context", frontend.render(map), 0.5, 0.1);
+}
diff --git a/test/map/map.test.cpp b/test/map/map.test.cpp
index 9358175297..9b34ea89b0 100644
--- a/test/map/map.test.cpp
+++ b/test/map/map.test.cpp
@@ -72,14 +72,14 @@ public:
HeadlessFrontend frontend;
Map map;
- MapTest(float pixelRatio = 1, MapMode mode = MapMode::Still)
+ MapTest(float pixelRatio = 1, MapMode mode = MapMode::Static)
: frontend(pixelRatio, fileSource, threadPool)
, map(frontend, observer, frontend.getSize(), pixelRatio, fileSource, threadPool, mode) {
}
template <typename T = FileSource>
MapTest(const std::string& cachePath, const std::string& assetRoot,
- float pixelRatio = 1, MapMode mode = MapMode::Still,
+ float pixelRatio = 1, MapMode mode = MapMode::Static,
typename std::enable_if<std::is_same<T, DefaultFileSource>::value>::type* = 0)
: fileSource { cachePath, assetRoot }
, frontend(pixelRatio, fileSource, threadPool)
diff --git a/test/map/prefetch.test.cpp b/test/map/prefetch.test.cpp
index 5c9a22d1bf..4c82b2c965 100644
--- a/test/map/prefetch.test.cpp
+++ b/test/map/prefetch.test.cpp
@@ -23,7 +23,7 @@ TEST(Map, PrefetchTiles) {
ThreadPool threadPool(4);
StubFileSource fileSource;
HeadlessFrontend frontend { { 512, 512 }, 1, fileSource, threadPool };
- Map map(frontend, MapObserver::nullObserver(), frontend.getSize(), 1, fileSource, threadPool, MapMode::Still);
+ Map map(frontend, MapObserver::nullObserver(), frontend.getSize(), 1, fileSource, threadPool, MapMode::Static);
std::vector<int> tiles;
diff --git a/test/renderer/backend_scope.test.cpp b/test/renderer/backend_scope.test.cpp
index 66cf88a9c6..05b82695b2 100644
--- a/test/renderer/backend_scope.test.cpp
+++ b/test/renderer/backend_scope.test.cpp
@@ -28,18 +28,13 @@ public:
if (updateAssumedStateFunction) updateAssumedStateFunction();
}
- gl::ProcAddress initializeExtension(const char* ext) override {
- if (initializeExtensionFunction) {
- return initializeExtensionFunction(ext);
- } else {
- return {};
- }
+ gl::ProcAddress getExtensionFunctionPointer(const char*) override {
+ return {};
}
std::function<void ()> activateFunction;
std::function<void ()> deactivateFunction;
std::function<void ()> updateAssumedStateFunction;
- std::function<gl::ProcAddress (const char*)> initializeExtensionFunction;
};
// A scope should activate on construction
diff --git a/test/src/app-info.plist b/test/src/app-info.plist
index 107e4058f9..6ee059b3b4 100644
--- a/test/src/app-info.plist
+++ b/test/src/app-info.plist
@@ -25,7 +25,7 @@
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSHumanReadableCopyright</key>
- <string>© 2014–2017 Mapbox</string>
+ <string>© 2014–2018 Mapbox</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>The map will ALWAYS display the user's location.</string>
<key>NSLocationWhenInUseUsageDescription</key>
diff --git a/test/src/mbgl/test/conversion_stubs.hpp b/test/src/mbgl/test/conversion_stubs.hpp
deleted file mode 100644
index 30395ddb97..0000000000
--- a/test/src/mbgl/test/conversion_stubs.hpp
+++ /dev/null
@@ -1,124 +0,0 @@
-#pragma once
-
-#include <mbgl/style/conversion.hpp>
-#include <mbgl/util/feature.hpp>
-#include <mbgl/util/optional.hpp>
-#include <mbgl/util/variant.hpp>
-
-#include <string>
-#include <unordered_map>
-
-namespace mbgl {
-namespace style {
-namespace conversion {
-
-class Value;
-using ValueMap = std::unordered_map<std::string, Value>;
-using ValueVector = std::vector<Value>;
-class Value : public mbgl::variant<std::string,
- float,
- double,
- bool,
- mapbox::util::recursive_wrapper<ValueMap>,
- mapbox::util::recursive_wrapper<ValueVector>> {
- using variant::variant;
-};
-
-inline bool isUndefined(const Value&) {
- // Variant is always intialized
- return false;
-}
-
-inline bool isArray(const Value& value) {
- return value.is<mapbox::util::recursive_wrapper<ValueVector>>();
-}
-
-inline std::size_t arrayLength(const Value& value) {
- return value.get<mapbox::util::recursive_wrapper<ValueVector>>().get().size();
-}
-
-inline Value arrayMember(const Value& value, std::size_t i) {
- return value.get<mapbox::util::recursive_wrapper<ValueVector>>().get()[i];
-}
-
-inline bool isObject(const Value& value) {
- return value.is<mapbox::util::recursive_wrapper<ValueMap>>();
-}
-
-inline optional<Value> objectMember(const Value& value, const char* key) {
- auto map = value.get<ValueMap>();
- auto iter = map.find(key);
-
- if (iter != map.end()) {
- return iter->second;
- } else {
- return {};
- }
-}
-
-using EachMemberFn = std::function<optional<Error>(const std::string&, const Value&)>;
-
-optional<Error> eachMember(const Value& value, EachMemberFn&& fn) {
- auto map = value.get<ValueMap>();
- auto iter = map.begin();
-
- while (iter != map.end()) {
- optional<Error> result = fn(iter->first, iter->second);
- if (result) {
- return result;
- }
-
- ++iter;
- }
-
- return {};
-}
-
-inline optional<bool> toBool(const Value& value) {
- if (value.is<bool>()) {
- return value.get<bool>();
- } else {
- return {};
- }
-}
-
-inline optional<float> toNumber(const Value& value) {
- if (value.is<float>()) {
- return value.get<float>();
- } else {
- return {};
- }
- return {};
-}
-
-
-inline optional<double> toDouble(const Value& value) {
- if (value.is<double>()) {
- return value.get<double>();
- }
- return {};
-}
-
-inline optional<std::string> toString(const Value& value) {
- if (value.is<std::string>()) {
- return value.get<std::string>();
- } else {
- return {};
- }
-}
-
-inline optional<mbgl::Value> toValue(const Value& value) {
- if (value.is<bool>()) {
- return { value.get<bool>() };
- } else if (value.is<std::string>()) {
- return { value.get<std::string>() };
- } else if (value.is<float>()) {
- return { double(value.get<float>()) };
- } else {
- return {};
- }
-}
-
-} // namespace conversion
-} // namespace style
-} // namespace mbgl
diff --git a/test/src/mbgl/test/stub_file_source.cpp b/test/src/mbgl/test/stub_file_source.cpp
index 7891d5d907..0bbff84ff3 100644
--- a/test/src/mbgl/test/stub_file_source.cpp
+++ b/test/src/mbgl/test/stub_file_source.cpp
@@ -17,7 +17,12 @@ public:
StubFileSource& fileSource;
};
-StubFileSource::StubFileSource() {
+StubFileSource::StubFileSource(ResponseType type_)
+ : type(type_) {
+ if (type == ResponseType::Synchronous) {
+ return;
+ }
+
timer.start(1ms, 1ms, [this] {
// Explicit copy to avoid iterator invalidation if ~StubFileRequest gets called within the loop.
auto pending_ = pending;
@@ -46,7 +51,14 @@ StubFileSource::~StubFileSource() = default;
std::unique_ptr<AsyncRequest> StubFileSource::request(const Resource& resource, Callback callback) {
auto req = std::make_unique<StubFileRequest>(*this);
- pending.emplace(req.get(), std::make_tuple(resource, response, callback));
+ if (type == ResponseType::Synchronous) {
+ optional<Response> res = response(resource);
+ if (res) {
+ callback(*res);
+ }
+ } else {
+ pending.emplace(req.get(), std::make_tuple(resource, response, callback));
+ }
return std::move(req);
}
diff --git a/test/src/mbgl/test/stub_file_source.hpp b/test/src/mbgl/test/stub_file_source.hpp
index 85118e1a77..6cee8377c6 100644
--- a/test/src/mbgl/test/stub_file_source.hpp
+++ b/test/src/mbgl/test/stub_file_source.hpp
@@ -9,7 +9,12 @@ namespace mbgl {
class StubFileSource : public FileSource {
public:
- StubFileSource();
+ enum class ResponseType {
+ Asynchronous = 0,
+ Synchronous
+ };
+
+ StubFileSource(ResponseType = ResponseType::Asynchronous);
~StubFileSource() override;
std::unique_ptr<AsyncRequest> request(const Resource&, Callback) override;
@@ -36,6 +41,7 @@ private:
optional<Response> defaultResponse(const Resource&);
std::unordered_map<AsyncRequest*, std::tuple<Resource, ResponseFunction, Callback>> pending;
+ ResponseType type;
util::Timer timer;
};
diff --git a/test/storage/offline.test.cpp b/test/storage/offline.test.cpp
index e7ebe5199f..59aebebaba 100644
--- a/test/storage/offline.test.cpp
+++ b/test/storage/offline.test.cpp
@@ -4,6 +4,7 @@
#include <gtest/gtest.h>
using namespace mbgl;
+using SourceType = mbgl::style::SourceType;
static const LatLngBounds sanFrancisco =
LatLngBounds::hull({ 37.6609, -122.5744 }, { 37.8271, -122.3204 });
diff --git a/test/style/conversion/function.test.cpp b/test/style/conversion/function.test.cpp
index 1eff94d939..a48be2c075 100644
--- a/test/style/conversion/function.test.cpp
+++ b/test/style/conversion/function.test.cpp
@@ -1,9 +1,9 @@
#include <mbgl/test/util.hpp>
-#include <mbgl/style/conversion.hpp>
-#include <mbgl/style/rapidjson_conversion.hpp>
+#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion/constant.hpp>
#include <mbgl/style/conversion/function.hpp>
+#include <mbgl/style/conversion/data_driven_property_value.hpp>
#include <mbgl/util/rapidjson.hpp>
using namespace mbgl;
@@ -13,10 +13,8 @@ using namespace mbgl::style::conversion;
TEST(StyleConversion, Function) {
Error error;
- auto parseFunction = [&](const std::string& src) {
- JSDocument doc;
- doc.Parse<0>(src);
- return convert<CameraFunction<float>, JSValue>(doc, error);
+ auto parseFunction = [&](const std::string& json) {
+ return convertJSON<CameraFunction<float>>(json, error);
};
auto fn1 = parseFunction(R"({"stops":[]})");
@@ -54,3 +52,29 @@ TEST(StyleConversion, Function) {
ASSERT_FALSE(fn9);
ASSERT_EQ("function base must be a number", error.message);
}
+
+TEST(StyleConversion, CompositeFunctionExpression) {
+ Error error;
+
+ auto parseFunction = [&](const std::string& src) {
+ JSDocument doc;
+ doc.Parse<0>(src);
+ return convert<DataDrivenPropertyValue<float>>(doc, error);
+ };
+
+ auto fn1 = parseFunction(R"(["interpolate", ["linear"], ["zoom"], 0, ["number", ["get", "x"]], 10, 10])");
+ ASSERT_TRUE(fn1);
+
+ auto fn2 = parseFunction(R"(["coalesce", ["interpolate", ["linear"], ["zoom"], 0, ["number", ["get", "x"]], 10, 10], 0])");
+ ASSERT_TRUE(fn2);
+
+ auto fn3 = parseFunction(R"(["let", "a", 0, ["interpolate", ["linear"], ["zoom"], 0, ["number", ["get", "x"]], 10, 10] ])");
+ ASSERT_TRUE(fn3);
+
+ auto fn4 = parseFunction(R"(["coalesce", ["let", "a", 0, ["interpolate", ["linear"], ["zoom"], 0, ["number", ["get", "x"]], 10, 10], 0 ])");
+ ASSERT_TRUE(fn4);
+
+ auto fn5 = parseFunction(R"(["coalesce", ["interpolate", ["linear"], ["number", ["get", "x"]], 0, ["zoom"], 10, 10], 0])");
+ ASSERT_FALSE(fn5);
+ ASSERT_EQ(R"("zoom" expression may only be used as input to a top-level "step" or "interpolate" expression.)", error.message);
+}
diff --git a/test/style/conversion/geojson_options.test.cpp b/test/style/conversion/geojson_options.test.cpp
index a798ad6559..4c5a0c9aa4 100644
--- a/test/style/conversion/geojson_options.test.cpp
+++ b/test/style/conversion/geojson_options.test.cpp
@@ -1,8 +1,7 @@
#include <mbgl/test/util.hpp>
-#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion/geojson_options.hpp>
-#include <mbgl/test/conversion_stubs.hpp>
#include <mbgl/util/logging.hpp>
@@ -10,26 +9,22 @@ using namespace mbgl::style;
using namespace mbgl::style::conversion;
TEST(GeoJSONOptions, Basic) {
- ValueMap map;
- Value raw(map);
Error error;
- mbgl::optional<GeoJSONOptions> converted = convert<GeoJSONOptions>(raw, error);
+ mbgl::optional<GeoJSONOptions> converted = convertJSON<GeoJSONOptions>("{}", error);
ASSERT_TRUE((bool) converted);
}
TEST(GeoJSONOptions, ErrorHandling) {
- ValueMap map {{"maxzoom", std::string{"should not be a string"}}};
- Value raw(map);
Error error;
- mbgl::optional<GeoJSONOptions> converted = convert<GeoJSONOptions>(raw, error);
+ mbgl::optional<GeoJSONOptions> converted = convertJSON<GeoJSONOptions>(R"JSON({
+ "maxzoom": "should not be a string"
+ })JSON", error);
ASSERT_FALSE((bool) converted);
}
TEST(GeoJSONOptions, RetainsDefaults) {
- ValueMap map;
- Value raw(map);
Error error;
- GeoJSONOptions converted = *convert<GeoJSONOptions>(raw, error);
+ GeoJSONOptions converted = *convertJSON<GeoJSONOptions>("{}", error);
GeoJSONOptions defaults;
// GeoJSON-VT
@@ -44,22 +39,16 @@ TEST(GeoJSONOptions, RetainsDefaults) {
ASSERT_EQ(converted.clusterMaxZoom, defaults.clusterMaxZoom);
}
-
TEST(GeoJSONOptions, FullConversion) {
- ValueMap map {
- // GeoJSON-VT
- {"maxzoom", 1.0f},
- {"buffer", 2.0f},
- {"tolerance", 3.0f},
-
- // Supercluster
- {"cluster", true},
- {"clusterRadius", 4.0f},
- {"clusterMaxZoom", 5.0f}
- };
- Value raw(map);
Error error;
- GeoJSONOptions converted = *convert<GeoJSONOptions>(raw, error);
+ GeoJSONOptions converted = *convertJSON<GeoJSONOptions>(R"JSON({
+ "maxzoom": 1,
+ "buffer": 2,
+ "tolerance": 3,
+ "cluster": true,
+ "clusterRadius": 4,
+ "clusterMaxZoom": 5
+ })JSON", error);
// GeoJSON-VT
ASSERT_EQ(converted.minzoom, 0);
diff --git a/test/style/conversion/layer.test.cpp b/test/style/conversion/layer.test.cpp
index d51d7d33e2..33cd329999 100644
--- a/test/style/conversion/layer.test.cpp
+++ b/test/style/conversion/layer.test.cpp
@@ -1,10 +1,8 @@
#include <mbgl/test/util.hpp>
-#include <mbgl/style/conversion.hpp>
-#include <mbgl/style/rapidjson_conversion.hpp>
+#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion/layer.hpp>
#include <mbgl/style/layers/background_layer_impl.hpp>
-#include <mbgl/util/rapidjson.hpp>
using namespace mbgl;
using namespace mbgl::style;
@@ -12,10 +10,8 @@ using namespace mbgl::style::conversion;
using namespace std::literals::chrono_literals;
std::unique_ptr<Layer> parseLayer(const std::string& src) {
- JSDocument doc;
- doc.Parse<0>(src);
Error error;
- return std::move(*convert<std::unique_ptr<Layer>, JSValue>(doc, error));
+ return std::move(*convertJSON<std::unique_ptr<Layer>>(src, error));
}
TEST(StyleConversion, LayerTransition) {
diff --git a/test/style/conversion/light.test.cpp b/test/style/conversion/light.test.cpp
index 28e22b3550..67e48c942e 100644
--- a/test/style/conversion/light.test.cpp
+++ b/test/style/conversion/light.test.cpp
@@ -1,11 +1,10 @@
#include <mbgl/test/util.hpp>
#include <mbgl/style/conversion.hpp>
-#include <mbgl/style/rapidjson_conversion.hpp>
+#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion/constant.hpp>
#include <mbgl/style/conversion/light.hpp>
#include <mbgl/style/position.hpp>
-#include <mbgl/util/rapidjson.hpp>
#include <mbgl/util/color.hpp>
#include <mbgl/util/chrono.hpp>
@@ -19,9 +18,7 @@ TEST(StyleConversion, Light) {
Error error;
auto parseLight = [&](const std::string& src) {
- JSDocument doc;
- doc.Parse<0>(src);
- return convert<Light>(doc, error);
+ return convertJSON<Light>(src, error);
};
{
diff --git a/test/style/expression/expression.test.cpp b/test/style/expression/expression.test.cpp
new file mode 100644
index 0000000000..694569695c
--- /dev/null
+++ b/test/style/expression/expression.test.cpp
@@ -0,0 +1,91 @@
+#include <mbgl/test/util.hpp>
+#include <mbgl/util/io.hpp>
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/util/rapidjson.hpp>
+#include <mbgl/style/rapidjson_conversion.hpp>
+#include <mbgl/style/expression/is_expression.hpp>
+
+#include <rapidjson/document.h>
+
+#include <iostream>
+#include <fstream>
+#include <dirent.h>
+
+
+using namespace mbgl;
+using namespace mbgl::style;
+
+TEST(Expression, IsExpression) {
+ rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> spec;
+ spec.Parse<0>(util::read_file("mapbox-gl-js/src/style-spec/reference/v8.json").c_str());
+ ASSERT_FALSE(spec.HasParseError());
+ ASSERT_TRUE(spec.IsObject() &&
+ spec.HasMember("expression_name") &&
+ spec["expression_name"].IsObject() &&
+ spec["expression_name"].HasMember("values") &&
+ spec["expression_name"]["values"].IsObject());
+
+ const auto& allExpressions = spec["expression_name"]["values"];
+
+ for(auto& entry : allExpressions.GetObject()) {
+ const std::string name { entry.name.GetString(), entry.name.GetStringLength() };
+ JSDocument document;
+ document.Parse<0>(R"([")" + name + R"("])");
+
+ const JSValue* expression = &document;
+ EXPECT_TRUE(expression::isExpression(conversion::Convertible(expression))) << name;
+ }
+}
+
+class ExpressionEqualityTest : public ::testing::TestWithParam<std::string> {};
+
+TEST_P(ExpressionEqualityTest, ExpressionEquality) {
+ const std::string base = std::string("test/fixtures/expression_equality/") + GetParam();
+
+ std::string error;
+ auto parse = [&](std::string filename, std::string& error_) -> std::unique_ptr<expression::Expression> {
+ rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> document;
+ document.Parse<0>(util::read_file(filename).c_str());
+ assert(!document.HasParseError());
+ const JSValue* expression = &document;
+ expression::ParsingContext ctx;
+ expression::ParseResult parsed = ctx.parse(conversion::Convertible(expression));
+ if (!parsed) {
+ error_ = ctx.getErrors().size() > 0 ? ctx.getErrors()[0].message : "failed to parse";
+ };
+ return std::move(*parsed);
+ };
+
+ std::unique_ptr<expression::Expression> expression_a1 = parse(base + ".a.json", error);
+ ASSERT_TRUE(expression_a1) << GetParam() << ": " << error;
+
+ std::unique_ptr<expression::Expression> expression_a2 = parse(base + ".a.json", error);
+ ASSERT_TRUE(expression_a2) << GetParam() << ": " << error;
+
+ std::unique_ptr<expression::Expression> expression_b = parse(base + ".b.json", error);
+ ASSERT_TRUE(expression_b) << GetParam() << ": " << error;
+
+
+ EXPECT_TRUE(*expression_a1 == *expression_a2);
+ EXPECT_TRUE(*expression_a1 != *expression_b);
+}
+
+INSTANTIATE_TEST_CASE_P(Expression, ExpressionEqualityTest, ::testing::ValuesIn([] {
+ std::vector<std::string> names;
+ const std::string ending = ".a.json";
+
+ const std::string style_directory = "test/fixtures/expression_equality";
+ DIR *dir = opendir(style_directory.c_str());
+ if (dir != nullptr) {
+ for (dirent *dp = nullptr; (dp = readdir(dir)) != nullptr;) {
+ const std::string name = dp->d_name;
+ if (name.length() >= ending.length() && name.compare(name.length() - ending.length(), ending.length(), ending) == 0) {
+ names.push_back(name.substr(0, name.length() - ending.length()));
+ }
+ }
+ closedir(dir);
+ }
+
+ EXPECT_GT(names.size(), 0u);
+ return names;
+}()));
diff --git a/test/style/expression/util.test.cpp b/test/style/expression/util.test.cpp
new file mode 100644
index 0000000000..0337cd871f
--- /dev/null
+++ b/test/style/expression/util.test.cpp
@@ -0,0 +1,23 @@
+#include <mbgl/test/util.hpp>
+#include <mbgl/style/expression/util.hpp>
+
+using namespace mbgl;
+using namespace mbgl::style::expression;
+
+TEST(Expression, Util_rgba) {
+ Result<Color> valid = rgba(0, 0, 0, 0);
+ ASSERT_TRUE(valid);
+ ASSERT_EQ(valid->r, 0);
+ ASSERT_EQ(valid->g, 0);
+ ASSERT_EQ(valid->b, 0);
+ ASSERT_EQ(valid->a, 0);
+
+ ASSERT_FALSE(rgba(0, 0, 0, -0.1));
+ ASSERT_FALSE(rgba(0, 0, 0, 1.1));
+ ASSERT_FALSE(rgba(0, 0, -1, 1));
+ ASSERT_FALSE(rgba(0, 0, 256, 1));
+ ASSERT_FALSE(rgba(0, -1, 0, 1));
+ ASSERT_FALSE(rgba(0, 256, 0, 1));
+ ASSERT_FALSE(rgba(-1, 1, 0, 1));
+ ASSERT_FALSE(rgba(-256, 1, 0, 1));
+}
diff --git a/test/style/filter.test.cpp b/test/style/filter.test.cpp
index 96de125945..73f8e7626d 100644
--- a/test/style/filter.test.cpp
+++ b/test/style/filter.test.cpp
@@ -4,20 +4,15 @@
#include <mbgl/style/filter.hpp>
#include <mbgl/style/filter_evaluator.hpp>
-#include <mbgl/style/rapidjson_conversion.hpp>
-#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion/filter.hpp>
-#include <rapidjson/document.h>
-
using namespace mbgl;
using namespace mbgl::style;
Filter parse(const char * expression) {
- rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> doc;
- doc.Parse<0>(expression);
conversion::Error error;
- optional<Filter> filter = conversion::convert<Filter, JSValue>(doc, error);
+ optional<Filter> filter = conversion::convertJSON<Filter>(expression, error);
EXPECT_TRUE(bool(filter));
return *filter;
}
diff --git a/test/style/source.test.cpp b/test/style/source.test.cpp
index 919260ffe9..eb419e8080 100644
--- a/test/style/source.test.cpp
+++ b/test/style/source.test.cpp
@@ -9,6 +9,7 @@
#include <mbgl/style/sources/vector_source.hpp>
#include <mbgl/style/sources/geojson_source.hpp>
#include <mbgl/style/sources/image_source.hpp>
+#include <mbgl/style/sources/custom_geometry_source.hpp>
#include <mbgl/style/layers/raster_layer.cpp>
#include <mbgl/style/layers/line_layer.hpp>
@@ -24,7 +25,7 @@
#include <mbgl/util/image.hpp>
#include <mbgl/util/tileset.hpp>
-#include <mbgl/util/default_thread_pool.hpp>
+#include <mbgl/util/shared_thread_pool.hpp>
#include <mbgl/util/logging.hpp>
#include <mbgl/util/optional.hpp>
#include <mbgl/util/range.hpp>
@@ -38,6 +39,7 @@
#include <cstdint>
using namespace mbgl;
+using SourceType = mbgl::style::SourceType;
class SourceTest {
public:
@@ -547,3 +549,39 @@ TEST(Source, ImageSourceImageUpdate) {
test.run();
}
+
+TEST(Source, CustomGeometrySourceSetTileData) {
+ SourceTest test;
+ std::shared_ptr<ThreadPool> threadPool = sharedThreadPool();
+ CustomGeometrySource source("source", CustomGeometrySource::Options());
+ source.loadDescription(test.fileSource);
+
+ LineLayer layer("id", "source");
+ layer.setSourceLayer("water");
+ std::vector<Immutable<Layer::Impl>> layers {{ layer.baseImpl }};
+
+ test.renderSourceObserver.tileChanged = [&] (RenderSource& source_, const OverscaledTileID&) {
+ EXPECT_EQ("source", source_.baseImpl->id);
+ test.end();
+ };
+
+ test.renderSourceObserver.tileError = [&] (RenderSource&, const OverscaledTileID&, std::exception_ptr) {
+ FAIL() << "Should never be called";
+ };
+
+ auto renderSource = RenderSource::create(source.baseImpl);
+ renderSource->setObserver(&test.renderSourceObserver);
+ renderSource->update(source.baseImpl,
+ layers,
+ true,
+ true,
+ test.tileParameters);
+
+ test.loop.invoke([&] () {
+ // Set Tile Data
+ source.setTileData(CanonicalTileID(0, 0, 0), GeoJSON{ FeatureCollection{} });
+ });
+
+ test.run();
+}
+
diff --git a/test/text/cross_tile_symbol_index.test.cpp b/test/text/cross_tile_symbol_index.test.cpp
new file mode 100644
index 0000000000..b40827d63e
--- /dev/null
+++ b/test/text/cross_tile_symbol_index.test.cpp
@@ -0,0 +1,85 @@
+#include <mbgl/text/cross_tile_symbol_index.hpp>
+#include <mbgl/renderer/buckets/symbol_bucket.hpp>
+#include <mbgl/test/util.hpp>
+
+using namespace mbgl;
+
+SymbolInstance makeSymbolInstance(float x, float y, std::u16string key) {
+ GeometryCoordinates line;
+ GlyphPositionMap gpm;
+ const std::pair<Shaping, Shaping> shaping(Shaping{}, Shaping{});
+ style::SymbolLayoutProperties::Evaluated layout_;
+ IndexedSubfeature subfeature(0, "", "", 0);
+ Anchor anchor(x, y, 0, 0);
+ return {anchor, line, shaping, {}, layout_, 0, 0, 0, 0, style::SymbolPlacementType::Point, {{0, 0}}, 0, 0, {{0, 0}}, gpm, subfeature, 0, key, 0 };
+}
+
+
+TEST(CrossTileSymbolLayerIndex, addBucket) {
+
+ uint32_t maxCrossTileID = 0;
+ CrossTileSymbolLayerIndex index;
+
+ style::SymbolLayoutProperties::PossiblyEvaluated layout;
+ bool sdfIcons = false;
+ bool iconsNeedLinear = false;
+ bool sortFeaturesByY = false;
+
+
+ OverscaledTileID mainID(6, 0, 6, 8, 8);
+ std::vector<SymbolInstance> mainInstances;
+ mainInstances.push_back(makeSymbolInstance(1000, 1000, u"Detroit"));
+ mainInstances.push_back(makeSymbolInstance(2000, 2000, u"Toronto"));
+ SymbolBucket mainBucket { layout, {}, 16.0f, 1.0f, 0, sdfIcons, iconsNeedLinear, sortFeaturesByY, std::move(mainInstances) };
+ index.addBucket(mainID, mainBucket, maxCrossTileID);
+
+ // Assigned new IDs
+ ASSERT_EQ(mainBucket.symbolInstances.at(0).crossTileID, 1u);
+ ASSERT_EQ(mainBucket.symbolInstances.at(1).crossTileID, 2u);
+
+
+ OverscaledTileID childID(7, 0, 7, 16, 16);
+ std::vector<SymbolInstance> childInstances;
+ childInstances.push_back(makeSymbolInstance(2000, 2000, u"Detroit"));
+ childInstances.push_back(makeSymbolInstance(2000, 2000, u"Windsor"));
+ childInstances.push_back(makeSymbolInstance(3000, 3000, u"Toronto"));
+ childInstances.push_back(makeSymbolInstance(4001, 4001, u"Toronto"));
+ SymbolBucket childBucket { layout, {}, 16.0f, 1.0f, 0, sdfIcons, iconsNeedLinear, sortFeaturesByY, std::move(childInstances) };
+ index.addBucket(childID, childBucket, maxCrossTileID);
+
+ // matched parent tile
+ ASSERT_EQ(childBucket.symbolInstances.at(0).crossTileID, 1u);
+ // does not match because of different key
+ ASSERT_EQ(childBucket.symbolInstances.at(1).crossTileID, 3u);
+ // does not match because of different location
+ ASSERT_EQ(childBucket.symbolInstances.at(2).crossTileID, 4u);
+ // matches with a slightly different location
+ ASSERT_EQ(childBucket.symbolInstances.at(3).crossTileID, 2u);
+
+ OverscaledTileID parentID(5, 0, 5, 4, 4);
+ std::vector<SymbolInstance> parentInstances;
+ parentInstances.push_back(makeSymbolInstance(500, 500, u"Detroit"));
+ SymbolBucket parentBucket { layout, {}, 16.0f, 1.0f, 0, sdfIcons, iconsNeedLinear, sortFeaturesByY, std::move(parentInstances) };
+ index.addBucket(parentID, parentBucket, maxCrossTileID);
+
+ // matched child tile
+ ASSERT_EQ(parentBucket.symbolInstances.at(0).crossTileID, 1u);
+
+ std::unordered_set<uint32_t> currentIDs;
+ currentIDs.insert(mainBucket.bucketInstanceId);
+ index.removeStaleBuckets(currentIDs);
+
+ // grandchild
+ OverscaledTileID grandchildID(8, 0, 8, 32, 32);
+ std::vector<SymbolInstance> grandchildInstances;
+ grandchildInstances.push_back(makeSymbolInstance(4000, 4000, u"Detroit"));
+ grandchildInstances.push_back(makeSymbolInstance(4000, 4000, u"Windsor"));
+ SymbolBucket grandchildBucket { layout, {}, 16.0f, 1.0f, 0, sdfIcons, iconsNeedLinear, sortFeaturesByY, std::move(grandchildInstances) };
+ index.addBucket(grandchildID, grandchildBucket, maxCrossTileID);
+
+ // Matches the symbol in `mainBucket`
+ ASSERT_EQ(grandchildBucket.symbolInstances.at(0).crossTileID, 1u);
+ // Does not match the previous value for Windsor because that tile was removed
+ ASSERT_EQ(grandchildBucket.symbolInstances.at(1).crossTileID, 5u);
+
+}
diff --git a/test/text/glyph_loader.test.cpp b/test/text/glyph_loader.test.cpp
deleted file mode 100644
index be197ebb46..0000000000
--- a/test/text/glyph_loader.test.cpp
+++ /dev/null
@@ -1,216 +0,0 @@
-#include <mbgl/test/util.hpp>
-#include <mbgl/test/stub_file_source.hpp>
-
-#include <mbgl/text/glyph_manager.hpp>
-#include <mbgl/util/run_loop.hpp>
-#include <mbgl/util/string.hpp>
-#include <mbgl/util/io.hpp>
-#include <mbgl/util/logging.hpp>
-
-using namespace mbgl;
-
-class StubGlyphManagerObserver : public GlyphManagerObserver {
-public:
- void onGlyphsLoaded(const FontStack& fontStack, const GlyphRange& glyphRange) override {
- if (glyphsLoaded) glyphsLoaded(fontStack, glyphRange);
- }
-
- void onGlyphsError(const FontStack& fontStack, const GlyphRange& glyphRange, std::exception_ptr error) override {
- if (glyphsError) glyphsError(fontStack, glyphRange, error);
- }
-
- std::function<void (const FontStack&, const GlyphRange&)> glyphsLoaded;
- std::function<void (const FontStack&, const GlyphRange&, std::exception_ptr)> glyphsError;
-};
-
-class StubGlyphRequestor : public GlyphRequestor {
-public:
- void onGlyphsAvailable(GlyphMap glyphs) override {
- if (glyphsAvailable) glyphsAvailable(std::move(glyphs));
- }
-
- std::function<void (GlyphMap)> glyphsAvailable;
-};
-
-class GlyphManagerTest {
-public:
- util::RunLoop loop;
- StubFileSource fileSource;
- StubGlyphManagerObserver observer;
- StubGlyphRequestor requestor;
- GlyphManager glyphManager { fileSource };
-
- void run(const std::string& url, GlyphDependencies dependencies) {
- // Squelch logging.
- Log::setObserver(std::make_unique<Log::NullObserver>());
-
- glyphManager.setURL(url);
- glyphManager.setObserver(&observer);
- glyphManager.getGlyphs(requestor, std::move(dependencies));
-
- loop.run();
- }
-
- void end() {
- loop.stop();
- }
-};
-
-TEST(GlyphManager, LoadingSuccess) {
- GlyphManagerTest test;
-
- test.fileSource.glyphsResponse = [&] (const Resource& resource) {
- EXPECT_EQ(Resource::Kind::Glyphs, resource.kind);
- Response response;
- response.data = std::make_shared<std::string>(util::read_file("test/fixtures/resources/glyphs.pbf"));
- return response;
- };
-
- test.observer.glyphsError = [&] (const FontStack&, const GlyphRange&, std::exception_ptr) {
- FAIL();
- test.end();
- };
-
- test.observer.glyphsLoaded = [&] (const FontStack& fontStack, const GlyphRange& range) {
- ASSERT_EQ(fontStack, FontStack {{"Test Stack"}});
- ASSERT_EQ(range, GlyphRange(0, 255));
- };
-
- test.requestor.glyphsAvailable = [&] (GlyphMap glyphs) {
- const auto& testPositions = glyphs.at({{"Test Stack"}});
-
- ASSERT_EQ(testPositions.size(), 3u);
- ASSERT_EQ(testPositions.count(u'a'), 1u);
- ASSERT_EQ(testPositions.count(u'å'), 1u);
- ASSERT_EQ(testPositions.count(u' '), 1u);
- ASSERT_TRUE(bool(testPositions.at(u' ')));
-
- test.end();
- };
-
- test.run(
- "test/fixtures/resources/glyphs.pbf",
- GlyphDependencies {
- {{{"Test Stack"}}, {u'a', u'å', u' '}}
- });
-}
-
-TEST(GlyphManager, LoadingFail) {
- GlyphManagerTest test;
-
- test.fileSource.glyphsResponse = [&] (const Resource&) {
- Response response;
- response.error = std::make_unique<Response::Error>(
- Response::Error::Reason::Other,
- "Failed by the test case");
- return response;
- };
-
- test.observer.glyphsError = [&] (const FontStack& fontStack, const GlyphRange& glyphRange, std::exception_ptr error) {
- EXPECT_EQ(fontStack, FontStack({"Test Stack"}));
- EXPECT_EQ(glyphRange, GlyphRange(0, 255));
-
- EXPECT_TRUE(error != nullptr);
- EXPECT_EQ(util::toString(error), "Failed by the test case");
-
- test.end();
- };
-
- test.requestor.glyphsAvailable = [&] (GlyphMap) {
- FAIL();
- test.end();
- };
-
- test.run(
- "test/fixtures/resources/glyphs.pbf",
- GlyphDependencies {
- {{{"Test Stack"}}, {u'a', u'å'}}
- });
-}
-
-TEST(GlyphManager, LoadingCorrupted) {
- GlyphManagerTest test;
-
- test.fileSource.glyphsResponse = [&] (const Resource&) {
- Response response;
- response.data = std::make_unique<std::string>("CORRUPTED");
- return response;
- };
-
- test.observer.glyphsError = [&] (const FontStack& fontStack, const GlyphRange& glyphRange, std::exception_ptr error) {
- EXPECT_EQ(fontStack, FontStack({"Test Stack"}));
- EXPECT_EQ(glyphRange, GlyphRange(0, 255));
-
- EXPECT_TRUE(error != nullptr);
- EXPECT_EQ(util::toString(error), "unknown pbf field type exception");
-
- test.end();
- };
-
- test.requestor.glyphsAvailable = [&] (GlyphMap) {
- FAIL();
- test.end();
- };
-
- test.run(
- "test/fixtures/resources/glyphs.pbf",
- GlyphDependencies {
- {{{"Test Stack"}}, {u'a', u'å'}}
- });
-}
-
-TEST(GlyphManager, LoadingCancel) {
- GlyphManagerTest test;
-
- test.fileSource.glyphsResponse = [&] (const Resource&) {
- test.end();
- return optional<Response>();
- };
-
- test.observer.glyphsLoaded = [&] (const FontStack&, const GlyphRange&) {
- FAIL() << "Should never be called";
- };
-
- test.run(
- "test/fixtures/resources/glyphs.pbf",
- GlyphDependencies {
- {{{"Test Stack"}}, {u'a', u'å'}}
- });
-}
-
-TEST(GlyphManager, LoadingInvalid) {
- GlyphManagerTest test;
-
- test.fileSource.glyphsResponse = [&] (const Resource& resource) {
- EXPECT_EQ(Resource::Kind::Glyphs, resource.kind);
- Response response;
- response.data = std::make_shared<std::string>(util::read_file("test/fixtures/resources/fake_glyphs-0-255.pbf"));
- return response;
- };
-
- test.observer.glyphsError = [&] (const FontStack&, const GlyphRange&, std::exception_ptr) {
- FAIL();
- test.end();
- };
-
- test.observer.glyphsLoaded = [&] (const FontStack& fontStack, const GlyphRange& range) {
- ASSERT_EQ(fontStack, FontStack {{"Test Stack"}});
- ASSERT_EQ(range, GlyphRange(0, 255));
- };
-
- test.requestor.glyphsAvailable = [&] (GlyphMap glyphs) {
- const auto& testPositions = glyphs.at({{"Test Stack"}});
-
- ASSERT_EQ(testPositions.size(), 2u);
- ASSERT_FALSE(bool(testPositions.at(u'A')));
- ASSERT_TRUE(bool(testPositions.at(u'E')));
-
- test.end();
- };
-
- test.run(
- "test/fixtures/resources/glyphs.pbf",
- GlyphDependencies {
- {{{"Test Stack"}}, {u'A', u'E'}}
- });
-}
diff --git a/test/text/glyph_manager.test.cpp b/test/text/glyph_manager.test.cpp
new file mode 100644
index 0000000000..a96e1b970c
--- /dev/null
+++ b/test/text/glyph_manager.test.cpp
@@ -0,0 +1,341 @@
+#include <mbgl/test/util.hpp>
+#include <mbgl/test/stub_file_source.hpp>
+
+#include <mbgl/text/glyph_manager.hpp>
+#include <mbgl/util/run_loop.hpp>
+#include <mbgl/util/string.hpp>
+#include <mbgl/util/i18n.hpp>
+#include <mbgl/util/io.hpp>
+#include <mbgl/util/logging.hpp>
+
+using namespace mbgl;
+
+// Alpha channel rendering of '中'
+static constexpr const uint8_t stubBitmap[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 95, 82, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 255, 233, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 255, 233, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 255, 227, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 22, 18, 18, 18, 18, 18, 15, 55, 255, 255, 42, 14, 18, 18, 18, 18, 18, 22, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 167, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 178, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 255, 120, 8, 15, 15, 15, 11, 51, 255, 233, 32, 11, 15, 15, 15, 8, 93, 255, 178, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 255, 100, 0, 0, 0, 0, 0, 37, 255, 233, 17, 0, 0, 0, 0, 0, 84, 255, 178, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 255, 107, 0, 0, 0, 0, 0, 37, 255, 233, 17, 0, 0, 0, 0, 0, 84, 255, 178, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 255, 107, 0, 0, 0, 0, 0, 37, 255, 233, 17, 0, 0, 0, 0, 0, 84, 255, 178, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 255, 100, 0, 0, 0, 0, 0, 32, 255, 227, 10, 0, 0, 0, 0, 0, 78, 255, 178, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 255, 170, 101, 101, 101, 101, 101, 129, 255, 255, 133, 100, 101, 101, 101, 96, 191, 255, 178, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 178, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 156, 255, 172, 110, 116, 116, 116, 115, 140, 255, 242, 127, 116, 116, 116, 116, 110, 163, 255, 169, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 255, 108, 0, 0, 0, 0, 0, 32, 255, 227, 10, 0, 0, 0, 0, 0, 89, 255, 194, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 27, 16, 0, 0, 0, 0, 0, 37, 255, 233, 17, 0, 0, 0, 0, 0, 14, 27, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 255, 233, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 255, 233, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 255, 233, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 255, 233, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 255, 233, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 205, 167, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+// SDF transformation of '中'
+static constexpr const uint8_t sdfBitmap[] = {0, 0, 0, 0, 0, 0, 0, 0, 19, 48, 76, 101, 119, 127, 127, 127, 126, 118, 100, 75, 48, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 19, 28, 31, 31, 31, 31, 59, 90, 119, 145, 158, 159, 159, 156, 144, 118, 89, 59, 31, 31, 31, 31, 28, 19, 5, 0, 0, 0, 10, 31, 48, 59, 63, 63, 63, 63, 63, 95, 127, 158, 182, 187, 186, 176, 156, 126, 94, 63, 63, 63, 63, 63, 59, 48, 31, 10, 0, 5, 31, 55, 75, 89, 94, 95, 95, 95, 95, 95, 127, 158, 181, 223, 204, 177, 157, 126, 95, 95, 95, 95, 95, 95, 89, 75, 55, 31, 10, 19, 48, 75, 100, 118, 126, 126, 126, 126, 126, 126, 127, 157, 180, 223, 204, 177, 157, 126, 126, 126, 126, 126, 126, 126, 119, 100, 75, 55, 31, 28, 59, 89, 118, 144, 156, 157, 157, 157, 157, 157, 157, 157, 180, 223, 204, 177, 156, 157, 157, 157, 157, 157, 157, 156, 144, 119, 100, 75, 48, 31, 63, 94, 126, 156, 176, 178, 178, 178, 178, 178, 178, 177, 182, 223, 223, 181, 177, 178, 178, 178, 178, 178, 178, 177, 156, 144, 118, 89, 59, 32, 64, 96, 128, 159, 193, 223, 223, 223, 223, 223, 223, 223, 223, 236, 236, 223, 223, 223, 223, 223, 223, 223, 223, 196, 176, 156, 126, 94, 63, 32, 64, 96, 128, 159, 194, 223, 223, 223, 223, 223, 223, 223, 223, 236, 226, 223, 223, 223, 223, 223, 223, 223, 224, 198, 176, 156, 126, 94, 63, 32, 64, 96, 127, 159, 187, 223, 190, 176, 177, 177, 177, 177, 182, 223, 204, 179, 177, 177, 177, 177, 176, 187, 223, 198, 176, 156, 126, 94, 63, 32, 64, 95, 127, 159, 186, 223, 188, 159, 156, 156, 156, 157, 180, 223, 204, 177, 157, 156, 156, 156, 159, 186, 223, 198, 176, 156, 126, 94, 63, 32, 64, 95, 127, 159, 186, 223, 189, 159, 127, 126, 127, 157, 180, 223, 204, 177, 157, 126, 126, 127, 159, 186, 223, 198, 176, 156, 126, 94, 63, 32, 64, 95, 127, 159, 186, 223, 189, 159, 127, 127, 127, 157, 180, 223, 204, 177, 157, 127, 127, 127, 159, 186, 223, 198, 176, 156, 126, 94, 63, 32, 64, 95, 127, 159, 186, 223, 188, 159, 159, 159, 159, 159, 179, 223, 204, 177, 159, 159, 159, 159, 159, 185, 223, 198, 176, 156, 126, 94, 63, 48, 75, 100, 127, 159, 186, 223, 197, 188, 188, 188, 188, 188, 191, 223, 223, 192, 188, 188, 188, 188, 187, 199, 224, 198, 176, 156, 126, 94, 63, 59, 89, 118, 143, 159, 188, 223, 224, 223, 223, 223, 223, 223, 223, 236, 226, 223, 223, 223, 223, 223, 223, 223, 224, 198, 176, 156, 126, 94, 63, 63, 94, 126, 156, 175, 195, 223, 197, 189, 190, 190, 190, 190, 193, 223, 206, 191, 190, 190, 190, 190, 189, 196, 223, 196, 176, 156, 126, 94, 63, 59, 89, 118, 143, 159, 193, 223, 189, 159, 159, 159, 159, 159, 179, 223, 204, 177, 159, 159, 159, 159, 159, 186, 223, 200, 176, 156, 126, 94, 63, 48, 75, 100, 126, 156, 176, 179, 177, 156, 127, 127, 127, 157, 180, 223, 204, 177, 157, 127, 127, 127, 156, 177, 179, 178, 157, 144, 118, 89, 59, 31, 59, 89, 118, 144, 156, 157, 156, 144, 119, 96, 127, 157, 180, 223, 204, 177, 157, 126, 96, 119, 144, 156, 157, 157, 144, 119, 100, 75, 48, 19, 48, 75, 100, 118, 126, 126, 126, 119, 100, 95, 127, 157, 180, 223, 204, 177, 157, 126, 95, 100, 119, 126, 126, 126, 119, 100, 76, 55, 31, 5, 31, 55, 75, 89, 94, 95, 95, 89, 75, 95, 127, 157, 180, 223, 204, 177, 157, 126, 95, 75, 89, 95, 95, 95, 90, 76, 55, 31, 10, 0, 10, 31, 48, 59, 63, 63, 63, 59, 63, 95, 127, 157, 180, 223, 204, 177, 157, 126, 95, 63, 59, 63, 63, 63, 59, 48, 31, 10, 0, 0, 0, 5, 19, 28, 31, 31, 31, 31, 63, 95, 127, 157, 180, 223, 204, 177, 157, 126, 95, 63, 31, 31, 31, 31, 28, 19, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 64, 95, 127, 159, 184, 201, 196, 176, 156, 126, 94, 63, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 60, 90, 120, 146, 159, 159, 159, 156, 144, 118, 89, 59, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 49, 76, 101, 120, 127, 128, 128, 126, 118, 100, 75, 48, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 32, 56, 76, 90, 95, 96, 96, 94, 89, 75, 55, 31, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 32, 49, 60, 64, 64, 64, 63, 59, 48, 31, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 19, 29, 32, 32, 32, 31, 28, 19, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+static constexpr const size_t stubBitmapLength = 900;
+
+class StubLocalGlyphRasterizer : public LocalGlyphRasterizer {
+public:
+ bool canRasterizeGlyph(const FontStack&, GlyphID glyphID) {
+ return util::i18n::allowsIdeographicBreaking(glyphID);
+ }
+
+ Glyph rasterizeGlyph(const FontStack&, GlyphID glyphID) {
+ Glyph stub;
+ stub.id = glyphID;
+
+ stub.metrics.width = 24;
+ stub.metrics.height = 24;
+ stub.metrics.left = 0;
+ stub.metrics.top = -8;
+ stub.metrics.advance = 24;
+
+ stub.bitmap = AlphaImage(Size(30, 30), stubBitmap, stubBitmapLength);
+
+ return stub;
+ }
+};
+
+class StubGlyphManagerObserver : public GlyphManagerObserver {
+public:
+ void onGlyphsLoaded(const FontStack& fontStack, const GlyphRange& glyphRange) override {
+ if (glyphsLoaded) glyphsLoaded(fontStack, glyphRange);
+ }
+
+ void onGlyphsError(const FontStack& fontStack, const GlyphRange& glyphRange, std::exception_ptr error) override {
+ if (glyphsError) glyphsError(fontStack, glyphRange, error);
+ }
+
+ std::function<void (const FontStack&, const GlyphRange&)> glyphsLoaded;
+ std::function<void (const FontStack&, const GlyphRange&, std::exception_ptr)> glyphsError;
+};
+
+class StubGlyphRequestor : public GlyphRequestor {
+public:
+ void onGlyphsAvailable(GlyphMap glyphs) override {
+ if (glyphsAvailable) glyphsAvailable(std::move(glyphs));
+ }
+
+ std::function<void (GlyphMap)> glyphsAvailable;
+};
+
+class GlyphManagerTest {
+public:
+ util::RunLoop loop;
+ StubFileSource fileSource;
+ StubGlyphManagerObserver observer;
+ StubGlyphRequestor requestor;
+ GlyphManager glyphManager{ fileSource, std::make_unique<StubLocalGlyphRasterizer>() };
+
+ void run(const std::string& url, GlyphDependencies dependencies) {
+ // Squelch logging.
+ Log::setObserver(std::make_unique<Log::NullObserver>());
+
+ glyphManager.setURL(url);
+ glyphManager.setObserver(&observer);
+ glyphManager.getGlyphs(requestor, std::move(dependencies));
+
+ loop.run();
+ }
+
+ void end() {
+ loop.stop();
+ }
+};
+
+TEST(GlyphManager, LoadingSuccess) {
+ GlyphManagerTest test;
+
+ test.fileSource.glyphsResponse = [&] (const Resource& resource) {
+ EXPECT_EQ(Resource::Kind::Glyphs, resource.kind);
+ Response response;
+ response.data = std::make_shared<std::string>(util::read_file("test/fixtures/resources/glyphs.pbf"));
+ return response;
+ };
+
+ test.observer.glyphsError = [&] (const FontStack&, const GlyphRange&, std::exception_ptr) {
+ FAIL();
+ test.end();
+ };
+
+ test.observer.glyphsLoaded = [&] (const FontStack& fontStack, const GlyphRange& range) {
+ ASSERT_EQ(fontStack, FontStack {{"Test Stack"}});
+ ASSERT_EQ(range, GlyphRange(0, 255));
+ };
+
+ test.requestor.glyphsAvailable = [&] (GlyphMap glyphs) {
+ const auto& testPositions = glyphs.at({{"Test Stack"}});
+
+ ASSERT_EQ(testPositions.size(), 3u);
+ ASSERT_EQ(testPositions.count(u'a'), 1u);
+ ASSERT_EQ(testPositions.count(u'å'), 1u);
+ ASSERT_EQ(testPositions.count(u' '), 1u);
+ ASSERT_TRUE(bool(testPositions.at(u' ')));
+
+ test.end();
+ };
+
+ test.run(
+ "test/fixtures/resources/glyphs.pbf",
+ GlyphDependencies {
+ {{{"Test Stack"}}, {u'a', u'å', u' '}}
+ });
+}
+
+TEST(GlyphManager, LoadingFail) {
+ GlyphManagerTest test;
+
+ test.fileSource.glyphsResponse = [&] (const Resource&) {
+ Response response;
+ response.error = std::make_unique<Response::Error>(
+ Response::Error::Reason::Other,
+ "Failed by the test case");
+ return response;
+ };
+
+ test.observer.glyphsError = [&] (const FontStack& fontStack, const GlyphRange& glyphRange, std::exception_ptr error) {
+ EXPECT_EQ(fontStack, FontStack({"Test Stack"}));
+ EXPECT_EQ(glyphRange, GlyphRange(0, 255));
+
+ EXPECT_TRUE(error != nullptr);
+ EXPECT_EQ(util::toString(error), "Failed by the test case");
+
+ test.end();
+ };
+
+ test.requestor.glyphsAvailable = [&] (GlyphMap) {
+ FAIL();
+ test.end();
+ };
+
+ test.run(
+ "test/fixtures/resources/glyphs.pbf",
+ GlyphDependencies {
+ {{{"Test Stack"}}, {u'a', u'å'}}
+ });
+}
+
+TEST(GlyphManager, LoadingCorrupted) {
+ GlyphManagerTest test;
+
+ test.fileSource.glyphsResponse = [&] (const Resource&) {
+ Response response;
+ response.data = std::make_unique<std::string>("CORRUPTED");
+ return response;
+ };
+
+ test.observer.glyphsError = [&] (const FontStack& fontStack, const GlyphRange& glyphRange, std::exception_ptr error) {
+ EXPECT_EQ(fontStack, FontStack({"Test Stack"}));
+ EXPECT_EQ(glyphRange, GlyphRange(0, 255));
+
+ EXPECT_TRUE(error != nullptr);
+ EXPECT_EQ(util::toString(error), "unknown pbf field type exception");
+
+ test.end();
+ };
+
+ test.requestor.glyphsAvailable = [&] (GlyphMap) {
+ FAIL();
+ test.end();
+ };
+
+ test.run(
+ "test/fixtures/resources/glyphs.pbf",
+ GlyphDependencies {
+ {{{"Test Stack"}}, {u'a', u'å'}}
+ });
+}
+
+TEST(GlyphManager, LoadingCancel) {
+ GlyphManagerTest test;
+
+ test.fileSource.glyphsResponse = [&] (const Resource&) {
+ test.end();
+ return optional<Response>();
+ };
+
+ test.observer.glyphsLoaded = [&] (const FontStack&, const GlyphRange&) {
+ FAIL() << "Should never be called";
+ };
+
+ test.run(
+ "test/fixtures/resources/glyphs.pbf",
+ GlyphDependencies {
+ {{{"Test Stack"}}, {u'a', u'å'}}
+ });
+}
+
+TEST(GlyphManager, LoadLocalCJKGlyph) {
+ GlyphManagerTest test;
+ int glyphResponses = 0;
+
+ test.fileSource.glyphsResponse = [&] (const Resource&) {
+ glyphResponses++;
+ return optional<Response>();
+ };
+
+ test.observer.glyphsLoaded = [&] (const FontStack&, const GlyphRange&) {
+ glyphResponses++;
+ };
+
+ test.requestor.glyphsAvailable = [&] (GlyphMap glyphs) {
+ EXPECT_EQ(glyphResponses, 0); // Local generation should prevent requesting any glyphs
+
+ const auto& testPositions = glyphs.at({{"Test Stack"}});
+
+ ASSERT_EQ(testPositions.size(), 1u);
+ ASSERT_EQ(testPositions.count(u'中'), 1u);
+
+ Immutable<Glyph> glyph = *testPositions.at(u'中');
+ EXPECT_EQ(glyph->id, u'中');
+ EXPECT_EQ(glyph->metrics.width, 24ul);
+ EXPECT_EQ(glyph->metrics.height, 24ul);
+ EXPECT_EQ(glyph->metrics.left, 0);
+ EXPECT_EQ(glyph->metrics.top, -8);
+ EXPECT_EQ(glyph->metrics.advance, 24ul);
+ EXPECT_EQ(glyph->bitmap.size, Size(30, 30));
+
+ size_t pixelCount = glyph->bitmap.size.width * glyph->bitmap.size.height;
+ for (size_t i = 0; i < pixelCount; i++) {
+ EXPECT_EQ(glyph->bitmap.data[i], sdfBitmap[i]);
+ }
+
+ test.end();
+ };
+
+ test.run(
+ "test/fixtures/resources/glyphs.pbf",
+ GlyphDependencies {
+ {{{"Test Stack"}}, {u'中'}}
+ });
+}
+
+
+TEST(GlyphManager, LoadingInvalid) {
+ GlyphManagerTest test;
+
+ test.fileSource.glyphsResponse = [&] (const Resource& resource) {
+ EXPECT_EQ(Resource::Kind::Glyphs, resource.kind);
+ Response response;
+ response.data = std::make_shared<std::string>(util::read_file("test/fixtures/resources/fake_glyphs-0-255.pbf"));
+ return response;
+ };
+
+ test.observer.glyphsError = [&] (const FontStack&, const GlyphRange&, std::exception_ptr) {
+ FAIL();
+ test.end();
+ };
+
+ test.observer.glyphsLoaded = [&] (const FontStack& fontStack, const GlyphRange& range) {
+ ASSERT_EQ(fontStack, FontStack {{"Test Stack"}});
+ ASSERT_EQ(range, GlyphRange(0, 255));
+ };
+
+ test.requestor.glyphsAvailable = [&] (GlyphMap glyphs) {
+ const auto& testPositions = glyphs.at({{"Test Stack"}});
+
+ ASSERT_EQ(testPositions.size(), 2u);
+ ASSERT_FALSE(bool(testPositions.at(u'A')));
+ ASSERT_TRUE(bool(testPositions.at(u'E')));
+
+ test.end();
+ };
+
+ test.run(
+ "test/fixtures/resources/glyphs.pbf",
+ GlyphDependencies {
+ {{{"Test Stack"}}, {u'A', u'E'}}
+ });
+}
+
+TEST(GlyphManager, ImmediateFileSource) {
+ class GlyphManagerTestSynchronous {
+ public:
+ util::RunLoop loop;
+ StubFileSource fileSource = { StubFileSource::ResponseType::Synchronous };
+ StubGlyphManagerObserver observer;
+ StubGlyphRequestor requestor;
+ GlyphManager glyphManager { fileSource };
+
+ void run(const std::string& url, GlyphDependencies dependencies) {
+ // Squelch logging.
+ Log::setObserver(std::make_unique<Log::NullObserver>());
+
+ glyphManager.setURL(url);
+ glyphManager.setObserver(&observer);
+ glyphManager.getGlyphs(requestor, std::move(dependencies));
+
+ loop.run();
+ }
+
+ void end() {
+ loop.stop();
+ }
+ };
+
+ GlyphManagerTestSynchronous test;
+
+ test.fileSource.glyphsResponse = [&] (const Resource&) {
+ Response response;
+ response.data = std::make_shared<std::string>(util::read_file("test/fixtures/resources/glyphs.pbf"));
+ return response;
+ };
+
+ test.observer.glyphsError = [&] (const FontStack&, const GlyphRange&, std::exception_ptr) {
+ FAIL();
+ test.end();
+ };
+
+ test.requestor.glyphsAvailable = [&] (GlyphMap) {
+ test.end();
+ };
+
+ test.run(
+ "test/fixtures/resources/glyphs.pbf",
+ GlyphDependencies {
+ {{{"Test Stack"}}, {u'a', u'å', u' '}}
+ });
+}
diff --git a/test/text/local_glyph_rasterizer.test.cpp b/test/text/local_glyph_rasterizer.test.cpp
new file mode 100644
index 0000000000..84c685d66f
--- /dev/null
+++ b/test/text/local_glyph_rasterizer.test.cpp
@@ -0,0 +1,86 @@
+#include <mbgl/test/util.hpp>
+#include <mbgl/test/stub_file_source.hpp>
+#include <mbgl/map/map.hpp>
+#include <mbgl/util/io.hpp>
+#include <mbgl/util/run_loop.hpp>
+#include <mbgl/util/color.hpp>
+#include <mbgl/renderer/renderer.hpp>
+#include <mbgl/gl/headless_frontend.hpp>
+#include <mbgl/util/default_thread_pool.hpp>
+#include <mbgl/style/style.hpp>
+
+/*
+ LoadLocalCJKGlyph in glyph_manager.test.cpp exercises the platform-independent
+ part of LocalGlyphRasterizer. This test actually exercises platform-dependent
+ font loading code for whatever platform it runs on. Different platforms have
+ different default fonts, so adding a new platform requires new "expected"
+ fixtures.
+
+ At the time of writing, we don't run `mbgl-test` on iOS or Android, so the only
+ supported test platform is macOS. Supporting Android would require adding a new
+ test case (probably using the "Droid" font family). iOS should theoretically
+ work -- the "PingFang" font family used below is expected to be available on
+ all iOS devices, and we use a relatively high image diff tolerance (0.05) to
+ account for small changes between the many possible variants of the PingFang
+ family.
+*/
+
+using namespace mbgl;
+
+namespace {
+
+class LocalGlyphRasterizerTest {
+public:
+ LocalGlyphRasterizerTest(const optional<std::string> fontFamily)
+ : frontend(pixelRatio, fileSource, threadPool, optional<std::string>(), GLContextMode::Unique, fontFamily)
+ {
+ }
+
+ util::RunLoop loop;
+ StubFileSource fileSource;
+ ThreadPool threadPool { 4 };
+ float pixelRatio { 1 };
+ HeadlessFrontend frontend;
+ Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, fileSource,
+ threadPool, MapMode::Static};
+
+ void checkRendering(const char * name) {
+ test::checkImage(std::string("test/fixtures/local_glyphs/") + name,
+ frontend.render(map), 0.05, 0.1);
+ }
+};
+
+} // end namespace
+
+#ifdef __APPLE__
+
+TEST(LocalGlyphRasterizer, PingFang) {
+ LocalGlyphRasterizerTest test(std::string("PingFang"));
+
+ test.fileSource.glyphsResponse = [&] (const Resource& resource) {
+ EXPECT_EQ(Resource::Kind::Glyphs, resource.kind);
+ Response response;
+ response.data = std::make_shared<std::string>(util::read_file("test/fixtures/resources/glyphs.pbf"));
+ return response;
+ };
+ test.map.getStyle().loadJSON(util::read_file("test/fixtures/local_glyphs/mixed.json"));
+ test.checkRendering("ping_fang");
+}
+
+#endif
+
+TEST(LocalGlyphRasterizer, NoLocal) {
+ // Expectation: without any local fonts set, and without any CJK glyphs provided,
+ // the output should just contain basic latin characters.
+ LocalGlyphRasterizerTest test({});
+
+ test.fileSource.glyphsResponse = [&] (const Resource& resource) {
+ EXPECT_EQ(Resource::Kind::Glyphs, resource.kind);
+ Response response;
+ response.data = std::make_shared<std::string>(util::read_file("test/fixtures/resources/glyphs.pbf"));
+ return response;
+ };
+ test.map.getStyle().loadJSON(util::read_file("test/fixtures/local_glyphs/mixed.json"));
+ test.checkRendering("no_local");
+}
+
diff --git a/test/tile/annotation_tile.test.cpp b/test/tile/annotation_tile.test.cpp
deleted file mode 100644
index 8f3f903925..0000000000
--- a/test/tile/annotation_tile.test.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-#include <mbgl/test/util.hpp>
-#include <mbgl/test/fake_file_source.hpp>
-
-#include <mbgl/util/default_thread_pool.hpp>
-#include <mbgl/util/run_loop.hpp>
-#include <mbgl/map/transform.hpp>
-#include <mbgl/renderer/tile_parameters.hpp>
-#include <mbgl/renderer/query.hpp>
-#include <mbgl/text/collision_tile.hpp>
-#include <mbgl/geometry/feature_index.hpp>
-#include <mbgl/annotation/annotation_manager.hpp>
-#include <mbgl/annotation/annotation_tile.hpp>
-#include <mbgl/renderer/image_manager.hpp>
-#include <mbgl/text/glyph_manager.hpp>
-#include <mbgl/renderer/backend_scope.hpp>
-#include <mbgl/gl/headless_backend.hpp>
-#include <mbgl/style/style.hpp>
-
-#include <memory>
-
-using namespace mbgl;
-
-class AnnotationTileTest {
-public:
- FakeFileSource fileSource;
- TransformState transformState;
- util::RunLoop loop;
- ThreadPool threadPool { 1 };
- style::Style style { loop, fileSource, 1 };
- AnnotationManager annotationManager { style };
- HeadlessBackend backend;
- BackendScope scope { backend };
- ImageManager imageManager;
- GlyphManager glyphManager { fileSource };
-
- TileParameters tileParameters {
- 1.0,
- MapDebugOptions(),
- transformState,
- threadPool,
- fileSource,
- MapMode::Continuous,
- annotationManager,
- imageManager,
- glyphManager,
- 0
- };
-};
-
-// Don't query stale collision tile
-TEST(AnnotationTile, Issue8289) {
- AnnotationTileTest test;
- AnnotationTile tile(OverscaledTileID(0, 0, 0), test.tileParameters);
-
- auto data = std::make_unique<AnnotationTileData>();
- data->addLayer("test")->addFeature(0, FeatureType::Point, GeometryCollection());
-
- // Simulate layout and placement of a symbol layer.
- tile.onLayout(GeometryTile::LayoutResult {
- std::unordered_map<std::string, std::shared_ptr<Bucket>>(),
- std::make_unique<FeatureIndex>(),
- std::move(data),
- }, 0);
-
- auto collisionTile = std::make_unique<CollisionTile>(PlacementConfig());
-
- IndexedSubfeature subfeature { 0, "", "", 0 };
- CollisionFeature feature(GeometryCoordinates(), Anchor(0, 0, 0, 0), -5, 5, -5, 5, 1, 0, style::SymbolPlacementType::Point, subfeature, CollisionFeature::AlignmentType::Curved);
- collisionTile->insertFeature(feature, 0, true);
- collisionTile->placeFeature(feature, false, false);
-
- tile.onPlacement(GeometryTile::PlacementResult {
- std::unordered_map<std::string, std::shared_ptr<Bucket>>(),
- std::move(collisionTile),
- {},
- {},
- }, 0);
-
- // Simulate a second layout with empty data.
- tile.onLayout(GeometryTile::LayoutResult {
- std::unordered_map<std::string, std::shared_ptr<Bucket>>(),
- std::make_unique<FeatureIndex>(),
- std::make_unique<AnnotationTileData>(),
- }, 0);
-
- std::unordered_map<std::string, std::vector<Feature>> result;
- GeometryCoordinates queryGeometry {{ Point<int16_t>(0, 0) }};
- TransformState transformState;
- RenderedQueryOptions options;
-
- tile.queryRenderedFeatures(result, queryGeometry, transformState, {}, options);
-
- EXPECT_TRUE(result.empty());
-}
-
diff --git a/test/tile/custom_geometry_tile.test.cpp b/test/tile/custom_geometry_tile.test.cpp
new file mode 100644
index 0000000000..21a3dd7953
--- /dev/null
+++ b/test/tile/custom_geometry_tile.test.cpp
@@ -0,0 +1,130 @@
+#include <mbgl/test/util.hpp>
+#include <mbgl/test/fake_file_source.hpp>
+#include <mbgl/test/stub_tile_observer.hpp>
+#include <mbgl/style/sources/custom_geometry_source.hpp>
+#include <mbgl/tile/custom_geometry_tile.hpp>
+#include <mbgl/style/custom_tile_loader.hpp>
+
+#include <mbgl/util/default_thread_pool.hpp>
+#include <mbgl/util/run_loop.hpp>
+#include <mbgl/map/transform.hpp>
+#include <mbgl/renderer/tile_parameters.hpp>
+#include <mbgl/style/style.hpp>
+#include <mbgl/style/layers/circle_layer.hpp>
+#include <mbgl/annotation/annotation_manager.hpp>
+#include <mbgl/renderer/image_manager.hpp>
+#include <mbgl/text/glyph_manager.hpp>
+
+#include <memory>
+
+using namespace mbgl;
+using namespace mbgl::style;
+
+class CustomTileTest {
+public:
+ FakeFileSource fileSource;
+ TransformState transformState;
+ util::RunLoop loop;
+ ThreadPool threadPool { 1 };
+ style::Style style { loop, fileSource, 1 };
+ AnnotationManager annotationManager { style };
+ ImageManager imageManager;
+ GlyphManager glyphManager { fileSource };
+
+ TileParameters tileParameters {
+ 1.0,
+ MapDebugOptions(),
+ transformState,
+ threadPool,
+ fileSource,
+ MapMode::Continuous,
+ annotationManager,
+ imageManager,
+ glyphManager,
+ 0
+ };
+};
+
+TEST(CustomGeometryTile, InvokeFetchTile) {
+ CustomTileTest test;
+
+ CircleLayer layer("circle", "source");
+
+ mapbox::geometry::feature_collection<double> features;
+ features.push_back(mapbox::geometry::feature<double> {
+ mapbox::geometry::point<double>(0, 0)
+ });
+ CustomTileLoader loader([&](const CanonicalTileID& tileId) {
+ EXPECT_EQ(tileId, CanonicalTileID(0,0,0));
+ test.loop.stop();
+ }, [&](const CanonicalTileID&) {
+
+ });
+ auto mb =std::make_shared<Mailbox>(*Scheduler::GetCurrent());
+ ActorRef<CustomTileLoader> loaderActor(loader, mb);
+
+ CustomGeometryTile tile(OverscaledTileID(0, 0, 0), "source", test.tileParameters, CustomGeometrySource::TileOptions(),
+ loaderActor);
+
+ tile.setNecessity(TileNecessity::Required);
+
+ test.loop.run();
+}
+
+TEST(CustomGeometryTile, InvokeCancelTile) {
+ CustomTileTest test;
+
+ CircleLayer layer("circle", "source");
+
+ mapbox::geometry::feature_collection<double> features;
+ features.push_back(mapbox::geometry::feature<double> {
+ mapbox::geometry::point<double>(0, 0)
+ });
+
+ CustomTileLoader loader([&](const CanonicalTileID&) { }, [&](const CanonicalTileID& tileId) {
+ EXPECT_EQ(tileId, CanonicalTileID(0,0,0));
+ test.loop.stop();
+ });
+ auto mb =std::make_shared<Mailbox>(*Scheduler::GetCurrent());
+ ActorRef<CustomTileLoader> loaderActor(loader, mb);
+
+ CustomGeometryTile tile(OverscaledTileID(0, 0, 0), "source", test.tileParameters, CustomGeometrySource::TileOptions(),
+ loaderActor);
+
+ tile.setNecessity(TileNecessity::Required);
+ tile.setNecessity(TileNecessity::Optional);
+ test.loop.run();
+}
+
+TEST(CustomGeometryTile, InvokeTileChanged) {
+ CustomTileTest test;
+
+ CircleLayer layer("circle", "source");
+
+ mapbox::geometry::feature_collection<double> features;
+ features.push_back(mapbox::geometry::feature<double> {
+ mapbox::geometry::point<double>(0, 0)
+ });
+
+ CustomTileLoader loader(nullptr, nullptr);
+ auto mb =std::make_shared<Mailbox>(*Scheduler::GetCurrent());
+ ActorRef<CustomTileLoader> loaderActor(loader, mb);
+
+ CustomGeometryTile tile(OverscaledTileID(0, 0, 0), "source", test.tileParameters, CustomGeometrySource::TileOptions(),
+ loaderActor);
+
+ StubTileObserver observer;
+ observer.tileChanged = [&] (const Tile&) {
+ // Once present, the bucket should never "disappear", which would cause
+ // flickering.
+ ASSERT_NE(nullptr, tile.getBucket(*layer.baseImpl));
+ };
+
+ tile.setLayers({{ layer.baseImpl }});
+ tile.setObserver(&observer);
+ tile.setTileData(features);
+
+ while (!tile.isComplete()) {
+ test.loop.runOnce();
+ }
+}
diff --git a/test/tile/geojson_tile.test.cpp b/test/tile/geojson_tile.test.cpp
index 953c3b8a5f..c05e04bc8d 100644
--- a/test/tile/geojson_tile.test.cpp
+++ b/test/tile/geojson_tile.test.cpp
@@ -66,7 +66,6 @@ TEST(GeoJSONTile, Issue7648) {
tile.setLayers({{ layer.baseImpl }});
tile.setObserver(&observer);
- tile.setPlacementConfig({});
while (!tile.isComplete()) {
test.loop.runOnce();
@@ -93,7 +92,6 @@ TEST(GeoJSONTile, Issue9927) {
GeoJSONTile tile(OverscaledTileID(0, 0, 0), "source", test.tileParameters, features);
tile.setLayers({{ layer.baseImpl }});
- tile.setPlacementConfig({});
while (!tile.isComplete()) {
test.loop.runOnce();
diff --git a/test/tile/vector_tile.test.cpp b/test/tile/vector_tile.test.cpp
index 7e8b659b7a..9d42f7ae74 100644
--- a/test/tile/vector_tile.test.cpp
+++ b/test/tile/vector_tile.test.cpp
@@ -11,7 +11,6 @@
#include <mbgl/renderer/tile_parameters.hpp>
#include <mbgl/renderer/buckets/symbol_bucket.hpp>
#include <mbgl/renderer/query.hpp>
-#include <mbgl/text/collision_tile.hpp>
#include <mbgl/geometry/feature_index.hpp>
#include <mbgl/annotation/annotation_manager.hpp>
#include <mbgl/renderer/image_manager.hpp>
@@ -71,12 +70,13 @@ TEST(VectorTile, Issue7615) {
VectorTile tile(OverscaledTileID(0, 0, 0), "source", test.tileParameters, test.tileset);
style::SymbolLayer symbolLayer("symbol", "source");
+ std::vector<SymbolInstance> symbolInstances;
auto symbolBucket = std::make_shared<SymbolBucket>(
style::SymbolLayoutProperties::PossiblyEvaluated(),
std::map<
std::string,
std::pair<style::IconPaintProperties::PossiblyEvaluated, style::TextPaintProperties::PossiblyEvaluated>>(),
- 16.0f, 1.0f, 0.0f, false, false);
+ 16.0f, 1.0f, 0.0f, false, false, false, std::move(symbolInstances));
// Simulate placement of a symbol layer.
tile.onPlacement(GeometryTile::PlacementResult {
@@ -84,7 +84,6 @@ TEST(VectorTile, Issue7615) {
symbolLayer.getID(),
symbolBucket
}},
- nullptr,
{},
{},
}, 0);
diff --git a/test/util/geo.test.cpp b/test/util/geo.test.cpp
index d0d01b6f88..6832ba3486 100644
--- a/test/util/geo.test.cpp
+++ b/test/util/geo.test.cpp
@@ -220,3 +220,128 @@ TEST(LatLngBounds, FromTileID) {
ASSERT_DOUBLE_EQ(util::LATITUDE_MAX, bounds.north());
}
}
+
+TEST(LatLngBounds, ContainsPoint) {
+ auto bounds = LatLngBounds::hull({50.0, -100.0},{-50.0, 100.0});
+
+ EXPECT_FALSE(bounds.contains(LatLng{0.0, 170.0}));
+ EXPECT_FALSE(bounds.contains(LatLng{0.0, -170.0}));
+ EXPECT_TRUE(bounds.contains(LatLng{0.0, -100.0}));
+ EXPECT_TRUE(bounds.contains(LatLng{-50.0, 100.0}));
+ EXPECT_FALSE(bounds.contains(LatLng{0.0, 365.0}));
+}
+
+TEST(LatLngBounds, ContainsPoint_Wrapped) {
+ auto bounds = LatLngBounds::hull({50.0, -160.0}, {-50.0, 160.0});
+ EXPECT_FALSE(bounds.contains(LatLng{0.0, 170.0}));
+ EXPECT_FALSE(bounds.contains(LatLng{0.0, -170.0}));
+
+ bounds = LatLngBounds::hull({50.0, -200}, {-50.0, -160.0});
+ EXPECT_FALSE(bounds.contains(LatLng{0.0, 170.0}));
+ EXPECT_TRUE(bounds.contains(LatLng{0.0, 170.0}, LatLng::Wrapped));
+ EXPECT_TRUE(bounds.contains(LatLng{0.0, -170.0}));
+ EXPECT_TRUE(bounds.contains(LatLng{0.0, -170.0}, LatLng::Wrapped));
+ EXPECT_FALSE(bounds.contains(LatLng{0.0, 190.0}));
+ EXPECT_TRUE(bounds.contains(LatLng{0.0, 190.0}, LatLng::Wrapped));
+ EXPECT_FALSE(bounds.contains(LatLng{0.0, 541.0}));
+ EXPECT_TRUE(bounds.contains(LatLng{0.0, 541.0}, LatLng::Wrapped));
+}
+
+TEST(LatLngBounds, ContainsBounds) {
+ auto bounds = LatLngBounds::hull({ 50.0, -160.0 }, {-50.0, 160.0});
+ EXPECT_TRUE(bounds.contains(bounds));
+
+ auto innerBounds = LatLngBounds::hull({10.0, -180.0}, {-10.0, -170.0});
+ EXPECT_FALSE(bounds.contains(innerBounds));
+ EXPECT_FALSE(innerBounds.contains(bounds));
+
+ innerBounds = LatLngBounds::hull({10, 120.0}, {-60, 125.0});
+ EXPECT_FALSE(bounds.contains(innerBounds));
+ EXPECT_FALSE(innerBounds.contains(bounds));
+
+ innerBounds = LatLngBounds::hull({10, 120.0}, {-10, 125.0});
+ EXPECT_TRUE(bounds.contains(innerBounds));
+ EXPECT_FALSE(innerBounds.contains(bounds));
+
+}
+
+TEST(LatLngBounds, ContainsBounds_Wrapped) {
+ auto bounds = LatLngBounds::hull({50.0, -200}, {-50.0, -160.0});
+
+ auto inner = LatLngBounds::hull({10.0, -180.0}, {-10.0, -170.0});
+ EXPECT_TRUE(bounds.contains(inner));
+ EXPECT_TRUE(bounds.contains(inner, LatLng::Wrapped));
+
+ inner = LatLngBounds::hull({10.0, 180.0}, {-10.0, 190.0});
+ EXPECT_FALSE(bounds.contains(inner));
+ EXPECT_TRUE(bounds.contains(inner, LatLng::Wrapped));
+
+ inner = LatLngBounds::hull({10.0, 190.0}, {-10.0, 220.0});
+ EXPECT_FALSE(bounds.contains(inner));
+ EXPECT_FALSE(bounds.contains(inner, LatLng::Wrapped));
+
+ auto unwrapped = LatLngBounds::hull({10.0, 170.0}, { -10.0, -175.0});
+ EXPECT_FALSE(bounds.contains(unwrapped));
+ EXPECT_FALSE(bounds.contains(unwrapped, LatLng::Wrapped));
+
+ unwrapped = LatLngBounds::hull({10.0, 0.0} , {-10.0, -10.0});
+ EXPECT_FALSE(bounds.contains(unwrapped));
+ EXPECT_FALSE(bounds.contains(unwrapped, LatLng::Wrapped));
+
+ unwrapped = LatLngBounds::hull({10.0, -165.0}, {-10.0, -180.0});
+ EXPECT_TRUE(bounds.contains(unwrapped));
+ EXPECT_TRUE(bounds.contains(unwrapped, LatLng::Wrapped));
+
+ unwrapped = LatLngBounds::hull({10.0, 180.0}, {-10.0, 160.0});
+ EXPECT_FALSE(bounds.contains(unwrapped));
+ EXPECT_TRUE(bounds.contains(unwrapped, LatLng::Wrapped));
+
+ unwrapped = LatLngBounds::hull({10.0, 540.0}, {-10.0, 560.0});
+ EXPECT_FALSE(bounds.contains(unwrapped));
+ EXPECT_TRUE(bounds.contains(unwrapped, LatLng::Wrapped));
+}
+
+TEST(LatLngBounds, ContainsTileIDs) {
+ LatLngBounds bounds(CanonicalTileID(4,2,6));
+ LatLngBounds innerBounds(CanonicalTileID(9,82,197));
+ EXPECT_TRUE(bounds.contains(innerBounds));
+ EXPECT_FALSE(bounds.contains(LatLngBounds{ CanonicalTileID(3, 1, 0) }));
+}
+
+TEST(LatLngBounds, Intersects) {
+ auto bounds = LatLngBounds::hull({ 50.0, -160.0 }, { -50.0, 160.0 });
+ EXPECT_TRUE(bounds.intersects(bounds));
+
+ auto other = LatLngBounds::hull({50.0, -160.0}, {10, 160.0});
+ EXPECT_TRUE(bounds.intersects(other));
+ EXPECT_TRUE(other.intersects(bounds));
+}
+
+TEST(LatLngBounds, Intersects_Wrapped) {
+ auto bounds = LatLngBounds::hull({50.0, -200.0}, {-50.0, -160.0});
+ EXPECT_TRUE(bounds.intersects(bounds));
+
+ auto other = LatLngBounds::hull({50.0, -150.0}, {10, 160.0});
+ EXPECT_FALSE(bounds.intersects(other));
+ EXPECT_FALSE(other.intersects(bounds));
+ EXPECT_FALSE(bounds.intersects(other, LatLng::Wrapped));
+ EXPECT_FALSE(other.intersects(bounds, LatLng::Wrapped));
+
+ other = LatLngBounds::hull({10.0, -150.0}, {-10.0, -210.0});
+ EXPECT_TRUE(bounds.intersects(other));
+ EXPECT_TRUE(bounds.intersects(other, LatLng::Wrapped));
+ EXPECT_TRUE(other.intersects(bounds));
+ EXPECT_TRUE(other.intersects(bounds, LatLng::Wrapped));
+
+ other = LatLngBounds::hull({10.0, 150.0}, {-10.0, 210.0});
+ EXPECT_FALSE(bounds.intersects(other));
+ EXPECT_FALSE(other.intersects(bounds));
+ EXPECT_TRUE(bounds.intersects(other, LatLng::Wrapped));
+ EXPECT_TRUE(other.intersects(bounds, LatLng::Wrapped));
+
+ other = LatLngBounds::hull({10.0, 195.0}, {-10.0, 300.0});
+ EXPECT_FALSE(bounds.intersects(other));
+ EXPECT_FALSE(other.intersects(bounds));
+ EXPECT_TRUE(bounds.intersects(other, LatLng::Wrapped));
+ EXPECT_TRUE(other.intersects(bounds, LatLng::Wrapped));
+}
diff --git a/test/util/grid_index.test.cpp b/test/util/grid_index.test.cpp
new file mode 100644
index 0000000000..b0a4e581a3
--- /dev/null
+++ b/test/util/grid_index.test.cpp
@@ -0,0 +1,53 @@
+#include <mbgl/util/grid_index.hpp>
+#include <mbgl/util/grid_index.cpp>
+
+#include <mbgl/test/util.hpp>
+
+using namespace mbgl;
+
+TEST(GridIndex, IndexesFeatures) {
+ GridIndex<int16_t> grid(100, 100, 10);
+ grid.insert(0, {{4, 10}, {6, 30}});
+ grid.insert(1, {{4, 10}, {30, 12}});
+ grid.insert(2, {{-10, 30}, {5, 35}});
+
+ EXPECT_EQ(grid.query({{4, 10}, {5, 11}}), (std::vector<int16_t>{0, 1}));
+ EXPECT_EQ(grid.query({{24, 10}, {25, 11}}), (std::vector<int16_t>{1}));
+ EXPECT_EQ(grid.query({{40, 40}, {100, 100}}), (std::vector<int16_t>{}));
+ EXPECT_EQ(grid.query({{-6, 0}, {3, 100}}), (std::vector<int16_t>{2}));
+ EXPECT_EQ(grid.query({{-1000, -1000}, {1000, 1000}}), (std::vector<int16_t>{0, 1, 2}));
+}
+
+TEST(GridIndex, DuplicateKeys) {
+ GridIndex<int16_t> grid(100, 100, 10);
+ #define KEY 123
+ grid.insert(KEY, {{3, 4}, {4, 4}});
+ grid.insert(KEY, {{13, 13}, {14, 14}});
+ grid.insert(KEY, {{23, 23}, {24, 24}});
+
+ EXPECT_EQ(grid.query({{0, 0}, {30, 30}}), (std::vector<int16_t>{KEY, KEY, KEY}));
+}
+
+TEST(GridIndex, CircleCircle) {
+ GridIndex<int16_t> grid(100, 100, 10);
+ grid.insert(0, {{50, 50}, 10});
+ grid.insert(1, {{60, 60}, 15});
+ grid.insert(2, {{-10, 110}, 20});
+
+ EXPECT_TRUE(grid.hitTest({{55, 55}, 2}));
+ EXPECT_FALSE(grid.hitTest({{10, 10}, 10}));
+ EXPECT_TRUE(grid.hitTest({{0, 100}, 10}));
+ EXPECT_TRUE(grid.hitTest({{80, 60}, 10}));
+}
+
+TEST(GridIndex, CircleBox) {
+ GridIndex<int16_t> grid(100, 100, 10);
+ grid.insert(0, {{50, 50}, 10});
+ grid.insert(1, {{60, 60}, 15});
+ grid.insert(2, {{-10, 110}, 20});
+
+ EXPECT_EQ(grid.query({{45, 45}, {55, 55}}), (std::vector<int16_t>{0, 1}));
+ EXPECT_EQ(grid.query({{0, 0}, {30, 30}}), (std::vector<int16_t>{}));
+ EXPECT_EQ(grid.query({{0, 80}, {20, 100}}), (std::vector<int16_t>{2}));
+}
+
diff --git a/test/util/mapbox.test.cpp b/test/util/mapbox.test.cpp
index cdbd85118f..301475dae4 100644
--- a/test/util/mapbox.test.cpp
+++ b/test/util/mapbox.test.cpp
@@ -7,6 +7,7 @@
#include <stdexcept>
using namespace mbgl;
+using SourceType = mbgl::style::SourceType;
TEST(Mapbox, SourceURL) {
EXPECT_EQ(
diff --git a/test/util/memory.test.cpp b/test/util/memory.test.cpp
index 54763cd9db..6befb521f0 100644
--- a/test/util/memory.test.cpp
+++ b/test/util/memory.test.cpp
@@ -72,7 +72,7 @@ TEST(Memory, Vector) {
HeadlessFrontend frontend { { 256, 256 }, ratio, test.fileSource, test.threadPool };
Map map(frontend, MapObserver::nullObserver(), frontend.getSize(), ratio, test.fileSource,
- test.threadPool, MapMode::Still);
+ test.threadPool, MapMode::Static);
map.setZoom(16); // more map features
map.getStyle().loadURL("mapbox://streets");
@@ -85,7 +85,7 @@ TEST(Memory, Raster) {
HeadlessFrontend frontend { { 256, 256 }, ratio, test.fileSource, test.threadPool };
Map map(frontend, MapObserver::nullObserver(), frontend.getSize(), ratio, test.fileSource,
- test.threadPool, MapMode::Still);
+ test.threadPool, MapMode::Static);
map.getStyle().loadURL("mapbox://satellite");
frontend.render(map);
@@ -122,7 +122,7 @@ TEST(Memory, Footprint) {
public:
FrontendAndMap(MemoryTest& test_, const char* style)
: frontend(Size{ 256, 256 }, 2, test_.fileSource, test_.threadPool)
- , map(frontend, MapObserver::nullObserver(), frontend.getSize(), 2, test_.fileSource, test_.threadPool, MapMode::Still) {
+ , map(frontend, MapObserver::nullObserver(), frontend.getSize(), 2, test_.fileSource, test_.threadPool, MapMode::Static) {
map.setZoom(16);
map.getStyle().loadURL(style);
frontend.render(map);
diff --git a/test/util/unique_any.test.cpp b/test/util/unique_any.test.cpp
new file mode 100644
index 0000000000..9357b9c0ec
--- /dev/null
+++ b/test/util/unique_any.test.cpp
@@ -0,0 +1,186 @@
+#include <mbgl/test/util.hpp>
+
+#include <mbgl/util/unique_any.hpp>
+
+using namespace mbgl::util;
+
+class TestType {
+public:
+ TestType() : i1(0), i2(1) {
+ str[0] = 'a';
+ }
+
+ TestType(unique_any& p) : TestType() {
+ p = std::unique_ptr<TestType>(this);
+ }
+
+ //Detect moves
+ TestType(TestType&& t): i1(t.i1+1), i2(t.i2+2) {
+ str[0] = t.str[0]+1;
+ }
+
+ int i1;
+ int i2;
+ char str[256];
+};
+
+bool IsStackAllocated (const unique_any& a, const void* obj1) {
+ uintptr_t a_ptr = (uintptr_t)(&a);
+ uintptr_t obj = (uintptr_t)(obj1);
+ return (obj >= a_ptr && obj < a_ptr + sizeof(unique_any));
+};
+
+TEST(UniqueAny, Empty) {
+ EXPECT_FALSE(unique_any().has_value());
+ EXPECT_TRUE(unique_any().type() == typeid(void));
+ EXPECT_THROW(any_cast<int>(unique_any()), bad_any_cast);
+}
+
+TEST(UniqueAny, BasicTypes) {
+ unique_any i = 3;
+ EXPECT_TRUE(i.has_value());
+ EXPECT_TRUE(i.type() == typeid(int));
+ EXPECT_TRUE(IsStackAllocated(i, any_cast<int>(&i)));
+
+ auto iValue = any_cast<int>(i);
+ EXPECT_TRUE(iValue == 3);
+
+ EXPECT_TRUE(unique_any(4).has_value());
+ EXPECT_TRUE(unique_any(4).type() == typeid(int));
+
+ unique_any f = 6.2f;
+ EXPECT_TRUE(f.has_value());
+ EXPECT_TRUE(f.type() == typeid(float));
+ EXPECT_TRUE(IsStackAllocated(f, any_cast<float>(&f)));
+
+ const float fValue = any_cast<const float>(f);
+ EXPECT_TRUE(fValue == 6.2f);
+
+ EXPECT_TRUE(unique_any(1.0f).has_value());
+ EXPECT_TRUE(unique_any(1.0f).type() == typeid(float));
+
+ unique_any c = 'z';
+ EXPECT_TRUE(c.has_value());
+ EXPECT_TRUE(c.type() == typeid(char));
+ EXPECT_TRUE(IsStackAllocated(c, any_cast<char>(&c)));
+
+ EXPECT_THROW(any_cast<float>(c), bad_any_cast);
+
+ EXPECT_TRUE(unique_any('4').has_value());
+ EXPECT_TRUE(unique_any('4').type() == typeid(char));
+}
+
+TEST(UniqueAny, BasicTypes_Move) {
+ unique_any i = 3;
+ EXPECT_TRUE(i.has_value());
+ EXPECT_TRUE(i.type() == typeid(int));
+
+ unique_any f = 6.2f;
+ EXPECT_TRUE(f.has_value());
+ EXPECT_TRUE(f.type() == typeid(float));
+
+ f = std::move(i);
+ EXPECT_FALSE(i.has_value());
+ EXPECT_TRUE(i.type() == typeid(void));
+
+ EXPECT_TRUE(f.has_value());
+ EXPECT_TRUE(f.type() == typeid(int));
+
+}
+
+TEST(UniqueAny, LargeType) {
+ TestType t1;
+ unique_any u1 = unique_any(std::move(t1));
+ EXPECT_TRUE(u1.has_value());
+ EXPECT_TRUE(u1.type() == typeid(TestType));
+ EXPECT_FALSE(IsStackAllocated(u1, any_cast<TestType>(&u1)));
+
+ //TestType should be moved into owning unique_any
+ EXPECT_EQ(any_cast<TestType>(&u1)->i1, 1);
+
+ auto u2(std::move(u1));
+ EXPECT_TRUE(u2.type() == typeid(TestType));
+ EXPECT_TRUE(u1.type() == typeid(void));
+
+ //TestType should not be moved when owning unique_any is moved;
+ EXPECT_EQ(any_cast<TestType>(&u2)->i1, 1);
+
+ //TestType should be moved out of owning unique_any
+ // Note: two moves are involved in returning the moved value
+ // First out of the unique_any, and then in the return statement
+ auto t2 = any_cast<TestType>(std::move(u2));
+ EXPECT_EQ(t2.i1, 3);
+ EXPECT_TRUE(u2.type() == typeid(void));
+}
+
+TEST(UniqueAny, Pointer) {
+ auto t1 = new TestType();
+
+ auto u1 = unique_any(std::move(t1));
+ EXPECT_TRUE(u1.has_value());
+ EXPECT_TRUE(u1.type() == typeid(TestType *));
+ EXPECT_TRUE(IsStackAllocated(u1, any_cast<TestType *>(&u1)));
+
+ //Only the pointer should be moved
+ TestType * t2 = *any_cast<TestType *>(&u1);
+ EXPECT_EQ(t2->i1, 0);
+
+ unique_any u2(4);
+ std::swap(u2, u1);
+
+ EXPECT_TRUE(u1.has_value());
+ EXPECT_TRUE(u1.type() == typeid(int));
+
+ EXPECT_TRUE(u2.has_value());
+ EXPECT_TRUE(u2.type() == typeid(TestType *));
+
+ t2 = *any_cast<TestType *>(&u2);
+ EXPECT_EQ(t2->i1, 0);
+ delete t2;
+}
+
+
+TEST(UniqueAny, UniquePtr) {
+ auto t1 = std::make_unique<TestType>();
+ auto u1 = unique_any(std::move(t1));
+
+ EXPECT_EQ(t1.get(), nullptr);
+ EXPECT_TRUE(u1.has_value());
+ EXPECT_TRUE(u1.type() == typeid(std::unique_ptr<TestType>));
+
+ EXPECT_TRUE(IsStackAllocated(u1, any_cast<std::unique_ptr<TestType>>(&u1)));
+
+ auto t2 = any_cast<std::unique_ptr<TestType> >(std::move(u1));
+ EXPECT_FALSE(u1.has_value());
+
+ unique_any u2;
+ TestType * t3 = new TestType();
+ u2 = std::unique_ptr<TestType>(t3);
+ EXPECT_TRUE(u2.has_value());
+ EXPECT_TRUE(any_cast<std::unique_ptr<TestType>>(&u2)->get() == t3);
+}
+
+TEST(UniqueAny, SharedPtr) {
+
+ std::shared_ptr<int> shared(new int(3));
+ std::weak_ptr<int> weak = shared;
+ unique_any u1 = 0;
+
+ EXPECT_THROW(any_cast<float>(u1), bad_any_cast);
+
+ EXPECT_EQ(weak.use_count(), 1);
+ unique_any u2 = shared;
+ EXPECT_EQ(weak.use_count(), 2);
+
+ EXPECT_EQ(any_cast<std::unique_ptr<int>>(&u1), nullptr);
+ EXPECT_FALSE(IsStackAllocated(u1, any_cast<std::shared_ptr<TestType>>(&u1)));
+
+ u1 = std::move(u2);
+ EXPECT_EQ(weak.use_count(), 2);
+ u2.swap(u1);
+ EXPECT_EQ(weak.use_count(), 2);
+ u2 = 0;
+ EXPECT_EQ(weak.use_count(), 1);
+ shared = nullptr;
+ EXPECT_EQ(weak.use_count(), 0);
+}