summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Bounds <jesse@rebounds.net>2016-10-25 15:48:29 -0700
committerJesse Bounds <jesse@rebounds.net>2016-10-25 15:48:29 -0700
commitdbfa8dcc89ff55fa1f8366433d24b1a270e53a02 (patch)
treea68cd34e2197012c2b0ab9525bc747bc7c4c94e7
parent1216050f9c5c472f1c8edcc32447004a40680ec7 (diff)
parenta4d259c33f9bb890bba97fd89552720e3e0ec09b (diff)
downloadqtlocation-mapboxgl-dbfa8dcc89ff55fa1f8366433d24b1a270e53a02.tar.gz
Merge branch 'master' into boundsj-release-ios-3.4.0-merge-master
-rw-r--r--CMakeLists.txt6
-rw-r--r--benchmark/api/query.benchmark.cpp16
-rw-r--r--benchmark/fixtures/api/cache.dbbin405504 -> 405504 bytes
-rw-r--r--benchmark/src/mbgl/benchmark/util.cpp8
-rw-r--r--benchmark/src/mbgl/benchmark/util.hpp3
-rw-r--r--bin/glfw.cpp14
-rw-r--r--bin/render.cpp16
-rw-r--r--cmake/core-files.cmake14
-rw-r--r--cmake/core.cmake2
-rw-r--r--cmake/node.cmake2
-rw-r--r--cmake/test-files.cmake2
-rw-r--r--include/mbgl/gl/implementation.hpp14
-rw-r--r--include/mbgl/map/backend.hpp45
-rw-r--r--include/mbgl/map/map.hpp25
-rw-r--r--include/mbgl/map/view.hpp59
-rw-r--r--include/mbgl/platform/default/glfw_view.hpp47
-rw-r--r--include/mbgl/platform/default/headless_backend.hpp (renamed from include/mbgl/platform/default/headless_view.hpp)53
-rw-r--r--include/mbgl/platform/default/headless_display.hpp9
-rw-r--r--include/mbgl/platform/default/offscreen_view.hpp33
-rw-r--r--include/mbgl/platform/default/thread_pool.hpp (renamed from src/mbgl/actor/thread_pool.hpp)0
-rw-r--r--include/mbgl/util/projection.hpp32
-rw-r--r--include/mbgl/util/run_loop.hpp4
-rw-r--r--package.json2
-rw-r--r--platform/android/CONTRIBUTING_MACOS.md20
-rw-r--r--platform/android/MapboxGLAndroidSDK/gradle.properties3
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java24
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java80
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java12
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java22
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java1
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CompassViewSettings.java21
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java206
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java33
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java29
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java14
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java26
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java145
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java68
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/package-info.java4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java44
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml1
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/layout/attribution_list_item.xml12
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/layout/attribution_telemetry_view.xml21
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values/arrays.xml10
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml1
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values/strings.xml3
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values/styles.xml2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/build.gradle20
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/gradle.properties2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/BaseActivityTest.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/activity/BaseTest.java)8
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/activity.junit.ejs (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/activity/activity.junit.ejs)6
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/AddRemoveMarkerActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/BulkMarkerActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/DynamicMarkerChangeActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/MarkerViewActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/MarkerViewScaleActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/PolygonActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/PolylineActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/PressForMarkerActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/CameraAnimationTypeActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/CameraPositionActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/LatLngBoundsActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/ManualZoomActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/MaxMinZoomActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/ScrollByActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/customlayer/CustomLayerActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/directions/DirectionsActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/feature/QueryRenderedFeaturesBoxCountActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/feature/QueryRenderedFeaturesPropertiesActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/geocoding/GeocoderActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/imagegenerator/PrintActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/infowindow/DynamicInfoWindowAdapterActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/infowindow/InfoWindowActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/infowindow/InfoWindowAdapterActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/DebugModeActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/MapPaddingActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/SurfaceViewMediaControlActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/VideoViewActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/offline/OfflineActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/CircleLayerActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/CustomSpriteActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/RuntimeStyleActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/RuntimeStyleTimingTestActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/StyleFileActivityTest.java33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/RotateActivityTest.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/camera/RotateTest.java)6
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/TiltActivityTest.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/camera/TiltTest.java)6
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/ZoomActivityTest.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/camera/ZoomTest.java)8
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BackgroundLayerStyleTest.java136
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BackgroundLayerTest.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/BackgroundLayerTest.java)6
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BaseStyleTest.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/BaseTest.java)8
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerStyleTest.java254
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerTest.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/CircleLayerTest.java)6
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerStyleTest.java276
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerTest.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/FillLayerTest.java)6
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerStyleTest.java408
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/LineLayerTest.java)6
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerStyleTest.java231
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerTest.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/RasterLayerTest.java)6
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleBackgroundLayerTest.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/RuntimeStyleBackgroundLayerTest.java)2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTests.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/RuntimeStyleTests.java)6
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTimingTests.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/RuntimeStyleTimingTests.java)6
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerStyleTest.java1222
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/SymbolLayerTest.java)6
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/layer.junit.ejs (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/layer.junit.ejs)6
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/DrawerUtils.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/utils/DrawerUtils.java)2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/GestureUtils.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/utils/GestureUtils.java)2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/OnMapReadyIdlingResource.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/utils/OnMapReadyIdlingResource.java)2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/ScreenshotUtil.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/utils/ScreenshotUtil.java)2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/ViewUtils.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/utils/ViewUtils.java)2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml15
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/DynamicMarkerChangeActivity.java2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolygonActivity.java1
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapInDialogActivity.java116
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RealTimeGeoJsonActivity.java141
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_default.xml19
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_dynamic_marker.xml8
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_manual_zoom.xml5
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_map_in_dialog.xml21
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/fragment_dialog_map.xml18
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml5
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java8
-rw-r--r--platform/android/MapboxGLAndroidSDKWearTestApp/build.gradle1
-rw-r--r--platform/android/bitrise.yml183
-rw-r--r--platform/android/config.cmake3
-rw-r--r--platform/android/scripts/generate-style-code.js6
-rw-r--r--platform/android/scripts/generate-test-code.js7
-rwxr-xr-xplatform/android/src/jni.cpp98
-rwxr-xr-xplatform/android/src/native_map_view.cpp43
-rwxr-xr-xplatform/android/src/native_map_view.hpp13
-rw-r--r--platform/android/src/style/layers/custom_layer.cpp2
-rw-r--r--platform/android/src/style/sources/geojson_source.cpp6
-rw-r--r--platform/android/src/style/sources/source.cpp13
-rw-r--r--platform/android/src/style/sources/source.hpp3
-rw-r--r--platform/darwin/src/headless_backend_cgl.cpp58
-rw-r--r--platform/darwin/src/headless_backend_eagl.mm46
-rw-r--r--platform/darwin/src/headless_view_cgl.cpp113
-rw-r--r--platform/darwin/src/headless_view_eagl.mm103
-rw-r--r--platform/default/glfw_view.cpp49
-rw-r--r--platform/default/headless_backend.cpp56
-rw-r--r--platform/default/headless_backend_glx.cpp67
-rw-r--r--platform/default/headless_display.cpp7
-rw-r--r--platform/default/headless_view.cpp118
-rw-r--r--platform/default/headless_view_glx.cpp128
-rw-r--r--platform/default/offscreen_view.cpp47
-rw-r--r--platform/default/thread_pool.cpp (renamed from src/mbgl/actor/thread_pool.cpp)6
-rw-r--r--platform/ios/config.cmake10
-rw-r--r--platform/ios/src/MGLMapView.mm78
-rw-r--r--platform/linux/config.cmake8
-rw-r--r--platform/macos/config.cmake8
-rw-r--r--platform/macos/src/MGLMapView.mm79
-rw-r--r--platform/node/bitrise.yml39
-rw-r--r--platform/node/src/node_log.cpp3
-rw-r--r--platform/node/src/node_log.hpp5
-rw-r--r--platform/node/src/node_map.cpp43
-rw-r--r--platform/node/src/node_map.hpp12
-rw-r--r--platform/node/src/node_mapbox_gl_native.cpp2
-rw-r--r--platform/node/src/node_request.cpp5
-rw-r--r--platform/node/src/node_request.hpp2
-rw-r--r--platform/node/src/node_thread_pool.cpp37
-rw-r--r--platform/node/src/node_thread_pool.hpp37
-rw-r--r--platform/node/src/util/async_queue.hpp4
-rw-r--r--platform/qt/app/mapwindow.cpp36
-rw-r--r--platform/qt/app/mapwindow.hpp2
-rw-r--r--platform/qt/config.cmake5
-rw-r--r--platform/qt/include/qmapboxgl.hpp13
-rw-r--r--platform/qt/qt.cmake3
-rw-r--r--platform/qt/src/qmapboxgl.cpp82
-rw-r--r--platform/qt/src/qmapboxgl_p.hpp21
-rw-r--r--platform/qt/src/qquickmapboxglrenderer.cpp12
-rw-r--r--platform/qt/src/qquickmapboxglrenderer.hpp1
-rw-r--r--platform/qt/test/headless_backend_qt.cpp46
-rw-r--r--platform/qt/test/headless_view_qt.cpp106
-rw-r--r--platform/qt/test/qmapboxgl.cpp2
-rw-r--r--scripts/generate-style-code.js2
-rw-r--r--src/mbgl/actor/mailbox.cpp6
-rw-r--r--src/mbgl/actor/mailbox.hpp2
-rw-r--r--src/mbgl/annotation/symbol_annotation_impl.cpp25
-rw-r--r--src/mbgl/gl/context.cpp183
-rw-r--r--src/mbgl/gl/context.hpp27
-rw-r--r--src/mbgl/gl/framebuffer.hpp17
-rw-r--r--src/mbgl/gl/gl.cpp1
-rw-r--r--src/mbgl/gl/object.cpp5
-rw-r--r--src/mbgl/gl/object.hpp6
-rw-r--r--src/mbgl/gl/renderbuffer.hpp19
-rw-r--r--src/mbgl/gl/state.hpp36
-rw-r--r--src/mbgl/gl/types.hpp5
-rw-r--r--src/mbgl/gl/value.cpp16
-rw-r--r--src/mbgl/gl/value.hpp9
-rw-r--r--src/mbgl/map/backend.cpp22
-rw-r--r--src/mbgl/map/map.cpp239
-rw-r--r--src/mbgl/map/transform.cpp22
-rw-r--r--src/mbgl/map/transform_state.cpp44
-rw-r--r--src/mbgl/map/transform_state.hpp12
-rw-r--r--src/mbgl/map/update.hpp (renamed from include/mbgl/map/update.hpp)1
-rw-r--r--src/mbgl/map/view.cpp22
-rw-r--r--src/mbgl/renderer/paint_parameters.hpp2
-rw-r--r--src/mbgl/renderer/painter.cpp50
-rw-r--r--src/mbgl/renderer/painter.hpp14
-rw-r--r--src/mbgl/renderer/painter_debug.cpp42
-rw-r--r--src/mbgl/renderer/painter_fill.cpp5
-rw-r--r--src/mbgl/style/source_impl.hpp2
-rw-r--r--src/mbgl/style/source_observer.hpp3
-rw-r--r--src/mbgl/style/sources/geojson_source_impl.cpp22
-rw-r--r--src/mbgl/style/sources/geojson_source_impl.hpp2
-rw-r--r--src/mbgl/style/style.cpp7
-rw-r--r--src/mbgl/style/style.hpp1
-rw-r--r--src/mbgl/text/collision_tile.cpp156
-rw-r--r--src/mbgl/text/collision_tile.hpp9
-rw-r--r--src/mbgl/util/intersection_tests.cpp32
-rw-r--r--src/mbgl/util/intersection_tests.hpp1
-rw-r--r--src/mbgl/util/offscreen_texture.cpp70
-rw-r--r--src/mbgl/util/offscreen_texture.hpp17
-rw-r--r--src/mbgl/util/tile_coordinate.hpp15
-rw-r--r--src/mbgl/util/tile_cover.cpp11
-rw-r--r--test/actor/actor.test.cpp2
-rw-r--r--test/actor/actor_ref.test.cpp2
-rw-r--r--test/api/annotations.test.cpp75
-rw-r--r--test/api/api_misuse.test.cpp25
-rw-r--r--test/api/custom_layer.test.cpp15
-rw-r--r--test/api/query.test.cpp14
-rw-r--r--test/api/render_missing.test.cpp15
-rw-r--r--test/api/repeated_render.test.cpp21
-rw-r--r--test/gl/object.test.cpp20
-rw-r--r--test/map/map.test.cpp68
-rw-r--r--test/src/mbgl/test/stub_style_observer.hpp5
-rw-r--r--test/src/mbgl/test/util.cpp7
-rw-r--r--test/src/mbgl/test/util.hpp3
-rw-r--r--test/style/source.test.cpp36
-rw-r--r--test/tile/raster_tile.test.cpp2
-rw-r--r--test/tile/tile_coordinate.test.cpp4
-rw-r--r--test/tile/vector_tile.test.cpp2
-rw-r--r--test/util/memory.test.cpp43
-rw-r--r--test/util/offscreen_texture.test.cpp27
233 files changed, 6636 insertions, 2122 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d021c856fb..9169dea812 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,6 @@
cmake_minimum_required(VERSION 3.1)
project(mbgl LANGUAGES CXX C)
+set(CMAKE_CXX_STANDARD 14)
include(cmake/mbgl.cmake)
@@ -44,6 +45,11 @@ if(APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=unused-command-line-argument")
endif()
+if(CMAKE_COMPILER_IS_GNUCXX)
+ # https://svn.boost.org/trac/boost/ticket/9240
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fext-numeric-literals")
+endif()
+
if(NOT EXISTS ${CMAKE_SOURCE_DIR}/platform/${MBGL_PLATFORM}/config.cmake)
message(ERROR "Can't find config.cmake file for platform ${MBGL_PLATFORM}")
endif()
diff --git a/benchmark/api/query.benchmark.cpp b/benchmark/api/query.benchmark.cpp
index 7fa0781450..5a95cd7666 100644
--- a/benchmark/api/query.benchmark.cpp
+++ b/benchmark/api/query.benchmark.cpp
@@ -2,8 +2,9 @@
#include <mbgl/benchmark/util.hpp>
#include <mbgl/map/map.hpp>
-#include <mbgl/platform/default/headless_display.hpp>
-#include <mbgl/platform/default/headless_view.hpp>
+#include <mbgl/platform/default/headless_backend.hpp>
+#include <mbgl/platform/default/offscreen_view.hpp>
+#include <mbgl/platform/default/thread_pool.hpp>
#include <mbgl/sprite/sprite_image.hpp>
#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/storage/network_status.hpp>
@@ -28,16 +29,15 @@ public:
auto image = std::make_unique<SpriteImage>(std::move(decoded), 1.0);
map.addImage("test-icon", std::move(image));
- view.resize(1000, 1000);
-
- mbgl::benchmark::render(map);
+ mbgl::benchmark::render(map, view);
}
util::RunLoop loop;
- std::shared_ptr<HeadlessDisplay> display{ std::make_shared<HeadlessDisplay>() };
- HeadlessView view{ display, 1 };
+ HeadlessBackend backend;
+ OffscreenView view{ backend.getContext(), {{ 1000, 1000 }} };
DefaultFileSource fileSource{ "benchmark/fixtures/api/cache.db", "." };
- Map map{ view, fileSource, MapMode::Still };
+ ThreadPool threadPool{ 4 };
+ Map map{ backend, view.getSize(), 1, fileSource, threadPool, MapMode::Still };
ScreenBox box{{ 0, 0 }, { 1000, 1000 }};
};
diff --git a/benchmark/fixtures/api/cache.db b/benchmark/fixtures/api/cache.db
index 102c4074ef..a62a3b0f00 100644
--- a/benchmark/fixtures/api/cache.db
+++ b/benchmark/fixtures/api/cache.db
Binary files differ
diff --git a/benchmark/src/mbgl/benchmark/util.cpp b/benchmark/src/mbgl/benchmark/util.cpp
index a8f71f1206..39c5f86883 100644
--- a/benchmark/src/mbgl/benchmark/util.cpp
+++ b/benchmark/src/mbgl/benchmark/util.cpp
@@ -1,16 +1,18 @@
#include <mbgl/benchmark/util.hpp>
+#include <mbgl/platform/default/offscreen_view.hpp>
#include <mbgl/map/map.hpp>
+#include <mbgl/map/view.hpp>
#include <mbgl/util/image.hpp>
#include <mbgl/util/run_loop.hpp>
namespace mbgl {
namespace benchmark {
-void render(Map& map) {
+void render(Map& map, OffscreenView& view) {
PremultipliedImage result;
- map.renderStill([&result](std::exception_ptr, PremultipliedImage&& image) {
- result = std::move(image);
+ map.renderStill(view, [&](std::exception_ptr) {
+ result = view.readStillImage();
});
while (!result.size()) {
diff --git a/benchmark/src/mbgl/benchmark/util.hpp b/benchmark/src/mbgl/benchmark/util.hpp
index 759015e0e3..73acfb69d5 100644
--- a/benchmark/src/mbgl/benchmark/util.hpp
+++ b/benchmark/src/mbgl/benchmark/util.hpp
@@ -3,10 +3,11 @@
namespace mbgl {
class Map;
+class OffscreenView;
namespace benchmark {
-void render(Map&);
+void render(Map&, OffscreenView&);
} // namespace benchmark
} // namespace mbgl
diff --git a/bin/glfw.cpp b/bin/glfw.cpp
index 142095f8a2..b51846b4e8 100644
--- a/bin/glfw.cpp
+++ b/bin/glfw.cpp
@@ -4,6 +4,7 @@
#include <mbgl/platform/platform.hpp>
#include <mbgl/platform/default/settings_json.hpp>
#include <mbgl/platform/default/glfw_view.hpp>
+#include <mbgl/platform/default/thread_pool.hpp>
#include <mbgl/storage/default_file_source.hpp>
#include <signal.h>
@@ -12,10 +13,11 @@
#include <sstream>
#include <cstdlib>
#include <cstdio>
+#include <array>
namespace {
-std::unique_ptr<GLFWView> view;
+GLFWView* view = nullptr;
}
@@ -103,7 +105,8 @@ int main(int argc, char *argv[]) {
mbgl::Log::Info(mbgl::Event::General, "BENCHMARK MODE: Some optimizations are disabled.");
}
- view = std::make_unique<GLFWView>(fullscreen, benchmark);
+ GLFWView backend(fullscreen, benchmark);
+ view = &backend;
mbgl::DefaultFileSource fileSource("/tmp/mbgl-cache.db", ".");
@@ -115,7 +118,11 @@ int main(int argc, char *argv[]) {
fileSource.setAccessToken(std::string(token));
}
- mbgl::Map map(*view, fileSource);
+ mbgl::ThreadPool threadPool(4);
+
+ mbgl::Map map(backend, view->getSize(), view->getPixelRatio(), fileSource, threadPool);
+
+ backend.setMap(&map);
// Load settings
mbgl::Settings_JSON settings;
@@ -178,5 +185,6 @@ int main(int argc, char *argv[]) {
"Exit location: --lat=\"%f\" --lon=\"%f\" --zoom=\"%f\" --bearing \"%f\"",
settings.latitude, settings.longitude, settings.zoom, settings.bearing);
+ view = nullptr;
return 0;
}
diff --git a/bin/render.cpp b/bin/render.cpp
index a43bf32ddd..ad29d91993 100644
--- a/bin/render.cpp
+++ b/bin/render.cpp
@@ -3,8 +3,9 @@
#include <mbgl/util/io.hpp>
#include <mbgl/util/run_loop.hpp>
-#include <mbgl/platform/default/headless_view.hpp>
-#include <mbgl/platform/default/headless_display.hpp>
+#include <mbgl/platform/default/headless_backend.hpp>
+#include <mbgl/platform/default/offscreen_view.hpp>
+#include <mbgl/platform/default/thread_pool.hpp>
#include <mbgl/storage/default_file_source.hpp>
#pragma GCC diagnostic push
@@ -28,7 +29,6 @@ int main(int argc, char *argv[]) {
int width = 512;
int height = 512;
- double pixelRatio = 1.0;
static std::string output = "out.png";
std::string cache_file = "cache.sqlite";
std::string asset_root = ".";
@@ -83,8 +83,10 @@ int main(int argc, char *argv[]) {
fileSource.setAccessToken(std::string(token));
}
- HeadlessView view(pixelRatio, width, height);
- Map map(view, fileSource, MapMode::Still);
+ HeadlessBackend backend;
+ OffscreenView view(backend.getContext(), {{ static_cast<uint16_t>(width), static_cast<uint16_t>(height) }});
+ ThreadPool threadPool(4);
+ Map map(backend, view.getSize(), 1, fileSource, threadPool, MapMode::Still);
map.setStyleJSON(style);
map.setClasses(classes);
@@ -97,7 +99,7 @@ int main(int argc, char *argv[]) {
map.setDebug(debug ? mbgl::MapDebugOptions::TileBorders | mbgl::MapDebugOptions::ParseStatus : mbgl::MapDebugOptions::NoDebug);
}
- map.renderStill([&](std::exception_ptr error, PremultipliedImage&& image) {
+ map.renderStill(view, [&](std::exception_ptr error) {
try {
if (error) {
std::rethrow_exception(error);
@@ -107,7 +109,7 @@ int main(int argc, char *argv[]) {
exit(1);
}
- util::write_file(output, encodePNG(image));
+ util::write_file(output, encodePNG(view.readStillImage()));
loop.stop();
});
diff --git a/cmake/core-files.cmake b/cmake/core-files.cmake
index 8940899c16..4d5cddbc49 100644
--- a/cmake/core-files.cmake
+++ b/cmake/core-files.cmake
@@ -8,8 +8,6 @@ set(MBGL_CORE_FILES
src/mbgl/actor/mailbox.hpp
src/mbgl/actor/message.hpp
src/mbgl/actor/scheduler.hpp
- src/mbgl/actor/thread_pool.cpp
- src/mbgl/actor/thread_pool.hpp
# algorithm
src/mbgl/algorithm/covered_by_children.hpp
@@ -56,6 +54,7 @@ set(MBGL_CORE_FILES
# gl
include/mbgl/gl/gl.hpp
+ include/mbgl/gl/implementation.hpp
src/mbgl/gl/attribute.hpp
src/mbgl/gl/context.cpp
src/mbgl/gl/context.hpp
@@ -63,10 +62,12 @@ set(MBGL_CORE_FILES
src/mbgl/gl/debugging.hpp
src/mbgl/gl/extension.cpp
src/mbgl/gl/extension.hpp
+ src/mbgl/gl/framebuffer.hpp
src/mbgl/gl/gl.cpp
src/mbgl/gl/index_buffer.hpp
src/mbgl/gl/object.cpp
src/mbgl/gl/object.hpp
+ src/mbgl/gl/renderbuffer.hpp
src/mbgl/gl/shader.cpp
src/mbgl/gl/shader.hpp
src/mbgl/gl/state.hpp
@@ -94,18 +95,19 @@ set(MBGL_CORE_FILES
src/mbgl/layout/symbol_layout.hpp
# map
+ include/mbgl/map/backend.hpp
include/mbgl/map/camera.hpp
include/mbgl/map/map.hpp
include/mbgl/map/mode.hpp
- include/mbgl/map/update.hpp
include/mbgl/map/view.hpp
+ src/mbgl/map/backend.cpp
src/mbgl/map/change.hpp
src/mbgl/map/map.cpp
src/mbgl/map/transform.cpp
src/mbgl/map/transform.hpp
src/mbgl/map/transform_state.cpp
src/mbgl/map/transform_state.hpp
- src/mbgl/map/view.cpp
+ src/mbgl/map/update.hpp
src/mbgl/map/zoom_history.hpp
# math
@@ -132,9 +134,11 @@ set(MBGL_CORE_FILES
# platform/default
include/mbgl/platform/default/glfw_view.hpp
+ include/mbgl/platform/default/headless_backend.hpp
include/mbgl/platform/default/headless_display.hpp
- include/mbgl/platform/default/headless_view.hpp
+ include/mbgl/platform/default/offscreen_view.hpp
include/mbgl/platform/default/settings_json.hpp
+ include/mbgl/platform/default/thread_pool.hpp
# renderer
src/mbgl/renderer/bucket.hpp
diff --git a/cmake/core.cmake b/cmake/core.cmake
index ef98c4eccb..bc5e7eb718 100644
--- a/cmake/core.cmake
+++ b/cmake/core.cmake
@@ -36,7 +36,7 @@ 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 PRIVATE unique_resource)
+target_add_mason_package(mbgl-core PUBLIC unique_resource)
target_add_mason_package(mbgl-core PRIVATE rapidjson)
target_add_mason_package(mbgl-core PRIVATE boost)
target_add_mason_package(mbgl-core PRIVATE geojson)
diff --git a/cmake/node.cmake b/cmake/node.cmake
index 75def7c468..8dd95a9419 100644
--- a/cmake/node.cmake
+++ b/cmake/node.cmake
@@ -11,6 +11,8 @@ target_sources(mbgl-node
PRIVATE platform/node/src/node_request.cpp
PRIVATE platform/node/src/node_feature.hpp
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/util/async_queue.hpp
# We are compiling with the uv loop, but since this target already has the headers for libuv,
diff --git a/cmake/test-files.cmake b/cmake/test-files.cmake
index 2ade1ba537..598e018224 100644
--- a/cmake/test-files.cmake
+++ b/cmake/test-files.cmake
@@ -89,9 +89,9 @@ set(MBGL_TEST_FILES
# tile
test/tile/geometry_tile_data.test.cpp
test/tile/raster_tile.test.cpp
+ test/tile/tile_coordinate.test.cpp
test/tile/tile_id.test.cpp
test/tile/vector_tile.test.cpp
- test/tile/tile_coordinate.test.cpp
# util
test/util/async_task.test.cpp
diff --git a/include/mbgl/gl/implementation.hpp b/include/mbgl/gl/implementation.hpp
new file mode 100644
index 0000000000..4e3a3e51c7
--- /dev/null
+++ b/include/mbgl/gl/implementation.hpp
@@ -0,0 +1,14 @@
+#pragma once
+
+#if defined(__QT__)
+ #define MBGL_USE_QT 1
+#elif defined(__APPLE__)
+ #include <TargetConditionals.h>
+ #if TARGET_OS_IOS
+ #define MBGL_USE_EAGL 1
+ #else
+ #define MBGL_USE_CGL 1
+ #endif
+#else
+ #define MBGL_USE_GLX 1
+#endif
diff --git a/include/mbgl/map/backend.hpp b/include/mbgl/map/backend.hpp
new file mode 100644
index 0000000000..c11d094906
--- /dev/null
+++ b/include/mbgl/map/backend.hpp
@@ -0,0 +1,45 @@
+#pragma once
+
+#include <mbgl/map/change.hpp>
+
+#include <memory>
+
+namespace mbgl {
+
+namespace gl {
+class Context;
+} // namespace gl
+
+class Backend {
+public:
+ Backend();
+ virtual ~Backend();
+
+ // Returns the backend's context which manages OpenGL state.
+ gl::Context& getContext();
+
+ // Called when the backend's GL context needs to be made active or inactive. These are called,
+ // as a matched pair, in four situations:
+ //
+ // 1. When releasing GL resources during Map destruction
+ // 2. When calling a CustomLayerInitializeFunction, during Map::addLayer
+ // 3. When calling a CustomLayerDeinitializeFunction, during Map::removeLayer
+ // 4. When rendering for Map::renderStill
+ //
+ // They are *not* called for Map::render; it is assumed that the correct context is already
+ // activated prior to calling Map::render.
+ virtual void activate() = 0;
+ virtual void deactivate() = 0;
+
+ // Called when the map needs to be rendered; the backend should call Map::render() at some point
+ // in the near future. (Not called for Map::renderStill() mode.)
+ virtual void invalidate() = 0;
+
+ // Notifies a watcher of map x/y/scale/rotation changes.
+ virtual void notifyMapChange(MapChange change);
+
+private:
+ const std::unique_ptr<gl::Context> context;
+};
+
+} // namespace mbgl
diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp
index 914c2cd0b3..b1c840e68d 100644
--- a/include/mbgl/map/map.hpp
+++ b/include/mbgl/map/map.hpp
@@ -2,8 +2,6 @@
#include <mbgl/util/optional.hpp>
#include <mbgl/util/chrono.hpp>
-#include <mbgl/util/image.hpp>
-#include <mbgl/map/update.hpp>
#include <mbgl/map/mode.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/util/feature.hpp>
@@ -19,8 +17,10 @@
namespace mbgl {
-class FileSource;
+class Backend;
class View;
+class FileSource;
+class Scheduler;
class SpriteImage;
struct CameraOptions;
struct AnimationOptions;
@@ -32,7 +32,11 @@ class Layer;
class Map : private util::noncopyable {
public:
- explicit Map(View&, FileSource&,
+ explicit Map(Backend&,
+ std::array<uint16_t, 2> size,
+ float pixelRatio,
+ FileSource&,
+ Scheduler&,
MapMode mapMode = MapMode::Continuous,
GLContextMode contextMode = GLContextMode::Unique,
ConstrainMode constrainMode = ConstrainMode::HeightOnly,
@@ -41,14 +45,14 @@ public:
// Register a callback that will get called (on the render thread) when all resources have
// been loaded and a complete render occurs.
- using StillImageCallback = std::function<void (std::exception_ptr, PremultipliedImage&&)>;
- void renderStill(StillImageCallback callback);
+ using StillImageCallback = std::function<void (std::exception_ptr)>;
+ void renderStill(View&, StillImageCallback callback);
- // Main render function.
- void render();
+ // Triggers a repaint.
+ void triggerRepaint();
- // Notifies the Map that the state has changed and an update might be necessary.
- void update(Update update);
+ // Main render function.
+ void render(View&);
// Styling
void addClass(const std::string&);
@@ -132,6 +136,7 @@ public:
ViewportMode getViewportMode() const;
// Size
+ void setSize(const std::array<uint16_t, 2>&);
uint16_t getWidth() const;
uint16_t getHeight() const;
diff --git a/include/mbgl/map/view.hpp b/include/mbgl/map/view.hpp
index 590eef7237..6517c6b220 100644
--- a/include/mbgl/map/view.hpp
+++ b/include/mbgl/map/view.hpp
@@ -1,63 +1,20 @@
#pragma once
-#include <mbgl/map/change.hpp>
-#include <mbgl/util/chrono.hpp>
-#include <mbgl/util/image.hpp>
-
-#include <array>
-#include <functional>
-#include <memory>
+#include <mbgl/util/noncopyable.hpp>
namespace mbgl {
class Map;
-class View {
+class View : private util::noncopyable {
public:
virtual ~View() = default;
- // Called directly after initialization. Must always return the same value, i.e. it may
- // not change over time.
- virtual float getPixelRatio() const = 0;
-
- // Called when the View signaled a dimension change. Must return the logical dimension
- // of this map in pixels.
- virtual std::array<uint16_t, 2> getSize() const = 0;
-
- // Called for every frame that is being rendered. Must return the absolute dimensions of
- // the current framebuffer. Typically, this is the logical width scaled by the pixel ratio,
- // but in case the view was moved to display with a different pixel ratio, it can also be
- // different from that rule.
- virtual std::array<uint16_t, 2> getFramebufferSize() const = 0;
-
- // Called when this View is associated with a Map object.
- virtual void initialize(Map*);
-
- // Called when the view's GL context needs to be made active or inactive. These are called,
- // as a matched pair, in four situations:
- //
- // 1. When releasing GL resources during Map destruction
- // 2. When calling a CustomLayerInitializeFunction, during Map::addLayer
- // 3. When calling a CustomLayerDeinitializeFunction, during Map::removeLayer
- // 4. When rendering for Map::renderStill
- //
- // They are *not* called for Map::render; it is assumed that the correct context is already
- // activated prior to calling Map::render.
- virtual void activate() = 0;
- virtual void deactivate() = 0;
-
- // Called when the map needs to be rendered; the view should call Map::render() at some point
- // in the near future. (Not called for Map::renderStill() mode.)
- virtual void invalidate() = 0;
-
- // Reads the pixel data from the current framebuffer. If your View implementation
- // doesn't support reading from the framebuffer, return a null pointer.
- virtual PremultipliedImage readStillImage(std::array<uint16_t, 2> size = {{ 0, 0 }});
-
- // Notifies a watcher of map x/y/scale/rotation changes.
- virtual void notifyMapChange(MapChange change);
-
-protected:
- mbgl::Map *map = nullptr;
+ // Called when this View is used for rendering. Implementations should ensure that a renderable
+ // object is bound and glClear/glDraw* calls can be done. They should also make sure that
+ // calling .bind() repeatedly is a no-op and that the appropriate gl::Context values are
+ // set to the current state.
+ virtual void bind() = 0;
};
+
} // namespace mbgl
diff --git a/include/mbgl/platform/default/glfw_view.hpp b/include/mbgl/platform/default/glfw_view.hpp
index b352709830..e832cd70d1 100644
--- a/include/mbgl/platform/default/glfw_view.hpp
+++ b/include/mbgl/platform/default/glfw_view.hpp
@@ -1,6 +1,7 @@
#pragma once
#include <mbgl/mbgl.hpp>
+#include <mbgl/map/backend.hpp>
#include <mbgl/util/run_loop.hpp>
#include <mbgl/util/timer.hpp>
#include <mbgl/util/geometry.hpp>
@@ -11,20 +12,38 @@
#define GL_GLEXT_PROTOTYPES
#include <GLFW/glfw3.h>
-class GLFWView : public mbgl::View {
+class GLFWView : public mbgl::View, public mbgl::Backend {
public:
GLFWView(bool fullscreen = false, bool benchmark = false);
~GLFWView() override;
- float getPixelRatio() const override;
- std::array<uint16_t, 2> getSize() const override;
- std::array<uint16_t, 2> getFramebufferSize() const override;
+ float getPixelRatio() const;
- void initialize(mbgl::Map*) override;
+ void setMap(mbgl::Map*);
+
+ // Callback called when the user presses the key mapped to style change.
+ // The expected action is to set a new style, different to the current one.
+ void setChangeStyleCallback(std::function<void()> callback);
+
+ void setShouldClose();
+
+ void setWindowTitle(const std::string&);
+
+ void run();
+
+ // mbgl::View implementation
+ void updateViewBinding();
+ void bind() override;
+ std::array<uint16_t, 2> getSize() const;
+ std::array<uint16_t, 2> getFramebufferSize() const;
+
+ // mbgl::Backend implementation
void activate() override;
void deactivate() override;
void invalidate() override;
+private:
+ // Window callbacks
static void onKey(GLFWwindow *window, int key, int scancode, int action, int mods);
static void onScroll(GLFWwindow *window, double xoffset, double yoffset);
static void onWindowResize(GLFWwindow *window, int width, int height);
@@ -32,18 +51,12 @@ public:
static void onMouseClick(GLFWwindow *window, int button, int action, int modifiers);
static void onMouseMove(GLFWwindow *window, double x, double y);
- // Callback called when the user presses the key mapped to style change.
- // The expected action is to set a new style, different to the current one.
- void setChangeStyleCallback(std::function<void()> callback);
-
- void setShouldClose();
-
- void setWindowTitle(const std::string&);
-
- void run();
+ // Internal
void report(float duration);
+
+ void setMapChangeCallback(std::function<void(mbgl::MapChange)> callback);
+ void notifyMapChange(mbgl::MapChange change) override;
-private:
mbgl::Color makeRandomColor() const;
mbgl::Point<double> makeRandomPoint() const;
static std::shared_ptr<const mbgl::SpriteImage>
@@ -62,7 +75,11 @@ private:
mbgl::AnnotationIDs annotationIDs;
std::vector<std::string> spriteIDs;
+ std::function<void(mbgl::MapChange)> mapChangeCallback;
+
private:
+ mbgl::Map* map = nullptr;
+
bool fullscreen = false;
const bool benchmark = false;
bool tracking = false;
diff --git a/include/mbgl/platform/default/headless_view.hpp b/include/mbgl/platform/default/headless_backend.hpp
index 23f1e8251a..2f4886a365 100644
--- a/include/mbgl/platform/default/headless_view.hpp
+++ b/include/mbgl/platform/default/headless_backend.hpp
@@ -1,18 +1,12 @@
#pragma once
-#if defined(__QT__)
-#define MBGL_USE_QT 1
+#include <mbgl/gl/implementation.hpp>
+
+#if MBGL_USE_QT
class QGLWidget;
-#elif defined(__APPLE__)
-#include <TargetConditionals.h>
-#if TARGET_OS_IOS
-#define MBGL_USE_EAGL 1
-#else
-#define MBGL_USE_CGL 1
-#endif
-#else
-#define GL_GLEXT_PROTOTYPES
-#define MBGL_USE_GLX 1
+#elif MBGL_USE_CGL
+#include <OpenGL/OpenGL.h>
+#elif MBGL_USE_GLX
typedef struct _XDisplay Display;
typedef struct __GLXcontextRec* GLXContext;
typedef struct __GLXFBConfigRec* GLXFBConfig;
@@ -20,53 +14,41 @@ typedef long unsigned int XID;
typedef XID GLXPbuffer;
#endif
-#include <mbgl/mbgl.hpp>
-#include <mbgl/gl/gl.hpp>
-#include <mbgl/gl/types.hpp>
+#include <mbgl/map/backend.hpp>
#include <mbgl/gl/extension.hpp>
#include <memory>
-#include <thread>
+#include <functional>
namespace mbgl {
class HeadlessDisplay;
-class HeadlessView : public View {
+class HeadlessBackend : public Backend {
public:
- HeadlessView(float pixelRatio, uint16_t width = 256, uint16_t height = 256);
- HeadlessView(std::shared_ptr<HeadlessDisplay> display, float pixelRatio, uint16_t width = 256, uint16_t height = 256);
- ~HeadlessView() override;
-
- float getPixelRatio() const override;
- std::array<uint16_t, 2> getSize() const override;
- std::array<uint16_t, 2> getFramebufferSize() const override;
+ HeadlessBackend();
+ HeadlessBackend(std::shared_ptr<HeadlessDisplay>);
+ ~HeadlessBackend() override;
void invalidate() override;
void activate() override;
void deactivate() override;
void notifyMapChange(MapChange) override;
- PremultipliedImage readStillImage(std::array<uint16_t, 2> size = {{ 0, 0 }}) override;
-
- void resize(uint16_t width, uint16_t height);
void setMapChangeCallback(std::function<void(MapChange)>&& cb) { mapChangeCallback = std::move(cb); }
private:
+ void activateContext();
+ void deactivateContext();
+
+private:
// Implementation specific functions
static gl::glProc initializeExtension(const char*);
void createContext();
void destroyContext();
- void clearBuffers();
- void resizeFramebuffer();
- void activateContext();
- void deactivateContext();
std::shared_ptr<HeadlessDisplay> display;
- const float pixelRatio;
- std::array<uint16_t, 2> dimensions;
- bool needsResize = false;
bool extensionsLoaded = false;
bool active = false;
@@ -91,9 +73,6 @@ private:
std::function<void(MapChange)> mapChangeCallback;
- gl::FramebufferID fbo = 0;
- gl::RenderbufferID fboDepthStencil = 0;
- gl::RenderbufferID fboColor = 0;
};
} // namespace mbgl
diff --git a/include/mbgl/platform/default/headless_display.hpp b/include/mbgl/platform/default/headless_display.hpp
index edcc905221..f43e61340f 100644
--- a/include/mbgl/platform/default/headless_display.hpp
+++ b/include/mbgl/platform/default/headless_display.hpp
@@ -1,6 +1,13 @@
#pragma once
-#include <mbgl/platform/default/headless_view.hpp>
+#include <mbgl/gl/implementation.hpp>
+
+#if MBGL_USE_CGL
+#include <OpenGL/OpenGL.h>
+#elif MBGL_USE_GLX
+typedef struct _XDisplay Display;
+typedef struct __GLXFBConfigRec* GLXFBConfig;
+#endif
namespace mbgl {
diff --git a/include/mbgl/platform/default/offscreen_view.hpp b/include/mbgl/platform/default/offscreen_view.hpp
new file mode 100644
index 0000000000..034aa3aaf3
--- /dev/null
+++ b/include/mbgl/platform/default/offscreen_view.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+#include <mbgl/map/view.hpp>
+#include <mbgl/gl/framebuffer.hpp>
+#include <mbgl/gl/renderbuffer.hpp>
+#include <mbgl/util/optional.hpp>
+#include <mbgl/util/image.hpp>
+
+namespace mbgl {
+
+namespace gl {
+class Context;
+} // namespace gl
+
+class OffscreenView : public View {
+public:
+ OffscreenView(gl::Context&, std::array<uint16_t, 2> size = {{ 256, 256 }});
+
+ void bind() override;
+
+ PremultipliedImage readStillImage();
+
+ std::array<uint16_t, 2> getSize() const;
+
+private:
+ gl::Context& context;
+ std::array<uint16_t, 2> size;
+ optional<gl::Framebuffer> framebuffer;
+ optional<gl::Renderbuffer<gl::RenderbufferType::RGBA>> color;
+ optional<gl::Renderbuffer<gl::RenderbufferType::DepthStencil>> depthStencil;
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/actor/thread_pool.hpp b/include/mbgl/platform/default/thread_pool.hpp
index a14d16d771..a14d16d771 100644
--- a/src/mbgl/actor/thread_pool.hpp
+++ b/include/mbgl/platform/default/thread_pool.hpp
diff --git a/include/mbgl/util/projection.hpp b/include/mbgl/util/projection.hpp
index eb45088580..9ca3cd4ab5 100644
--- a/include/mbgl/util/projection.hpp
+++ b/include/mbgl/util/projection.hpp
@@ -2,20 +2,26 @@
#include <mbgl/util/constants.hpp>
#include <mbgl/util/geo.hpp>
+#include <mbgl/util/geometry.hpp>
#include <mbgl/math/clamp.hpp>
-#include <cmath>
namespace mbgl {
+// Spherical Mercator projection
+// http://docs.openlayers.org/library/spherical_mercator.html
class Projection {
-
public:
+ // Map pixel width at given scale.
+ static double worldSize(double scale) {
+ return scale * util::tileSize;
+ }
+
static double getMetersPerPixelAtLatitude(double lat, double zoom) {
const double constrainedZoom = util::clamp(zoom, util::MIN_ZOOM, util::MAX_ZOOM);
- const double mapPixelWidthAtZoom = std::pow(2.0, constrainedZoom) * util::tileSize;
+ const double constrainedScale = std::pow(2.0, constrainedZoom);
const double constrainedLatitude = util::clamp(lat, -util::LATITUDE_MAX, util::LATITUDE_MAX);
- return std::cos(constrainedLatitude * util::DEG2RAD) * util::M2PI * util::EARTH_RADIUS_M / mapPixelWidthAtZoom;
+ return std::cos(constrainedLatitude * util::DEG2RAD) * util::M2PI * util::EARTH_RADIUS_M / worldSize(constrainedScale);
}
static ProjectedMeters projectedMetersForLatLng(const LatLng& latLng) {
@@ -32,7 +38,7 @@ public:
}
static LatLng latLngForProjectedMeters(const ProjectedMeters& projectedMeters) {
- double latitude = (2 * std::atan(std::exp(projectedMeters.northing / util::EARTH_RADIUS_M)) - (M_PI / 2)) * util::RAD2DEG;
+ double latitude = (2 * std::atan(std::exp(projectedMeters.northing / util::EARTH_RADIUS_M)) - (M_PI / 2.0)) * util::RAD2DEG;
double longitude = projectedMeters.easting * util::RAD2DEG / util::EARTH_RADIUS_M;
latitude = util::clamp(latitude, -util::LATITUDE_MAX, util::LATITUDE_MAX);
@@ -40,6 +46,22 @@ public:
return LatLng(latitude, longitude);
}
+
+ static Point<double> project(const LatLng& latLng, double scale) {
+ return Point<double> {
+ util::LONGITUDE_MAX + latLng.longitude,
+ util::LONGITUDE_MAX - util::RAD2DEG * std::log(std::tan(M_PI / 4 + latLng.latitude * M_PI / util::DEGREES_MAX))
+ } * worldSize(scale) / util::DEGREES_MAX;
+ }
+
+ static LatLng unproject(const Point<double>& p, double scale, LatLng::WrapMode wrapMode = LatLng::Unwrapped) {
+ auto p2 = p * util::DEGREES_MAX / worldSize(scale);
+ return LatLng {
+ util::DEGREES_MAX / M_PI * std::atan(std::exp((util::LONGITUDE_MAX - p2.y) * util::DEG2RAD)) - 90.0,
+ p2.x - util::LONGITUDE_MAX,
+ wrapMode
+ };
+ }
};
} // namespace mbgl
diff --git a/include/mbgl/util/run_loop.hpp b/include/mbgl/util/run_loop.hpp
index 939531d6c3..5236850d83 100644
--- a/include/mbgl/util/run_loop.hpp
+++ b/include/mbgl/util/run_loop.hpp
@@ -83,9 +83,7 @@ private:
void schedule(std::weak_ptr<Mailbox> mailbox) override {
invoke([mailbox] () {
- if (auto locked = mailbox.lock()) {
- locked->receive();
- }
+ Mailbox::maybeReceive(mailbox);
});
}
diff --git a/package.json b/package.json
index 61936e2fe7..de2f6ff39e 100644
--- a/package.json
+++ b/package.json
@@ -23,7 +23,7 @@
"lodash": "^4.16.4",
"mapbox-gl-shaders": "mapbox/mapbox-gl-shaders#98a56d538b11fb331aa67a6d632d6ecd6821b007",
"mapbox-gl-style-spec": "mapbox/mapbox-gl-style-spec#7f62a4fc9f21e619824d68abbc4b03cbc1685572",
- "mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#6df3b27868cc00432197e3fc9c166fdba7067913",
+ "mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#844ecd23c3314eec509dbcdaf0f956d5504e6fef",
"mkdirp": "^0.5.1",
"node-cmake": "^1.2.1",
"request": "^2.72.0",
diff --git a/platform/android/CONTRIBUTING_MACOS.md b/platform/android/CONTRIBUTING_MACOS.md
index 8343dab835..6ab55921e3 100644
--- a/platform/android/CONTRIBUTING_MACOS.md
+++ b/platform/android/CONTRIBUTING_MACOS.md
@@ -1,15 +1,8 @@
# Contributing to the Android SDK on macOS
-Install Oracle JDK 7+ and Android Studio:
+## Install JDK 7+ and Android Studio:
- brew tap caskroom/cask
- brew install brew-cask
- brew cask install java
-
- brew cask install android-studio
-
-You can [download Android Studio instead of installing it with Homebrew, but you'll still need to `brew install java`](https://developer.android.com/sdk/index.html)
-for it to work.
+ Android Studio requires the Java Development Kit (JDK) which you can [download here](http://www.oracle.com/technetwork/java/javase/downloads/index.html). Once the JDK is installed, you can grab the [latest version of Android Studio here](https://developer.android.com/sdk/index.html) and install it following the on screen instructions.
Once Android Studio is installed, the [first time it's run it'll ask to install the Android SDK](http://developer.android.com/sdk/installing/index.html?pkg=studio) which you should do. While doing so in the Android SDK Manager make sure to also select and install the latest versions of "Android Support Repository" and "Android Support Library" from "Extras":
@@ -46,6 +39,15 @@ export ANDROID_HOME=/<installation location>/android-sdk-macosx
This environment variable configuration should go into a file that's read on
your shell's startup, like `~/.profile`.
+## Speeding up gradle builds
+
+To optimise you development machine for faster gradle builds create the following `/Users/name/.gradle/gradle.properties` file:
+
+```
+org.gradle.daemon=true
+org.gradle.jvmargs=-Xmx3072M
+```
+
## Running The TestApp
In order to run the TestApp on an emulator or device the Core GL portion needs to built first. Core GL is the common C++ based OpenGL engine that powers the maps for iOS, Android, and Qt in the project. To build it, open Terminal and run the following commands from the root of the `mapbox-gl-native` source code
diff --git a/platform/android/MapboxGLAndroidSDK/gradle.properties b/platform/android/MapboxGLAndroidSDK/gradle.properties
index 19c1370a6c..6aab985298 100644
--- a/platform/android/MapboxGLAndroidSDK/gradle.properties
+++ b/platform/android/MapboxGLAndroidSDK/gradle.properties
@@ -20,6 +20,3 @@ ANDROID_BUILD_SDK_VERSION=23
POM_NAME=Mapbox Android SDK
POM_ARTIFACT_ID=mapbox-android-sdk
POM_PACKAGING=aar
-
-# allows gradle to use more memory
-org.gradle.jvmargs=-Xmx2048M
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java
index b41eebff09..175fd57da4 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java
@@ -21,11 +21,14 @@ public class MarkerView extends Marker {
private MarkerViewManager markerViewManager;
+ private float width;
+ private float height;
+
private float anchorU;
private float anchorV;
- private float offsetX = -1;
- private float offsetY = -1;
+ private float offsetX = MapboxConstants.UNMEASURED;
+ private float offsetY = MapboxConstants.UNMEASURED;
private float infoWindowAnchorU;
private float infoWindowAnchorV;
@@ -41,6 +44,7 @@ public class MarkerView extends Marker {
private boolean selected;
+
/**
* Publicly hidden default constructor
*/
@@ -64,6 +68,22 @@ public class MarkerView extends Marker {
this.selected = baseMarkerViewOptions.selected;
}
+ float getWidth() {
+ return width;
+ }
+
+ void setWidth(float width) {
+ this.width = width;
+ }
+
+ float getHeight() {
+ return height;
+ }
+
+ void setHeight(float height) {
+ this.height = height;
+ }
+
/**
* Specifies the anchor being set on a particular point point of the MarkerView.
* <p>
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java
index ded3130715..cd333268a1 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java
@@ -130,14 +130,18 @@ public class MarkerViewManager {
PointF point = mapboxMap.getProjection().toScreenLocation(marker.getPosition());
if (marker.getOffsetX() == MapboxConstants.UNMEASURED) {
// ensure view is measured first
- if (convertView.getWidth() == 0) {
+ if (marker.getWidth() == 0) {
convertView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
+ if (convertView.getMeasuredWidth() != 0) {
+ marker.setWidth(convertView.getMeasuredWidth());
+ marker.setHeight(convertView.getMeasuredHeight());
+ }
}
- if (convertView.getMeasuredWidth() != 0) {
- int x = (int) (marker.getAnchorU() * convertView.getMeasuredWidth());
- int y = (int) (marker.getAnchorV() * convertView.getMeasuredHeight());
- marker.setOffset(x, y);
- }
+ }
+ if (marker.getWidth() != 0) {
+ int x = (int) (marker.getAnchorU() * marker.getWidth());
+ int y = (int) (marker.getAnchorV() * marker.getHeight());
+ marker.setOffset(x, y);
}
convertView.setX(point.x - marker.getOffsetX());
@@ -293,6 +297,17 @@ public class MarkerViewManager {
return markerViewMap.get(marker);
}
+ @Nullable
+ public MapboxMap.MarkerViewAdapter getViewAdapter(MarkerView markerView) {
+ MapboxMap.MarkerViewAdapter adapter = null;
+ for (MapboxMap.MarkerViewAdapter a : markerViewAdapters) {
+ if (a.getMarkerClass().equals(markerView.getClass())) {
+ adapter = a;
+ }
+ }
+ return adapter;
+ }
+
/**
* Remove a MarkerView from a map.
* <p>
@@ -311,7 +326,7 @@ public class MarkerViewManager {
if (adapter.getMarkerClass().equals(marker.getClass())) {
if (adapter.prepareViewForReuse(marker, viewHolder)) {
// reset offset for reuse
- marker.setOffset(-1, -1);
+ marker.setOffset(MapboxConstants.UNMEASURED, MapboxConstants.UNMEASURED);
adapter.releaseView(viewHolder);
}
}
@@ -429,21 +444,6 @@ public class MarkerViewManager {
}
}
- adaptedView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(final View v) {
- boolean clickHandled = false;
- if (onMarkerViewClickListener != null) {
- clickHandled = onMarkerViewClickListener.onMarkerClick(marker, v, adapter);
- }
-
- if (!clickHandled) {
- ensureInfoWindowOffset(marker);
- select(marker, v, adapter);
- }
- }
- });
-
marker.setMapboxMap(mapboxMap);
markerViewMap.put(marker, adaptedView);
if (convertView == null) {
@@ -460,6 +460,26 @@ public class MarkerViewManager {
update();
}
+ public void onClickMarkerView(MarkerView markerView) {
+ boolean clickHandled = false;
+
+ MapboxMap.MarkerViewAdapter adapter = getViewAdapter(markerView);
+ View view = getView(markerView);
+ if (adapter == null || view == null) {
+ // not a valid state
+ return;
+ }
+
+ if (onMarkerViewClickListener != null) {
+ clickHandled = onMarkerViewClickListener.onMarkerClick(markerView, view, adapter);
+ }
+
+ if (!clickHandled) {
+ ensureInfoWindowOffset(markerView);
+ select(markerView, view, adapter);
+ }
+ }
+
//TODO: This whole method is a stopgap for: https://github.com/mapbox/mapbox-gl-native/issues/5384
public void ensureInfoWindowOffset(MarkerView marker) {
View view = null;
@@ -476,15 +496,19 @@ public class MarkerViewManager {
}
if (view != null) {
- //Ensure the marker's view is measured first
- if (view.getMeasuredWidth() == 0) {
- view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
+ if (marker.getWidth() == 0) {
+ if(view.getMeasuredWidth()==0) {
+ //Ensure the marker's view is measured first
+ view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
+ }
+ marker.setWidth(view.getMeasuredWidth());
+ marker.setHeight(view.getMeasuredHeight());
}
// update position on map
- if (marker.getOffsetX() == -1) {
- int x = (int) (marker.getAnchorU() * view.getMeasuredWidth());
- int y = (int) (marker.getAnchorV() * view.getMeasuredHeight());
+ if (marker.getOffsetX() == MapboxConstants.UNMEASURED) {
+ int x = (int) (marker.getAnchorU() * marker.getWidth());
+ int y = (int) (marker.getAnchorV() * marker.getHeight());
marker.setOffset(x, y);
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java
index f65d012c49..3888abc041 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java
@@ -171,10 +171,10 @@ public final class CameraPosition implements Parcelable {
public Builder(CameraUpdateFactory.CameraPositionUpdate update) {
super();
if (update != null) {
- bearing(update.getBearing());
- target(update.getTarget());
- tilt(update.getTilt());
- zoom(update.getZoom());
+ bearing = update.getBearing();
+ target = update.getTarget();
+ tilt = update.getTilt();
+ zoom = update.getZoom();
}
}
@@ -202,7 +202,7 @@ public final class CameraPosition implements Parcelable {
super();
if (nativeCameraValues != null && nativeCameraValues.length == 5) {
target(new LatLng(nativeCameraValues[0], nativeCameraValues[1]));
- bearing(-nativeCameraValues[2]);
+ bearing(nativeCameraValues[2]);
tilt(nativeCameraValues[3]);
zoom((float) nativeCameraValues[4]);
}
@@ -217,7 +217,7 @@ public final class CameraPosition implements Parcelable {
public Builder bearing(double bearing) {
double direction = bearing;
- while (direction > 360) {
+ while (direction >= 360) {
direction -= 360;
}
while (direction < 0) {
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java
index b12dea6437..db05486bc2 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java
@@ -200,16 +200,16 @@ public final class CameraUpdateFactory {
private LatLngBounds bounds;
private RectF padding;
- public CameraBoundsUpdate(LatLngBounds bounds, RectF padding) {
+ CameraBoundsUpdate(LatLngBounds bounds, RectF padding) {
this.bounds = bounds;
this.padding = padding;
}
- public CameraBoundsUpdate(LatLngBounds bounds, int[] padding) {
+ CameraBoundsUpdate(LatLngBounds bounds, int[] padding) {
this(bounds, new RectF(padding[0], padding[1], padding[2], padding[3]));
}
- public CameraBoundsUpdate(LatLngBounds bounds, int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) {
+ CameraBoundsUpdate(LatLngBounds bounds, int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) {
this(bounds, new int[]{paddingLeft, paddingTop, paddingRight, paddingBottom});
}
@@ -283,7 +283,7 @@ public final class CameraUpdateFactory {
private float x;
private float y;
- public CameraMoveUpdate(float x, float y) {
+ CameraMoveUpdate(float x, float y) {
this.x = x;
this.y = y;
}
@@ -315,14 +315,14 @@ public final class CameraUpdateFactory {
@IntDef({ZOOM_IN, ZOOM_OUT, ZOOM_BY, ZOOM_TO, ZOOM_TO_POINT})
@Retention(RetentionPolicy.SOURCE)
- public @interface Type {
+ @interface Type {
}
- public static final int ZOOM_IN = 0;
- public static final int ZOOM_OUT = 1;
- public static final int ZOOM_BY = 2;
- public static final int ZOOM_TO = 3;
- public static final int ZOOM_TO_POINT = 4;
+ static final int ZOOM_IN = 0;
+ static final int ZOOM_OUT = 1;
+ static final int ZOOM_BY = 2;
+ static final int ZOOM_TO = 3;
+ static final int ZOOM_TO_POINT = 4;
@Type
private final int type;
@@ -364,7 +364,7 @@ public final class CameraUpdateFactory {
return y;
}
- public double transformZoom(double currentZoom) {
+ double transformZoom(double currentZoom) {
switch (getType()) {
case CameraUpdateFactory.ZoomUpdate.ZOOM_IN:
currentZoom++;
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java
index 10ebecee27..10d5c55044 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java
@@ -115,6 +115,7 @@ public class MapboxConstants {
public static final String STATE_COMPASS_MARGIN_TOP = "compassMarginTop";
public static final String STATE_COMPASS_MARGIN_RIGHT = "compassMarginRight";
public static final String STATE_COMPASS_MARGIN_BOTTOM = "compassMarginBottom";
+ public static final String STATE_COMPASS_FADE_WHEN_FACING_NORTH = "compassFade";
public static final String STATE_LOGO_GRAVITY = "logoGravity";
public static final String STATE_LOGO_MARGIN_LEFT = "logoMarginLeft";
public static final String STATE_LOGO_MARGIN_TOP = "logoMarginTop";
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CompassViewSettings.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CompassViewSettings.java
new file mode 100644
index 0000000000..3e1b14d641
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CompassViewSettings.java
@@ -0,0 +1,21 @@
+package com.mapbox.mapboxsdk.maps;
+
+/**
+ * Settings for the overlain views of a MapboxMap. Used by UiSettings.
+ */
+class CompassViewSettings extends ViewSettings{
+
+ private boolean fadeFacingNorth = true;
+
+ public CompassViewSettings() {
+ super();
+ }
+
+ public boolean isFadeFacingNorth() {
+ return fadeFacingNorth;
+ }
+
+ public void setFadeFacingNorth(boolean fadeFacingNorth) {
+ this.fadeFacingNorth = fadeFacingNorth;
+ }
+}
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 0735c4c197..32b327e8d0 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
@@ -18,7 +18,6 @@ import android.graphics.Canvas;
import android.graphics.PointF;
import android.graphics.RectF;
import android.graphics.SurfaceTexture;
-import android.graphics.drawable.ColorDrawable;
import android.location.Location;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
@@ -51,11 +50,9 @@ import android.view.TextureView;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
-import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.FrameLayout;
import android.widget.ImageView;
-import android.widget.ListView;
import android.widget.ZoomButtonsController;
import com.almeros.android.multitouch.gesturedetectors.RotateGestureDetector;
@@ -332,6 +329,7 @@ public class MapView extends FrameLayout {
int tenDp = (int) getResources().getDimension(R.dimen.ten_dp);
uiSettings.setCompassMargins(tenDp, tenDp, tenDp, tenDp);
}
+ uiSettings.setCompassFadeFacingNorth(options.getCompassFadeFacingNorth());
// Logo
uiSettings.setLogoEnabled(options.getLogoEnabled());
@@ -417,6 +415,7 @@ public class MapView extends FrameLayout {
savedInstanceState.getInt(MapboxConstants.STATE_COMPASS_MARGIN_TOP),
savedInstanceState.getInt(MapboxConstants.STATE_COMPASS_MARGIN_RIGHT),
savedInstanceState.getInt(MapboxConstants.STATE_COMPASS_MARGIN_BOTTOM));
+ uiSettings.setCompassFadeFacingNorth(savedInstanceState.getBoolean(MapboxConstants.STATE_COMPASS_FADE_WHEN_FACING_NORTH));
// Logo
uiSettings.setLogoEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_LOGO_ENABLED));
@@ -554,6 +553,7 @@ public class MapView extends FrameLayout {
outState.putInt(MapboxConstants.STATE_COMPASS_MARGIN_TOP, uiSettings.getCompassMarginTop());
outState.putInt(MapboxConstants.STATE_COMPASS_MARGIN_BOTTOM, uiSettings.getCompassMarginBottom());
outState.putInt(MapboxConstants.STATE_COMPASS_MARGIN_RIGHT, uiSettings.getCompassMarginRight());
+ outState.putBoolean(MapboxConstants.STATE_COMPASS_FADE_WHEN_FACING_NORTH, uiSettings.isCompassFadeWhenFacingNorth());
// UiSettings - Logo
outState.putInt(MapboxConstants.STATE_LOGO_GRAVITY, uiSettings.getLogoGravity());
@@ -1017,12 +1017,12 @@ public class MapView extends FrameLayout {
icon = IconFactory.getInstance(getContext()).defaultMarker();
Bitmap bitmap = icon.getBitmap();
averageIconHeight = averageIconHeight + (bitmap.getHeight() / 2 - averageIconHeight) / iconSize;
- averageIconWidth = averageIconHeight + (bitmap.getWidth() - averageIconHeight) / iconSize;
+ averageIconWidth = averageIconWidth + (bitmap.getWidth() - averageIconWidth) / iconSize;
marker.setIcon(icon);
} else {
Bitmap bitmap = icon.getBitmap();
averageIconHeight = averageIconHeight + (bitmap.getHeight() - averageIconHeight) / iconSize;
- averageIconWidth = averageIconHeight + (bitmap.getWidth() - averageIconHeight) / iconSize;
+ averageIconWidth = averageIconWidth + (bitmap.getWidth() - averageIconWidth) / iconSize;
}
if (!icons.contains(icon)) {
@@ -1037,6 +1037,27 @@ public class MapView extends FrameLayout {
return icon;
}
+ Icon loadIconForMarkerView(MarkerView marker) {
+ Icon icon = marker.getIcon();
+ int iconSize = icons.size() + 1;
+ if (icon == null) {
+ icon = IconFactory.getInstance(getContext()).defaultMarkerView();
+ marker.setIcon(icon);
+ }
+ Bitmap bitmap = icon.getBitmap();
+ averageIconHeight = averageIconHeight + (bitmap.getHeight() - averageIconHeight) / iconSize;
+ averageIconWidth = averageIconWidth + (bitmap.getWidth() - averageIconWidth) / iconSize;
+ if (!icons.contains(icon)) {
+ icons.add(icon);
+ } else {
+ Icon oldIcon = icons.get(icons.indexOf(icon));
+ if (!oldIcon.getBitmap().sameAs(icon.getBitmap())) {
+ throw new IconBitmapChangedException();
+ }
+ }
+ return icon;
+ }
+
void loadIcon(Icon icon) {
if (destroyed) {
return;
@@ -1323,7 +1344,7 @@ public class MapView extends FrameLayout {
return;
}
nativeMapView.cancelTransitions();
- nativeMapView.jumpTo(Math.toRadians(-bearing), center, Math.toRadians(pitch), zoom);
+ nativeMapView.jumpTo(bearing, center, pitch, zoom);
}
void easeTo(double bearing, LatLng center, long duration, double pitch, double zoom, boolean easingInterpolator, @Nullable final MapboxMap.CancelableCallback cancelableCallback) {
@@ -1347,7 +1368,7 @@ public class MapView extends FrameLayout {
});
}
- nativeMapView.easeTo(Math.toRadians(-bearing), center, duration, Math.toRadians(pitch), zoom, easingInterpolator);
+ nativeMapView.easeTo(bearing, center, duration, pitch, zoom, easingInterpolator);
}
void flyTo(double bearing, LatLng center, long duration, double pitch, double zoom, @Nullable final MapboxMap.CancelableCallback cancelableCallback) {
@@ -1371,7 +1392,7 @@ public class MapView extends FrameLayout {
});
}
- nativeMapView.flyTo(Math.toRadians(-bearing), center, duration, Math.toRadians(pitch), zoom);
+ nativeMapView.flyTo(bearing, center, duration, pitch, zoom);
}
private void adjustTopOffsetPixels() {
@@ -1878,9 +1899,10 @@ public class MapView extends FrameLayout {
if (annotation instanceof Marker) {
if (annotation.getId() == newSelectedMarkerId) {
if (selectedMarkers.isEmpty() || !selectedMarkers.contains(annotation)) {
- // only handle click if no marker view is available
if (!(annotation instanceof MarkerView)) {
mapboxMap.selectMarker((Marker) annotation);
+ } else {
+ mapboxMap.getMarkerViewManager().onClickMarkerView((MarkerView) annotation);
}
}
break;
@@ -2717,6 +2739,10 @@ public class MapView extends FrameLayout {
setWidgetMargins(compassView, left, top, right, bottom);
}
+ void setCompassFadeFacingNorth(boolean compassFadeFacingNorth) {
+ compassView.fadeCompassViewFacingNorth(compassFadeFacingNorth);
+ }
+
//
// Logo
//
@@ -2869,14 +2895,15 @@ public class MapView extends FrameLayout {
// Called when someone presses the attribution icon
@Override
- public void onClick(View v) {
- Context context = v.getContext();
- String[] items = context.getResources().getStringArray(R.array.attribution_names);
- AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.AttributionAlertDialogStyle);
+ public void onClick(View view) {
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(mapView.getContext(), R.style.TelemAlertDialogStyle);
builder.setTitle(R.string.attributionsDialogTitle);
- builder.setAdapter(new ArrayAdapter<>(context, R.layout.attribution_list_item, items), this);
- AlertDialog dialog = builder.show();
- dialog.getWindow().setBackgroundDrawable(new ColorDrawable(mapView.getAttributionTintColor()));
+ String[] items = mapView.getContext().getResources().getStringArray(R.array.attribution_names);
+ builder.setAdapter(new ArrayAdapter<>(mapView.getContext(), R.layout.attribution_list_item, items), this);
+ AlertDialog attributionDialog = builder.show();
+
+ // TODO Change listview text color to mapView.getAttributionTintColor()
}
// Called when someone selects an attribution, 'Improve this map' adds location data to the url
@@ -2884,45 +2911,38 @@ public class MapView extends FrameLayout {
public void onClick(DialogInterface dialog, int which) {
final Context context = ((Dialog) dialog).getContext();
if (which == ATTRIBUTION_INDEX_TELEMETRY_SETTINGS) {
-
- int array = R.array.attribution_telemetry_options;
- if (MapboxEventManager.getMapboxEventManager().isTelemetryEnabled()) {
- array = R.array.attribution_telemetry_options_already_participating;
- }
- String[] items = context.getResources().getStringArray(array);
- AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.AttributionAlertDialogStyle);
+ AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.TelemAlertDialogStyle);
builder.setTitle(R.string.attributionTelemetryTitle);
- LayoutInflater factory = LayoutInflater.from(context);
- View content = factory.inflate(R.layout.attribution_telemetry_view, null);
-
- ListView lv = (ListView) content.findViewById(R.id.telemetryOptionsList);
- lv.setAdapter(new ArrayAdapter<String>(context, R.layout.attribution_list_item, items));
- lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
-
- builder.setView(content);
- final AlertDialog telemDialog = builder.show();
- lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ builder.setMessage(R.string.attributionTelemetryMessage);
+ builder.setPositiveButton(R.string.attributionTelemetryPositive, new DialogInterface.OnClickListener() {
@Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- switch (position) {
- case 0:
- String url = context.getResources().getStringArray(R.array.attribution_links)[3];
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setData(Uri.parse(url));
- context.startActivity(intent);
- telemDialog.cancel();
- return;
- case 1:
- MapboxEventManager.getMapboxEventManager().setTelemetryEnabled(false);
- telemDialog.cancel();
- return;
- case 2:
- MapboxEventManager.getMapboxEventManager().setTelemetryEnabled(true);
- telemDialog.cancel();
- return;
- }
+ public void onClick(DialogInterface dialog, int which) {
+ MapboxEventManager.getMapboxEventManager().setTelemetryEnabled(true);
+ dialog.cancel();
+ }
+ });
+ builder.setNeutralButton(R.string.attributionTelemetryNeutral, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ String url = context.getResources().getStringArray(R.array.attribution_links)[3];
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(Uri.parse(url));
+ context.startActivity(intent);
+ dialog.cancel();
+ }
+ });
+ builder.setNegativeButton(R.string.attributionTelemetryNegative, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ MapboxEventManager.getMapboxEventManager().setTelemetryEnabled(false);
+ dialog.cancel();
}
});
+
+ AlertDialog telemDialog = builder.show();
+ telemDialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(mapView.getAttributionTintColor());
+ telemDialog.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(mapView.getAttributionTintColor());
+ telemDialog.getButton(AlertDialog.BUTTON_NEUTRAL).setTextColor(mapView.getAttributionTintColor());
return;
}
String url = context.getResources().getStringArray(R.array.attribution_links)[which];
@@ -2977,162 +2997,180 @@ public class MapView extends FrameLayout {
}
/**
- * <p>
- * This {@link MapChange} is triggered whenever the currently displayed map region is about to changing
+ * This event is triggered whenever the currently displayed map region is about to changing
* without an animation.
- * </p>
* <p>
- * This event is followed by a series of {@link MapView#REGION_IS_CHANGING} and ends
- * with {@link MapView#REGION_DID_CHANGE}.
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
* </p>
*
+ * @see MapChange
* @see MapView.OnMapChangedListener
*/
public static final int REGION_WILL_CHANGE = 0;
/**
- * <p>
- * This {@link MapChange} is triggered whenever the currently displayed map region is about to changing
+ * This event is triggered whenever the currently displayed map region is about to changing
* with an animation.
- * </p>
- * <p>
- * This event is followed by a series of {@link MapView#REGION_IS_CHANGING} and ends
- * with {@link MapView#REGION_DID_CHANGE_ANIMATED}.
+ * <p
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}
* </p>
*
+ * @see MapChange
* @see MapView.OnMapChangedListener
*/
public static final int REGION_WILL_CHANGE_ANIMATED = 1;
/**
+ * This event is triggered whenever the currently displayed map region is changing.
* <p>
- * This {@link MapChange} is triggered whenever the currently displayed map region is changing.
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
* </p>
*
+ * @see MapChange
* @see MapView.OnMapChangedListener
*/
public static final int REGION_IS_CHANGING = 2;
/**
- * <p>
- * This {@link MapChange} is triggered whenever the currently displayed map region finished changing
+ * This event is triggered whenever the currently displayed map region finished changing
* without an animation.
+ * <p>
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
* </p>
*
+ * @see MapChange
* @see MapView.OnMapChangedListener
*/
public static final int REGION_DID_CHANGE = 3;
/**
- * <p>
- * This {@link MapChange} is triggered whenever the currently displayed map region finished changing
+ * This event is triggered whenever the currently displayed map region finished changing
* with an animation.
+ * <p>
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
* </p>
*
+ * @see MapChange
* @see MapView.OnMapChangedListener
*/
public static final int REGION_DID_CHANGE_ANIMATED = 4;
/**
+ * This event is triggered when the map is about to start loading a new map style.
* <p>
- * This {@link MapChange} is triggered when the map is about to start loading a new map style.
- * </p>
- * <p>
- * This event is followed by {@link MapView#DID_FINISH_LOADING_MAP} or
- * {@link MapView#DID_FAIL_LOADING_MAP}.
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
* </p>
*
+ * @see MapChange
* @see MapView.OnMapChangedListener
*/
public static final int WILL_START_LOADING_MAP = 5;
/**
+ * This is triggered when the map has successfully loaded a new map style.
* <p>
- * This {@link MapChange} is triggered when the map has successfully loaded a new map style.
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
* </p>
*
+ * @see MapChange
* @see MapView.OnMapChangedListener
*/
public static final int DID_FINISH_LOADING_MAP = 6;
/**
- * <p>
- * This {@link MapChange} is currently not implemented.
- * </p>
- * <p>
* This event is triggered when the map has failed to load a new map style.
+ * <p>
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
* </p>
*
+ * @see MapChange
* @see MapView.OnMapChangedListener
*/
public static final int DID_FAIL_LOADING_MAP = 7;
/**
+ * This event is triggered when the map will start rendering a frame.
* <p>
- * This {@link MapChange} is currently not implemented.
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
* </p>
*
+ * @see MapChange
* @see MapView.OnMapChangedListener
*/
public static final int WILL_START_RENDERING_FRAME = 8;
/**
+ * This event is triggered when the map finished rendering a frame.
* <p>
- * This {@link MapChange} is currently not implemented.
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
* </p>
*
+ * @see MapChange
* @see MapView.OnMapChangedListener
*/
public static final int DID_FINISH_RENDERING_FRAME = 9;
/**
+ * This event is triggered when the map finished rendeirng the frame fully.
* <p>
- * This {@link MapChange} is currently not implemented.
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
* </p>
*
+ * @see MapChange
* @see MapView.OnMapChangedListener
*/
public static final int DID_FINISH_RENDERING_FRAME_FULLY_RENDERED = 10;
/**
+ * This event is triggered when the map will start rendering the map.
* <p>
- * This {@link MapChange} is currently not implemented.
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
* </p>
*
+ * @see MapChange
* @see MapView.OnMapChangedListener
*/
public static final int WILL_START_RENDERING_MAP = 11;
/**
+ * This event is triggered when the map finished rendering the map.
* <p>
- * This {@link MapChange} is currently not implemented.
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
* </p>
*
+ * @see MapChange
* @see MapView.OnMapChangedListener
*/
public static final int DID_FINISH_RENDERING_MAP = 12;
/**
+ * This event is triggered when the map is fully rendered.
* <p>
- * This {@link MapChange} is currently not implemented.
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
* </p>
*
+ * @see MapChange
* @see MapView.OnMapChangedListener
*/
public static final int DID_FINISH_RENDERING_MAP_FULLY_RENDERED = 13;
/**
+ * This {@link MapChange} is triggered when a style has finished loading.
* <p>
- * This {@link MapChange} is triggered when a style is loaded
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
* </p>
*
+ * @see MapChange
* @see MapView.OnMapChangedListener
*/
public static final int DID_FINISH_LOADING_STYLE = 14;
/**
* Interface definition for a callback to be invoked when the displayed map view changes.
+ * <p>
+ * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
+ * </p>
*
* @see MapView#addOnMapChangedListener(OnMapChangedListener)
* @see MapView.MapChange
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 ea4bb4eafa..b1f0984e3c 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
@@ -22,7 +22,6 @@ import com.mapbox.mapboxsdk.annotations.Annotation;
import com.mapbox.mapboxsdk.annotations.BaseMarkerOptions;
import com.mapbox.mapboxsdk.annotations.BaseMarkerViewOptions;
import com.mapbox.mapboxsdk.annotations.Icon;
-import com.mapbox.mapboxsdk.annotations.IconFactory;
import com.mapbox.mapboxsdk.annotations.InfoWindow;
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
@@ -389,15 +388,16 @@ public class MapboxMap {
*/
@UiThread
public final void moveCamera(CameraUpdate update, MapboxMap.CancelableCallback callback) {
- // dismiss tracking, moving camera is equal to a gesture
-
cameraPosition = update.getCameraPosition(this);
mapView.resetTrackingModesIfRequired(cameraPosition);
mapView.jumpTo(cameraPosition.bearing, cameraPosition.target, cameraPosition.tilt, cameraPosition.zoom);
if (callback != null) {
callback.onFinish();
}
- invalidateCameraPosition();
+
+ if (onCameraChangeListener != null) {
+ onCameraChangeListener.onCameraChange(this.cameraPosition);
+ }
}
/**
@@ -560,8 +560,6 @@ public class MapboxMap {
*/
@UiThread
public final void animateCamera(CameraUpdate update, int durationMs, final MapboxMap.CancelableCallback callback) {
- // dismiss tracking, moving camera is equal to a gesture
-
cameraPosition = update.getCameraPosition(this);
mapView.resetTrackingModesIfRequired(cameraPosition);
mapView.flyTo(cameraPosition.bearing, cameraPosition.target, getDurationNano(durationMs), cameraPosition.tilt,
@@ -602,15 +600,17 @@ public class MapboxMap {
* Invalidates the current camera position by reconstructing it from mbgl
*/
private void invalidateCameraPosition() {
- invalidCameraPosition = false;
+ if(invalidCameraPosition) {
+ invalidCameraPosition = false;
- CameraPosition cameraPosition = mapView.invalidateCameraPosition();
- if (cameraPosition != null) {
- this.cameraPosition = cameraPosition;
- }
+ CameraPosition cameraPosition = mapView.invalidateCameraPosition();
+ if (cameraPosition != null) {
+ this.cameraPosition = cameraPosition;
+ }
- if (onCameraChangeListener != null) {
- onCameraChangeListener.onCameraChange(this.cameraPosition);
+ if (onCameraChangeListener != null) {
+ onCameraChangeListener.onCameraChange(this.cameraPosition);
+ }
}
}
@@ -1404,12 +1404,7 @@ public class MapboxMap {
private MarkerView prepareViewMarker(BaseMarkerViewOptions markerViewOptions) {
MarkerView marker = markerViewOptions.getMarker();
-
- Icon icon = markerViewOptions.getIcon();
- if (icon == null) {
- icon = IconFactory.getInstance(mapView.getContext()).defaultMarkerView();
- }
- marker.setIcon(icon);
+ mapView.loadIconForMarkerView(marker);
return marker;
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java
index 352b3ad12a..a54d246913 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java
@@ -44,6 +44,7 @@ public class MapboxMapOptions implements Parcelable {
private boolean debugActive;
private boolean compassEnabled = true;
+ private boolean fadeCompassFacingNorth = true;
private int compassGravity = Gravity.TOP | Gravity.END;
private int[] compassMargins;
@@ -98,6 +99,7 @@ public class MapboxMapOptions implements Parcelable {
compassEnabled = in.readByte() != 0;
compassGravity = in.readInt();
compassMargins = in.createIntArray();
+ fadeCompassFacingNorth = in.readByte() != 0;
logoEnabled = in.readByte() != 0;
logoGravity = in.readInt();
@@ -193,6 +195,7 @@ public class MapboxMapOptions implements Parcelable {
, ((int) typedArray.getDimension(R.styleable.MapView_compass_margin_top, DIMENSION_TEN_DP * screenDensity))
, ((int) typedArray.getDimension(R.styleable.MapView_compass_margin_right, DIMENSION_TEN_DP * screenDensity))
, ((int) typedArray.getDimension(R.styleable.MapView_compass_margin_bottom, DIMENSION_TEN_DP * screenDensity))});
+ mapboxMapOptions.compassFadesWhenFacingNorth(typedArray.getBoolean(R.styleable.MapView_compass_fade_facing_north, true));
mapboxMapOptions.logoEnabled(typedArray.getBoolean(R.styleable.MapView_logo_enabled, true));
mapboxMapOptions.logoGravity(typedArray.getInt(R.styleable.MapView_logo_gravity, Gravity.BOTTOM | Gravity.START));
@@ -359,6 +362,20 @@ public class MapboxMapOptions implements Parcelable {
}
/**
+ * Specifies if the compass fades to invisible when facing north.
+ * <p>
+ * By default this value is true.
+ * </p>
+ *
+ * @param compassFadeWhenFacingNorth true is compass fades to invisble
+ * @return This
+ */
+ public MapboxMapOptions compassFadesWhenFacingNorth(boolean compassFadeWhenFacingNorth) {
+ this.fadeCompassFacingNorth = compassFadeWhenFacingNorth;
+ return this;
+ }
+
+ /**
* Specifies the visibility state of a logo for a map view.
*
* @param enabled True and logo is shown
@@ -680,6 +697,15 @@ public class MapboxMapOptions implements Parcelable {
}
/**
+ * Get the current configured state for fading the compass when facing north.
+ *
+ * @return True if compass fades to invisible when facing north
+ */
+ public boolean getCompassFadeFacingNorth() {
+ return fadeCompassFacingNorth;
+ }
+
+ /**
* Get the current configured visibility state for compass for a map view.
*
* @return Visibility state of the compass
@@ -934,6 +960,7 @@ public class MapboxMapOptions implements Parcelable {
dest.writeByte((byte) (compassEnabled ? 1 : 0));
dest.writeInt(compassGravity);
dest.writeIntArray(compassMargins);
+ dest.writeByte((byte) (fadeCompassFacingNorth ? 1 : 0));
dest.writeByte((byte) (logoEnabled ? 1 : 0));
dest.writeInt(logoGravity);
@@ -979,6 +1006,7 @@ public class MapboxMapOptions implements Parcelable {
if (debugActive != options.debugActive) return false;
if (compassEnabled != options.compassEnabled) return false;
+ if (fadeCompassFacingNorth != options.fadeCompassFacingNorth) return false;
if (compassGravity != options.compassGravity) return false;
if (logoEnabled != options.logoEnabled) return false;
if (logoGravity != options.logoGravity) return false;
@@ -1022,6 +1050,7 @@ public class MapboxMapOptions implements Parcelable {
int result = cameraPosition != null ? cameraPosition.hashCode() : 0;
result = 31 * result + (debugActive ? 1 : 0);
result = 31 * result + (compassEnabled ? 1 : 0);
+ result = 31 * result + (fadeCompassFacingNorth ? 1 : 0);
result = 31 * result + compassGravity;
result = 31 * result + Arrays.hashCode(compassMargins);
result = 31 * result + (logoEnabled ? 1 : 0);
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 7753787fd6..4e0ce33c5b 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
@@ -9,12 +9,14 @@ import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.DisplayMetrics;
+import android.util.Log;
import android.view.Surface;
import com.mapbox.mapboxsdk.annotations.Icon;
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.Polygon;
import com.mapbox.mapboxsdk.annotations.Polyline;
+import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.ProjectedMeters;
import com.mapbox.mapboxsdk.offline.OfflineManager;
@@ -151,13 +153,17 @@ final class NativeMapView {
}
if (width > 65535) {
- throw new IllegalArgumentException(
- "width cannot be greater than 65535.");
+ // we have seen edge cases where devices return incorrect values #6111
+ Log.e(MapboxConstants.TAG, "Device returned an out of range width size, " +
+ "capping value at 65535 instead of " + width);
+ width = 65535;
}
if (height > 65535) {
- throw new IllegalArgumentException(
- "height cannot be greater than 65535.");
+ // we have seen edge cases where devices return incorrect values #6111
+ Log.e(MapboxConstants.TAG, "Device returned an out of range height size, " +
+ "capping value at 65535 instead of " + height);
+ height = 65535;
}
nativeViewResize(nativeMapViewPtr, width, height);
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java
index a06f449309..d6ad80d11e 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java
@@ -15,7 +15,7 @@ public class UiSettings {
private MapView mapView;
- private ViewSettings compassSettings;
+ private CompassViewSettings compassSettings;
private ViewSettings logoSettings;
private ViewSettings attributionSettings;
@@ -39,7 +39,7 @@ public class UiSettings {
UiSettings(@NonNull MapView mapView) {
this.mapView = mapView;
- this.compassSettings = new ViewSettings();
+ this.compassSettings = new CompassViewSettings();
this.logoSettings = new ViewSettings();
this.attributionSettings = new ViewSettings();
}
@@ -86,6 +86,28 @@ public class UiSettings {
}
/**
+ * Enables or disables fading of the compass when facing north.
+ * <p>
+ * By default this feature is enabled
+ * </p>
+ *
+ * @param compassFadeFacingNorth True to enable the fading animation; false to disable it
+ */
+ public void setCompassFadeFacingNorth(boolean compassFadeFacingNorth) {
+ compassSettings.setFadeFacingNorth(compassFadeFacingNorth);
+ mapView.setCompassFadeFacingNorth(compassFadeFacingNorth);
+ }
+
+ /**
+ * Returns whether the compass performs a fading animation out when facing north.
+ *
+ * @return True if the compass will fade, false if it remains visible
+ */
+ public boolean isCompassFadeWhenFacingNorth(){
+ return compassSettings.isFadeFacingNorth();
+ }
+
+ /**
* Returns the gravity value of the CompassView
*
* @return The gravity
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java
index e469eb14ab..163c7a610a 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java
@@ -15,18 +15,24 @@ import com.mapbox.mapboxsdk.R;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import java.lang.ref.WeakReference;
-import java.util.Timer;
-import java.util.TimerTask;
/**
- * UI element overlaid on a map to show the map's bearing
- * when it isn't true north (0.0). Tapping the compass resets the bearing to true
- * north and hides the compass.
+ * UI element overlaid on a map to show the map's bearing when it isn't true north (0.0). Tapping
+ * the compass resets the bearing to true north and hides the compass.
+ * <p>
+ * You can change the behaviour of this View during initialisation with
+ * {@link com.mapbox.mapboxsdk.maps.MapboxMapOptions}, and xml attributes. While running you can
+ * use {@link com.mapbox.mapboxsdk.maps.UiSettings}.
+ * </p>
*/
-public final class CompassView extends ImageView {
+public final class CompassView extends ImageView implements Runnable {
- private Timer northTimer;
- private double direction = 0.0f;
+ private static final long TIME_WAIT_IDLE = 500;
+ private static final long TIME_FADE_ANIMATION = TIME_WAIT_IDLE;
+ private static final long TIME_MAP_NORTH_ANIMATION = 150;
+
+ private double direction = 0.0;
+ private boolean fadeCompassViewFacingNorth = true;
private ViewPropertyAnimatorCompat fadeAnimator;
public CompassView(Context context) {
@@ -45,8 +51,6 @@ public final class CompassView extends ImageView {
}
private void initialize(Context context) {
-
- // View configuration
setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.compass));
setContentDescription(getResources().getString(R.string.compassContentDescription));
setEnabled(false);
@@ -57,105 +61,98 @@ public final class CompassView extends ImageView {
setLayoutParams(lp);
}
- public void setMapboxMap(@NonNull MapboxMap mapboxMap){
- setOnClickListener(new CompassClickListener(mapboxMap));
+ public void setMapboxMap(@NonNull MapboxMap mapboxMap) {
+ setOnClickListener(new CompassClickListener(mapboxMap, this));
+ }
+
+ private void resetAnimation() {
+ if (fadeAnimator != null) {
+ fadeAnimator.cancel();
+ }
+ fadeAnimator = null;
+ }
+
+ public boolean isHidden() {
+ return fadeCompassViewFacingNorth && isFacingNorth();
+ }
+
+ public boolean isFacingNorth() {
+ // increase range more than just 0.0
+ return direction >= 359.0 || direction <= 1.0;
}
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
- if (enabled) {
- if (direction != 0.0) {
- if (northTimer != null) {
- northTimer.cancel();
- northTimer = null;
- }
- if (fadeAnimator != null) {
- fadeAnimator.cancel();
- }
- fadeAnimator = null;
- setAlpha(1.0f);
- setVisibility(View.VISIBLE);
- }
+ if (enabled && !isHidden()) {
+ resetAnimation();
+ setAlpha(1.0f);
+ setVisibility(View.VISIBLE);
} else {
- if (northTimer != null) {
- northTimer.cancel();
- northTimer = null;
- }
- if (fadeAnimator != null) {
- fadeAnimator.cancel();
- }
- fadeAnimator = null;
+ resetAnimation();
+ setAlpha(0.0f);
setVisibility(View.INVISIBLE);
}
}
- public void update(double direction) {
+ public void update(final double direction) {
this.direction = direction;
- setRotation((float) direction);
if (!isEnabled()) {
return;
}
- if (direction == 0.0) {
- if (getVisibility() == View.INVISIBLE) {
+ if (isHidden()) {
+ if (getVisibility() == View.INVISIBLE || fadeAnimator != null) {
return;
}
-
- if (northTimer == null) {
- if (fadeAnimator != null) {
- fadeAnimator.cancel();
- }
- fadeAnimator = null;
-
- northTimer = new Timer("CompassView North timer");
- northTimer.schedule(new TimerTask() {
- @Override
- public void run() {
- post(new Runnable() {
- @Override
- public void run() {
- setAlpha(1.0f);
- fadeAnimator = ViewCompat.animate(CompassView.this).alpha(0.0f).setDuration(1000).withLayer();
- fadeAnimator.setListener(new ViewPropertyAnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(View view) {
- setVisibility(View.INVISIBLE);
- northTimer = null;
- }
- });
- }
- });
- }
- }, 1000);
- }
+ postDelayed(this, TIME_WAIT_IDLE);
+ return;
} else {
- if (northTimer != null) {
- northTimer.cancel();
- northTimer = null;
- }
- if (fadeAnimator != null) {
- fadeAnimator.cancel();
- }
+ resetAnimation();
setAlpha(1.0f);
setVisibility(View.VISIBLE);
}
+
+ setRotation((float) direction);
+ }
+
+ public void fadeCompassViewFacingNorth(boolean compassFadeFacingNorth) {
+ fadeCompassViewFacingNorth = compassFadeFacingNorth;
+ }
+
+ @Override
+ public void run() {
+ if (isFacingNorth() && fadeCompassViewFacingNorth) {
+ resetAnimation();
+ fadeAnimator = ViewCompat.animate(CompassView.this).alpha(0.0f).setDuration(TIME_FADE_ANIMATION).withLayer();
+ fadeAnimator.setListener(new ViewPropertyAnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(View view) {
+ setVisibility(View.INVISIBLE);
+ resetAnimation();
+ }
+ });
+ }
}
static class CompassClickListener implements View.OnClickListener {
private WeakReference<MapboxMap> mapboxMap;
+ private WeakReference<CompassView> compassView;
- public CompassClickListener(final MapboxMap mapboxMap) {
+ CompassClickListener(final MapboxMap mapboxMap, CompassView compassView) {
this.mapboxMap = new WeakReference<>(mapboxMap);
+ this.compassView = new WeakReference<>(compassView);
}
@Override
public void onClick(View view) {
final MapboxMap mapboxMap = this.mapboxMap.get();
- if (mapboxMap != null) {
+ final CompassView compassView = this.compassView.get();
+ if (mapboxMap != null && compassView != null) {
mapboxMap.resetNorth();
+ compassView.postDelayed(compassView, TIME_WAIT_IDLE + TIME_MAP_NORTH_ANIMATION);
}
}
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java
index 114bf5f3c6..45e0c4903e 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java
@@ -55,13 +55,9 @@ public class MyLocationView extends View {
private float contentPaddingX;
private float contentPaddingY;
- private Location location;
private LatLng latLng;
- private LatLng interpolatedLocation;
- private LatLng previousLocation;
+ private Location location;
private long locationUpdateTimestamp;
-
- private float gpsDirection;
private float previousDirection;
private float accuracy;
@@ -454,27 +450,29 @@ public class MyLocationView extends View {
compassListener.onPause();
if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) {
// always face north
- gpsDirection = bearing;
- setCompass(gpsDirection);
+ setCompass(0);
}
}
invalidate();
- update();
}
public void setMyLocationTrackingMode(@MyLocationTracking.Mode int myLocationTrackingMode) {
-
MyLocationBehaviorFactory factory = new MyLocationBehaviorFactory();
myLocationBehavior = factory.getBehavioralModel(myLocationTrackingMode);
- if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW && location != null) {
- // center map directly if we have a location fix
+ if (location != null) {
+ if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) {
+ // center map directly
+ mapboxMap.easeCamera(CameraUpdateFactory.newLatLng(new LatLng(location)), 0, false /*linear interpolator*/, false /*do not disable tracking*/, null);
+ } else {
+ // do not use interpolated location from tracking mode
+ latLng = null;
+ }
myLocationBehavior.updateLatLng(location);
- mapboxMap.easeCamera(CameraUpdateFactory.newLatLng(new LatLng(location)), 0, false /*linear interpolator*/, false /*do not disable tracking*/, null);
}
+
this.myLocationTrackingMode = myLocationTrackingMode;
invalidate();
- update();
}
private void setCompass(float bearing) {
@@ -641,7 +639,9 @@ public class MyLocationView extends View {
private abstract class MyLocationBehavior {
- abstract void updateLatLng(@NonNull Location location);
+ void updateLatLng(@NonNull Location newLocation) {
+ location = newLocation;
+ }
void updateLatLng(double lat, double lon) {
if (latLng != null) {
@@ -670,6 +670,7 @@ public class MyLocationView extends View {
@Override
void updateLatLng(@NonNull Location location) {
+ super.updateLatLng(location);
if (latLng == null) {
// first location fix
latLng = new LatLng(location);
@@ -677,39 +678,34 @@ public class MyLocationView extends View {
}
// updateLatLng timestamp
- long previousUpdateTimeStamp = locationUpdateTimestamp;
+ float previousUpdateTimeStamp = locationUpdateTimestamp;
locationUpdateTimestamp = SystemClock.elapsedRealtime();
// calculate animation duration
- long locationUpdateDuration;
+ float animationDuration;
if (previousUpdateTimeStamp == 0) {
- locationUpdateDuration = 0;
+ animationDuration = 0;
} else {
- locationUpdateDuration = locationUpdateTimestamp - previousUpdateTimeStamp;
+ animationDuration = (locationUpdateTimestamp - previousUpdateTimeStamp) * 1.1f /*make animation slightly longer*/;
}
// calculate interpolated location
- previousLocation = latLng;
latLng = new LatLng(location);
- interpolatedLocation = new LatLng(latLng.getLatitude() , latLng.getLongitude());
-
- // build new camera
- CameraPosition.Builder builder = new CameraPosition.Builder().target(interpolatedLocation);
+ CameraPosition.Builder builder = new CameraPosition.Builder().target(latLng);
// add direction
if (myBearingTrackingMode == MyBearingTracking.GPS) {
if (location.hasBearing()) {
builder.bearing(location.getBearing());
}
- gpsDirection = location.getBearing();
- setCompass(gpsDirection);
+ setCompass(0);
}
// accuracy
updateAccuracy(location);
// ease to new camera position with a linear interpolator
- mapboxMap.easeCamera(CameraUpdateFactory.newCameraPosition(builder.build()), (int) locationUpdateDuration, false /*linear interpolator*/, false /*do not disable tracking*/, null);
+ mapboxMap.easeCamera(CameraUpdateFactory.newCameraPosition(builder.build()), (int) animationDuration, false /*linear interpolator*/, false /*do not disable tracking*/, null);
}
@Override
@@ -726,6 +722,7 @@ public class MyLocationView extends View {
@Override
void updateLatLng(@NonNull final Location location) {
+ super.updateLatLng(location);
if (latLng == null) {
// first location update
latLng = new LatLng(location);
@@ -733,13 +730,11 @@ public class MyLocationView extends View {
}
// update LatLng location
- previousLocation = latLng;
- latLng = new LatLng(location);
+ LatLng newLocation = new LatLng(location);
// update LatLng direction
if (myBearingTrackingMode == MyBearingTracking.GPS && location.hasBearing()) {
- gpsDirection = location.getBearing();
- setCompass(gpsDirection);
+ setCompass(location.getBearing() + bearing);
}
// update LatLng accuracy
@@ -748,10 +743,7 @@ public class MyLocationView extends View {
// calculate updateLatLng time + add some extra offset to improve animation
long previousUpdateTimeStamp = locationUpdateTimestamp;
locationUpdateTimestamp = SystemClock.elapsedRealtime();
- long locationUpdateDuration = (long) ((locationUpdateTimestamp - previousUpdateTimeStamp) * 1.3);
-
- // calculate interpolated entity
- interpolatedLocation = new LatLng(latLng.getLatitude() , latLng.getLongitude());
+ long locationUpdateDuration = (long) ((locationUpdateTimestamp - previousUpdateTimeStamp) * 1.2f);
// animate changes
if (locationChangeAnimator != null) {
@@ -760,14 +752,12 @@ public class MyLocationView extends View {
}
locationChangeAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
- locationChangeAnimator.setDuration((long) (locationUpdateDuration * 1.2));
+ locationChangeAnimator.setDuration(locationUpdateDuration);
locationChangeAnimator.addUpdateListener(new MarkerCoordinateAnimatorListener(this,
- previousLocation, interpolatedLocation
+ latLng, newLocation
));
locationChangeAnimator.start();
-
- // use interpolated location as current location
- latLng = interpolatedLocation;
+ latLng = newLocation;
}
@Override
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/package-info.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/package-info.java
new file mode 100644
index 0000000000..1b207820c2
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Contains the Mapbox Maps Android Network API classes.
+ */
+package com.mapbox.mapboxsdk.net;
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java
index 7d22292601..bedb54ca46 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java
@@ -65,6 +65,7 @@ public class MapboxEventManager {
private static MapboxEventManager mapboxEventManager = null;
private boolean initialized = false;
+ private boolean stagingEnv;
private boolean telemetryEnabled;
private final Vector<Hashtable<String, Object>> events = new Vector<>();
@@ -173,12 +174,10 @@ public class MapboxEventManager {
stagingAccessToken = prefs.getString(MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_STAGING_ACCESS_TOKEN, null);
}
- if (!TextUtils.isEmpty(stagingURL)) {
+ if (!TextUtils.isEmpty(stagingURL) && !TextUtils.isEmpty(stagingAccessToken)) {
eventsURL = stagingURL;
- }
-
- if (!TextUtils.isEmpty(stagingAccessToken)) {
- this.accessToken = stagingAccessToken;
+ this.accessToken = accessToken;
+ stagingEnv = true;
}
// Build User Agent
@@ -715,29 +714,32 @@ public class MapboxEventManager {
}
// Based on http://square.github.io/okhttp/3.x/okhttp/okhttp3/CertificatePinner.html
- CertificatePinner certificatePinner = new CertificatePinner.Builder()
- // Staging - Geotrust
- .add("cloudfront-staging.tilestream.net", "sha256/kR9ysyN/lzBl/ecearDERV7qO7xqSN4jt6XuQjIVL0I=")
- .add("cloudfront-staging.tilestream.net", "sha256/sPbNCVpVasMJxps3IqFfLTRKkVnRCLrTlZVc5kspqlkw=")
- .add("cloudfront-staging.tilestream.net", "sha256/h6801m+z8v3zbgkRHpq6L29Esgfzhj89C1SyUCOQmqU=")
- // Prod - Geotrust
- .add("events.mapbox.com", "sha256/BhynraKizavqoC5U26qgYuxLZst6pCu9J5stfL6RSYY=")
- .add("events.mapbox.com", "sha256/owrR9U9FWDWtrFF+myoRIu75JwU4sJwzvhCNLZoY37g=")
- .add("events.mapbox.com", "sha256/SQVGZiOrQXi+kqxcvWWE96HhfydlLVqFr4lQTqI5qqo=")
- // Prod - DigiCert
- .add("events.mapbox.com", "sha256/Tb0uHZ/KQjWh8N9+CZFLc4zx36LONQ55l6laDi1qtT4=")
- .add("events.mapbox.com", "sha256/RRM1dGqnDFsCJXBTHky16vi1obOlCgFFn/yOhI/y+ho=")
- .add("events.mapbox.com", "sha256/WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18=")
- .build();
+ CertificatePinner.Builder certificatePinnerBuilder = new CertificatePinner.Builder();
+ if(stagingEnv){
+ // Staging - Geotrust
+ certificatePinnerBuilder
+ .add("cloudfront-staging.tilestream.net", "sha256/3euxrJOrEZI15R4104UsiAkDqe007EPyZ6eTL/XxdAY=")
+ .add("cloudfront-staging.tilestream.net", "sha256/5kJvNEMw0KjrCAu7eXY5HZdvyCS13BbA0VJG1RSP91w=")
+ .add("cloudfront-staging.tilestream.net", "sha256/r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=");
+ }else{
+ certificatePinnerBuilder
+ // Prod - Geotrust
+ .add("events.mapbox.com", "sha256/BhynraKizavqoC5U26qgYuxLZst6pCu9J5stfL6RSYY=")
+ .add("events.mapbox.com", "sha256/owrR9U9FWDWtrFF+myoRIu75JwU4sJwzvhCNLZoY37g=")
+ .add("events.mapbox.com", "sha256/SQVGZiOrQXi+kqxcvWWE96HhfydlLVqFr4lQTqI5qqo=")
+ // Prod - DigiCert
+ .add("events.mapbox.com", "sha256/Tb0uHZ/KQjWh8N9+CZFLc4zx36LONQ55l6laDi1qtT4=")
+ .add("events.mapbox.com", "sha256/RRM1dGqnDFsCJXBTHky16vi1obOlCgFFn/yOhI/y+ho=")
+ .add("events.mapbox.com", "sha256/WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18=");
+ }
OkHttpClient client = new OkHttpClient.Builder()
- .certificatePinner(certificatePinner)
+ .certificatePinner(certificatePinnerBuilder.build())
.addInterceptor(new GzipRequestInterceptor())
.build();
RequestBody body = RequestBody.create(JSON, jsonArray.toString());
String url = eventsURL + "/events/v2?access_token=" + accessToken;
-// Log.d(TAG, "Events URL = " + url);
Request request = new Request.Builder()
.url(url)
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml b/platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml
index 777d879d48..4fbf3d5fe1 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml
@@ -29,6 +29,7 @@
<public name="compass_margin_top" type="attr" />
<public name="compass_margin_right" type="attr" />
<public name="compass_margin_bottom" type="attr" />
+ <public name="compass_fade_facing_north" type="attr" />
<public name="logo_gravity" type="attr" />
<public name="logo_margin_left" type="attr" />
<public name="logo_margin_top" type="attr" />
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/attribution_list_item.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/attribution_list_item.xml
index 1252fb194f..763bb118e0 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/attribution_list_item.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/attribution_list_item.xml
@@ -1,11 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+<TextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
- android:paddingLeft="16dp"
- android:paddingRight="16dp"
- android:textAppearance="?android:attr/textAppearanceListItemSmall"
- android:textColor="@android:color/white" />
+ android:paddingLeft="24dp"
+ android:paddingRight="24dp"
+ android:textAllCaps="true"
+ android:textAppearance="?android:attr/textAppearanceButton"
+ android:textColor="@color/mapbox_blue"/>
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/attribution_telemetry_view.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/attribution_telemetry_view.xml
deleted file mode 100644
index b4d2326833..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/attribution_telemetry_view.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical"
- >
-
- <TextView
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="@string/attributionTelemetryMessage"
- android:gravity="center_horizontal"/>
-
- <ListView
- android:id="@+id/telemetryOptionsList"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- />
-
-</LinearLayout>
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/arrays.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/arrays.xml
index d5d26d09d2..bb466880aa 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/arrays.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/arrays.xml
@@ -6,16 +6,6 @@
<item>Improve this map</item>
<item>Telemetry Settings</item>
</array>
- <array name="attribution_telemetry_options">
- <item>Tell Me More</item>
- <item>Don\'t Participate</item>
- <item>Participate</item>
- </array>
- <array name="attribution_telemetry_options_already_participating">
- <item>Tell Me More</item>
- <item>Stop Participating</item>
- <item>Keep Participating</item>
- </array>
<!-- If editing this array update MapView.ATTRIBUTION_INDEX_IMPROVE_THIS_MAP -->
<array name="attribution_links" formatted="false" translatable="false">
<item>https://www.mapbox.com/about/maps/</item>
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml
index f0740a4e53..458056c14e 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml
@@ -64,6 +64,7 @@
<attr name="compass_margin_top" format="dimension" />
<attr name="compass_margin_right" format="dimension" />
<attr name="compass_margin_bottom" format="dimension" />
+ <attr name="compass_fade_facing_north" format="boolean" />
<!--Logo-->
<attr name="logo_gravity">
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/strings.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/strings.xml
index 687b85b2d8..c8bb9d65ba 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/strings.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/strings.xml
@@ -5,6 +5,9 @@
<string name="attributionsDialogTitle">Mapbox Android SDK</string>
<string name="attributionTelemetryTitle">Make Mapbox Maps Better</string>
<string name="attributionTelemetryMessage">You are helping to make OpenStreetMap and Mapbox maps better by contributing anonymous usage data.</string>
+ <string name="attributionTelemetryPositive">Agree</string>
+ <string name="attributionTelemetryNegative">Disagree</string>
+ <string name="attributionTelemetryNeutral">More info</string>
<string name="mapboxIconContentDescription">The Mapbox logo.</string>
<string name="infoWindowTitle">Title</string>
<string name="infoWindowDescription">Description</string>
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/styles.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/styles.xml
index a46f58ae80..708cfc72e9 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/styles.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/styles.xml
@@ -6,4 +6,6 @@
<item name="android:textColorPrimary">@android:color/white</item>
</style>
+ <style name="TelemAlertDialogStyle" parent="Theme.AppCompat.Light.Dialog.Alert"/>
+
</resources> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/build.gradle b/platform/android/MapboxGLAndroidSDKTestApp/build.gradle
index 859740e212..f5f4ec3f54 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/build.gradle
+++ b/platform/android/MapboxGLAndroidSDKTestApp/build.gradle
@@ -113,11 +113,21 @@ checkstyle {
}
def getAccessKeyDeviceFarm() {
- return hasProperty('AWS_ACCESS_KEY_ID_DEVICE_FARM') ? AWS_ACCESS_KEY_ID_DEVICE_FARM : ""
+ if (project.hasProperty('AWS_ACCESS_KEY_ID_DEVICE_FARM')) {
+ return AWS_ACCESS_KEY_ID_DEVICE_FARM
+ } else {
+ println("Could not locate AWS_ACCESS_KEY_ID_DEVICE_FARM in gradle.properties")
+ return ""
+ }
}
def getSecretAccessKeyDeviceFarm() {
- return hasProperty('AWS_SECRET_ACCESS_KEY_DEVICE_FARM') ? AWS_SECRET_ACCESS_KEY_DEVICE_FARM : ""
+ if (project.hasProperty('AWS_SECRET_ACCESS_KEY_DEVICE_FARM')) {
+ return AWS_SECRET_ACCESS_KEY_DEVICE_FARM
+ } else {
+ println("Could not locate AWS_SECRET_ACCESS_KEY_DEVICE_FARM in gradle.properties")
+ return ""
+ }
}
devicefarm {
@@ -130,10 +140,7 @@ devicefarm {
secretKey getSecretAccessKeyDeviceFarm()
}
- // optional block, radios default to 'on' state, all parameters optional
devicestate {
- ///extraDataZipFile file("path/to/zip") // or ‘null’ if you have no extra data. Default is null.
- //auxiliaryApps files(file("path/to/app"), file("path/to/app2")) // or ‘files()’ if you have no auxiliary apps. Default is an empty list.
wifi "on"
bluetooth "off"
gps "on"
@@ -142,9 +149,6 @@ devicefarm {
longitude - 122.3491 // default
}
- // Instrumentation
- // optional filter "my-filter"
- // See AWS Developer docs
instrumentation {
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/gradle.properties b/platform/android/MapboxGLAndroidSDKTestApp/gradle.properties
deleted file mode 100644
index ef89e27366..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/gradle.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-# allows gradle to use more memory
-org.gradle.jvmargs=-Xmx2048M
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/activity/BaseTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/BaseActivityTest.java
index 144073ae27..b00255a6c7 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/activity/BaseTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/BaseActivityTest.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.activity;
+package com.mapbox.mapboxsdk.testapp.activity;
import android.app.Activity;
import android.support.test.espresso.Espresso;
@@ -9,8 +9,8 @@ import android.util.Log;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.utils.OnMapReadyIdlingResource;
-import com.mapbox.mapboxsdk.utils.ScreenshotUtil;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
+import com.mapbox.mapboxsdk.testapp.utils.ScreenshotUtil;
import org.junit.After;
import org.junit.Before;
@@ -21,7 +21,7 @@ import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
-public abstract class BaseTest {
+public abstract class BaseActivityTest {
@Rule
public ActivityTestRule<Activity> rule = new ActivityTestRule<>(getActivityClass());
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/activity/activity.junit.ejs b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/activity.junit.ejs
index df75f8633d..3e3ef36c39 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/activity/activity.junit.ejs
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/activity.junit.ejs
@@ -3,11 +3,11 @@
const subPackage = locals[1];
-%>
// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
-package com.mapbox.mapboxsdk.activity.gen.<%- subPackage %>;
+package com.mapbox.mapboxsdk.testapp.activity.gen.<%- subPackage %>;
import android.support.test.runner.AndroidJUnit4;
-import com.mapbox.mapboxsdk.activity.BaseTest;
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.activity.<%- subPackage %>.<%- activity %>;
@@ -23,7 +23,7 @@ import static android.support.test.espresso.matcher.ViewMatchers.withId;
* Sanity test for <%- activity %>
*/
@RunWith(AndroidJUnit4.class)
-public class <%- activity %>Test extends BaseTest {
+public class <%- activity %>Test extends BaseActivityTest {
@Test
public void testSanity() {
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/AddRemoveMarkerActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/AddRemoveMarkerActivityTest.java
new file mode 100644
index 0000000000..76ee101904
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/AddRemoveMarkerActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.annotation;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.annotation.AddRemoveMarkerActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for AddRemoveMarkerActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class AddRemoveMarkerActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return AddRemoveMarkerActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/BulkMarkerActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/BulkMarkerActivityTest.java
new file mode 100644
index 0000000000..33bfb23b25
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/BulkMarkerActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.annotation;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.annotation.BulkMarkerActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for BulkMarkerActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class BulkMarkerActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return BulkMarkerActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/DynamicMarkerChangeActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/DynamicMarkerChangeActivityTest.java
new file mode 100644
index 0000000000..040affafda
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/DynamicMarkerChangeActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.annotation;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.annotation.DynamicMarkerChangeActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for DynamicMarkerChangeActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class DynamicMarkerChangeActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return DynamicMarkerChangeActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/MarkerViewActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/MarkerViewActivityTest.java
new file mode 100644
index 0000000000..9a0b66d8bc
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/MarkerViewActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.annotation;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.annotation.MarkerViewActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for MarkerViewActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class MarkerViewActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return MarkerViewActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/MarkerViewScaleActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/MarkerViewScaleActivityTest.java
new file mode 100644
index 0000000000..373b2d3d10
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/MarkerViewScaleActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.annotation;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.annotation.MarkerViewScaleActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for MarkerViewScaleActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class MarkerViewScaleActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return MarkerViewScaleActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/PolygonActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/PolygonActivityTest.java
new file mode 100644
index 0000000000..9569b7880b
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/PolygonActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.annotation;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.annotation.PolygonActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for PolygonActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class PolygonActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return PolygonActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/PolylineActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/PolylineActivityTest.java
new file mode 100644
index 0000000000..32f099cbc8
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/PolylineActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.annotation;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.annotation.PolylineActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for PolylineActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class PolylineActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return PolylineActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/PressForMarkerActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/PressForMarkerActivityTest.java
new file mode 100644
index 0000000000..3475a47263
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/annotation/PressForMarkerActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.annotation;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.annotation.PressForMarkerActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for PressForMarkerActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class PressForMarkerActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return PressForMarkerActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/CameraAnimationTypeActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/CameraAnimationTypeActivityTest.java
new file mode 100644
index 0000000000..a4ee61de4d
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/CameraAnimationTypeActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.camera;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.camera.CameraAnimationTypeActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for CameraAnimationTypeActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class CameraAnimationTypeActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return CameraAnimationTypeActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/CameraPositionActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/CameraPositionActivityTest.java
new file mode 100644
index 0000000000..784488668c
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/CameraPositionActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.camera;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.camera.CameraPositionActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for CameraPositionActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class CameraPositionActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return CameraPositionActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/LatLngBoundsActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/LatLngBoundsActivityTest.java
new file mode 100644
index 0000000000..f0b061a1c5
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/LatLngBoundsActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.camera;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.camera.LatLngBoundsActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for LatLngBoundsActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class LatLngBoundsActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return LatLngBoundsActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/ManualZoomActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/ManualZoomActivityTest.java
new file mode 100644
index 0000000000..2a50f5f820
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/ManualZoomActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.camera;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.camera.ManualZoomActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for ManualZoomActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class ManualZoomActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return ManualZoomActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/MaxMinZoomActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/MaxMinZoomActivityTest.java
new file mode 100644
index 0000000000..cb63bb8838
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/MaxMinZoomActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.camera;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.camera.MaxMinZoomActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for MaxMinZoomActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class MaxMinZoomActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return MaxMinZoomActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/ScrollByActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/ScrollByActivityTest.java
new file mode 100644
index 0000000000..ce594efd1f
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/camera/ScrollByActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.camera;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.camera.ScrollByActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for ScrollByActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class ScrollByActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return ScrollByActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/customlayer/CustomLayerActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/customlayer/CustomLayerActivityTest.java
new file mode 100644
index 0000000000..56c2eae817
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/customlayer/CustomLayerActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.customlayer;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.customlayer.CustomLayerActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for CustomLayerActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class CustomLayerActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return CustomLayerActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/directions/DirectionsActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/directions/DirectionsActivityTest.java
new file mode 100644
index 0000000000..379c57e55a
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/directions/DirectionsActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.directions;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.directions.DirectionsActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for DirectionsActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class DirectionsActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return DirectionsActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/feature/QueryRenderedFeaturesBoxCountActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/feature/QueryRenderedFeaturesBoxCountActivityTest.java
new file mode 100644
index 0000000000..c4a71d8279
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/feature/QueryRenderedFeaturesBoxCountActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.feature;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.feature.QueryRenderedFeaturesBoxCountActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for QueryRenderedFeaturesBoxCountActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class QueryRenderedFeaturesBoxCountActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return QueryRenderedFeaturesBoxCountActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/feature/QueryRenderedFeaturesPropertiesActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/feature/QueryRenderedFeaturesPropertiesActivityTest.java
new file mode 100644
index 0000000000..8a474fb9bf
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/feature/QueryRenderedFeaturesPropertiesActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.feature;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.feature.QueryRenderedFeaturesPropertiesActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for QueryRenderedFeaturesPropertiesActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class QueryRenderedFeaturesPropertiesActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return QueryRenderedFeaturesPropertiesActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/geocoding/GeocoderActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/geocoding/GeocoderActivityTest.java
new file mode 100644
index 0000000000..05d1f29547
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/geocoding/GeocoderActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.geocoding;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.geocoding.GeocoderActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for GeocoderActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class GeocoderActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return GeocoderActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/imagegenerator/PrintActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/imagegenerator/PrintActivityTest.java
new file mode 100644
index 0000000000..c14cc413cf
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/imagegenerator/PrintActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.imagegenerator;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.imagegenerator.PrintActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for PrintActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class PrintActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return PrintActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/infowindow/DynamicInfoWindowAdapterActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/infowindow/DynamicInfoWindowAdapterActivityTest.java
new file mode 100644
index 0000000000..b7a8245795
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/infowindow/DynamicInfoWindowAdapterActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.infowindow;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.infowindow.DynamicInfoWindowAdapterActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for DynamicInfoWindowAdapterActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class DynamicInfoWindowAdapterActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return DynamicInfoWindowAdapterActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/infowindow/InfoWindowActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/infowindow/InfoWindowActivityTest.java
new file mode 100644
index 0000000000..5ba4d56a03
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/infowindow/InfoWindowActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.infowindow;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.infowindow.InfoWindowActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for InfoWindowActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class InfoWindowActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return InfoWindowActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/infowindow/InfoWindowAdapterActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/infowindow/InfoWindowAdapterActivityTest.java
new file mode 100644
index 0000000000..7071874435
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/infowindow/InfoWindowAdapterActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.infowindow;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.infowindow.InfoWindowAdapterActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for InfoWindowAdapterActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class InfoWindowAdapterActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return InfoWindowAdapterActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/DebugModeActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/DebugModeActivityTest.java
new file mode 100644
index 0000000000..5764d364e0
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/DebugModeActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.maplayout;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.maplayout.DebugModeActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for DebugModeActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class DebugModeActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return DebugModeActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/MapPaddingActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/MapPaddingActivityTest.java
new file mode 100644
index 0000000000..3f94b11246
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/MapPaddingActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.maplayout;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.maplayout.MapPaddingActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for MapPaddingActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class MapPaddingActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return MapPaddingActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/SurfaceViewMediaControlActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/SurfaceViewMediaControlActivityTest.java
new file mode 100644
index 0000000000..a52a4b0edb
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/SurfaceViewMediaControlActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.maplayout;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.maplayout.SurfaceViewMediaControlActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for SurfaceViewMediaControlActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class SurfaceViewMediaControlActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return SurfaceViewMediaControlActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/VideoViewActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/VideoViewActivityTest.java
new file mode 100644
index 0000000000..fb9330f0f4
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/maplayout/VideoViewActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.maplayout;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.maplayout.VideoViewActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for VideoViewActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class VideoViewActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return VideoViewActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/offline/OfflineActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/offline/OfflineActivityTest.java
new file mode 100644
index 0000000000..00a953f37e
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/offline/OfflineActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.offline;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.offline.OfflineActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for OfflineActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class OfflineActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return OfflineActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/CircleLayerActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/CircleLayerActivityTest.java
new file mode 100644
index 0000000000..5299f2e716
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/CircleLayerActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.style;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.style.CircleLayerActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for CircleLayerActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class CircleLayerActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return CircleLayerActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/CustomSpriteActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/CustomSpriteActivityTest.java
new file mode 100644
index 0000000000..5e482b2b38
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/CustomSpriteActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.style;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.style.CustomSpriteActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for CustomSpriteActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class CustomSpriteActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return CustomSpriteActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/RuntimeStyleActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/RuntimeStyleActivityTest.java
new file mode 100644
index 0000000000..37d5f64e8c
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/RuntimeStyleActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.style;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.style.RuntimeStyleActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for RuntimeStyleActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class RuntimeStyleActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return RuntimeStyleActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/RuntimeStyleTimingTestActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/RuntimeStyleTimingTestActivityTest.java
new file mode 100644
index 0000000000..7320b8527c
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/RuntimeStyleTimingTestActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.style;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.style.RuntimeStyleTimingTestActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for RuntimeStyleTimingTestActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class RuntimeStyleTimingTestActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return RuntimeStyleTimingTestActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/StyleFileActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/StyleFileActivityTest.java
new file mode 100644
index 0000000000..29116b85cb
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen/style/StyleFileActivityTest.java
@@ -0,0 +1,33 @@
+// This file is generated. Edit android/platform/scripts/generate-test-code.js, then run `make generate-test-android`.
+package com.mapbox.mapboxsdk.testapp.activity.gen.style;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.style.StyleFileActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Sanity test for StyleFileActivity
+ */
+@RunWith(AndroidJUnit4.class)
+public class StyleFileActivityTest extends BaseActivityTest {
+
+ @Test
+ public void testSanity() {
+ onView(withId(R.id.mapView)).check(matches(isDisplayed()));
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return StyleFileActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/camera/RotateTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/RotateActivityTest.java
index 4fe2a66043..edef97027e 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/camera/RotateTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/RotateActivityTest.java
@@ -1,13 +1,13 @@
-package com.mapbox.mapboxsdk.camera;
+package com.mapbox.mapboxsdk.testapp.camera;
import android.support.test.espresso.UiController;
import android.support.test.espresso.ViewAction;
import android.view.View;
-import com.mapbox.mapboxsdk.activity.BaseTest;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMapUtils;
import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
import com.mapbox.mapboxsdk.testapp.activity.infowindow.InfoWindowActivity;
import org.hamcrest.Matcher;
@@ -17,7 +17,7 @@ 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;
-public class RotateTest extends BaseTest {
+public class RotateActivityTest extends BaseActivityTest {
@Test
// longer testing change second param
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/camera/TiltTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/TiltActivityTest.java
index c404bd3143..8f21f60fb0 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/camera/TiltTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/TiltActivityTest.java
@@ -1,13 +1,13 @@
-package com.mapbox.mapboxsdk.camera;
+package com.mapbox.mapboxsdk.testapp.camera;
import android.support.test.espresso.UiController;
import android.support.test.espresso.ViewAction;
import android.view.View;
-import com.mapbox.mapboxsdk.activity.BaseTest;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMapUtils;
import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
import com.mapbox.mapboxsdk.testapp.activity.annotation.DynamicMarkerChangeActivity;
import org.hamcrest.Matcher;
@@ -17,7 +17,7 @@ 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;
-public class TiltTest extends BaseTest {
+public class TiltActivityTest extends BaseActivityTest {
@Test
// longer testing change param
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/camera/ZoomTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/ZoomActivityTest.java
index 01f8dcb48e..700e8f6c5c 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/camera/ZoomTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/ZoomActivityTest.java
@@ -1,13 +1,15 @@
-package com.mapbox.mapboxsdk.camera;
+package com.mapbox.mapboxsdk.testapp.camera;
import android.support.test.espresso.UiController;
import android.support.test.espresso.ViewAction;
import android.view.View;
-import com.mapbox.mapboxsdk.activity.BaseTest;
+import com.mapbox.mapboxsdk.camera.CameraPosition;
+import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
import com.mapbox.mapboxsdk.testapp.activity.maplayout.DebugModeActivity;
import org.hamcrest.Matcher;
@@ -17,7 +19,7 @@ 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;
-public class ZoomTest extends BaseTest {
+public class ZoomActivityTest extends BaseActivityTest {
@Test
// longer testing increase second param
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BackgroundLayerStyleTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BackgroundLayerStyleTest.java
new file mode 100644
index 0000000000..d4c00c5f05
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BackgroundLayerStyleTest.java
@@ -0,0 +1,136 @@
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
+package com.mapbox.mapboxsdk.testapp.style;
+
+import android.graphics.Color;
+import android.support.test.espresso.Espresso;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Log;
+
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.style.layers.BackgroundLayer;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.style.RuntimeStyleTestActivity;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+import static com.mapbox.mapboxsdk.style.layers.Property.*;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
+
+/**
+ * Basic smoke tests for BackgroundLayer
+ */
+@RunWith(AndroidJUnit4.class)
+public class BackgroundLayerStyleTest extends BaseStyleTest {
+ private static final String TAG = BackgroundLayerStyleTest.class.getSimpleName();
+
+ @Rule
+ public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
+
+ private BackgroundLayer layer;
+
+ private OnMapReadyIdlingResource idlingResource;
+
+ private MapboxMap mapboxMap;
+
+ @Before
+ public void setup() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
+
+ @Test
+ public void testSetVisibility() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ Log.i(TAG, "Retrieving layer");
+ layer = mapboxMap.getLayerAs("background");
+ Log.i(TAG, "visibility");
+ assertNotNull(layer);
+
+ //Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
+
+ //Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
+ }
+
+ @Test
+ public void testBackgroundColor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ Log.i(TAG, "Retrieving layer");
+ layer = mapboxMap.getLayerAs("background");
+ Log.i(TAG, "background-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(backgroundColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getBackgroundColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ }
+
+ @Test
+ public void testBackgroundColorAsInt() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ Log.i(TAG, "Retrieving layer");
+ layer = mapboxMap.getLayerAs("background");
+ Log.i(TAG, "background-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(backgroundColor(Color.RED));
+ assertEquals(layer.getBackgroundColorAsInt(), Color.RED);
+ }
+
+ @Test
+ public void testBackgroundPattern() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ Log.i(TAG, "Retrieving layer");
+ layer = mapboxMap.getLayerAs("background");
+ Log.i(TAG, "background-pattern");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(backgroundPattern("pedestrian-polygon"));
+ assertEquals((String) layer.getBackgroundPattern().getValue(), (String) "pedestrian-polygon");
+ }
+
+ @Test
+ public void testBackgroundOpacity() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ Log.i(TAG, "Retrieving layer");
+ layer = mapboxMap.getLayerAs("background");
+ Log.i(TAG, "background-opacity");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(backgroundOpacity(0.3f));
+ assertEquals((Float) layer.getBackgroundOpacity().getValue(), (Float) 0.3f);
+ }
+
+
+ @After
+ public void unregisterIntentServiceIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/BackgroundLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BackgroundLayerTest.java
index f6c2d971f7..b56c8f648f 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/BackgroundLayerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BackgroundLayerTest.java
@@ -1,5 +1,5 @@
// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
-package com.mapbox.mapboxsdk.style;
+package com.mapbox.mapboxsdk.testapp.style;
import android.graphics.Color;
import android.support.test.espresso.Espresso;
@@ -11,7 +11,7 @@ import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.style.layers.BackgroundLayer;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.activity.style.RuntimeStyleTestActivity;
-import com.mapbox.mapboxsdk.utils.OnMapReadyIdlingResource;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
import org.junit.After;
import org.junit.Before;
@@ -27,7 +27,7 @@ import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
* Basic smoke tests for BackgroundLayer
*/
@RunWith(AndroidJUnit4.class)
-public class BackgroundLayerTest extends BaseTest {
+public class BackgroundLayerTest extends BaseStyleTest {
private static final String TAG = BackgroundLayerTest.class.getSimpleName();
@Rule
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/BaseTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BaseStyleTest.java
index c79820f42e..5ec4e5437b 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/BaseTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BaseStyleTest.java
@@ -1,8 +1,8 @@
-package com.mapbox.mapboxsdk.style;
+package com.mapbox.mapboxsdk.testapp.style;
import android.app.Activity;
-import com.mapbox.mapboxsdk.utils.ScreenshotUtil;
+import com.mapbox.mapboxsdk.testapp.utils.ScreenshotUtil;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
@@ -10,9 +10,9 @@ import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
/**
- * Base Espresso class for all tests, helps working with ActivityInstrumentationTestCase2
+ * Base Test class for Style tests
*/
-public class BaseTest {
+public class BaseStyleTest {
protected final static String HOME_BUTTON_STRING = "Navigate up";
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerStyleTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerStyleTest.java
new file mode 100644
index 0000000000..a7301962d1
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerStyleTest.java
@@ -0,0 +1,254 @@
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
+package com.mapbox.mapboxsdk.testapp.style;
+
+import android.graphics.Color;
+import android.support.test.espresso.Espresso;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Log;
+
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.style.layers.CircleLayer;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.style.RuntimeStyleTestActivity;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+import static com.mapbox.mapboxsdk.style.layers.Property.*;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
+
+/**
+ * Basic smoke tests for CircleLayer
+ */
+@RunWith(AndroidJUnit4.class)
+public class CircleLayerStyleTest extends BaseStyleTest {
+ private static final String TAG = CircleLayerStyleTest.class.getSimpleName();
+
+ @Rule
+ public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
+
+ private CircleLayer layer;
+
+ private OnMapReadyIdlingResource idlingResource;
+
+ private MapboxMap mapboxMap;
+
+ @Before
+ public void setup() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
+
+ @Test
+ public void testSetVisibility() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "visibility");
+ assertNotNull(layer);
+
+ //Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
+
+ //Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
+ }
+
+ @Test
+ public void testCircleRadius() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "circle-radius");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(circleRadius(0.3f));
+ assertEquals((Float) layer.getCircleRadius().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testCircleColor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "circle-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(circleColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getCircleColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ }
+
+ @Test
+ public void testCircleColorAsInt() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "circle-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(circleColor(Color.RED));
+ assertEquals(layer.getCircleColorAsInt(), Color.RED);
+ }
+
+ @Test
+ public void testCircleBlur() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "circle-blur");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(circleBlur(0.3f));
+ assertEquals((Float) layer.getCircleBlur().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testCircleOpacity() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "circle-opacity");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(circleOpacity(0.3f));
+ assertEquals((Float) layer.getCircleOpacity().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testCircleTranslate() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "circle-translate");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(circleTranslate(new Float[]{0f,0f}));
+ assertEquals((Float[]) layer.getCircleTranslate().getValue(), (Float[]) new Float[]{0f,0f});
+ }
+
+ @Test
+ public void testCircleTranslateAnchor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "circle-translate-anchor");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(circleTranslateAnchor(CIRCLE_TRANSLATE_ANCHOR_MAP));
+ assertEquals((String) layer.getCircleTranslateAnchor().getValue(), (String) CIRCLE_TRANSLATE_ANCHOR_MAP);
+ }
+
+ @Test
+ public void testCirclePitchScale() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "circle-pitch-scale");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(circlePitchScale(CIRCLE_PITCH_SCALE_MAP));
+ assertEquals((String) layer.getCirclePitchScale().getValue(), (String) CIRCLE_PITCH_SCALE_MAP);
+ }
+
+
+ @After
+ public void unregisterIntentServiceIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/CircleLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerTest.java
index 60a793981c..8b0f1af17b 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/CircleLayerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerTest.java
@@ -1,5 +1,5 @@
// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
-package com.mapbox.mapboxsdk.style;
+package com.mapbox.mapboxsdk.testapp.style;
import android.graphics.Color;
import android.support.test.espresso.Espresso;
@@ -11,7 +11,7 @@ import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.style.layers.CircleLayer;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.activity.style.RuntimeStyleTestActivity;
-import com.mapbox.mapboxsdk.utils.OnMapReadyIdlingResource;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
import org.junit.After;
import org.junit.Before;
@@ -27,7 +27,7 @@ import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
* Basic smoke tests for CircleLayer
*/
@RunWith(AndroidJUnit4.class)
-public class CircleLayerTest extends BaseTest {
+public class CircleLayerTest extends BaseStyleTest {
private static final String TAG = CircleLayerTest.class.getSimpleName();
@Rule
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerStyleTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerStyleTest.java
new file mode 100644
index 0000000000..46ad1da879
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerStyleTest.java
@@ -0,0 +1,276 @@
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
+package com.mapbox.mapboxsdk.testapp.style;
+
+import android.graphics.Color;
+import android.support.test.espresso.Espresso;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Log;
+
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.style.layers.FillLayer;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.style.RuntimeStyleTestActivity;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+import static com.mapbox.mapboxsdk.style.layers.Property.*;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
+
+/**
+ * Basic smoke tests for FillLayer
+ */
+@RunWith(AndroidJUnit4.class)
+public class FillLayerStyleTest extends BaseStyleTest {
+ private static final String TAG = FillLayerStyleTest.class.getSimpleName();
+
+ @Rule
+ public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
+
+ private FillLayer layer;
+
+ private OnMapReadyIdlingResource idlingResource;
+
+ private MapboxMap mapboxMap;
+
+ @Before
+ public void setup() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
+
+ @Test
+ public void testSetVisibility() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "visibility");
+ assertNotNull(layer);
+
+ //Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
+
+ //Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
+ }
+
+ @Test
+ public void testFillAntialias() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "fill-antialias");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(fillAntialias(true));
+ assertEquals((Boolean) layer.getFillAntialias().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testFillOpacity() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "fill-opacity");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(fillOpacity(0.3f));
+ assertEquals((Float) layer.getFillOpacity().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testFillColor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "fill-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(fillColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getFillColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ }
+
+ @Test
+ public void testFillColorAsInt() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "fill-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(fillColor(Color.RED));
+ assertEquals(layer.getFillColorAsInt(), Color.RED);
+ }
+
+ @Test
+ public void testFillOutlineColor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "fill-outline-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(fillOutlineColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getFillOutlineColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ }
+
+ @Test
+ public void testFillOutlineColorAsInt() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "fill-outline-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(fillOutlineColor(Color.RED));
+ assertEquals(layer.getFillOutlineColorAsInt(), Color.RED);
+ }
+
+ @Test
+ public void testFillTranslate() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "fill-translate");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(fillTranslate(new Float[]{0f,0f}));
+ assertEquals((Float[]) layer.getFillTranslate().getValue(), (Float[]) new Float[]{0f,0f});
+ }
+
+ @Test
+ public void testFillTranslateAnchor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "fill-translate-anchor");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(fillTranslateAnchor(FILL_TRANSLATE_ANCHOR_MAP));
+ assertEquals((String) layer.getFillTranslateAnchor().getValue(), (String) FILL_TRANSLATE_ANCHOR_MAP);
+ }
+
+ @Test
+ public void testFillPattern() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "fill-pattern");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(fillPattern("pedestrian-polygon"));
+ assertEquals((String) layer.getFillPattern().getValue(), (String) "pedestrian-polygon");
+ }
+
+
+ @After
+ public void unregisterIntentServiceIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/FillLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerTest.java
index 749e4b7ebe..593d444bc4 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/FillLayerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerTest.java
@@ -1,5 +1,5 @@
// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
-package com.mapbox.mapboxsdk.style;
+package com.mapbox.mapboxsdk.testapp.style;
import android.graphics.Color;
import android.support.test.espresso.Espresso;
@@ -11,7 +11,7 @@ import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.style.layers.FillLayer;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.activity.style.RuntimeStyleTestActivity;
-import com.mapbox.mapboxsdk.utils.OnMapReadyIdlingResource;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
import org.junit.After;
import org.junit.Before;
@@ -27,7 +27,7 @@ import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
* Basic smoke tests for FillLayer
*/
@RunWith(AndroidJUnit4.class)
-public class FillLayerTest extends BaseTest {
+public class FillLayerTest extends BaseStyleTest {
private static final String TAG = FillLayerTest.class.getSimpleName();
@Rule
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerStyleTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerStyleTest.java
new file mode 100644
index 0000000000..09c1ae797d
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerStyleTest.java
@@ -0,0 +1,408 @@
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
+package com.mapbox.mapboxsdk.testapp.style;
+
+import android.graphics.Color;
+import android.support.test.espresso.Espresso;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Log;
+
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.style.layers.LineLayer;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.style.RuntimeStyleTestActivity;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+import static com.mapbox.mapboxsdk.style.layers.Property.*;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
+
+/**
+ * Basic smoke tests for LineLayer
+ */
+@RunWith(AndroidJUnit4.class)
+public class LineLayerStyleTest extends BaseStyleTest {
+ private static final String TAG = LineLayerStyleTest.class.getSimpleName();
+
+ @Rule
+ public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
+
+ private LineLayer layer;
+
+ private OnMapReadyIdlingResource idlingResource;
+
+ private MapboxMap mapboxMap;
+
+ @Before
+ public void setup() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
+
+ @Test
+ public void testSetVisibility() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "visibility");
+ assertNotNull(layer);
+
+ //Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
+
+ //Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
+ }
+
+ @Test
+ public void testLineCap() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "line-cap");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineCap(LINE_CAP_BUTT));
+ assertEquals((String) layer.getLineCap().getValue(), (String) LINE_CAP_BUTT);
+ }
+
+ @Test
+ public void testLineJoin() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "line-join");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineJoin(LINE_JOIN_BEVEL));
+ assertEquals((String) layer.getLineJoin().getValue(), (String) LINE_JOIN_BEVEL);
+ }
+
+ @Test
+ public void testLineMiterLimit() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "line-miter-limit");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineMiterLimit(0.3f));
+ assertEquals((Float) layer.getLineMiterLimit().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testLineRoundLimit() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "line-round-limit");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineRoundLimit(0.3f));
+ assertEquals((Float) layer.getLineRoundLimit().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testLineOpacity() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "line-opacity");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineOpacity(0.3f));
+ assertEquals((Float) layer.getLineOpacity().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testLineColor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "line-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getLineColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ }
+
+ @Test
+ public void testLineColorAsInt() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "line-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineColor(Color.RED));
+ assertEquals(layer.getLineColorAsInt(), Color.RED);
+ }
+
+ @Test
+ public void testLineTranslate() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "line-translate");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineTranslate(new Float[]{0f,0f}));
+ assertEquals((Float[]) layer.getLineTranslate().getValue(), (Float[]) new Float[]{0f,0f});
+ }
+
+ @Test
+ public void testLineTranslateAnchor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "line-translate-anchor");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineTranslateAnchor(LINE_TRANSLATE_ANCHOR_MAP));
+ assertEquals((String) layer.getLineTranslateAnchor().getValue(), (String) LINE_TRANSLATE_ANCHOR_MAP);
+ }
+
+ @Test
+ public void testLineWidth() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "line-width");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineWidth(0.3f));
+ assertEquals((Float) layer.getLineWidth().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testLineGapWidth() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "line-gap-width");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineGapWidth(0.3f));
+ assertEquals((Float) layer.getLineGapWidth().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testLineOffset() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "line-offset");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineOffset(0.3f));
+ assertEquals((Float) layer.getLineOffset().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testLineBlur() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "line-blur");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineBlur(0.3f));
+ assertEquals((Float) layer.getLineBlur().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testLineDasharray() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "line-dasharray");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(lineDasharray(new Float[]{}));
+ assertEquals((Float[]) layer.getLineDasharray().getValue(), (Float[]) new Float[]{});
+ }
+
+ @Test
+ public void testLinePattern() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "line-pattern");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(linePattern("pedestrian-polygon"));
+ assertEquals((String) layer.getLinePattern().getValue(), (String) "pedestrian-polygon");
+ }
+
+
+ @After
+ public void unregisterIntentServiceIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/LineLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java
index 5a2adb6646..15fd35f0a8 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/LineLayerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java
@@ -1,5 +1,5 @@
// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
-package com.mapbox.mapboxsdk.style;
+package com.mapbox.mapboxsdk.testapp.style;
import android.graphics.Color;
import android.support.test.espresso.Espresso;
@@ -11,7 +11,7 @@ import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.style.layers.LineLayer;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.activity.style.RuntimeStyleTestActivity;
-import com.mapbox.mapboxsdk.utils.OnMapReadyIdlingResource;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
import org.junit.After;
import org.junit.Before;
@@ -27,7 +27,7 @@ import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
* Basic smoke tests for LineLayer
*/
@RunWith(AndroidJUnit4.class)
-public class LineLayerTest extends BaseTest {
+public class LineLayerTest extends BaseStyleTest {
private static final String TAG = LineLayerTest.class.getSimpleName();
@Rule
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerStyleTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerStyleTest.java
new file mode 100644
index 0000000000..2baddd6fa1
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerStyleTest.java
@@ -0,0 +1,231 @@
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
+package com.mapbox.mapboxsdk.testapp.style;
+
+import android.support.test.espresso.Espresso;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Log;
+
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.style.layers.RasterLayer;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.style.RuntimeStyleTestActivity;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+import static com.mapbox.mapboxsdk.style.layers.Property.*;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
+
+/**
+ * Basic smoke tests for RasterLayer
+ */
+@RunWith(AndroidJUnit4.class)
+public class RasterLayerStyleTest extends BaseStyleTest {
+ private static final String TAG = RasterLayerStyleTest.class.getSimpleName();
+
+ @Rule
+ public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
+
+ private RasterLayer layer;
+
+ private OnMapReadyIdlingResource idlingResource;
+
+ private MapboxMap mapboxMap;
+
+ @Before
+ public void setup() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
+
+ @Test
+ public void testSetVisibility() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "visibility");
+ assertNotNull(layer);
+
+ //Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
+
+ //Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
+ }
+
+ @Test
+ public void testRasterOpacity() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "raster-opacity");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(rasterOpacity(0.3f));
+ assertEquals((Float) layer.getRasterOpacity().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testRasterHueRotate() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "raster-hue-rotate");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(rasterHueRotate(0.3f));
+ assertEquals((Float) layer.getRasterHueRotate().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testRasterBrightnessMin() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "raster-brightness-min");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(rasterBrightnessMin(0.3f));
+ assertEquals((Float) layer.getRasterBrightnessMin().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testRasterBrightnessMax() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "raster-brightness-max");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(rasterBrightnessMax(0.3f));
+ assertEquals((Float) layer.getRasterBrightnessMax().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testRasterSaturation() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "raster-saturation");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(rasterSaturation(0.3f));
+ assertEquals((Float) layer.getRasterSaturation().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testRasterContrast() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "raster-contrast");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(rasterContrast(0.3f));
+ assertEquals((Float) layer.getRasterContrast().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testRasterFadeDuration() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "raster-fade-duration");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(rasterFadeDuration(0.3f));
+ assertEquals((Float) layer.getRasterFadeDuration().getValue(), (Float) 0.3f);
+ }
+
+
+ @After
+ public void unregisterIntentServiceIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/RasterLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerTest.java
index a42793013e..b64c9a244c 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/RasterLayerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerTest.java
@@ -1,5 +1,5 @@
// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
-package com.mapbox.mapboxsdk.style;
+package com.mapbox.mapboxsdk.testapp.style;
import android.graphics.Color;
import android.support.test.espresso.Espresso;
@@ -11,7 +11,7 @@ import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.style.layers.RasterLayer;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.activity.style.RuntimeStyleTestActivity;
-import com.mapbox.mapboxsdk.utils.OnMapReadyIdlingResource;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
import org.junit.After;
import org.junit.Before;
@@ -27,7 +27,7 @@ import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
* Basic smoke tests for RasterLayer
*/
@RunWith(AndroidJUnit4.class)
-public class RasterLayerTest extends BaseTest {
+public class RasterLayerTest extends BaseStyleTest {
private static final String TAG = RasterLayerTest.class.getSimpleName();
@Rule
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/RuntimeStyleBackgroundLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleBackgroundLayerTest.java
index 70ebf78556..f562a5d8a3 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/RuntimeStyleBackgroundLayerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleBackgroundLayerTest.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.style;
+package com.mapbox.mapboxsdk.testapp.style;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/RuntimeStyleTests.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTests.java
index 38a5f10fbf..783601b1dd 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/RuntimeStyleTests.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTests.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.style;
+package com.mapbox.mapboxsdk.testapp.style;
import android.support.test.espresso.Espresso;
import android.support.test.rule.ActivityTestRule;
@@ -13,7 +13,7 @@ import com.mapbox.mapboxsdk.style.sources.NoSuchSourceException;
import com.mapbox.mapboxsdk.style.sources.VectorSource;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.activity.style.RuntimeStyleTestActivity;
-import com.mapbox.mapboxsdk.utils.OnMapReadyIdlingResource;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
import org.junit.After;
import org.junit.Before;
@@ -31,7 +31,7 @@ import static org.junit.Assert.assertTrue;
* Basic smoke tests for Layer and Source
*/
@RunWith(AndroidJUnit4.class)
-public class RuntimeStyleTests extends BaseTest {
+public class RuntimeStyleTests extends BaseStyleTest {
@Rule
public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/RuntimeStyleTimingTests.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTimingTests.java
index 4d327433c0..0282e1bcd0 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/RuntimeStyleTimingTests.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTimingTests.java
@@ -1,12 +1,12 @@
-package com.mapbox.mapboxsdk.style;
+package com.mapbox.mapboxsdk.testapp.style;
import android.support.test.espresso.Espresso;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
-import com.mapbox.mapboxsdk.utils.OnMapReadyIdlingResource;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.activity.style.RuntimeStyleTimingTestActivity;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
import org.junit.After;
import org.junit.Before;
@@ -18,7 +18,7 @@ import org.junit.runner.RunWith;
* Basic smoke tests for adding Layer and Source as early as possible (in onCreate)
*/
@RunWith(AndroidJUnit4.class)
-public class RuntimeStyleTimingTests extends BaseTest {
+public class RuntimeStyleTimingTests extends BaseStyleTest {
@Rule
public final ActivityTestRule<RuntimeStyleTimingTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTimingTestActivity.class);
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerStyleTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerStyleTest.java
new file mode 100644
index 0000000000..7132705ca9
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerStyleTest.java
@@ -0,0 +1,1222 @@
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
+package com.mapbox.mapboxsdk.testapp.style;
+
+import android.graphics.Color;
+import android.support.test.espresso.Espresso;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Log;
+
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.style.RuntimeStyleTestActivity;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+import static com.mapbox.mapboxsdk.style.layers.Property.*;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
+
+/**
+ * Basic smoke tests for SymbolLayer
+ */
+@RunWith(AndroidJUnit4.class)
+public class SymbolLayerStyleTest extends BaseStyleTest {
+ private static final String TAG = SymbolLayerStyleTest.class.getSimpleName();
+
+ @Rule
+ public final ActivityTestRule<RuntimeStyleTestActivity> rule = new ActivityTestRule<>(RuntimeStyleTestActivity.class);
+
+ private SymbolLayer layer;
+
+ private OnMapReadyIdlingResource idlingResource;
+
+ private MapboxMap mapboxMap;
+
+ @Before
+ public void setup() {
+ idlingResource = new OnMapReadyIdlingResource(rule.getActivity());
+ Espresso.registerIdlingResources(idlingResource);
+ }
+
+ @Test
+ public void testSetVisibility() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "visibility");
+ assertNotNull(layer);
+
+ //Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
+
+ //Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
+ }
+
+ @Test
+ public void testSymbolPlacement() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "symbol-placement");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(symbolPlacement(SYMBOL_PLACEMENT_POINT));
+ assertEquals((String) layer.getSymbolPlacement().getValue(), (String) SYMBOL_PLACEMENT_POINT);
+ }
+
+ @Test
+ public void testSymbolSpacing() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "symbol-spacing");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(symbolSpacing(0.3f));
+ assertEquals((Float) layer.getSymbolSpacing().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testSymbolAvoidEdges() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "symbol-avoid-edges");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(symbolAvoidEdges(true));
+ assertEquals((Boolean) layer.getSymbolAvoidEdges().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testIconAllowOverlap() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "icon-allow-overlap");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconAllowOverlap(true));
+ assertEquals((Boolean) layer.getIconAllowOverlap().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testIconIgnorePlacement() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "icon-ignore-placement");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconIgnorePlacement(true));
+ assertEquals((Boolean) layer.getIconIgnorePlacement().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testIconOptional() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "icon-optional");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconOptional(true));
+ assertEquals((Boolean) layer.getIconOptional().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testIconRotationAlignment() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "icon-rotation-alignment");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconRotationAlignment(ICON_ROTATION_ALIGNMENT_MAP));
+ assertEquals((String) layer.getIconRotationAlignment().getValue(), (String) ICON_ROTATION_ALIGNMENT_MAP);
+ }
+
+ @Test
+ public void testIconSize() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "icon-size");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconSize(0.3f));
+ assertEquals((Float) layer.getIconSize().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testIconTextFit() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "icon-text-fit");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconTextFit(ICON_TEXT_FIT_NONE));
+ assertEquals((String) layer.getIconTextFit().getValue(), (String) ICON_TEXT_FIT_NONE);
+ }
+
+ @Test
+ public void testIconTextFitPadding() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "icon-text-fit-padding");
+ 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});
+ }
+
+ @Test
+ public void testIconImage() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "icon-image");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconImage("undefined"));
+ assertEquals((String) layer.getIconImage().getValue(), (String) "undefined");
+ }
+
+ @Test
+ public void testIconRotate() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "icon-rotate");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconRotate(0.3f));
+ assertEquals((Float) layer.getIconRotate().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testIconPadding() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "icon-padding");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconPadding(0.3f));
+ assertEquals((Float) layer.getIconPadding().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testIconKeepUpright() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "icon-keep-upright");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconKeepUpright(true));
+ assertEquals((Boolean) layer.getIconKeepUpright().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testIconOffset() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "icon-offset");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconOffset(new Float[]{0f,0f}));
+ assertEquals((Float[]) layer.getIconOffset().getValue(), (Float[]) new Float[]{0f,0f});
+ }
+
+ @Test
+ public void testTextPitchAlignment() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "text-pitch-alignment");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textPitchAlignment(TEXT_PITCH_ALIGNMENT_MAP));
+ assertEquals((String) layer.getTextPitchAlignment().getValue(), (String) TEXT_PITCH_ALIGNMENT_MAP);
+ }
+
+ @Test
+ public void testTextRotationAlignment() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "text-rotation-alignment");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textRotationAlignment(TEXT_ROTATION_ALIGNMENT_MAP));
+ assertEquals((String) layer.getTextRotationAlignment().getValue(), (String) TEXT_ROTATION_ALIGNMENT_MAP);
+ }
+
+ @Test
+ public void testTextField() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "text-field");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textField(""));
+ assertEquals((String) layer.getTextField().getValue(), (String) "");
+ }
+
+ @Test
+ public void testTextFont() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "text-font");
+ 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"});
+ }
+
+ @Test
+ public void testTextSize() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "text-size");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textSize(0.3f));
+ assertEquals((Float) layer.getTextSize().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextMaxWidth() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "text-max-width");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textMaxWidth(0.3f));
+ assertEquals((Float) layer.getTextMaxWidth().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextLineHeight() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "text-line-height");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textLineHeight(0.3f));
+ assertEquals((Float) layer.getTextLineHeight().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextLetterSpacing() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "text-letter-spacing");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textLetterSpacing(0.3f));
+ assertEquals((Float) layer.getTextLetterSpacing().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextJustify() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "text-justify");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textJustify(TEXT_JUSTIFY_LEFT));
+ assertEquals((String) layer.getTextJustify().getValue(), (String) TEXT_JUSTIFY_LEFT);
+ }
+
+ @Test
+ public void testTextAnchor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "text-anchor");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textAnchor(TEXT_ANCHOR_CENTER));
+ assertEquals((String) layer.getTextAnchor().getValue(), (String) TEXT_ANCHOR_CENTER);
+ }
+
+ @Test
+ public void testTextMaxAngle() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "text-max-angle");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textMaxAngle(0.3f));
+ assertEquals((Float) layer.getTextMaxAngle().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextRotate() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "text-rotate");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textRotate(0.3f));
+ assertEquals((Float) layer.getTextRotate().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextPadding() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "text-padding");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textPadding(0.3f));
+ assertEquals((Float) layer.getTextPadding().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextKeepUpright() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "text-keep-upright");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textKeepUpright(true));
+ assertEquals((Boolean) layer.getTextKeepUpright().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testTextTransform() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "text-transform");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textTransform(TEXT_TRANSFORM_NONE));
+ assertEquals((String) layer.getTextTransform().getValue(), (String) TEXT_TRANSFORM_NONE);
+ }
+
+ @Test
+ public void testTextOffset() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "text-offset");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textOffset(new Float[]{0f,0f}));
+ assertEquals((Float[]) layer.getTextOffset().getValue(), (Float[]) new Float[]{0f,0f});
+ }
+
+ @Test
+ public void testTextAllowOverlap() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "text-allow-overlap");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textAllowOverlap(true));
+ assertEquals((Boolean) layer.getTextAllowOverlap().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testTextIgnorePlacement() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "text-ignore-placement");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textIgnorePlacement(true));
+ assertEquals((Boolean) layer.getTextIgnorePlacement().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testTextOptional() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "text-optional");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textOptional(true));
+ assertEquals((Boolean) layer.getTextOptional().getValue(), (Boolean) true);
+ }
+
+ @Test
+ public void testIconOpacity() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "icon-opacity");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconOpacity(0.3f));
+ assertEquals((Float) layer.getIconOpacity().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testIconColor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "icon-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getIconColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ }
+
+ @Test
+ public void testIconColorAsInt() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "icon-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconColor(Color.RED));
+ assertEquals(layer.getIconColorAsInt(), Color.RED);
+ }
+
+ @Test
+ public void testIconHaloColor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "icon-halo-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconHaloColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getIconHaloColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ }
+
+ @Test
+ public void testIconHaloColorAsInt() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "icon-halo-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconHaloColor(Color.RED));
+ assertEquals(layer.getIconHaloColorAsInt(), Color.RED);
+ }
+
+ @Test
+ public void testIconHaloWidth() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "icon-halo-width");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconHaloWidth(0.3f));
+ assertEquals((Float) layer.getIconHaloWidth().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testIconHaloBlur() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "icon-halo-blur");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconHaloBlur(0.3f));
+ assertEquals((Float) layer.getIconHaloBlur().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testIconTranslate() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "icon-translate");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconTranslate(new Float[]{0f,0f}));
+ assertEquals((Float[]) layer.getIconTranslate().getValue(), (Float[]) new Float[]{0f,0f});
+ }
+
+ @Test
+ public void testIconTranslateAnchor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "icon-translate-anchor");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(iconTranslateAnchor(ICON_TRANSLATE_ANCHOR_MAP));
+ assertEquals((String) layer.getIconTranslateAnchor().getValue(), (String) ICON_TRANSLATE_ANCHOR_MAP);
+ }
+
+ @Test
+ public void testTextOpacity() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "text-opacity");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textOpacity(0.3f));
+ assertEquals((Float) layer.getTextOpacity().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextColor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "text-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getTextColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ }
+
+ @Test
+ public void testTextColorAsInt() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "text-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textColor(Color.RED));
+ assertEquals(layer.getTextColorAsInt(), Color.RED);
+ }
+
+ @Test
+ public void testTextHaloColor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "text-halo-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textHaloColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getTextHaloColor().getValue(), (String) "rgba(0, 0, 0, 1)");
+ }
+
+ @Test
+ public void testTextHaloColorAsInt() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "text-halo-color");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textHaloColor(Color.RED));
+ assertEquals(layer.getTextHaloColorAsInt(), Color.RED);
+ }
+
+ @Test
+ public void testTextHaloWidth() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "text-halo-width");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textHaloWidth(0.3f));
+ assertEquals((Float) layer.getTextHaloWidth().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextHaloBlur() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "text-halo-blur");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textHaloBlur(0.3f));
+ assertEquals((Float) layer.getTextHaloBlur().getValue(), (Float) 0.3f);
+ }
+
+ @Test
+ public void testTextTranslate() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "text-translate");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textTranslate(new Float[]{0f,0f}));
+ assertEquals((Float[]) layer.getTextTranslate().getValue(), (Float[]) new Float[]{0f,0f});
+ }
+
+ @Test
+ public void testTextTranslateAnchor() {
+ checkViewIsDisplayed(R.id.mapView);
+
+ mapboxMap = rule.getActivity().getMapboxMap();
+
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Log.i(TAG, "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");
+ }
+ Log.i(TAG, "text-translate-anchor");
+ assertNotNull(layer);
+
+ //Set and Get
+ layer.setProperties(textTranslateAnchor(TEXT_TRANSLATE_ANCHOR_MAP));
+ assertEquals((String) layer.getTextTranslateAnchor().getValue(), (String) TEXT_TRANSLATE_ANCHOR_MAP);
+ }
+
+
+ @After
+ public void unregisterIntentServiceIdlingResource() {
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/SymbolLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java
index 2dd8a4aafd..5bc3f597c1 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/SymbolLayerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java
@@ -1,5 +1,5 @@
// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
-package com.mapbox.mapboxsdk.style;
+package com.mapbox.mapboxsdk.testapp.style;
import android.graphics.Color;
import android.support.test.espresso.Espresso;
@@ -11,7 +11,7 @@ import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.activity.style.RuntimeStyleTestActivity;
-import com.mapbox.mapboxsdk.utils.OnMapReadyIdlingResource;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
import org.junit.After;
import org.junit.Before;
@@ -27,7 +27,7 @@ import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
* Basic smoke tests for SymbolLayer
*/
@RunWith(AndroidJUnit4.class)
-public class SymbolLayerTest extends BaseTest {
+public class SymbolLayerTest extends BaseStyleTest {
private static final String TAG = SymbolLayerTest.class.getSimpleName();
@Rule
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/layer.junit.ejs b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/layer.junit.ejs
index 6c2c3f0255..bc0d22bb25 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/layer.junit.ejs
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/layer.junit.ejs
@@ -3,7 +3,7 @@
const properties = locals.properties;
-%>
// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
-package com.mapbox.mapboxsdk.style;
+package com.mapbox.mapboxsdk.testapp.style;
import android.graphics.Color;
import android.support.test.espresso.Espresso;
@@ -15,7 +15,7 @@ import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.style.layers.<%- camelize(type) %>Layer;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.activity.style.RuntimeStyleTestActivity;
-import com.mapbox.mapboxsdk.utils.OnMapReadyIdlingResource;
+import com.mapbox.mapboxsdk.testapp.utils.OnMapReadyIdlingResource;
import org.junit.After;
import org.junit.Before;
@@ -31,7 +31,7 @@ import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
* Basic smoke tests for <%- camelize(type) %>Layer
*/
@RunWith(AndroidJUnit4.class)
-public class <%- camelize(type) %>LayerTest extends BaseTest {
+public class <%- camelize(type) %>LayerTest extends BaseStyleTest {
private static final String TAG = <%- camelize(type) %>LayerTest.class.getSimpleName();
@Rule
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/utils/DrawerUtils.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/DrawerUtils.java
index 8b39503d45..8d8905fdf4 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/utils/DrawerUtils.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/DrawerUtils.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.utils;
+package com.mapbox.mapboxsdk.testapp.utils;
import android.support.annotation.StringRes;
import android.support.test.espresso.Espresso;
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/utils/GestureUtils.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/GestureUtils.java
index 38d76f5d83..114fbc549e 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/utils/GestureUtils.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/GestureUtils.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.utils;
+package com.mapbox.mapboxsdk.testapp.utils;
import android.support.annotation.IdRes;
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/utils/OnMapReadyIdlingResource.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/OnMapReadyIdlingResource.java
index 43f3c07589..c966f61f8c 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/utils/OnMapReadyIdlingResource.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/OnMapReadyIdlingResource.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.utils;
+package com.mapbox.mapboxsdk.testapp.utils;
import android.app.Activity;
import android.support.test.espresso.IdlingResource;
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/utils/ScreenshotUtil.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/ScreenshotUtil.java
index 87b2d181f9..8fedf38619 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/utils/ScreenshotUtil.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/ScreenshotUtil.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.utils;
+package com.mapbox.mapboxsdk.testapp.utils;
import android.app.Activity;
import android.graphics.Bitmap;
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/utils/ViewUtils.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/ViewUtils.java
index 739fce1cfb..01ee3e9b9f 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/utils/ViewUtils.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/ViewUtils.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.utils;
+package com.mapbox.mapboxsdk.testapp.utils;
import android.support.annotation.IdRes;
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
index 164625d3fb..c8a0de9826 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
@@ -348,6 +348,13 @@
android:name="@string/category"
android:value="@string/category_style" />
</activity>
+ <activity android:name=".activity.style.RealTimeGeoJsonActivity"
+ android:description="@string/description_geojson_realtime"
+ android:label="@string/activity_geojson_realtime">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_style" />
+ </activity>
<activity
android:name=".activity.style.StyleFileActivity"
android:description="@string/description_style_file"
@@ -422,6 +429,14 @@
android:name="@string/category"
android:value="@string/category_annotation" />
</activity>
+ <activity
+ android:name=".activity.maplayout.MapInDialogActivity"
+ android:description="@string/description_map_in_dialog"
+ android:label="@string/activity_map_in_dialog">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_maplayout" />
+ </activity>
<!-- For Unit tests -->
<activity android:name=".activity.style.RuntimeStyleTestActivity" />
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 7842542ef1..3c3399168a 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
@@ -54,8 +54,6 @@ public class DynamicMarkerChangeActivity extends AppCompatActivity {
@Override
public void onMapReady(@NonNull MapboxMap mapboxMap) {
DynamicMarkerChangeActivity.this.mapboxMap = mapboxMap;
- mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(51.506675, -0.128699), 10));
-
// Create marker
MarkerOptions markerOptions = new MarkerOptions()
.position(LAT_LNG_CHELSEA)
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 d8c3cb6011..dd80b2ba5a 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
@@ -58,6 +58,7 @@ public class PolygonActivity extends AppCompatActivity implements OnMapReadyCall
.attributionTintColor(RED_COLOR)
// deprecated feature!
.textureMode(true)
+ .compassFadesWhenFacingNorth(false)
.styleUrl(Style.MAPBOX_STREETS)
.camera(new CameraPosition.Builder()
.target(new LatLng(45.520486, -122.673541))
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
new file mode 100644
index 0000000000..3df236f43c
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapInDialogActivity.java
@@ -0,0 +1,116 @@
+package com.mapbox.mapboxsdk.testapp.activity.maplayout;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.app.DialogFragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.LayoutInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+
+import com.mapbox.mapboxsdk.maps.MapView;
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
+import com.mapbox.mapboxsdk.testapp.R;
+
+public class MapInDialogActivity extends AppCompatActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_map_in_dialog);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
+
+ 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");
+ }
+ });
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ public static class MapDialogFragment extends DialogFragment {
+
+ private MapView mapView;
+
+ public MapDialogFragment() {}
+
+ public static MapDialogFragment newInstance(String title) {
+ MapDialogFragment frag = new MapDialogFragment();
+ Bundle args = new Bundle();
+ args.putString("title", title);
+ frag.setArguments(args);
+ return frag;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.fragment_dialog_map, container);
+ }
+
+ @Override
+ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+
+ mapView = (MapView) view.findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RealTimeGeoJsonActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RealTimeGeoJsonActivity.java
new file mode 100644
index 0000000000..debd44fb1f
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RealTimeGeoJsonActivity.java
@@ -0,0 +1,141 @@
+package com.mapbox.mapboxsdk.testapp.activity.style;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.annotation.NonNull;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.util.Log;
+import android.view.MenuItem;
+
+import com.mapbox.mapboxsdk.constants.MapboxConstants;
+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;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage;
+
+/**
+ * Use realtime GeoJSON data streams to move a symbol on your map
+ * <p>
+ * GL-native equivalent of https://www.mapbox.com/mapbox-gl-js/example/live-geojson/
+ * </p>
+ */
+public class RealTimeGeoJsonActivity extends AppCompatActivity implements OnMapReadyCallback {
+
+ private final static String ID_GEOJSON_LAYER = "wanderdrone";
+ private final static String ID_GEOJSON_SOURCE = ID_GEOJSON_LAYER;
+ private final static String URL_GEOJSON_SOURCE = "https://wanderdrone.appspot.com/";
+
+ private MapView mapView;
+ private MapboxMap mapboxMap;
+
+ private Handler handler;
+ private Runnable runnable;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_default);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
+
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(@NonNull final MapboxMap map) {
+ mapboxMap = map;
+
+ // add source
+ try {
+ mapboxMap.addSource(new GeoJsonSource(ID_GEOJSON_SOURCE, new URL(URL_GEOJSON_SOURCE)));
+ }catch (MalformedURLException e){
+ Log.e(MapboxConstants.TAG, "Invalid URL", e);
+ }
+
+ // add layer
+ SymbolLayer layer = new SymbolLayer(ID_GEOJSON_LAYER, ID_GEOJSON_SOURCE);
+ layer.setProperties(iconImage("rocket-15"));
+ mapboxMap.addLayer(layer);
+
+ // loop refresh geojson
+ handler = new Handler();
+ runnable = new RefreshGeoJsonRunnable(mapboxMap, handler);
+ handler.postDelayed(runnable, 2000);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ handler.removeCallbacks(runnable);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ private static class RefreshGeoJsonRunnable implements Runnable {
+
+ private MapboxMap mapboxMap;
+ private Handler handler;
+
+ RefreshGeoJsonRunnable(MapboxMap mapboxMap, Handler handler) {
+ this.mapboxMap = mapboxMap;
+ this.handler = handler;
+ }
+
+ @Override
+ public void run() {
+ ((GeoJsonSource) mapboxMap.getSource(ID_GEOJSON_SOURCE)).setUrl(URL_GEOJSON_SOURCE);
+ handler.postDelayed(this, 2000);
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_default.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_default.xml
new file mode 100644
index 0000000000..742f6612bd
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_default.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <android.support.v7.widget.Toolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="?attr/actionBarSize"
+ android:background="@color/primary"
+ android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
+
+ <com.mapbox.mapboxsdk.maps.MapView
+ android:id="@+id/mapView"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_below="@id/toolbar" />
+
+</RelativeLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_dynamic_marker.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_dynamic_marker.xml
index 6d9a15af89..d6507559ec 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_dynamic_marker.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_dynamic_marker.xml
@@ -25,7 +25,13 @@
<com.mapbox.mapboxsdk.maps.MapView
android:id="@id/mapView"
android:layout_width="match_parent"
- android:layout_height="match_parent" />
+ android:layout_height="match_parent"
+ app:center_latitude="51.506675"
+ app:center_longitude="-0.128699"
+ app:compass_fade_facing_north="false"
+ app:direction="90"
+ app:tilt="40"
+ app:zoom="10" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_manual_zoom.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_manual_zoom.xml
index 746b8ffb11..c1f09a36d0 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_manual_zoom.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_manual_zoom.xml
@@ -2,6 +2,7 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
@@ -13,6 +14,10 @@
<com.mapbox.mapboxsdk.maps.MapView
android:id="@id/mapView"
+ app:center_latitude="50.871062"
+ app:center_longitude="1.583210"
+ app:direction="220"
+ app:zoom="10"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/toolbar" />
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_map_in_dialog.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_map_in_dialog.xml
new file mode 100644
index 0000000000..1edc456252
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_map_in_dialog.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <android.support.v7.widget.Toolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="?attr/actionBarSize"
+ android:background="@color/primary"
+ android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
+
+ <Button
+ android:id="@+id/button_open_dialog"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:text="@string/button_open_dialog"/>
+
+</FrameLayout> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/fragment_dialog_map.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/fragment_dialog_map.xml
new file mode 100644
index 0000000000..51ec3c4677
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/fragment_dialog_map.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:mapbox="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"
+ mapbox:center_latitude="47.6077"
+ mapbox:center_longitude="-122.3421"
+ mapbox:style_url="mapbox://styles/mapbox/streets-v9"
+ mapbox:zoom="11"/>
+
+</LinearLayout> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml
index 855e9a0bef..a4f19f1e01 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml
@@ -60,6 +60,7 @@
<string name="activity_runtime_style">Runtime Style</string>
<string name="activity_style_file">Local Style file</string>
<string name="activity_geojson_clustering">GeoJson Clustering</string>
+ <string name="activity_geojson_realtime">Add live realtime data</string>
<string name="activity_print">Print a map</string>
<string name="activity_surfaceview_overlay">SurfaceView MediaOverlay</string>
<string name="activity_query_rendered_feature_properties">Query feature properties</string>
@@ -69,6 +70,7 @@
<string name="activity_add_sprite">Add Custom Sprite</string>
<string name="activity_navigation_drawer">Android SDK View integration</string>
<string name="activity_video_view">Video View</string>
+ <string name="activity_map_in_dialog">Dialog with map</string>
<!-- Description -->
<string name="description_user_location_tracking">Tracks the location of the user</string>
@@ -112,6 +114,7 @@
<string name="description_circle">Use GeoJson source to show a circle</string>
<string name="description_custom_sprite">Use a custom sprite in a Symbol Layer</string>
<string name="description_geojson_clustering">Use GeoJson sources and dynamic layers to cluster information</string>
+ <string name="description_geojson_realtime">Use realtime GeoJSON data streams to move a symbol on your map</string>
<string name="description_print">Shows how to print a map</string>
<string name="description_navigation_drawer">Test animation of Android SDK View components</string>
<string name="description_surfaceview_mediacontrols">Test overlaying SurfaceView</string>
@@ -122,6 +125,7 @@
<string name="description_video_view">Android video view on top of the map view</string>
<string name="description_add_remove_markers">Based on zoom level</string>
<string name="description_style_file">Use a local file as the style</string>
+ <string name="description_map_in_dialog">Display a map inside a dialog fragment</string>
<string name="menuitem_title_concurrent_infowindow">Concurrent Open InfoWindows</string>
<string name="menuitem_title_deselect_markers_on_tap">Deselect Markers On Tap</string>
@@ -161,6 +165,7 @@
<string name="button_user_dot_default">Default</string>
<string name="button_user_dot_tint">Tint dot</string>
<string name="button_user_accuracy_ring_tint">Tint ring</string>
+ <string name="button_open_dialog">Open dialog</string>
<string name="label_fps">FPS:</string>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java
index 300ed1d73a..14fc84723d 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java
@@ -7,6 +7,7 @@ import org.junit.Test;
import org.mockito.InjectMocks;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
@@ -57,6 +58,13 @@ public class UiSettingsTest {
}
@Test
+ public void testCompassFadeWhenFacingNorth(){
+ assertTrue("Compass should fade when facing north by default.", uiSettings.isCompassFadeWhenFacingNorth());
+ uiSettings.setCompassFadeFacingNorth(false);
+ assertFalse("Compass fading should be disabled", uiSettings.isCompassFadeWhenFacingNorth());
+ }
+
+ @Test
public void testLogoEnabled() {
uiSettings.setLogoEnabled(true);
assertEquals("Logo should be enabled", true, uiSettings.isLogoEnabled());
diff --git a/platform/android/MapboxGLAndroidSDKWearTestApp/build.gradle b/platform/android/MapboxGLAndroidSDKWearTestApp/build.gradle
index 6fbab3a32c..6bd1fac322 100644
--- a/platform/android/MapboxGLAndroidSDKWearTestApp/build.gradle
+++ b/platform/android/MapboxGLAndroidSDKWearTestApp/build.gradle
@@ -30,6 +30,7 @@ android {
versionCode 1
versionName "1.0"
}
+
buildTypes {
release {
minifyEnabled false
diff --git a/platform/android/bitrise.yml b/platform/android/bitrise.yml
index 5fe160214b..c168a9a6d6 100644
--- a/platform/android/bitrise.yml
+++ b/platform/android/bitrise.yml
@@ -26,58 +26,101 @@ workflows:
envman add --key SKIPCI --value false
fi
- script:
- title: Build
+ title: Configure GL-native build environement
run_if: '{{enveq "SKIPCI" "false"}}'
inputs:
- content: |-
#!/bin/bash
+ set -eu -o pipefail
+ curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash -
+ sudo apt-get install -y pkg-config nodejs cmake
+ - script:
+ title: Configure Google Cloud SDK
+ run_if: '{{enveq "SKIPCI" "false"}}'
+ inputs:
+ - content: |-
+ #!/bin/bash
+ # Install python tools for pip
sudo apt-get install -y gcc python-dev python-setuptools
sudo easy_install -U pip
sudo pip uninstall crcmod
sudo pip install -U crcmod
- set -eu -o pipefail
- curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash -
- sudo apt-get install -y pkg-config nodejs cmake
- export BUILDTYPE=Debug
- make android
- make android-test
- make android-generate-test
- wget -O platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/developer-config.xml "$BITRISEIO_TEST_ACCESS_TOKEN_UI_TEST_URL"
- make android-test-apk
- wget -O secret.json "$BITRISEIO_GCLOUD_SERVICE_ACCOUNT_JSON_URL"
+
+ # Install Google Cloud SDK for Firebase
export CLOUD_SDK_REPO="cloud-sdk-$(lsb_release -c -s)"
echo "deb http://packages.cloud.google.com/apt $CLOUD_SDK_REPO 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 google-cloud-sdk
- gcloud auth activate-service-account --key-file secret.json --project android-gl-native
- gcloud beta test android devices list
- gcloud beta test android run --type instrumentation --app platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk/MapboxGLAndroidSDKTestApp-debug.apk --test platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk/MapboxGLAndroidSDKTestApp-debug-androidTest-unaligned.apk --device-ids shamu --os-version-ids 22 --locales en --orientations portrait --timeout 15m --test-targets "class com.mapbox.mapboxsdk.camera.RotateTest"
+
+ # Get authentication secret
+ echo "Downloading Google Cloud authnetication:"
+ wget -O secret.json "$BITRISEIO_GCLOUD_SERVICE_ACCOUNT_JSON_URL"
- script:
- title: Download test results
- is_always_run: true
+ title: Build libmapbox-gl.so for armeabi-v7a
+ run_if: '{{enveq "SKIPCI" "false"}}'
inputs:
- content: |-
#!/bin/bash
- testUri="gs://test-lab-wrrntqk05p31w-h3y1qk44vuunw/"
- testUri=$(gsutil ls $testUri | tail -n1)
- echo "Downloading from : "$testUri
- cd platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk && gsutil -m cp -R -Z $testUri .
- - deploy-to-bitrise-io@1.2.3:
+ echo "Compile libmapbox-gl.so for armeabi-v7a abi:"
+ export BUILDTYPE=Debug
+ make android-lib-arm-v7
+ - script:
+ title: Run local JVM Unit tests
+ run_if: '{{enveq "SKIPCI" "false"}}'
inputs:
- - deploy_path: "platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk"
- - notify_user_groups: none
- - is_compress: 'true'
+ - content: |-
+ #!/bin/bash
+ echo "Running unit tests from testapp/src/test:"
+ make android-test
+ - script:
+ title: Generate Espresso sanity tests
+ run_if: '{{enveq "SKIPCI" "false"}}'
+ inputs:
+ - content: |-
+ #!/bin/bash
+ echo "Generate these test locally by executing:"
+ make android-generate-test
- script:
- title: Run ndk-stack
+ title: Run Firebase instrumentation tests
+ run_if: '{{enveq "SKIPCI" "false"}}'
+ inputs:
+ - content: |-
+ #!/bin/bash
+ echo "Downloading Mapbox accesstoken for running tests:"
+ wget -O platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/developer-config.xml "$BITRISEIO_TEST_ACCESS_TOKEN_UI_TEST_URL"
+
+ echo "Build seperate test apk:"
+ make android-test-apk
+
+ echo "Run tests on firebase:"
+ gcloud auth activate-service-account --key-file secret.json --project android-gl-native
+ gcloud beta test android devices list
+ gcloud beta test android run --type instrumentation --app platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk/MapboxGLAndroidSDKTestApp-debug.apk --test platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk/MapboxGLAndroidSDKTestApp-debug-androidTest-unaligned.apk --device-ids shamu --os-version-ids 22 --locales en --orientations portrait --timeout 15m --test-targets "class com.mapbox.mapboxsdk.testapp.camera.RotateActivityTest"
+ echo "The details are made available as a zipped build artefact on top of this page."
+ - script:
+ title: Download Firebase results
+ run_if: '{{enveq "SKIPCI" "false"}}'
is_always_run: true
inputs:
- content: |-
#!/bin/bash
+ echo "The details from Firebase will be downloaded, zipped and attached as a build artefact."
+ testUri=$(gsutil ls "gs://test-lab-wrrntqk05p31w-h3y1qk44vuunw/" | tail -n1)
+ echo "Downloading from : "$testUri
+ cd platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk && gsutil -m cp -R -Z $testUri .
+
+ echo "Try running ndk-stack on downloaded logcat to symbolicate the stacktraces:"
find platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk -type f -name "logcat" -print0 | xargs -0 -Imylogcat mv -i mylogcat ./
cat logcat | ndk-stack -sym build/android-arm-v7/Debug
+ - deploy-to-bitrise-io:
+ run_if: '{{enveq "SKIPCI" "false"}}'
+ inputs:
+ - deploy_path: platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk
+ - is_compress: 'true'
+ - notify_user_groups: none
- slack:
- title: Post to Slack
run_if: '{{enveq "SKIPCI" "false"}}'
+ title: Post to Slack
inputs:
- webhook_url: "$SLACK_HOOK_URL"
- channel: "#gl-bots"
@@ -96,50 +139,98 @@ workflows:
scheduled:
steps:
- script:
- title: Build
+ title: Configure GL-native build environement
inputs:
- content: |-
#!/bin/bash
set -eu -o pipefail
-
curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash -
- apt-get install -y pkg-config python-pip python-dev build-essential nodejs cmake
+ sudo apt-get install -y pkg-config nodejs cmake
+ - script:
+ title: Configure AWS-CLI
+ inputs:
+ - content: |-
+ #!/bin/bash
+ apt-get install -y python-pip python-dev build-essential
pip install awscli
-
+ - script:
+ title: Download maven credentials
+ inputs:
+ - content: |-
+ #!/bin/bash
aws s3 cp s3://mapbox/android/signing-credentials/secring.gpg platform/android/MapboxGLAndroidSDK/secring.gpg
+ # Add maven credentals for publishing
echo "NEXUS_USERNAME=$PUBLISH_NEXUS_USERNAME
NEXUS_PASSWORD=$PUBLISH_NEXUS_PASSWORD
signing.keyId=$SIGNING_KEYID
signing.password=$SIGNING_PASSWORD
signing.secretKeyRingFile=secring.gpg" >> platform/android/MapboxGLAndroidSDK/gradle.properties
-
+ - script:
+ title: Build release
+ inputs:
+ - content: |-
+ #!/bin/bash
+ echo "Compile libmapbox-gl.so for all supportd abi's:"
export BUILDTYPE=Release
make apackage
-
- cd platform/android
- ./gradlew uploadArchives
+ - script:
+ title: Publish to maven
+ inputs:
+ - content: |-
+ #!/bin/bash
+ echo "Upload aar file to maven:"
+ cd platform/android && ./gradlew uploadArchives
+ - slack:
+ title: Post to Slack
+ inputs:
+ - webhook_url: "$SLACK_HOOK_URL"
+ - channel: "#gl-bots"
+ - from_username: 'Bitrise Android'
+ - from_username_on_error: 'Bitrise Android'
+ - message: '<${BITRISE_BUILD_URL}|Build #${BITRISE_BUILD_NUMBER}> Publish to maven SUCCESS.'
+ - message_on_error: '<${BITRISE_BUILD_URL}|Build #${BITRISE_BUILD_NUMBER}> Publish to maven FAILED.'
+ - icon_url: https://bitrise-public-content-production.s3.amazonaws.com/slack/bitrise-slack-icon-128.png
+ - icon_url_on_error: https://bitrise-public-content-production.s3.amazonaws.com/slack/bitrise-slack-error-icon-128.png
devicefarmUpload:
steps:
- script:
- title: Build
+ title: Configure GL-native build environement
inputs:
- content: |-
#!/bin/bash
set -eu -o pipefail
curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash -
sudo apt-get install -y pkg-config nodejs cmake
-
- echo "AWS_ACCESS_KEY_ID_DEVICE_FARM=$AWS_ACCESS_KEY_ID_DEVICE_FARM
- AWS_SECRET_ACCESS_KEY_DEVICE_FARM=$AWS_SECRET_ACCESS_KEY_DEVICE_FARM"
- >> platform/android/MapboxGLAndroidSDK/gradle.properties
-
+ - script:
+ title: Build release
+ inputs:
+ - content: |-
+ #!/bin/bash
+ echo "Compile libmapbox-gl.so for all supportd abi's:"
export BUILDTYPE=Release
make apackage
-
+ - script:
+ title: Add AWS credentials
+ inputs:
+ - content: |-
+ #!/bin/bash
+ echo "AWS_ACCESS_KEY_ID_DEVICE_FARM=$AWS_ACCESS_KEY_ID_DEVICE_FARM" >> platform/android/MapboxGLAndroidSDKTestApp/gradle.properties
+ echo "AWS_SECRET_ACCESS_KEY_DEVICE_FARM=$AWS_SECRET_ACCESS_KEY_DEVICE_FARM" >> platform/android/MapboxGLAndroidSDKTestApp/gradle.properties
+ - script:
+ title: Generate sanity tests
+ inputs:
+ - content: |-
+ #!/bin/bash
+ echo "Generate these test locally by executing:"
make android-generate-test
- cd platform/android/
- ./gradlew devicefarmUpload
+ - script:
+ title: Run AWS Device Farm instrumentation tests
+ inputs:
+ - content: |-
+ #!/bin/bash
+ echo "Run tests on device farm:"
+ cd platform/android && ./gradlew devicefarmUpload
- slack:
title: Post to Slack
inputs:
@@ -147,9 +238,7 @@ workflows:
- channel: "#gl-bots"
- from_username: 'Bitrise Android'
- from_username_on_error: 'Bitrise Android'
- - message: '<${BITRISE_BUILD_URL}|Build #${BITRISE_BUILD_NUMBER}>
- for devicefarmUpload passed'
- - message_on_error: '<${BITRISE_BUILD_URL}|Build #${BITRISE_BUILD_NUMBER}>
- for devicefarmUpload failed'
+ - message: '<${BITRISE_BUILD_URL}|Build #${BITRISE_BUILD_NUMBER}> for devicefarmUpload passed'
+ - message_on_error: '<${BITRISE_BUILD_URL}|Build #${BITRISE_BUILD_NUMBER}> for devicefarmUpload failed'
- icon_url: https://bitrise-public-content-production.s3.amazonaws.com/slack/bitrise-slack-icon-128.png
- icon_url_on_error: https://bitrise-public-content-production.s3.amazonaws.com/slack/bitrise-slack-error-icon-128.png
diff --git a/platform/android/config.cmake b/platform/android/config.cmake
index 1e6132dc30..74412e4ae5 100644
--- a/platform/android/config.cmake
+++ b/platform/android/config.cmake
@@ -48,6 +48,9 @@ macro(mbgl_platform_core)
# Headless view
# TODO
+
+ # Thread pool
+ PRIVATE platform/default/thread_pool.cpp
)
target_include_directories(mbgl-core
diff --git a/platform/android/scripts/generate-style-code.js b/platform/android/scripts/generate-style-code.js
index ca2d2e6778..1216bd4cbe 100644
--- a/platform/android/scripts/generate-style-code.js
+++ b/platform/android/scripts/generate-style-code.js
@@ -103,7 +103,7 @@ global.propertyNativeType = function (property) {
if (/-translate-anchor$/.test(property.name)) {
return 'TranslateAnchorType';
}
- if (/-(rotation|pitch)-alignment$/.test(property.name)) {
+ if (/-(rotation|pitch|illumination)-alignment$/.test(property.name)) {
return 'AlignmentType';
}
switch (property.type) {
@@ -240,13 +240,13 @@ global.propertyValueDoc = function (property, value) {
const layerHpp = ejs.compile(fs.readFileSync('platform/android/src/style/layers/layer.hpp.ejs', 'utf8'), {strict: true});
const layerCpp = ejs.compile(fs.readFileSync('platform/android/src/style/layers/layer.cpp.ejs', 'utf8'), {strict: true});
const layerJava = ejs.compile(fs.readFileSync('platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/layer.java.ejs', 'utf8'), {strict: true});
-const layerJavaUnitTests = ejs.compile(fs.readFileSync('platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/layer.junit.ejs', 'utf8'), {strict: true});
+const layerJavaUnitTests = ejs.compile(fs.readFileSync('platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/layer.junit.ejs', 'utf8'), {strict: true});
for (const layer of layers) {
fs.writeFileSync(`platform/android/src/style/layers/${layer.type}_layer.hpp`, layerHpp(layer));
fs.writeFileSync(`platform/android/src/style/layers/${layer.type}_layer.cpp`, layerCpp(layer));
fs.writeFileSync(`platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/${camelize(layer.type)}Layer.java`, layerJava(layer));
- fs.writeFileSync(`platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/style/${camelize(layer.type)}LayerTest.java`, layerJavaUnitTests(layer));
+ fs.writeFileSync(`platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/${camelize(layer.type)}LayerTest.java`, layerJavaUnitTests(layer));
}
diff --git a/platform/android/scripts/generate-test-code.js b/platform/android/scripts/generate-test-code.js
index 5ec1d0b3bf..17f0079906 100644
--- a/platform/android/scripts/generate-test-code.js
+++ b/platform/android/scripts/generate-test-code.js
@@ -14,11 +14,11 @@ global.camelize = function (str) {
}
-const excludeActivities = ["UpdateMetadataActivity","CarDrivingActivity","MyLocationTrackingModeActivity","MyLocationToggleActivity","MyLocationTintActivity","MyLocationDrawableActivity","DoubleMapActivity", "LocationPickerActivity","GeoJsonClusteringActivity","RuntimeStyleTestActivity", "AnimatedMarkerActivity", "ViewPagerActivity","MapFragmentActivity","SupportMapFragmentActivity","SnapshotActivity","NavigationDrawerActivity", "QueryRenderedFeaturesBoxHighlightActivity", "MultiMapActivity"];
+const excludeActivities = ["UpdateMetadataActivity","CarDrivingActivity","MyLocationTrackingModeActivity","MyLocationToggleActivity","MyLocationTintActivity","MyLocationDrawableActivity","DoubleMapActivity", "LocationPickerActivity","GeoJsonClusteringActivity","RuntimeStyleTestActivity", "AnimatedMarkerActivity", "ViewPagerActivity","MapFragmentActivity","SupportMapFragmentActivity","SnapshotActivity","NavigationDrawerActivity", "QueryRenderedFeaturesBoxHighlightActivity", "MultiMapActivity", "MapInDialogActivity"];
const appBasePath = 'platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity';
-const testBasePath = 'platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/activity/gen';
+const testBasePath = 'platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen';
const subPackages = fs.readdirSync(appBasePath);
-const ejsConversionTask = ejs.compile(fs.readFileSync('platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/activity/activity.junit.ejs', 'utf8'), {strict: true});
+const ejsConversionTask = ejs.compile(fs.readFileSync('platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/activity.junit.ejs', 'utf8'), {strict: true});
if (!fs.existsSync(testBasePath)){
fs.mkdirSync(testBasePath);
@@ -60,4 +60,3 @@ for(const subPackage of subPackages) {
}
}
}
-
diff --git a/platform/android/src/jni.cpp b/platform/android/src/jni.cpp
index 4313b19323..6dcd177cd6 100755
--- a/platform/android/src/jni.cpp
+++ b/platform/android/src/jni.cpp
@@ -257,7 +257,6 @@ jni::jarray<jlong>* std_vector_uint_to_jobject(JNIEnv *env, const std::vector<ui
}
static std::vector<uint8_t> metadata_from_java(JNIEnv* env, jni::jarray<jbyte>& j) {
- mbgl::Log::Debug(mbgl::Event::JNI, "metadata_from_java");
std::size_t length = jni::GetArrayLength(*env, j);
std::vector<uint8_t> c;
c.resize(length);
@@ -266,7 +265,6 @@ static std::vector<uint8_t> metadata_from_java(JNIEnv* env, jni::jarray<jbyte>&
}
static jni::jarray<jbyte>* metadata_from_native(JNIEnv* env, const std::vector<uint8_t>& c) {
- mbgl::Log::Debug(mbgl::Event::JNI, "metadata_from_java");
std::size_t length = static_cast<std::size_t>(c.size());
jni::jarray<jbyte>& j = jni::NewArray<jbyte>(*env, length);
jni::SetArrayRegion(*env, j, 0, c.size(), reinterpret_cast<const jbyte*>(c.data()));
@@ -358,10 +356,9 @@ void nativeDestroySurface(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr
}
void nativeUpdate(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeUpdate");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->getMap().update(mbgl::Update::Repaint);
+ nativeMapView->invalidate();
}
void nativeRender(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
@@ -393,77 +390,66 @@ void nativeFramebufferResize(JNIEnv *env, jni::jobject* obj, jlong nativeMapView
}
void nativeRemoveClass(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* clazz) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeRemoveClass");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
nativeMapView->getMap().removeClass(std_string_from_jstring(env, clazz));
}
jboolean nativeHasClass(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* clazz) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeHasClass");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
return nativeMapView->getMap().hasClass(std_string_from_jstring(env, clazz));
}
void nativeAddClass(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* clazz) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddClass");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
nativeMapView->getMap().addClass(std_string_from_jstring(env, clazz));
}
void nativeSetClasses(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jobject* classes) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetClasses");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
nativeMapView->getMap().setClasses(std_vector_string_from_jobject(env, classes));
}
jni::jobject* nativeGetClasses(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetClasses");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
return std_vector_string_to_jobject(env, nativeMapView->getMap().getClasses());
}
void nativeSetAPIBaseURL(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* url) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetAPIBaseURL");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
nativeMapView->getFileSource().setAPIBaseURL(std_string_from_jstring(env, url));
}
void nativeSetStyleUrl(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* url) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetStyleURL");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
nativeMapView->getMap().setStyleURL(std_string_from_jstring(env, url));
}
void nativeSetStyleJson(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* newStyleJson) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetStyleJSON");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
nativeMapView->getMap().setStyleJSON(std_string_from_jstring(env, newStyleJson));
}
jni::jstring* nativeGetStyleJson(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetStyleJSON");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
return std_string_to_jstring(env, nativeMapView->getMap().getStyleJSON());
}
void nativeSetAccessToken(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* accessToken) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetAccessToken");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
nativeMapView->getFileSource().setAccessToken(std_string_from_jstring(env, accessToken));
}
jni::jstring* nativeGetAccessToken(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetAccessToken");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
return std_string_to_jstring(env, nativeMapView->getFileSource().getAccessToken());
@@ -512,7 +498,7 @@ jdoubleArray nativeGetCameraValues(JNIEnv *env, jni::jobject* obj, jlong nativeM
jdouble buf[5];
buf[0] = latLng.latitude;
buf[1] = latLng.longitude;
- buf[2] = nativeMapView->getMap().getBearing();
+ buf[2] = -(nativeMapView->getMap().getBearing()-360);
buf[3] = nativeMapView->getMap().getPitch();
buf[4] = nativeMapView->getMap().getZoom();
env->SetDoubleArrayRegion(output, start, leng, buf);
@@ -526,21 +512,18 @@ jdoubleArray nativeGetCameraValues(JNIEnv *env, jni::jobject* obj, jlong nativeM
}
void nativeResetPosition(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeResetPosition");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
nativeMapView->getMap().resetPosition();
}
jdouble nativeGetPitch(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetPitch");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
return nativeMapView->getMap().getPitch();
}
void nativeSetPitch(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble pitch, jlong milliseconds) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetPitch");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
mbgl::Duration duration((mbgl::Milliseconds(milliseconds)));
@@ -549,7 +532,6 @@ void nativeSetPitch(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdou
void nativeScaleBy(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble ds, jdouble cx,
jdouble cy, jlong duration) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeScaleBy");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
mbgl::ScreenCoordinate center(cx, cy);
@@ -558,7 +540,6 @@ void nativeScaleBy(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdoub
void nativeSetScale(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble scale,
jdouble cx, jdouble cy, jlong duration) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetScale");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
mbgl::ScreenCoordinate center(cx, cy);
@@ -566,56 +547,48 @@ void nativeSetScale(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdou
}
jdouble nativeGetScale(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetScale");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
return nativeMapView->getMap().getScale();
}
void nativeSetZoom(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble zoom, jlong duration) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetZoom");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
nativeMapView->getMap().setZoom(zoom, mbgl::Milliseconds(duration));
}
jdouble nativeGetZoom(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetZoom");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
return nativeMapView->getMap().getZoom();
}
void nativeResetZoom(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeResetZoom");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
nativeMapView->getMap().resetZoom();
}
void nativeSetMinZoom(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble zoom) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetMinZoom");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
nativeMapView->getMap().setMinZoom(zoom);
}
jdouble nativeGetMinZoom(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetMinZoom");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
return nativeMapView->getMap().getMinZoom();
}
void nativeSetMaxZoom(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble zoom) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetMaxZoom");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
nativeMapView->getMap().setMaxZoom(zoom);
}
jdouble nativeGetMaxZoom(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetMaxZoom");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
return nativeMapView->getMap().getMaxZoom();
@@ -623,7 +596,6 @@ jdouble nativeGetMaxZoom(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr)
void nativeRotateBy(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble sx,
jdouble sy, jdouble ex, jdouble ey, jlong duration) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeRotateBy");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
mbgl::ScreenCoordinate first(sx, sy);
@@ -633,7 +605,6 @@ void nativeRotateBy(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdou
void nativeSetBearing(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble degrees,
jlong milliseconds) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetBearing");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
mbgl::Duration duration((mbgl::Milliseconds(milliseconds)));
@@ -642,7 +613,6 @@ void nativeSetBearing(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jd
void nativeSetBearingXY(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble degrees,
jdouble cx, jdouble cy) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetBearingXY");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
mbgl::ScreenCoordinate center(cx, cy);
@@ -650,21 +620,18 @@ void nativeSetBearingXY(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr,
}
jdouble nativeGetBearing(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetBearing");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
return nativeMapView->getMap().getBearing();
}
void nativeResetNorth(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeResetNorth");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
nativeMapView->getMap().resetNorth();
}
void nativeUpdateMarker(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jlong markerId, jdouble lat, jdouble lon, jni::jstring* jid) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeUpdateMarker");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
if (markerId == -1) {
@@ -676,7 +643,6 @@ void nativeUpdateMarker(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr,
}
jni::jarray<jlong>* nativeAddMarkers(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jarray<jni::jobject>* jarray) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddMarkers");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
@@ -747,7 +713,6 @@ Geometry toGeometry(JNIEnv *env, jni::jobject* jlist) {
}
jni::jarray<jlong>* nativeAddPolylines(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jarray<jni::jobject>* jarray) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddPolylines");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
@@ -774,7 +739,6 @@ jni::jarray<jlong>* nativeAddPolylines(JNIEnv *env, jni::jobject* obj, jlong nat
}
jni::jarray<jlong>* nativeAddPolygons(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jarray<jni::jobject>* jarray) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddPolygons");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
@@ -801,7 +765,6 @@ jni::jarray<jlong>* nativeAddPolygons(JNIEnv *env, jni::jobject* obj, jlong nati
}
void nativeUpdatePolygon(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jlong polygonId, jni::jobject* polygon) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeUpdatePolygon");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
jni::jobject* points = jni::GetField<jni::jobject*>(*env, polygon, *polygonPointsId);
@@ -814,7 +777,6 @@ void nativeUpdatePolygon(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr,
}
void nativeUpdatePolyline(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jlong polylineId, jni::jobject* polyline) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeUpdatePolyline");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
jni::jobject* points = jni::GetField<jni::jobject*>(*env, polyline, *polylinePointsId);
@@ -827,7 +789,6 @@ void nativeUpdatePolyline(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr
}
void nativeRemoveAnnotations(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jarray<jlong>* jarray) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeRemoveAnnotations");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
@@ -844,7 +805,6 @@ void nativeRemoveAnnotations(JNIEnv *env, jni::jobject* obj, jlong nativeMapView
}
jni::jarray<jlong>* nativeQueryPointAnnotations(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jobject* rect) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeQueryPointAnnotations");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
@@ -866,7 +826,6 @@ jni::jarray<jlong>* nativeQueryPointAnnotations(JNIEnv *env, jni::jobject* obj,
void nativeAddAnnotationIcon(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr,
jni::jstring* symbol, jint width, jint height, jfloat scale, jni::jarray<jbyte>* jpixels) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddAnnotationIcon");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
@@ -891,7 +850,6 @@ void nativeAddAnnotationIcon(JNIEnv *env, jni::jobject* obj, jlong nativeMapView
void nativeSetVisibleCoordinateBounds(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr,
jni::jarray<jni::jobject>* coordinates, jni::jobject* padding, jdouble direction, jlong duration) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetVisibleCoordinateBounds");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
@@ -933,7 +891,6 @@ jni::jarray<jni::jobject>* nativeQueryRenderedFeaturesForPoint(JNIEnv *env, jni:
using namespace mbgl::android::conversion;
using namespace mapbox::geometry;
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeQueryRenderedFeatures for Point");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
@@ -950,7 +907,6 @@ jni::jarray<jni::jobject>* nativeQueryRenderedFeaturesForBox(JNIEnv *env, jni::j
using namespace mbgl::android::conversion;
using namespace mapbox::geometry;
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeQueryRenderedFeatures for Box %.2f %.2f %.2f %.2f", left, top, right, bottom);
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
@@ -964,14 +920,12 @@ jni::jarray<jni::jobject>* nativeQueryRenderedFeaturesForBox(JNIEnv *env, jni::j
}
void nativeOnLowMemory(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeOnLowMemory");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
nativeMapView->getMap().onLowMemory();
}
void nativeSetDebug(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jboolean debug) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetDebug");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
@@ -982,7 +936,6 @@ void nativeSetDebug(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jboo
}
void nativeToggleDebug(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeToggleDebug");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
nativeMapView->getMap().cycleDebugOptions();
@@ -990,21 +943,18 @@ void nativeToggleDebug(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
}
jboolean nativeGetDebug(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetDebug");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
return nativeMapView->getMap().getDebug() != DebugOptions::NoDebug;
}
jboolean nativeIsFullyLoaded(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeIsFullyLoaded");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
return nativeMapView->getMap().isFullyLoaded();
}
void nativeSetReachability(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jboolean status) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetReachability");
assert(nativeMapViewPtr != 0);
if (status) {
mbgl::NetworkStatus::Reachable();
@@ -1057,12 +1007,12 @@ void nativeJumpTo(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdoubl
mbgl::CameraOptions options;
if (angle != -1) {
- options.angle = angle;
+ options.angle = angle * M_PI / 180;
}
options.center = mbgl::LatLng(latitude, longitude);
options.padding = nativeMapView->getInsets();
if (pitch != -1) {
- options.pitch = pitch;
+ options.pitch = pitch * M_PI / 180;
}
if (zoom != -1) {
options.zoom = zoom;
@@ -1077,12 +1027,12 @@ void nativeEaseTo(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdoubl
mbgl::CameraOptions cameraOptions;
if (angle != -1) {
- cameraOptions.angle = angle;
+ cameraOptions.angle = angle * M_PI / 180;
}
cameraOptions.center = mbgl::LatLng(latitude, longitude);
cameraOptions.padding = nativeMapView->getInsets();
if (pitch != -1) {
- cameraOptions.pitch = pitch;
+ cameraOptions.pitch = pitch * M_PI / 180;
}
if (zoom != -1) {
cameraOptions.zoom = zoom;
@@ -1110,12 +1060,12 @@ void nativeFlyTo(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble
mbgl::CameraOptions cameraOptions;
if (angle != -1) {
- cameraOptions.angle = angle;
+ cameraOptions.angle = angle * M_PI / 180 ;
}
cameraOptions.center = mbgl::LatLng(latitude, longitude);
cameraOptions.padding = nativeMapView->getInsets();
if (pitch != -1) {
- cameraOptions.pitch = pitch;
+ cameraOptions.pitch = pitch * M_PI / 180;
}
if (zoom != -1) {
cameraOptions.zoom = zoom;
@@ -1127,8 +1077,6 @@ void nativeFlyTo(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble
}
jni::jobject* nativeGetLayer(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* layerId) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetLayer");
-
assert(env);
assert(nativeMapViewPtr != 0);
@@ -1147,7 +1095,6 @@ jni::jobject* nativeGetLayer(JNIEnv *env, jni::jobject* obj, jlong nativeMapView
}
void nativeAddLayer(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jlong nativeLayerPtr, jni::jstring* before) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddLayer");
assert(nativeMapViewPtr != 0);
assert(nativeLayerPtr != 0);
@@ -1161,7 +1108,6 @@ void nativeAddLayer(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jlon
}
void nativeRemoveLayer(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* id) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeRemoveLayer");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
try {
@@ -1172,8 +1118,6 @@ void nativeRemoveLayer(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, j
}
jni::jobject* nativeGetSource(JNIEnv *env, jni::jobject* obj, jni::jlong nativeMapViewPtr, jni::jstring* sourceId) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetSource");
-
assert(env);
assert(nativeMapViewPtr != 0);
@@ -1192,7 +1136,6 @@ jni::jobject* nativeGetSource(JNIEnv *env, jni::jobject* obj, jni::jlong nativeM
}
void nativeAddSource(JNIEnv *env, jni::jobject* obj, jni::jlong nativeMapViewPtr, jni::jlong nativeSourcePtr) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddSource");
assert(nativeMapViewPtr != 0);
assert(nativeSourcePtr != 0);
@@ -1203,13 +1146,12 @@ void nativeAddSource(JNIEnv *env, jni::jobject* obj, jni::jlong nativeMapViewPtr
}
void nativeRemoveSource(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* id) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeRemoveSource");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
try {
nativeMapView->getMap().removeSource(std_string_from_jstring(env, id));
} catch (const std::runtime_error& error) {
- jni::ThrowNew(*env, jni::FindClass(*env, "com/mapbox/mapboxsdk/style/layers/NoSuchSourceException"), error.what());
+ jni::ThrowNew(*env, jni::FindClass(*env, "com/mapbox/mapboxsdk/style/sources/NoSuchSourceException"), error.what());
}
}
@@ -1241,7 +1183,6 @@ void nativeRemoveImage(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, j
}
void nativeScheduleTakeSnapshot(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeRenderToOffscreen");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
nativeMapView->scheduleTakeSnapshot();
@@ -1250,7 +1191,6 @@ void nativeScheduleTakeSnapshot(JNIEnv *env, jni::jobject* obj, jlong nativeMapV
// Offline calls begin
jlong createDefaultFileSource(JNIEnv *env, jni::jobject* obj, jni::jstring* cachePath_, jni::jstring* assetRoot_, jlong maximumCacheSize) {
- mbgl::Log::Debug(mbgl::Event::JNI, "createDefaultFileSource");
std::string cachePath = std_string_from_jstring(env, cachePath_);
std::string assetRoot = std_string_from_jstring(env, assetRoot_);
mbgl::DefaultFileSource *defaultFileSource = new mbgl::DefaultFileSource(cachePath, assetRoot, maximumCacheSize);
@@ -1259,7 +1199,6 @@ jlong createDefaultFileSource(JNIEnv *env, jni::jobject* obj, jni::jstring* cach
}
void setAccessToken(JNIEnv *env, jni::jobject* obj, jlong defaultFileSourcePtr, jni::jstring* accessToken_) {
- mbgl::Log::Debug(mbgl::Event::JNI, "setAccessToken");
assert(defaultFileSourcePtr != 0);
std::string accessToken = std_string_from_jstring(env, accessToken_);
mbgl::DefaultFileSource *defaultFileSource = reinterpret_cast<mbgl::DefaultFileSource *>(defaultFileSourcePtr);
@@ -1267,7 +1206,6 @@ void setAccessToken(JNIEnv *env, jni::jobject* obj, jlong defaultFileSourcePtr,
}
jni::jstring* getAccessToken(JNIEnv *env, jni::jobject* obj, jlong defaultFileSourcePtr) {
- mbgl::Log::Debug(mbgl::Event::JNI, "getAccessToken");
assert(defaultFileSourcePtr != 0);
mbgl::DefaultFileSource *defaultFileSource = reinterpret_cast<mbgl::DefaultFileSource *>(defaultFileSourcePtr);
std::string accessToken = defaultFileSource->getAccessToken();
@@ -1275,8 +1213,6 @@ jni::jstring* getAccessToken(JNIEnv *env, jni::jobject* obj, jlong defaultFileSo
}
void listOfflineRegions(JNIEnv *env, jni::jobject* obj, jlong defaultFileSourcePtr, jni::jobject* listCallback) {
- mbgl::Log::Debug(mbgl::Event::JNI, "listOfflineRegions");
-
// Checks
assert(defaultFileSourcePtr != 0);
NullCheck(*env, listCallback);
@@ -1347,8 +1283,6 @@ void listOfflineRegions(JNIEnv *env, jni::jobject* obj, jlong defaultFileSourceP
}
void createOfflineRegion(JNIEnv *env, jni::jobject* obj, jlong defaultFileSourcePtr, jni::jobject* definition_, jni::jarray<jbyte>* metadata_, jni::jobject* createCallback) {
- mbgl::Log::Debug(mbgl::Event::JNI, "createOfflineRegion");
-
// Checks
assert(defaultFileSourcePtr != 0);
NullCheck(*env, createCallback);
@@ -1417,8 +1351,6 @@ void createOfflineRegion(JNIEnv *env, jni::jobject* obj, jlong defaultFileSource
}
void setOfflineMapboxTileCountLimit(JNIEnv *env, jni::jobject* obj, jlong defaultFileSourcePtr, jlong limit) {
- mbgl::Log::Debug(mbgl::Event::JNI, "setOfflineMapboxTileCountLimit");
-
// Checks
assert(defaultFileSourcePtr != 0);
assert(limit > 0);
@@ -1438,8 +1370,6 @@ mbgl::OfflineRegion* getOfflineRegionPeer(JNIEnv *env, jni::jobject* offlineRegi
}
void destroyOfflineRegion(JNIEnv *env, jni::jobject* offlineRegion_) {
- mbgl::Log::Debug(mbgl::Event::JNI, "destroyOfflineRegion");
-
// Offline region
jlong offlineRegionPtr = jni::GetField<jlong>(*env, offlineRegion_, *offlineRegionPtrId);
if (!offlineRegionPtr) {
@@ -1459,8 +1389,6 @@ void destroyOfflineRegion(JNIEnv *env, jni::jobject* offlineRegion_) {
}
void setOfflineRegionObserver(JNIEnv *env, jni::jobject* offlineRegion_, jni::jobject* observerCallback) {
- mbgl::Log::Debug(mbgl::Event::JNI, "setOfflineRegionObserver");
-
// Offline region
mbgl::OfflineRegion* offlineRegion = getOfflineRegionPeer(env, offlineRegion_);
@@ -1580,8 +1508,6 @@ void setOfflineRegionObserver(JNIEnv *env, jni::jobject* offlineRegion_, jni::jo
}
void setOfflineRegionDownloadState(JNIEnv *env, jni::jobject* offlineRegion_, jint offlineRegionDownloadState) {
- mbgl::Log::Debug(mbgl::Event::JNI, "setOfflineRegionDownloadState");
-
// State
mbgl::OfflineRegionDownloadState state;
if (offlineRegionDownloadState == 0) {
@@ -1606,8 +1532,6 @@ void setOfflineRegionDownloadState(JNIEnv *env, jni::jobject* offlineRegion_, ji
}
void getOfflineRegionStatus(JNIEnv *env, jni::jobject* offlineRegion_, jni::jobject* statusCallback) {
- mbgl::Log::Debug(mbgl::Event::JNI, "getOfflineRegionStatus");
-
// Offline region
mbgl::OfflineRegion* offlineRegion = getOfflineRegionPeer(env, offlineRegion_);
@@ -1661,8 +1585,6 @@ void getOfflineRegionStatus(JNIEnv *env, jni::jobject* offlineRegion_, jni::jobj
}
void deleteOfflineRegion(JNIEnv *env, jni::jobject* offlineRegion_, jni::jobject* deleteCallback) {
- mbgl::Log::Debug(mbgl::Event::JNI, "deleteOfflineRegion");
-
// Offline region
mbgl::OfflineRegion* offlineRegion = getOfflineRegionPeer(env, offlineRegion_);
@@ -1699,8 +1621,6 @@ void deleteOfflineRegion(JNIEnv *env, jni::jobject* offlineRegion_, jni::jobject
}
void updateOfflineRegionMetadata(JNIEnv *env, jni::jobject* offlineRegion_, jni::jarray<jbyte>* metadata_, jni::jobject* updateCallback) {
- mbgl::Log::Debug(mbgl::Event::JNI, "updateOfflineRegionMetadata");
-
// Offline region
mbgl::OfflineRegion* offlineRegion = getOfflineRegionPeer(env, offlineRegion_);
diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp
index 2714b832e3..8f594f2c0e 100755
--- a/platform/android/src/native_map_view.cpp
+++ b/platform/android/src/native_map_view.cpp
@@ -17,7 +17,9 @@
#include <mbgl/platform/log.hpp>
#include <mbgl/gl/extension.hpp>
#include <mbgl/gl/gl.hpp>
+#include <mbgl/gl/context.hpp>
#include <mbgl/util/constants.hpp>
+#include <mbgl/util/image.hpp>
namespace mbgl {
namespace android {
@@ -55,12 +57,11 @@ void log_gl_string(GLenum name, const char *label) {
}
}
-NativeMapView::NativeMapView(JNIEnv *env_, jobject obj_, float pixelRatio_, int availableProcessors_, size_t totalMemory_)
- : mbgl::View(*this),
- env(env_),
- pixelRatio(pixelRatio_),
+NativeMapView::NativeMapView(JNIEnv *env_, jobject obj_, float pixelRatio, int availableProcessors_, size_t totalMemory_)
+ : env(env_),
availableProcessors(availableProcessors_),
- totalMemory(totalMemory_) {
+ totalMemory(totalMemory_),
+ threadPool(4) {
mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::NativeMapView");
assert(env_ != nullptr);
@@ -81,7 +82,10 @@ NativeMapView::NativeMapView(JNIEnv *env_, jobject obj_, float pixelRatio_, int
mbgl::android::cachePath + "/mbgl-offline.db",
mbgl::android::apkPath);
- map = std::make_unique<mbgl::Map>(*this, *fileSource, MapMode::Continuous);
+ map = std::make_unique<mbgl::Map>(
+ *this,
+ std::array<uint16_t, 2>{{ static_cast<uint16_t>(width), static_cast<uint16_t>(height) }},
+ pixelRatio, *fileSource, threadPool, MapMode::Continuous);
float zoomFactor = map->getMaxZoom() - map->getMinZoom() + 1;
float cpuFactor = availableProcessors;
@@ -113,16 +117,14 @@ NativeMapView::~NativeMapView() {
vm = nullptr;
}
-float NativeMapView::getPixelRatio() const {
- return pixelRatio;
+void NativeMapView::updateViewBinding() {
+ getContext().bindFramebuffer.setCurrentValue(0);
+ getContext().viewport.setCurrentValue({ 0, 0, static_cast<uint16_t>(fbWidth), static_cast<uint16_t>(fbHeight) });
}
-std::array<uint16_t, 2> NativeMapView::getSize() const {
- return {{ static_cast<uint16_t>(width), static_cast<uint16_t>(height) }};
-}
-
-std::array<uint16_t, 2> NativeMapView::getFramebufferSize() const {
- return {{ static_cast<uint16_t>(fbWidth), static_cast<uint16_t>(fbHeight) }};
+void NativeMapView::bind() {
+ getContext().bindFramebuffer = 0;
+ getContext().viewport = { 0, 0, static_cast<uint16_t>(fbWidth), static_cast<uint16_t>(fbHeight) };
}
void NativeMapView::activate() {
@@ -190,12 +192,8 @@ void NativeMapView::invalidate() {
void NativeMapView::render() {
activate();
- if(sizeChanged){
- sizeChanged = false;
- glViewport(0, 0, fbWidth, fbHeight);
- }
-
- map->render();
+ updateViewBinding();
+ map->render(*this);
if(snapshot){
snapshot = false;
@@ -720,14 +718,13 @@ void NativeMapView::updateFps() {
void NativeMapView::resizeView(int w, int h) {
width = w;
height = h;
- sizeChanged = true;
- map->update(mbgl::Update::Dimensions);
+ map->setSize({{ static_cast<uint16_t>(width), static_cast<uint16_t>(height) }});
}
void NativeMapView::resizeFramebuffer(int w, int h) {
fbWidth = w;
fbHeight = h;
- map->update(mbgl::Update::Repaint);
+ invalidate();
}
void NativeMapView::setInsets(mbgl::EdgeInsets insets_) {
diff --git a/platform/android/src/native_map_view.hpp b/platform/android/src/native_map_view.hpp
index 7974f282d9..43fb0c1ccd 100755
--- a/platform/android/src/native_map_view.hpp
+++ b/platform/android/src/native_map_view.hpp
@@ -2,7 +2,9 @@
#include <mbgl/map/map.hpp>
#include <mbgl/map/view.hpp>
+#include <mbgl/map/backend.hpp>
#include <mbgl/util/noncopyable.hpp>
+#include <mbgl/platform/default/thread_pool.hpp>
#include <mbgl/storage/default_file_source.hpp>
#include <string>
@@ -13,14 +15,14 @@
namespace mbgl {
namespace android {
-class NativeMapView : public mbgl::View, private mbgl::util::noncopyable {
+class NativeMapView : public mbgl::View, public mbgl::Backend {
public:
NativeMapView(JNIEnv *env, jobject obj, float pixelRatio, int availableProcessors, size_t totalMemory);
virtual ~NativeMapView();
- float getPixelRatio() const override;
- std::array<uint16_t, 2> getSize() const override;
- std::array<uint16_t, 2> getFramebufferSize() const override;
+ void updateViewBinding();
+ void bind() override;
+
void activate() override;
void deactivate() override;
void invalidate() override;
@@ -80,7 +82,6 @@ private:
bool firstTime = false;
bool fpsEnabled = false;
- bool sizeChanged = false;
bool snapshot = false;
double fps = 0.0;
@@ -88,13 +89,13 @@ private:
int height = 0;
int fbWidth = 0;
int fbHeight = 0;
- const float pixelRatio;
int availableProcessors = 0;
size_t totalMemory = 0;
// Ensure these are initialised last
std::unique_ptr<mbgl::DefaultFileSource> fileSource;
+ mbgl::ThreadPool threadPool;
std::unique_ptr<mbgl::Map> map;
mbgl::EdgeInsets insets;
diff --git a/platform/android/src/style/layers/custom_layer.cpp b/platform/android/src/style/layers/custom_layer.cpp
index aeabb4e19d..6568455c67 100644
--- a/platform/android/src/style/layers/custom_layer.cpp
+++ b/platform/android/src/style/layers/custom_layer.cpp
@@ -26,7 +26,7 @@ namespace android {
void CustomLayer::update(jni::JNIEnv&) {
Log::Debug(mbgl::Event::JNI, "Updating map");
if (map) {
- map->update(mbgl::Update::Repaint);
+ map->triggerRepaint();
} else {
Log::Error(mbgl::Event::JNI, "No map reference, cannot update");
}
diff --git a/platform/android/src/style/sources/geojson_source.cpp b/platform/android/src/style/sources/geojson_source.cpp
index cb03cc06c6..234dccb315 100644
--- a/platform/android/src/style/sources/geojson_source.cpp
+++ b/platform/android/src/style/sources/geojson_source.cpp
@@ -36,17 +36,11 @@ namespace android {
//Update the core source
source.as<mbgl::style::GeoJSONSource>()->GeoJSONSource::setGeoJSON(*converted);
-
- //Repaint
- updateStyle(false);
}
void GeoJSONSource::setURL(jni::JNIEnv& env, jni::String url) {
//Update the core source
source.as<mbgl::style::GeoJSONSource>()->GeoJSONSource::setURL(jni::Make<std::string>(env, url));
-
- //Repaint
- updateStyle(false);
}
jni::Class<GeoJSONSource> GeoJSONSource::javaClass;
diff --git a/platform/android/src/style/sources/source.cpp b/platform/android/src/style/sources/source.cpp
index 4f306e7c54..f3daa777d1 100644
--- a/platform/android/src/style/sources/source.cpp
+++ b/platform/android/src/style/sources/source.cpp
@@ -35,19 +35,6 @@ namespace android {
return jni::Make<jni::String>(env, source.getID());
}
- void Source::updateStyle(jni::jboolean updateClasses) {
- //Update the style only if attached
- if (ownedSource == nullptr) {
- Update flags = mbgl::Update::RecalculateStyle;
- if(updateClasses) {
- flags = flags | mbgl::Update::Classes;
- }
- map->update(flags);
- } else {
- mbgl::Log::Debug(mbgl::Event::JNI, "Not updating as source is not attached to map (yet)");
- }
- }
-
std::unique_ptr<mbgl::style::Source> Source::releaseCoreSource() {
assert(ownedSource != nullptr);
return std::move(ownedSource);
diff --git a/platform/android/src/style/sources/source.hpp b/platform/android/src/style/sources/source.hpp
index 7fdc43a833..0785e4d4e0 100644
--- a/platform/android/src/style/sources/source.hpp
+++ b/platform/android/src/style/sources/source.hpp
@@ -40,12 +40,9 @@ public:
std::unique_ptr<mbgl::style::Source> releaseCoreSource();
protected:
- void updateStyle(jni::jboolean);
-
std::unique_ptr<mbgl::style::Source> ownedSource;
mbgl::style::Source& source;
mbgl::Map* map;
-
};
} //android
diff --git a/platform/darwin/src/headless_backend_cgl.cpp b/platform/darwin/src/headless_backend_cgl.cpp
new file mode 100644
index 0000000000..4ca567f55c
--- /dev/null
+++ b/platform/darwin/src/headless_backend_cgl.cpp
@@ -0,0 +1,58 @@
+#include <mbgl/platform/default/headless_backend.hpp>
+#include <mbgl/platform/default/headless_display.hpp>
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include <string>
+#include <stdexcept>
+
+namespace mbgl {
+
+gl::glProc 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::glProc>(symbol);
+}
+
+void HeadlessBackend::createContext() {
+ CGLError error = CGLCreateContext(display->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");
+ }
+}
+
+void HeadlessBackend::destroyContext() {
+ CGLDestroyContext(glContext);
+}
+
+void HeadlessBackend::activateContext() {
+ CGLError error = CGLSetCurrentContext(glContext);
+ if (error != kCGLNoError) {
+ throw std::runtime_error(std::string("Switching OpenGL context failed:") +
+ CGLErrorString(error) + "\n");
+ }
+}
+
+void HeadlessBackend::deactivateContext() {
+ CGLError error = CGLSetCurrentContext(nullptr);
+ if (error != kCGLNoError) {
+ throw std::runtime_error(std::string("Removing OpenGL context failed:") +
+ CGLErrorString(error) + "\n");
+ }
+}
+
+} // namespace mbgl
diff --git a/platform/darwin/src/headless_backend_eagl.mm b/platform/darwin/src/headless_backend_eagl.mm
new file mode 100644
index 0000000000..0a1ae706b8
--- /dev/null
+++ b/platform/darwin/src/headless_backend_eagl.mm
@@ -0,0 +1,46 @@
+#include <mbgl/platform/default/headless_backend.hpp>
+
+#include <mbgl/gl/extension.hpp>
+
+#include <OpenGLES/EAGL.h>
+
+#include <stdexcept>
+
+namespace mbgl {
+
+gl::glProc 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::glProc>(symbol);
+}
+
+void HeadlessBackend::createContext() {
+ glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
+ if (glContext == nil) {
+ throw std::runtime_error("Error creating GL context object");
+ }
+ [reinterpret_cast<EAGLContext*>(glContext) retain];
+ reinterpret_cast<EAGLContext*>(glContext).multiThreaded = YES;
+}
+
+void HeadlessBackend::destroyContext() {
+ [reinterpret_cast<EAGLContext*>(glContext) release];
+ glContext = nil;
+}
+
+void HeadlessBackend::activateContext() {
+ [EAGLContext setCurrentContext:reinterpret_cast<EAGLContext*>(glContext)];
+}
+
+void HeadlessBackend::deactivateContext() {
+ [EAGLContext setCurrentContext:nil];
+}
+
+} // namespace mbgl
diff --git a/platform/darwin/src/headless_view_cgl.cpp b/platform/darwin/src/headless_view_cgl.cpp
deleted file mode 100644
index dc58463b5d..0000000000
--- a/platform/darwin/src/headless_view_cgl.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-#include <mbgl/platform/default/headless_view.hpp>
-#include <mbgl/platform/default/headless_display.hpp>
-
-#include <CoreFoundation/CoreFoundation.h>
-
-namespace mbgl {
-
-gl::glProc HeadlessView::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::glProc>(symbol);
-}
-
-void HeadlessView::createContext() {
- CGLError error = CGLCreateContext(display->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");
- }
-}
-
-void HeadlessView::destroyContext() {
- CGLDestroyContext(glContext);
-}
-
-void HeadlessView::resizeFramebuffer() {
- const unsigned int w = dimensions[0] * pixelRatio;
- const unsigned int h = dimensions[1] * pixelRatio;
-
- // Create depth/stencil buffer
- MBGL_CHECK_ERROR(glGenRenderbuffersEXT(1, &fboDepthStencil));
- MBGL_CHECK_ERROR(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fboDepthStencil));
- MBGL_CHECK_ERROR(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, w, h));
- MBGL_CHECK_ERROR(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0));
-
- MBGL_CHECK_ERROR(glGenRenderbuffersEXT(1, &fboColor));
- MBGL_CHECK_ERROR(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fboColor));
- MBGL_CHECK_ERROR(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, w, h));
- MBGL_CHECK_ERROR(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0));
-
- MBGL_CHECK_ERROR(glGenFramebuffersEXT(1, &fbo));
- MBGL_CHECK_ERROR(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo));
-
- MBGL_CHECK_ERROR(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, fboColor));
- MBGL_CHECK_ERROR(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER_EXT, fboDepthStencil));
-
- GLenum status = MBGL_CHECK_ERROR(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT));
-
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
- std::string error("Couldn't create framebuffer: ");
- switch (status) {
- case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: (error += "incomplete attachment"); break;
- case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: error += "incomplete missing attachment"; break;
- case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: error += "incomplete dimensions"; break;
- case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: error += "incomplete formats"; break;
- case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: error += "incomplete draw buffer"; break;
- case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: error += "incomplete read buffer"; break;
- case GL_FRAMEBUFFER_UNSUPPORTED: error += "unsupported"; break;
- default: error += "other"; break;
- }
- throw std::runtime_error(error);
- }
-
- MBGL_CHECK_ERROR(glViewport(0, 0, w, h));
-}
-
-void HeadlessView::clearBuffers() {
- assert(active);
-
- MBGL_CHECK_ERROR(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
-
- if (fbo) {
- MBGL_CHECK_ERROR(glDeleteFramebuffersEXT(1, &fbo));
- fbo = 0;
- }
-
- if (fboColor) {
- MBGL_CHECK_ERROR(glDeleteRenderbuffersEXT(1, &fboColor));
- fboColor = 0;
- }
-
- if (fboDepthStencil) {
- MBGL_CHECK_ERROR(glDeleteRenderbuffersEXT(1, &fboDepthStencil));
- fboDepthStencil = 0;
- }
-}
-
-void HeadlessView::activateContext() {
- CGLError error = CGLSetCurrentContext(glContext);
- if (error != kCGLNoError) {
- throw std::runtime_error(std::string("Switching OpenGL context failed:") + CGLErrorString(error) + "\n");
- }
-}
-
-void HeadlessView::deactivateContext() {
- CGLError error = CGLSetCurrentContext(nullptr);
- if (error != kCGLNoError) {
- throw std::runtime_error(std::string("Removing OpenGL context failed:") + CGLErrorString(error) + "\n");
- }
-}
-
-} // namespace mbgl
diff --git a/platform/darwin/src/headless_view_eagl.mm b/platform/darwin/src/headless_view_eagl.mm
deleted file mode 100644
index a1f335fc6e..0000000000
--- a/platform/darwin/src/headless_view_eagl.mm
+++ /dev/null
@@ -1,103 +0,0 @@
-#include <mbgl/platform/default/headless_view.hpp>
-#include <mbgl/platform/default/headless_display.hpp>
-
-#include <OpenGLES/EAGL.h>
-
-namespace mbgl {
-
-gl::glProc HeadlessView::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::glProc>(symbol);
-}
-
-void HeadlessView::createContext() {
- glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
- if (glContext == nil) {
- throw std::runtime_error("Error creating GL context object");
- }
- [reinterpret_cast<EAGLContext*>(glContext) retain];
- reinterpret_cast<EAGLContext*>(glContext).multiThreaded = YES;
-}
-
-void HeadlessView::destroyContext() {
- [reinterpret_cast<EAGLContext*>(glContext) release];
- glContext = nil;
-}
-
-void HeadlessView::resizeFramebuffer() {
- const unsigned int w = dimensions[0] * pixelRatio;
- const unsigned int h = dimensions[1] * pixelRatio;
-
- // Create depth/stencil buffer
- MBGL_CHECK_ERROR(glGenRenderbuffers(1, &fboDepthStencil));
- MBGL_CHECK_ERROR(glBindRenderbuffer(GL_RENDERBUFFER, fboDepthStencil));
- MBGL_CHECK_ERROR(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, w, h));
- MBGL_CHECK_ERROR(glBindRenderbuffer(GL_RENDERBUFFER, 0));
-
- MBGL_CHECK_ERROR(glGenRenderbuffers(1, &fboColor));
- MBGL_CHECK_ERROR(glBindRenderbuffer(GL_RENDERBUFFER, fboColor));
- MBGL_CHECK_ERROR(glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, w, h));
- MBGL_CHECK_ERROR(glBindRenderbuffer(GL_RENDERBUFFER, 0));
-
- MBGL_CHECK_ERROR(glGenFramebuffers(1, &fbo));
- MBGL_CHECK_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, fbo));
-
- MBGL_CHECK_ERROR(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fboColor));
- MBGL_CHECK_ERROR(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fboDepthStencil));
- MBGL_CHECK_ERROR(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fboDepthStencil));
-
- GLenum status = MBGL_CHECK_ERROR(glCheckFramebufferStatus(GL_FRAMEBUFFER));
-
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- std::string error("Couldn't create framebuffer: ");
- switch (status) {
- case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: (error += "incomplete attachment"); break;
- case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: error += "incomplete missing attachment"; break;
- case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: error += "incomplete dimensions"; break;
- case GL_FRAMEBUFFER_UNSUPPORTED: error += "unsupported"; break;
- default: error += "other"; break;
- }
- throw std::runtime_error(error);
- }
-
- MBGL_CHECK_ERROR(glViewport(0, 0, w, h));
-}
-
-void HeadlessView::clearBuffers() {
- assert(active);
-
- MBGL_CHECK_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, 0));
-
- if (fbo) {
- MBGL_CHECK_ERROR(glDeleteFramebuffers(1, &fbo));
- fbo = 0;
- }
-
- if (fboColor) {
- MBGL_CHECK_ERROR(glDeleteRenderbuffers(1, &fboColor));
- fboColor = 0;
- }
-
- if (fboDepthStencil) {
- MBGL_CHECK_ERROR(glDeleteRenderbuffers(1, &fboDepthStencil));
- fboDepthStencil = 0;
- }
-}
-
-void HeadlessView::activateContext() {
- [EAGLContext setCurrentContext:reinterpret_cast<EAGLContext*>(glContext)];
-}
-
-void HeadlessView::deactivateContext() {
- [EAGLContext setCurrentContext:nil];
-}
-
-} // namespace mbgl
diff --git a/platform/default/glfw_view.cpp b/platform/default/glfw_view.cpp
index fa5190c80c..47551d786f 100644
--- a/platform/default/glfw_view.cpp
+++ b/platform/default/glfw_view.cpp
@@ -4,6 +4,7 @@
#include <mbgl/style/transition_options.hpp>
#include <mbgl/gl/gl.hpp>
#include <mbgl/gl/extension.hpp>
+#include <mbgl/gl/context.hpp>
#include <mbgl/platform/log.hpp>
#include <mbgl/platform/platform.hpp>
#include <mbgl/util/string.hpp>
@@ -124,11 +125,23 @@ GLFWView::~GLFWView() {
glfwTerminate();
}
-void GLFWView::initialize(mbgl::Map *map_) {
- View::initialize(map_);
+void GLFWView::setMap(mbgl::Map *map_) {
+ map = map_;
map->addAnnotationIcon("default_marker", makeSpriteImage(22, 22, 1));
}
+void GLFWView::updateViewBinding() {
+ getContext().bindFramebuffer.setCurrentValue(0);
+ getContext().viewport.setCurrentValue(
+ { 0, 0, static_cast<uint16_t>(fbWidth), static_cast<uint16_t>(fbHeight) });
+}
+
+void GLFWView::bind() {
+ getContext().bindFramebuffer = 0;
+ getContext().viewport = { 0, 0, static_cast<uint16_t>(fbWidth),
+ static_cast<uint16_t>(fbHeight) };
+}
+
void GLFWView::onKey(GLFWwindow *window, int key, int /*scancode*/, int action, int mods) {
GLFWView *view = reinterpret_cast<GLFWView *>(glfwGetWindowUserPointer(window));
@@ -178,7 +191,11 @@ void GLFWView::onKey(GLFWwindow *window, int key, int /*scancode*/, int action,
case GLFW_KEY_Z:
view->nextOrientation();
break;
- case GLFW_KEY_Q:
+ case GLFW_KEY_Q: {
+ auto result = view->map->queryPointAnnotations({ {}, { double(view->getSize()[0]), double(view->getSize()[1]) } });
+ printf("visible point annotations: %lu\n", result.size());
+ } break;
+ case GLFW_KEY_C:
view->clearAnnotations();
break;
case GLFW_KEY_P:
@@ -357,8 +374,8 @@ void GLFWView::onWindowResize(GLFWwindow *window, int width, int height) {
GLFWView *view = reinterpret_cast<GLFWView *>(glfwGetWindowUserPointer(window));
view->width = width;
view->height = height;
-
- view->map->update(mbgl::Update::Dimensions);
+ view->map->setSize({{ static_cast<uint16_t>(view->width),
+ static_cast<uint16_t>(view->height) }});
}
void GLFWView::onFramebufferResize(GLFWwindow *window, int width, int height) {
@@ -366,7 +383,11 @@ void GLFWView::onFramebufferResize(GLFWwindow *window, int width, int height) {
view->fbWidth = width;
view->fbHeight = height;
- view->map->update(mbgl::Update::Repaint);
+ // This is only triggered when the framebuffer is resized, but not the window. It can
+ // happen when you move the window between screens with a different pixel ratio.
+ // We are forcing a repaint my invalidating the view, which triggers a rerender with the
+ // new framebuffer dimensions.
+ view->invalidate();
}
void GLFWView::onMouseClick(GLFWwindow *window, int button, int action, int modifiers) {
@@ -432,15 +453,15 @@ void GLFWView::run() {
const double started = glfwGetTime();
glfwMakeContextCurrent(window);
- glViewport(0, 0, fbWidth, fbHeight);
- map->render();
+ updateViewBinding();
+ map->render(*this);
glfwSwapBuffers(window);
report(1000 * (glfwGetTime() - started));
if (benchmark) {
- map->update(mbgl::Update::Repaint);
+ invalidate();
}
dirty = false;
@@ -508,6 +529,16 @@ void GLFWView::setWindowTitle(const std::string& title) {
glfwSetWindowTitle(window, (std::string { "Mapbox GL: " } + title).c_str());
}
+void GLFWView::setMapChangeCallback(std::function<void(mbgl::MapChange)> callback) {
+ this->mapChangeCallback = callback;
+}
+
+void GLFWView::notifyMapChange(mbgl::MapChange change) {
+ if (mapChangeCallback) {
+ mapChangeCallback(change);
+ }
+}
+
namespace mbgl {
namespace platform {
diff --git a/platform/default/headless_backend.cpp b/platform/default/headless_backend.cpp
new file mode 100644
index 0000000000..279a7973c9
--- /dev/null
+++ b/platform/default/headless_backend.cpp
@@ -0,0 +1,56 @@
+#include <mbgl/platform/default/headless_backend.hpp>
+#include <mbgl/platform/default/headless_display.hpp>
+
+#include <cassert>
+#include <stdexcept>
+
+namespace mbgl {
+
+HeadlessBackend::HeadlessBackend() : display(std::make_shared<HeadlessDisplay>()) {
+ activate();
+}
+
+HeadlessBackend::HeadlessBackend(std::shared_ptr<HeadlessDisplay> display_)
+ : display(std::move(display_)) {
+ activate();
+}
+
+HeadlessBackend::~HeadlessBackend() {
+ deactivate();
+ destroyContext();
+}
+
+void HeadlessBackend::activate() {
+ active = true;
+
+ if (!glContext) {
+ if (!display) {
+ throw std::runtime_error("Display is not set");
+ }
+ createContext();
+ }
+
+ activateContext();
+
+ if (!extensionsLoaded) {
+ gl::InitializeExtensions(initializeExtension);
+ extensionsLoaded = true;
+ }
+}
+
+void HeadlessBackend::deactivate() {
+ deactivateContext();
+ active = false;
+}
+
+void HeadlessBackend::invalidate() {
+ assert(false);
+}
+
+void HeadlessBackend::notifyMapChange(MapChange change) {
+ if (mapChangeCallback) {
+ mapChangeCallback(change);
+ }
+}
+
+} // namespace mbgl
diff --git a/platform/default/headless_backend_glx.cpp b/platform/default/headless_backend_glx.cpp
new file mode 100644
index 0000000000..bbfd19345b
--- /dev/null
+++ b/platform/default/headless_backend_glx.cpp
@@ -0,0 +1,67 @@
+#include <mbgl/platform/default/headless_backend.hpp>
+#include <mbgl/platform/default/headless_display.hpp>
+
+#include <mbgl/platform/log.hpp>
+
+// #include <cassert>
+
+#include <GL/glx.h>
+
+namespace mbgl {
+
+gl::glProc HeadlessBackend::initializeExtension(const char* name) {
+ return glXGetProcAddress(reinterpret_cast<const GLubyte*>(name));
+}
+
+void HeadlessBackend::createContext() {
+ xDisplay = display->xDisplay;
+ fbConfigs = display->fbConfigs;
+
+ if (!glContext) {
+ // Try to create a legacy context
+ glContext = glXCreateNewContext(xDisplay, fbConfigs[0], GLX_RGBA_TYPE, None, True);
+ if (glContext) {
+ if (!glXIsDirect(xDisplay, glContext)) {
+ Log::Error(Event::OpenGL, "failed to create direct OpenGL Legacy context");
+ glXDestroyContext(xDisplay, glContext);
+ glContext = nullptr;
+ }
+ }
+ }
+
+ if (glContext == nullptr) {
+ throw std::runtime_error("Error creating GL context object.");
+ }
+
+ // 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(xDisplay, fbConfigs[0], pbufferAttributes);
+}
+
+void HeadlessBackend::destroyContext() {
+ if (glxPbuffer) {
+ glXDestroyPbuffer(xDisplay, glxPbuffer);
+ glxPbuffer = 0;
+ }
+
+ glXDestroyContext(xDisplay, glContext);
+}
+
+void HeadlessBackend::activateContext() {
+ if (!glXMakeContextCurrent(xDisplay, glxPbuffer, glxPbuffer, glContext)) {
+ throw std::runtime_error("Switching OpenGL context failed.\n");
+ }
+}
+
+void HeadlessBackend::deactivateContext() {
+ if (!glXMakeContextCurrent(xDisplay, 0, 0, nullptr)) {
+ throw std::runtime_error("Removing OpenGL context failed.\n");
+ }
+}
+
+} // namespace mbgl
diff --git a/platform/default/headless_display.cpp b/platform/default/headless_display.cpp
index 8b9f3fe04b..b98aef7903 100644
--- a/platform/default/headless_display.cpp
+++ b/platform/default/headless_display.cpp
@@ -1,12 +1,13 @@
#include <mbgl/platform/default/headless_display.hpp>
-#include <cstring>
-#include <stdexcept>
-
#if MBGL_USE_GLX
#include <GL/glx.h>
#endif
+#include <cstring>
+#include <stdexcept>
+#include <string>
+
namespace mbgl {
HeadlessDisplay::HeadlessDisplay() {
diff --git a/platform/default/headless_view.cpp b/platform/default/headless_view.cpp
deleted file mode 100644
index 95b196b746..0000000000
--- a/platform/default/headless_view.cpp
+++ /dev/null
@@ -1,118 +0,0 @@
-#include <mbgl/platform/default/headless_view.hpp>
-#include <mbgl/platform/default/headless_display.hpp>
-
-#include <cassert>
-#include <cstring>
-
-namespace mbgl {
-
-HeadlessView::HeadlessView(float pixelRatio_, uint16_t width, uint16_t height)
- : display(std::make_shared<HeadlessDisplay>())
- , pixelRatio(pixelRatio_)
- , dimensions({{ width, height }})
- , needsResize(true) {
-}
-
-HeadlessView::HeadlessView(std::shared_ptr<HeadlessDisplay> display_,
- float pixelRatio_,
- uint16_t width,
- uint16_t height)
- : display(std::move(display_))
- , pixelRatio(pixelRatio_)
- , dimensions({{ width, height }})
- , needsResize(true) {
-}
-
-HeadlessView::~HeadlessView() {
- activate();
- clearBuffers();
- deactivate();
-
- destroyContext();
-}
-
-void HeadlessView::resize(const uint16_t width, const uint16_t height) {
- if(dimensions[0] == width &&
- dimensions[1] == height) {
- return;
- }
- dimensions = {{ width, height }};
- needsResize = true;
-}
-
-PremultipliedImage HeadlessView::readStillImage(std::array<uint16_t, 2> size) {
- assert(active);
-
- if (!size[0] || !size[1]) {
- size[0] = dimensions[0] * pixelRatio;
- size[1] = dimensions[1] * pixelRatio;
- }
-
- PremultipliedImage image { size[0], size[1] };
- MBGL_CHECK_ERROR(glReadPixels(0, 0, size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE, image.data.get()));
-
- const auto stride = image.stride();
- auto tmp = std::make_unique<uint8_t[]>(stride);
- uint8_t* rgba = image.data.get();
- for (int i = 0, j = size[1] - 1; i < j; i++, j--) {
- std::memcpy(tmp.get(), rgba + i * stride, stride);
- std::memcpy(rgba + i * stride, rgba + j * stride, stride);
- std::memcpy(rgba + j * stride, tmp.get(), stride);
- }
-
- return image;
-}
-
-float HeadlessView::getPixelRatio() const {
- return pixelRatio;
-}
-
-std::array<uint16_t, 2> HeadlessView::getSize() const {
- return dimensions;
-}
-
-std::array<uint16_t, 2> HeadlessView::getFramebufferSize() const {
- return {{ static_cast<uint16_t>(dimensions[0] * pixelRatio),
- static_cast<uint16_t>(dimensions[1] * pixelRatio) }};
-}
-
-void HeadlessView::activate() {
- active = true;
-
- if (!glContext) {
- if (!display) {
- throw std::runtime_error("Display is not set");
- }
- createContext();
- }
-
- activateContext();
-
- if (!extensionsLoaded) {
- gl::InitializeExtensions(initializeExtension);
- extensionsLoaded = true;
- }
-
- if (needsResize) {
- clearBuffers();
- resizeFramebuffer();
- needsResize = false;
- }
-}
-
-void HeadlessView::deactivate() {
- deactivateContext();
- active = false;
-}
-
-void HeadlessView::invalidate() {
- assert(false);
-}
-
-void HeadlessView::notifyMapChange(MapChange change) {
- if (mapChangeCallback) {
- mapChangeCallback(change);
- }
-}
-
-} // namespace mbgl
diff --git a/platform/default/headless_view_glx.cpp b/platform/default/headless_view_glx.cpp
deleted file mode 100644
index 55d9313f99..0000000000
--- a/platform/default/headless_view_glx.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-#include <mbgl/platform/default/headless_view.hpp>
-#include <mbgl/platform/default/headless_display.hpp>
-#include <mbgl/platform/log.hpp>
-
-#include <cassert>
-
-#include <GL/glx.h>
-
-namespace mbgl {
-
-gl::glProc HeadlessView::initializeExtension(const char* name) {
- return glXGetProcAddress(reinterpret_cast<const GLubyte*>(name));
-}
-
-void HeadlessView::createContext() {
- xDisplay = display->xDisplay;
- fbConfigs = display->fbConfigs;
-
- if (!glContext) {
- // Try to create a legacy context
- glContext = glXCreateNewContext(xDisplay, fbConfigs[0], GLX_RGBA_TYPE, None, True);
- if (glContext) {
- if (!glXIsDirect(xDisplay, glContext)) {
- Log::Error(Event::OpenGL, "failed to create direct OpenGL Legacy context");
- glXDestroyContext(xDisplay, glContext);
- glContext = nullptr;
- }
- }
- }
-
- if (glContext == nullptr) {
- throw std::runtime_error("Error creating GL context object.");
- }
-
- // 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(xDisplay, fbConfigs[0], pbufferAttributes);
-}
-
-void HeadlessView::destroyContext() {
- if (glxPbuffer) {
- glXDestroyPbuffer(xDisplay, glxPbuffer);
- glxPbuffer = 0;
- }
-
- glXDestroyContext(xDisplay, glContext);
-}
-
-void HeadlessView::resizeFramebuffer() {
- const unsigned int w = dimensions[0] * pixelRatio;
- const unsigned int h = dimensions[1] * pixelRatio;
-
- // Create depth/stencil buffer
- MBGL_CHECK_ERROR(glGenRenderbuffersEXT(1, &fboDepthStencil));
- MBGL_CHECK_ERROR(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fboDepthStencil));
- MBGL_CHECK_ERROR(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, w, h));
- MBGL_CHECK_ERROR(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0));
-
- MBGL_CHECK_ERROR(glGenRenderbuffersEXT(1, &fboColor));
- MBGL_CHECK_ERROR(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fboColor));
- MBGL_CHECK_ERROR(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, w, h));
- MBGL_CHECK_ERROR(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0));
-
- MBGL_CHECK_ERROR(glGenFramebuffersEXT(1, &fbo));
- MBGL_CHECK_ERROR(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo));
-
- MBGL_CHECK_ERROR(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, fboColor));
- MBGL_CHECK_ERROR(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER_EXT, fboDepthStencil));
-
- GLenum status = MBGL_CHECK_ERROR(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT));
-
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
- std::string error("Couldn't create framebuffer: ");
- switch (status) {
- case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: (error += "incomplete attachment"); break;
- case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: error += "incomplete missing attachment"; break;
- case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: error += "incomplete dimensions"; break;
- case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: error += "incomplete formats"; break;
- case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: error += "incomplete draw buffer"; break;
- case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: error += "incomplete read buffer"; break;
- case GL_FRAMEBUFFER_UNSUPPORTED: error += "unsupported"; break;
- default: error += "other"; break;
- }
- throw std::runtime_error(error);
- }
-
- MBGL_CHECK_ERROR(glViewport(0, 0, w, h));
-}
-
-void HeadlessView::clearBuffers() {
- assert(active);
-
- MBGL_CHECK_ERROR(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
-
- if (fbo) {
- MBGL_CHECK_ERROR(glDeleteFramebuffersEXT(1, &fbo));
- fbo = 0;
- }
-
- if (fboColor) {
- MBGL_CHECK_ERROR(glDeleteRenderbuffersEXT(1, &fboColor));
- fboColor = 0;
- }
-
- if (fboDepthStencil) {
- MBGL_CHECK_ERROR(glDeleteRenderbuffersEXT(1, &fboDepthStencil));
- fboDepthStencil = 0;
- }
-}
-
-void HeadlessView::activateContext() {
- if (!glXMakeContextCurrent(xDisplay, glxPbuffer, glxPbuffer, glContext)) {
- throw std::runtime_error("Switching OpenGL context failed.\n");
- }
-}
-
-void HeadlessView::deactivateContext() {
- if (!glXMakeContextCurrent(xDisplay, 0, 0, nullptr)) {
- throw std::runtime_error("Removing OpenGL context failed.\n");
- }
-}
-
-} // namespace mbgl
diff --git a/platform/default/offscreen_view.cpp b/platform/default/offscreen_view.cpp
new file mode 100644
index 0000000000..eaf87d0f87
--- /dev/null
+++ b/platform/default/offscreen_view.cpp
@@ -0,0 +1,47 @@
+#include <mbgl/platform/default/offscreen_view.hpp>
+#include <mbgl/gl/context.hpp>
+#include <mbgl/gl/gl.hpp>
+
+#include <cstring>
+#include <cassert>
+
+namespace mbgl {
+
+OffscreenView::OffscreenView(gl::Context& context_, std::array<uint16_t, 2> size_)
+ : context(context_), size(std::move(size_)) {
+ assert(size[0] > 0 && size[1] > 0);
+}
+
+void OffscreenView::bind() {
+ if (!framebuffer) {
+ color = context.createRenderbuffer<gl::RenderbufferType::RGBA>(size);
+ depthStencil = context.createRenderbuffer<gl::RenderbufferType::DepthStencil>(size);
+ framebuffer = context.createFramebuffer(*color, *depthStencil);
+ } else {
+ context.bindFramebuffer = framebuffer->framebuffer;
+ }
+
+ context.viewport = { 0, 0, size[0], size[1] };
+}
+
+PremultipliedImage OffscreenView::readStillImage() {
+ PremultipliedImage image { size[0], size[1] };
+ MBGL_CHECK_ERROR(glReadPixels(0, 0, size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE, image.data.get()));
+
+ const auto stride = image.stride();
+ auto tmp = std::make_unique<uint8_t[]>(stride);
+ uint8_t* rgba = image.data.get();
+ for (int i = 0, j = size[1] - 1; i < j; i++, j--) {
+ std::memcpy(tmp.get(), rgba + i * stride, stride);
+ std::memcpy(rgba + i * stride, rgba + j * stride, stride);
+ std::memcpy(rgba + j * stride, tmp.get(), stride);
+ }
+
+ return image;
+}
+
+std::array<uint16_t, 2> OffscreenView::getSize() const {
+ return size;
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/actor/thread_pool.cpp b/platform/default/thread_pool.cpp
index 2995ed26ad..b7e02db157 100644
--- a/src/mbgl/actor/thread_pool.cpp
+++ b/platform/default/thread_pool.cpp
@@ -1,4 +1,4 @@
-#include <mbgl/actor/thread_pool.hpp>
+#include <mbgl/platform/default/thread_pool.hpp>
#include <mbgl/actor/mailbox.hpp>
namespace mbgl {
@@ -22,9 +22,7 @@ ThreadPool::ThreadPool(std::size_t count) {
queue.pop();
lock.unlock();
- if (auto locked = mailbox.lock()) {
- locked->receive();
- }
+ Mailbox::maybeReceive(mailbox);
}
});
}
diff --git a/platform/ios/config.cmake b/platform/ios/config.cmake
index 6c83395a3e..0813d0338f 100644
--- a/platform/ios/config.cmake
+++ b/platform/ios/config.cmake
@@ -37,9 +37,13 @@ macro(mbgl_platform_core)
PRIVATE platform/darwin/src/image.mm
# Headless view
- PRIVATE platform/darwin/src/headless_view_eagl.mm
+ PRIVATE platform/darwin/src/headless_backend_eagl.mm
+ PRIVATE platform/default/headless_backend.cpp
PRIVATE platform/default/headless_display.cpp
- PRIVATE platform/default/headless_view.cpp
+ PRIVATE platform/default/offscreen_view.cpp
+
+ # Thread pool
+ PRIVATE platform/default/thread_pool.cpp
)
target_add_mason_package(mbgl-core PUBLIC geojson)
@@ -50,7 +54,7 @@ macro(mbgl_platform_core)
# TODO: Remove this by converting to ARC
set_source_files_properties(
- platform/darwin/src/headless_view_eagl.mm
+ platform/darwin/src/headless_backend_eagl.mm
PROPERTIES
COMPILE_FLAGS -fno-objc-arc
)
diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm
index bb7e446620..c6c0920f56 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -2,6 +2,7 @@
#include <mbgl/platform/log.hpp>
#include <mbgl/gl/extension.hpp>
+#include <mbgl/gl/context.hpp>
#import <GLKit/GLKit.h>
#import <OpenGLES/EAGL.h>
@@ -13,10 +14,12 @@
#include <mbgl/map/mode.hpp>
#include <mbgl/platform/platform.hpp>
#include <mbgl/platform/darwin/reachability.h>
+#include <mbgl/platform/default/thread_pool.hpp>
#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/storage/network_status.hpp>
#include <mbgl/style/transition_options.hpp>
#include <mbgl/style/layers/custom_layer.hpp>
+#include <mbgl/map/backend.hpp>
#include <mbgl/math/wrap.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/util/constants.hpp>
@@ -24,7 +27,7 @@
#include <mbgl/util/projection.hpp>
#include <mbgl/util/default_styles.hpp>
#include <mbgl/util/chrono.hpp>
-#import <mbgl/util/run_loop.hpp>
+#include <mbgl/util/run_loop.hpp>
#import "Mapbox.h"
#import "MGLFeature_Private.h"
@@ -258,6 +261,7 @@ public:
{
mbgl::Map *_mbglMap;
MBGLView *_mbglView;
+ mbgl::ThreadPool *_mbglThreadPool;
BOOL _opaque;
@@ -387,8 +391,7 @@ public:
self.clipsToBounds = YES;
// setup mbgl view
- const float scaleFactor = [UIScreen instancesRespondToSelector:@selector(nativeScale)] ? [[UIScreen mainScreen] nativeScale] : [[UIScreen mainScreen] scale];
- _mbglView = new MBGLView(self, scaleFactor);
+ _mbglView = new MBGLView(self);
// Delete the pre-offline ambient cache at ~/Library/Caches/cache.db.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
@@ -396,8 +399,12 @@ public:
[[NSFileManager defaultManager] removeItemAtPath:fileCachePath error:NULL];
// setup mbgl map
+ const std::array<uint16_t, 2> size = {{ static_cast<uint16_t>(self.bounds.size.width),
+ static_cast<uint16_t>(self.bounds.size.height) }};
mbgl::DefaultFileSource *mbglFileSource = [MGLOfflineStorage sharedOfflineStorage].mbglFileSource;
- _mbglMap = new mbgl::Map(*_mbglView, *mbglFileSource, mbgl::MapMode::Continuous, mbgl::GLContextMode::Unique, mbgl::ConstrainMode::None, mbgl::ViewportMode::Default);
+ const float scaleFactor = [UIScreen instancesRespondToSelector:@selector(nativeScale)] ? [[UIScreen mainScreen] nativeScale] : [[UIScreen mainScreen] scale];
+ _mbglThreadPool = new mbgl::ThreadPool(4);
+ _mbglMap = new mbgl::Map(*_mbglView, size, scaleFactor, *mbglFileSource, *_mbglThreadPool, mbgl::MapMode::Continuous, mbgl::GLContextMode::Unique, mbgl::ConstrainMode::None, mbgl::ViewportMode::Default);
[self validateTileCacheSize];
// start paused if in IB
@@ -650,6 +657,12 @@ public:
_mbglView = nullptr;
}
+ if (_mbglThreadPool)
+ {
+ delete _mbglThreadPool;
+ _mbglThreadPool = nullptr;
+ }
+
if ([[EAGLContext currentContext] isEqual:_context])
{
[EAGLContext setCurrentContext:nil];
@@ -858,7 +871,8 @@ public:
{
if ( ! self.dormant)
{
- _mbglMap->render();
+ _mbglView->updateViewBinding();
+ _mbglMap->render(*_mbglView);
[self updateUserLocationAnnotationView];
}
@@ -873,7 +887,8 @@ public:
if ( ! _isTargetingInterfaceBuilder)
{
- _mbglMap->update(mbgl::Update::Dimensions);
+ _mbglMap->setSize({{ static_cast<uint16_t>(self.bounds.size.width),
+ static_cast<uint16_t>(self.bounds.size.height) }});
}
if (self.attributionSheet.visible)
@@ -4923,25 +4938,39 @@ public:
return _annotationViewReuseQueueByIdentifier[identifier];
}
-class MBGLView : public mbgl::View
+class MBGLView : public mbgl::View, public mbgl::Backend
{
public:
- MBGLView(MGLMapView* nativeView_, const float scaleFactor_)
- : nativeView(nativeView_), scaleFactor(scaleFactor_) {
- }
-
- float getPixelRatio() const override {
- return scaleFactor;
- }
-
- std::array<uint16_t, 2> getSize() const override {
- return {{ static_cast<uint16_t>([nativeView bounds].size.width),
- static_cast<uint16_t>([nativeView bounds].size.height) }};
- }
-
- std::array<uint16_t, 2> getFramebufferSize() const override {
- return {{ static_cast<uint16_t>([[nativeView glView] drawableWidth]),
- static_cast<uint16_t>([[nativeView glView] drawableHeight]) }};
+ MBGLView(MGLMapView* nativeView_)
+ : nativeView(nativeView_) {
+ }
+
+ mbgl::gl::value::Viewport::Type getViewport() const {
+ return { 0, 0, static_cast<uint16_t>(nativeView.glView.drawableWidth),
+ static_cast<uint16_t>(nativeView.glView.drawableHeight) };
+ }
+
+ /// This function is called before we start rendering, when iOS invokes our rendering method.
+ /// iOS already sets the correct framebuffer and viewport for us, so we need to update the
+ /// context state with the anticipated values.
+ void updateViewBinding() {
+ // We are using 0 as the placeholder value for the GLKView's framebuffer.
+ getContext().bindFramebuffer.setCurrentValue(0);
+ getContext().viewport.setCurrentValue(getViewport());
+ }
+
+ void bind() override {
+ if (getContext().bindFramebuffer != 0) {
+ // Something modified our state, and we need to bind the original drawable again.
+ // Doing this also sets the viewport to the full framebuffer.
+ // Note that in reality, iOS does not use the Framebuffer 0 (it's typically 1), and we
+ // only use this is a placeholder value.
+ [nativeView.glView bindDrawable];
+ updateViewBinding();
+ } else {
+ // Our framebuffer is still bound, but the viewport might have changed.
+ getContext().viewport = getViewport();
+ }
}
void notifyMapChange(mbgl::MapChange change) override
@@ -4966,7 +4995,6 @@ public:
private:
__weak MGLMapView *nativeView = nullptr;
- const float scaleFactor;
};
@end
@@ -5180,7 +5208,7 @@ void MGLFinishCustomStyleLayer(void *context)
- (void)setCustomStyleLayersNeedDisplay
{
- _mbglMap->update(mbgl::Update::Repaint);
+ [self setNeedsGLDisplay];
}
- (mbgl::Map *)mbglMap {
diff --git a/platform/linux/config.cmake b/platform/linux/config.cmake
index 050a03bcb2..6bde3136f2 100644
--- a/platform/linux/config.cmake
+++ b/platform/linux/config.cmake
@@ -41,9 +41,13 @@ macro(mbgl_platform_core)
PRIVATE platform/default/webp_reader.cpp
# Headless view
+ PRIVATE platform/default/headless_backend_glx.cpp
+ PRIVATE platform/default/headless_backend.cpp
PRIVATE platform/default/headless_display.cpp
- PRIVATE platform/default/headless_view.cpp
- PRIVATE platform/default/headless_view_glx.cpp
+ PRIVATE platform/default/offscreen_view.cpp
+
+ # Thread pool
+ PRIVATE platform/default/thread_pool.cpp
)
target_include_directories(mbgl-core
diff --git a/platform/macos/config.cmake b/platform/macos/config.cmake
index f8d4ab398f..27bf555ec6 100644
--- a/platform/macos/config.cmake
+++ b/platform/macos/config.cmake
@@ -35,9 +35,13 @@ macro(mbgl_platform_core)
PRIVATE platform/darwin/src/image.mm
# Headless view
- PRIVATE platform/darwin/src/headless_view_cgl.cpp
+ PRIVATE platform/darwin/src/headless_backend_cgl.cpp
+ PRIVATE platform/default/headless_backend.cpp
PRIVATE platform/default/headless_display.cpp
- PRIVATE platform/default/headless_view.cpp
+ PRIVATE platform/default/offscreen_view.cpp
+
+ # Thread pool
+ PRIVATE platform/default/thread_pool.cpp
)
target_add_mason_package(mbgl-core PUBLIC geojson)
diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm
index 81f9e249b6..14b83762a3 100644
--- a/platform/macos/src/MGLMapView.mm
+++ b/platform/macos/src/MGLMapView.mm
@@ -22,8 +22,11 @@
#import <mbgl/annotation/annotation.hpp>
#import <mbgl/map/camera.hpp>
#import <mbgl/platform/darwin/reachability.h>
+#import <mbgl/platform/default/thread_pool.hpp>
#import <mbgl/gl/extension.hpp>
#import <mbgl/gl/gl.hpp>
+#import <mbgl/gl/context.hpp>
+#import <mbgl/map/backend.hpp>
#import <mbgl/sprite/sprite_image.hpp>
#import <mbgl/storage/default_file_source.hpp>
#import <mbgl/storage/network_status.hpp>
@@ -158,6 +161,7 @@ public:
/// Cross-platform map view controller.
mbgl::Map *_mbglMap;
MGLMapViewImpl *_mbglView;
+ mbgl::ThreadPool *_mbglThreadPool;
NSPanGestureRecognizer *_panGestureRecognizer;
NSMagnificationGestureRecognizer *_magnificationGestureRecognizer;
@@ -246,7 +250,7 @@ public:
_isTargetingInterfaceBuilder = NSProcessInfo.processInfo.mgl_isInterfaceBuilderDesignablesAgent;
// Set up cross-platform controllers and resources.
- _mbglView = new MGLMapViewImpl(self, [NSScreen mainScreen].backingScaleFactor);
+ _mbglView = new MGLMapViewImpl(self);
// Delete the pre-offline ambient cache at
// ~/Library/Caches/com.mapbox.sdk.ios/cache.db.
@@ -260,8 +264,12 @@ public:
NSURL *legacyCacheURL = [cachesDirectoryURL URLByAppendingPathComponent:@"cache.db"];
[[NSFileManager defaultManager] removeItemAtURL:legacyCacheURL error:NULL];
- mbgl::DefaultFileSource *mbglFileSource = [MGLOfflineStorage sharedOfflineStorage].mbglFileSource;
- _mbglMap = new mbgl::Map(*_mbglView, *mbglFileSource, mbgl::MapMode::Continuous, mbgl::GLContextMode::Unique, mbgl::ConstrainMode::None, mbgl::ViewportMode::Default);
+ mbgl::DefaultFileSource* mbglFileSource = [MGLOfflineStorage sharedOfflineStorage].mbglFileSource;
+
+ const std::array<uint16_t, 2> size = {{ static_cast<uint16_t>(self.bounds.size.width),
+ static_cast<uint16_t>(self.bounds.size.height) }};
+ _mbglThreadPool = new mbgl::ThreadPool(4);
+ _mbglMap = new mbgl::Map(*_mbglView, size, [NSScreen mainScreen].backingScaleFactor, *mbglFileSource, *_mbglThreadPool, mbgl::MapMode::Continuous, mbgl::GLContextMode::Unique, mbgl::ConstrainMode::None, mbgl::ViewportMode::Default);
[self validateTileCacheSize];
// Install the OpenGL layer. Interface Builder’s synchronous drawing means
@@ -466,6 +474,10 @@ public:
delete _mbglView;
_mbglView = nullptr;
}
+ if (_mbglThreadPool) {
+ delete _mbglThreadPool;
+ _mbglThreadPool = nullptr;
+ }
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(__unused NSDictionary *)change context:(void *)context {
@@ -627,7 +639,8 @@ public:
[self validateTileCacheSize];
}
if (!_isTargetingInterfaceBuilder) {
- _mbglMap->update(mbgl::Update::Dimensions);
+ _mbglMap->setSize({{ static_cast<uint16_t>(self.bounds.size.width),
+ static_cast<uint16_t>(self.bounds.size.height) }});
}
}
@@ -738,7 +751,8 @@ public:
return reinterpret_cast<mbgl::gl::glProc>(symbol);
});
- _mbglMap->render();
+ _mbglView->updateViewBinding();
+ _mbglMap->render(*_mbglView);
if (_isPrinting) {
_isPrinting = NO;
@@ -2519,25 +2533,10 @@ public:
}
/// Adapter responsible for bridging calls from mbgl to MGLMapView and Cocoa.
-class MGLMapViewImpl : public mbgl::View {
+class MGLMapViewImpl : public mbgl::View, public mbgl::Backend {
public:
- MGLMapViewImpl(MGLMapView *nativeView_, const float scaleFactor_)
- : nativeView(nativeView_), scaleFactor(scaleFactor_) {}
-
- float getPixelRatio() const override {
- return scaleFactor;
- }
-
- std::array<uint16_t, 2> getSize() const override {
- return {{ static_cast<uint16_t>(nativeView.bounds.size.width),
- static_cast<uint16_t>(nativeView.bounds.size.height) }};
- }
-
- std::array<uint16_t, 2> getFramebufferSize() const override {
- NSRect bounds = [nativeView convertRectToBacking:nativeView.bounds];
- return {{ static_cast<uint16_t>(bounds.size.width),
- static_cast<uint16_t>(bounds.size.height) }};
- }
+ MGLMapViewImpl(MGLMapView *nativeView_)
+ : nativeView(nativeView_) {}
void notifyMapChange(mbgl::MapChange change) override {
[nativeView notifyMapChange:change];
@@ -2556,18 +2555,34 @@ public:
[NSOpenGLContext clearCurrentContext];
}
- mbgl::PremultipliedImage readStillImage(std::array<uint16_t, 2> size = {{ 0, 0 }}) override {
- if (!size[0] || !size[1]) {
- size = getFramebufferSize();
- }
+ mbgl::gl::value::Viewport::Type getViewport() const {
+ return { 0, 0, static_cast<uint16_t>(nativeView.bounds.size.width),
+ static_cast<uint16_t>(nativeView.bounds.size.height) };
+ }
+
+ void updateViewBinding() {
+ fbo = mbgl::gl::value::BindFramebuffer::Get();
+ getContext().bindFramebuffer.setCurrentValue(fbo);
+ getContext().viewport.setCurrentValue(getViewport());
+ }
+
+ void bind() override {
+ getContext().bindFramebuffer = fbo;
+ getContext().viewport = getViewport();
+ }
- mbgl::PremultipliedImage image { size[0], size[1] };
- MBGL_CHECK_ERROR(glReadPixels(0, 0, size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE, image.data.get()));
+ mbgl::PremultipliedImage readStillImage() {
+ NSRect bounds = [nativeView convertRectToBacking:nativeView.bounds];
+ const uint16_t width = bounds.size.width;
+ const uint16_t height = bounds.size.height;
+ mbgl::PremultipliedImage image{ width, height };
+ MBGL_CHECK_ERROR(
+ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, image.data.get()));
const size_t stride = image.stride();
auto tmp = std::make_unique<uint8_t[]>(stride);
uint8_t *rgba = image.data.get();
- for (int i = 0, j = size[1] - 1; i < j; i++, j--) {
+ for (int i = 0, j = height - 1; i < j; i++, j--) {
std::memcpy(tmp.get(), rgba + i * stride, stride);
std::memcpy(rgba + i * stride, rgba + j * stride, stride);
std::memcpy(rgba + j * stride, tmp.get(), stride);
@@ -2580,8 +2595,8 @@ private:
/// Cocoa map view that this adapter bridges to.
__weak MGLMapView *nativeView = nullptr;
- /// Backing scale factor of the view.
- const float scaleFactor;
+ /// The current framebuffer of the NSOpenGLLayer we are painting to.
+ GLint fbo = 0;
};
@end
diff --git a/platform/node/bitrise.yml b/platform/node/bitrise.yml
index b968554781..af22fe65ea 100644
--- a/platform/node/bitrise.yml
+++ b/platform/node/bitrise.yml
@@ -1,9 +1,12 @@
-format_version: 1.1.0
+format_version: 1.3.0
default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git
trigger_map:
-- pattern: "*"
- is_pull_request_allowed: true
+- tag: "node-v*"
+ workflow: primary
+- push_branch: "*"
+ workflow: primary
+- pull_request_target_branch: "*"
workflow: primary
workflows:
@@ -23,6 +26,16 @@ workflows:
envman add --key SKIPCI --value false
fi
- script:
+ title: Check for publishing
+ run_if: '{{enveq "SKIPCI" "false"}}'
+ inputs:
+ - content: |-
+ #!/bin/bash
+ PACKAGE_JSON_VERSION=$(node -e "console.log(require('./package.json').version)")
+ if [[ "${BITRISE_GIT_TAG:-}" == "node-v${PACKAGE_JSON_VERSION}" ]]; then
+ envman add --key PUBLISH --value true
+ fi
+ - script:
title: Run build script
run_if: '{{enveq "SKIPCI" "false"}}'
inputs:
@@ -35,9 +48,23 @@ workflows:
brew link homebrew/versions/node4-lts
gem install xcpretty --no-rdoc --no-ri
make node
- make test-node || result=$?
- ./platform/node/scripts/after_script.sh ${BITRISE_BUILD_NUMBER} ${BITRISE_GIT_TAG:-}
- exit ${result:-0}
+ - script:
+ title: Run test script
+ run_if: '{{and (enveq "SKIPCI" "false") (enveq "PUBLISH" "")}}'
+ inputs:
+ - content: |-
+ #!/bin/bash
+ set -eu -o pipefail
+ make test-node || envman add --key RESULT --value $?
+ - script:
+ title: Run publish script
+ run_if: '{{enveq "SKIPCI" "false"}}'
+ inputs:
+ - content: |-
+ #!/bin/bash
+ set -eu -o pipefail
+ ./platform/node/scripts/after_script.sh ${BITRISE_BUILD_NUMBER}
+ exit ${RESULT:-0}
- slack:
title: Post to Slack
run_if: '{{enveq "SKIPCI" "false"}}'
diff --git a/platform/node/src/node_log.cpp b/platform/node/src/node_log.cpp
index 5ea0bcc06a..0a97ebce36 100644
--- a/platform/node/src/node_log.cpp
+++ b/platform/node/src/node_log.cpp
@@ -1,5 +1,4 @@
#include "node_log.hpp"
-#include "util/async_queue.hpp"
#include <mbgl/util/enum.hpp>
@@ -19,7 +18,7 @@ struct NodeLogObserver::LogMessage {
};
NodeLogObserver::NodeLogObserver(v8::Local<v8::Object> target)
- : queue(new Queue(uv_default_loop(), [this](LogMessage &message) {
+ : queue(new util::AsyncQueue<LogMessage>(uv_default_loop(), [this](LogMessage &message) {
Nan::HandleScope scope;
auto msg = Nan::New<v8::Object>();
diff --git a/platform/node/src/node_log.hpp b/platform/node/src/node_log.hpp
index d29e4e28e0..a19c61284b 100644
--- a/platform/node/src/node_log.hpp
+++ b/platform/node/src/node_log.hpp
@@ -1,5 +1,7 @@
#pragma once
+#include "util/async_queue.hpp"
+
#include <mbgl/platform/log.hpp>
#pragma GCC diagnostic push
@@ -24,8 +26,7 @@ private:
Nan::Persistent<v8::Object> module;
struct LogMessage;
- using Queue = util::AsyncQueue<LogMessage>;
- Queue *queue = nullptr;
+ util::AsyncQueue<LogMessage>* queue;
};
}
diff --git a/platform/node/src/node_map.cpp b/platform/node/src/node_map.cpp
index 4d4be5be66..671bf3e0fd 100644
--- a/platform/node/src/node_map.cpp
+++ b/platform/node/src/node_map.cpp
@@ -356,21 +356,28 @@ void NodeMap::Render(const Nan::FunctionCallbackInfo<v8::Value>& info) {
}
void NodeMap::startRender(NodeMap::RenderOptions options) {
- view.resize(options.width, options.height);
- map->update(mbgl::Update::Dimensions);
+ map->setSize(std::array<uint16_t, 2>{{ static_cast<uint16_t>(options.width),
+ static_cast<uint16_t>(options.height) }});
+
+ const std::array<uint16_t, 2> fbSize{{ static_cast<uint16_t>(options.width * pixelRatio),
+ static_cast<uint16_t>(options.height * pixelRatio) }};
+ if (!view || view->getSize() != fbSize) {
+ view.reset();
+ view = std::make_unique<mbgl::OffscreenView>(backend.getContext(), fbSize);
+ }
map->setClasses(options.classes);
map->setLatLngZoom(mbgl::LatLng(options.latitude, options.longitude), options.zoom);
map->setBearing(options.bearing);
map->setPitch(options.pitch);
map->setDebug(options.debugOptions);
- map->renderStill([this](const std::exception_ptr eptr, mbgl::PremultipliedImage&& result) {
+ map->renderStill(*view, [this](const std::exception_ptr eptr) {
if (eptr) {
error = std::move(eptr);
uv_async_send(async);
} else {
assert(!image.data);
- image = std::move(result);
+ image = view->readStillImage();
uv_async_send(async);
}
});
@@ -772,15 +779,25 @@ void NodeMap::QueryRenderedFeatures(const Nan::FunctionCallbackInfo<v8::Value>&
}
}
-NodeMap::NodeMap(v8::Local<v8::Object> options) :
- view(sharedDisplay(), [&] {
- Nan::HandleScope scope;
- return Nan::Has(options, Nan::New("ratio").ToLocalChecked()).FromJust() ? Nan::Get(options, Nan::New("ratio").ToLocalChecked()).ToLocalChecked()->NumberValue() : 1.0;
- }()),
- map(std::make_unique<mbgl::Map>(view, *this, mbgl::MapMode::Still)),
- async(new uv_async_t) {
-
- view.setMapChangeCallback([&](mbgl::MapChange change) {
+NodeMap::NodeMap(v8::Local<v8::Object> options)
+ : pixelRatio([&] {
+ Nan::HandleScope scope;
+ return Nan::Has(options, Nan::New("ratio").ToLocalChecked()).FromJust()
+ ? Nan::Get(options, Nan::New("ratio").ToLocalChecked())
+ .ToLocalChecked()
+ ->NumberValue()
+ : 1.0;
+ }()),
+ backend(sharedDisplay()),
+ map(std::make_unique<mbgl::Map>(backend,
+ std::array<uint16_t, 2>{{ 256, 256 }},
+ pixelRatio,
+ *this,
+ threadpool,
+ mbgl::MapMode::Still)),
+ async(new uv_async_t) {
+
+ backend.setMapChangeCallback([&](mbgl::MapChange change) {
if (change == mbgl::MapChangeDidFailLoadingMap) {
throw std::runtime_error("Requires a map style to be a valid style JSON");
}
diff --git a/platform/node/src/node_map.hpp b/platform/node/src/node_map.hpp
index c0b025c369..45de2733cc 100644
--- a/platform/node/src/node_map.hpp
+++ b/platform/node/src/node_map.hpp
@@ -1,8 +1,11 @@
#pragma once
+#include "node_thread_pool.hpp"
+
#include <mbgl/map/map.hpp>
#include <mbgl/storage/file_source.hpp>
-#include <mbgl/platform/default/headless_view.hpp>
+#include <mbgl/platform/default/headless_backend.hpp>
+#include <mbgl/platform/default/offscreen_view.hpp>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
@@ -23,7 +26,7 @@ public:
static Nan::Persistent<v8::Function> constructor;
- static void Init(v8::Local<v8::Object> exports);
+ static void Init(v8::Local<v8::Object>);
static void New(const Nan::FunctionCallbackInfo<v8::Value>&);
static void Load(const Nan::FunctionCallbackInfo<v8::Value>&);
@@ -51,7 +54,10 @@ public:
std::unique_ptr<mbgl::AsyncRequest> request(const mbgl::Resource&, mbgl::FileSource::Callback);
- mbgl::HeadlessView view;
+ const float pixelRatio;
+ mbgl::HeadlessBackend backend;
+ std::unique_ptr<mbgl::OffscreenView> view;
+ NodeThreadPool threadpool;
std::unique_ptr<mbgl::Map> map;
std::exception_ptr error;
diff --git a/platform/node/src/node_mapbox_gl_native.cpp b/platform/node/src/node_mapbox_gl_native.cpp
index 7c5a959553..042def9fdd 100644
--- a/platform/node/src/node_mapbox_gl_native.cpp
+++ b/platform/node/src/node_mapbox_gl_native.cpp
@@ -19,7 +19,7 @@ void RegisterModule(v8::Local<v8::Object> target, v8::Local<v8::Object> module)
nodeRunLoop.stop();
node_mbgl::NodeMap::Init(target);
- node_mbgl::NodeRequest::Init(target);
+ node_mbgl::NodeRequest::Init();
// Exports Resource constants.
v8::Local<v8::Object> resource = Nan::New<v8::Object>();
diff --git a/platform/node/src/node_request.cpp b/platform/node/src/node_request.cpp
index 607e6e8b03..de16710f78 100644
--- a/platform/node/src/node_request.cpp
+++ b/platform/node/src/node_request.cpp
@@ -26,7 +26,7 @@ NodeRequest::~NodeRequest() {
Nan::Persistent<v8::Function> NodeRequest::constructor;
-NAN_MODULE_INIT(NodeRequest::Init) {
+void NodeRequest::Init() {
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
tpl->InstanceTemplate()->SetInternalFieldCount(1);
@@ -35,9 +35,6 @@ NAN_MODULE_INIT(NodeRequest::Init) {
Nan::SetPrototypeMethod(tpl, "respond", HandleCallback);
constructor.Reset(tpl->GetFunction());
-
- // TODO: Remove this from the public JavaScript API
- Nan::Set(target, Nan::New("Request").ToLocalChecked(), tpl->GetFunction());
}
void NodeRequest::New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
diff --git a/platform/node/src/node_request.hpp b/platform/node/src/node_request.hpp
index f7fce91726..7d7679a3c7 100644
--- a/platform/node/src/node_request.hpp
+++ b/platform/node/src/node_request.hpp
@@ -27,7 +27,7 @@ public:
static Nan::Persistent<v8::Function> constructor;
- static NAN_MODULE_INIT(Init);
+ static void Init();
static void New(const Nan::FunctionCallbackInfo<v8::Value>&);
static void HandleCallback(const Nan::FunctionCallbackInfo<v8::Value>&);
diff --git a/platform/node/src/node_thread_pool.cpp b/platform/node/src/node_thread_pool.cpp
new file mode 100644
index 0000000000..fd6df575fc
--- /dev/null
+++ b/platform/node/src/node_thread_pool.cpp
@@ -0,0 +1,37 @@
+#include "node_thread_pool.hpp"
+#include "util/async_queue.hpp"
+
+#include <mbgl/actor/mailbox.hpp>
+
+namespace node_mbgl {
+
+NodeThreadPool::NodeThreadPool()
+ : queue(new util::AsyncQueue<std::weak_ptr<mbgl::Mailbox>>(uv_default_loop(), [this](std::weak_ptr<mbgl::Mailbox> mailbox) {
+ Worker* worker = new Worker(mailbox);
+ Nan::AsyncQueueWorker(worker);
+ })) {
+ // Don't keep the event loop alive.
+ queue->unref();
+}
+
+NodeThreadPool::~NodeThreadPool() {
+ queue->stop();
+}
+
+void NodeThreadPool::schedule(std::weak_ptr<mbgl::Mailbox> mailbox) {
+ queue->send(std::move(mailbox));
+}
+
+NodeThreadPool::Worker::Worker(std::weak_ptr<mbgl::Mailbox> mailbox_)
+ : AsyncWorker(nullptr),
+ mailbox(std::move(mailbox_)) {};
+
+void NodeThreadPool::Worker::Execute() {
+ mbgl::Mailbox::maybeReceive(mailbox);
+}
+
+void NodeThreadPool::Worker::WorkComplete() {
+ // no-op to avoid calling nullptr callback
+}
+
+} // namespace node_mbgl
diff --git a/platform/node/src/node_thread_pool.hpp b/platform/node/src/node_thread_pool.hpp
new file mode 100644
index 0000000000..d412e53d3d
--- /dev/null
+++ b/platform/node/src/node_thread_pool.hpp
@@ -0,0 +1,37 @@
+#pragma once
+
+#include <mbgl/actor/scheduler.hpp>
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#pragma GCC diagnostic ignored "-Wshadow"
+#include <nan.h>
+#pragma GCC diagnostic pop
+
+namespace node_mbgl {
+
+namespace util { template <typename T> class AsyncQueue; }
+
+class NodeThreadPool : public mbgl::Scheduler {
+public:
+ NodeThreadPool();
+ ~NodeThreadPool();
+
+ void schedule(std::weak_ptr<mbgl::Mailbox>) override;
+
+private:
+ util::AsyncQueue<std::weak_ptr<mbgl::Mailbox>>* queue;
+
+ class Worker : public Nan::AsyncWorker {
+ public:
+ Worker(std::weak_ptr<mbgl::Mailbox>);
+
+ void Execute();
+ void WorkComplete();
+
+ private:
+ std::weak_ptr<mbgl::Mailbox> mailbox;
+ };
+};
+
+} // namespace node_mbgl
diff --git a/platform/node/src/util/async_queue.hpp b/platform/node/src/util/async_queue.hpp
index b9081b3aeb..87737437c3 100644
--- a/platform/node/src/util/async_queue.hpp
+++ b/platform/node/src/util/async_queue.hpp
@@ -28,6 +28,7 @@ public:
q->process();
});
}
+ ~AsyncQueue() {}
void send(T &&data) {
{
@@ -60,9 +61,6 @@ public:
}
private:
- ~AsyncQueue() {
- }
-
void process() {
std::unique_ptr<T> item;
while (true) {
diff --git a/platform/qt/app/mapwindow.cpp b/platform/qt/app/mapwindow.cpp
index ca73b0a8da..e8e3a13489 100644
--- a/platform/qt/app/mapwindow.cpp
+++ b/platform/qt/app/mapwindow.cpp
@@ -9,10 +9,15 @@
#include <QMouseEvent>
#include <QString>
+#if QT_VERSION >= 0x050000
+#include <QWindow>
+#endif
+
int kAnimationDuration = 10000;
+
MapWindow::MapWindow(const QMapboxGLSettings &settings)
- : m_map(nullptr, settings)
+ : m_map(nullptr, settings, size(), pixelRatio())
, m_bearingAnimation(&m_map, "bearing")
, m_zoomAnimation(&m_map, "zoom")
{
@@ -46,6 +51,17 @@ void MapWindow::selfTest()
m_zoomAnimation.start();
}
+qreal MapWindow::pixelRatio() {
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
+ return devicePixelRatioF();
+#elif (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
+ return devicePixelRatio();
+#else
+ return 1;
+#endif
+}
+
+
void MapWindow::animationFinished()
{
qDebug() << "Animation ticks/s: " << m_animationTicks / static_cast<float>(kAnimationDuration) * 1000.;
@@ -288,14 +304,20 @@ void MapWindow::initializeGL()
QMapbox::initializeGLExtensions();
}
-void MapWindow::resizeGL(int w, int h)
-{
- QSize size(w, h);
- m_map.resize(size);
-}
-
void MapWindow::paintGL()
{
m_frameDraws++;
+
+ m_map.resize(size(), size() * pixelRatio());
+
+#if QT_VERSION < 0x050400 && defined(__APPLE__)
+ // XXX GL framebuffer is valid only after first attempt of painting on
+ // older versions of Qt on macOS.
+ // See https://bugreports.qt.io/browse/QTBUG-36802 for details.
+ static bool first = true;
+ if (!first) m_map.render();
+ first = false;
+#else
m_map.render();
+#endif
}
diff --git a/platform/qt/app/mapwindow.hpp b/platform/qt/app/mapwindow.hpp
index fa1c3f4b3b..a579a5bcc5 100644
--- a/platform/qt/app/mapwindow.hpp
+++ b/platform/qt/app/mapwindow.hpp
@@ -24,6 +24,7 @@ protected slots:
private:
void changeStyle();
+ qreal pixelRatio();
// QGLWidget implementation.
void keyPressEvent(QKeyEvent *ev) final;
@@ -32,7 +33,6 @@ private:
void wheelEvent(QWheelEvent *ev) final;
void initializeGL() final;
- void resizeGL(int w, int h) final;
void paintGL() final;
QPointF m_lastPos;
diff --git a/platform/qt/config.cmake b/platform/qt/config.cmake
index d8ede6b450..ff86a0dee1 100644
--- a/platform/qt/config.cmake
+++ b/platform/qt/config.cmake
@@ -43,10 +43,11 @@ endmacro()
macro(mbgl_platform_test)
target_sources(mbgl-test
PRIVATE test/src/main.cpp
- PRIVATE platform/qt/test/headless_view_qt.cpp
+ PRIVATE platform/qt/test/headless_backend_qt.cpp
PRIVATE platform/qt/test/qmapboxgl.cpp
+ PRIVATE platform/default/headless_backend.cpp
PRIVATE platform/default/headless_display.cpp
- PRIVATE platform/default/headless_view.cpp
+ PRIVATE platform/default/offscreen_view.cpp
)
set_source_files_properties(
diff --git a/platform/qt/include/qmapboxgl.hpp b/platform/qt/include/qmapboxgl.hpp
index ba5631e1e4..d3937ce083 100644
--- a/platform/qt/include/qmapboxgl.hpp
+++ b/platform/qt/include/qmapboxgl.hpp
@@ -3,6 +3,7 @@
#include <QMapbox>
#include <QObject>
+#include <QSize>
#include <QPointF>
class QImage;
@@ -10,6 +11,7 @@ class QMargins;
class QSize;
class QString;
class QStringList;
+class QOpenGLFramebufferObject;
class QMapboxGLPrivate;
@@ -95,7 +97,10 @@ public:
NorthLeftwards,
};
- QMapboxGL(QObject *parent = 0, const QMapboxGLSettings& = QMapboxGLSettings());
+ QMapboxGL(QObject* parent = 0,
+ const QMapboxGLSettings& = QMapboxGLSettings(),
+ const QSize& size = QSize(),
+ qreal pixelRatio = 1);
virtual ~QMapboxGL();
void cycleDebugOptions();
@@ -167,7 +172,7 @@ public:
void scaleBy(double scale, const QPointF &center = QPointF());
void rotateBy(const QPointF &first, const QPointF &second);
- void resize(const QSize &size);
+ void resize(const QSize &size, const QSize &framebufferSize);
void addAnnotationIcon(const QString &name, const QImage &sprite);
@@ -198,7 +203,11 @@ public:
void setFilter(const QString &layer, const QVariant &filter);
public slots:
+#if QT_VERSION >= 0x050000
+ void render(QOpenGLFramebufferObject *fbo = NULL);
+#else
void render();
+#endif
void connectionEstablished();
signals:
diff --git a/platform/qt/qt.cmake b/platform/qt/qt.cmake
index dc60455b0a..398e173cfa 100644
--- a/platform/qt/qt.cmake
+++ b/platform/qt/qt.cmake
@@ -30,6 +30,9 @@ set(MBGL_QT_FILES
# Misc
PRIVATE platform/default/log_stderr.cpp
+ # Thread pool
+ PRIVATE platform/default/thread_pool.cpp
+
# Platform integration
PRIVATE platform/qt/src/async_task.cpp
PRIVATE platform/qt/src/async_task_impl.hpp
diff --git a/platform/qt/src/qmapboxgl.cpp b/platform/qt/src/qmapboxgl.cpp
index 103ed83256..edda1f9599 100644
--- a/platform/qt/src/qmapboxgl.cpp
+++ b/platform/qt/src/qmapboxgl.cpp
@@ -6,6 +6,7 @@
#include <mbgl/annotation/annotation.hpp>
#include <mbgl/gl/gl.hpp>
+#include <mbgl/gl/context.hpp>
#include <mbgl/map/camera.hpp>
#include <mbgl/map/map.hpp>
#include <mbgl/style/conversion.hpp>
@@ -23,6 +24,7 @@
#if QT_VERSION >= 0x050000
#include <QGuiApplication>
#include <QWindow>
+#include <QOpenGLFramebufferObject>
#else
#include <QCoreApplication>
#endif
@@ -271,7 +273,7 @@ void QMapboxGLSettings::setAccessToken(const QString &token)
Constructs a QMapboxGL object with \a settings and sets \a parent as the parent
object. The \a settings cannot be changed after the object is constructed.
*/
-QMapboxGL::QMapboxGL(QObject *parent, const QMapboxGLSettings &settings)
+QMapboxGL::QMapboxGL(QObject *parent, const QMapboxGLSettings &settings, const QSize& size, qreal pixelRatio)
: QObject(parent)
{
// Multiple QMapboxGL running on the same thread
@@ -280,7 +282,7 @@ QMapboxGL::QMapboxGL(QObject *parent, const QMapboxGLSettings &settings)
loop.setLocalData(std::make_shared<mbgl::util::RunLoop>());
}
- d_ptr = new QMapboxGLPrivate(this, settings);
+ d_ptr = new QMapboxGLPrivate(this, settings, size, pixelRatio);
}
QMapboxGL::~QMapboxGL()
@@ -602,15 +604,14 @@ void QMapboxGL::rotateBy(const QPointF &first, const QPointF &second)
mbgl::ScreenCoordinate { second.x(), second.y() });
}
-void QMapboxGL::resize(const QSize& size)
+void QMapboxGL::resize(const QSize& size, const QSize& framebufferSize)
{
- QSize converted = size / d_ptr->getPixelRatio();
- if (d_ptr->size == converted) return;
+ if (d_ptr->size == size && d_ptr->fbSize == framebufferSize) return;
- glViewport(0, 0, converted.width(), converted.height());
+ d_ptr->size = size;
+ d_ptr->fbSize = framebufferSize;
- d_ptr->size = converted;
- d_ptr->mapObj->update(mbgl::Update::Dimensions);
+ d_ptr->mapObj->setSize({{ static_cast<uint16_t>(size.width()), static_cast<uint16_t>(size.height()) }});
}
void QMapboxGL::addAnnotationIcon(const QString &name, const QImage &sprite)
@@ -793,26 +794,38 @@ void QMapboxGL::setFilter(const QString& layer_, const QVariant& filter_)
qWarning() << "Layer doesn't support filters";
}
+#if QT_VERSION >= 0x050000
+void QMapboxGL::render(QOpenGLFramebufferObject *fbo)
+{
+ d_ptr->dirty = false;
+ d_ptr->updateFramebufferBinding(fbo);
+ d_ptr->mapObj->render(*d_ptr);
+}
+#else
void QMapboxGL::render()
{
d_ptr->dirty = false;
- d_ptr->mapObj->render();
+ d_ptr->mapObj->render(*d_ptr);
}
+#endif
void QMapboxGL::connectionEstablished()
{
d_ptr->connectionEstablished();
}
-QMapboxGLPrivate::QMapboxGLPrivate(QMapboxGL *q, const QMapboxGLSettings &settings)
+QMapboxGLPrivate::QMapboxGLPrivate(QMapboxGL *q, const QMapboxGLSettings &settings, const QSize &size_, qreal pixelRatio)
: QObject(q)
+ , size(size_)
, q_ptr(q)
, fileSourceObj(std::make_unique<mbgl::DefaultFileSource>(
settings.cacheDatabasePath().toStdString(),
settings.assetPath().toStdString(),
settings.cacheDatabaseMaximumSize()))
+ , threadPool(4)
, mapObj(std::make_unique<mbgl::Map>(
- *this, *fileSourceObj,
+ *this, std::array<uint16_t, 2>{{ static_cast<uint16_t>(size.width()), static_cast<uint16_t>(size.height()) }},
+ pixelRatio, *fileSourceObj, threadPool,
static_cast<mbgl::MapMode>(settings.mapMode()),
static_cast<mbgl::GLContextMode>(settings.contextMode()),
static_cast<mbgl::ConstrainMode>(settings.constrainMode()),
@@ -829,31 +842,42 @@ QMapboxGLPrivate::~QMapboxGLPrivate()
{
}
-float QMapboxGLPrivate::getPixelRatio() const
-{
#if QT_VERSION >= 0x050000
- // QWindow is the most reliable pixel ratio because QGuiApplication returns
- // the maximum pixel ratio of all available QScreen objects - this is not
- // valid for cases e.g. where two or more QScreen objects with different
- // pixel ratios are present and the window shows on the screen with lower
- // pixel ratio.
- static const float pixelRatio = QGuiApplication::allWindows().first()->devicePixelRatio();
-#else
- static const float pixelRatio = 1.0;
-#endif
- return pixelRatio;
+void QMapboxGLPrivate::updateFramebufferBinding(QOpenGLFramebufferObject *fbo_)
+{
+ fbo = fbo_;
+ if (fbo) {
+ getContext().bindFramebuffer.setDirty();
+ getContext().viewport.setCurrentValue(
+ { 0, 0, static_cast<uint16_t>(fbo->width()), static_cast<uint16_t>(fbo->height()) });
+ } else {
+ getContext().bindFramebuffer.setCurrentValue(0);
+ getContext().viewport.setCurrentValue({ 0, 0, static_cast<uint16_t>(fbSize.width()),
+ static_cast<uint16_t>(fbSize.height()) });
+ }
}
-std::array<uint16_t, 2> QMapboxGLPrivate::getSize() const
+void QMapboxGLPrivate::bind()
{
- return {{ static_cast<uint16_t>(size.width()), static_cast<uint16_t>(size.height()) }};
+ if (fbo) {
+ fbo->bind();
+ getContext().bindFramebuffer.setDirty();
+ getContext().viewport = { 0, 0, static_cast<uint16_t>(fbo->width()),
+ static_cast<uint16_t>(fbo->height()) };
+ } else {
+ getContext().bindFramebuffer = 0;
+ getContext().viewport = { 0, 0, static_cast<uint16_t>(fbSize.width()),
+ static_cast<uint16_t>(fbSize.height()) };
+ }
}
-
-std::array<uint16_t, 2> QMapboxGLPrivate::getFramebufferSize() const
+#else
+void QMapboxGLPrivate::bind()
{
- return {{ static_cast<uint16_t>(size.width() * getPixelRatio()),
- static_cast<uint16_t>(size.height() * getPixelRatio()) }};
+ getContext().bindFramebuffer = 0;
+ getContext().viewport = { 0, 0, static_cast<uint16_t>(fbSize.width()),
+ static_cast<uint16_t>(fbSize.height()) };
}
+#endif
void QMapboxGLPrivate::invalidate()
{
diff --git a/platform/qt/src/qmapboxgl_p.hpp b/platform/qt/src/qmapboxgl_p.hpp
index 11b5f695ca..e7a14601c1 100644
--- a/platform/qt/src/qmapboxgl_p.hpp
+++ b/platform/qt/src/qmapboxgl_p.hpp
@@ -3,41 +3,52 @@
#include "qmapboxgl.hpp"
#include <mbgl/map/map.hpp>
+#include <mbgl/map/backend.hpp>
#include <mbgl/map/view.hpp>
+#include <mbgl/platform/default/thread_pool.hpp>
#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/util/geo.hpp>
#include <QObject>
#include <QSize>
-class QMapboxGLPrivate : public QObject, public mbgl::View
+class QMapboxGLPrivate : public QObject, public mbgl::View, public mbgl::Backend
{
Q_OBJECT
public:
- explicit QMapboxGLPrivate(QMapboxGL *, const QMapboxGLSettings &);
+ explicit QMapboxGLPrivate(QMapboxGL *, const QMapboxGLSettings &, const QSize &size, qreal pixelRatio);
virtual ~QMapboxGLPrivate();
// mbgl::View implementation.
- float getPixelRatio() const final;
- std::array<uint16_t, 2> getSize() const final;
- std::array<uint16_t, 2> getFramebufferSize() const final;
+ float getPixelRatio() const;
+ void bind() final;
+ std::array<uint16_t, 2> getSize() const;
+ std::array<uint16_t, 2> getFramebufferSize() const;
void activate() final {}
void deactivate() final {}
void invalidate() final;
void notifyMapChange(mbgl::MapChange) final;
+#if QT_VERSION >= 0x050000
+ void updateFramebufferBinding(QOpenGLFramebufferObject *);
+#endif
+
mbgl::EdgeInsets margins;
QSize size { 0, 0 };
+ QSize fbSize { 0, 0 };
QMapboxGL *q_ptr { nullptr };
std::unique_ptr<mbgl::DefaultFileSource> fileSourceObj;
+ mbgl::ThreadPool threadPool;
std::unique_ptr<mbgl::Map> mapObj;
bool dirty { false };
+ QOpenGLFramebufferObject *fbo { nullptr };
+
public slots:
void connectionEstablished();
diff --git a/platform/qt/src/qquickmapboxglrenderer.cpp b/platform/qt/src/qquickmapboxglrenderer.cpp
index d550794d64..903e1c0b05 100644
--- a/platform/qt/src/qquickmapboxglrenderer.cpp
+++ b/platform/qt/src/qquickmapboxglrenderer.cpp
@@ -19,7 +19,7 @@ QQuickMapboxGLRenderer::QQuickMapboxGLRenderer()
settings.setCacheDatabaseMaximumSize(20 * 1024 * 1024);
settings.setViewportMode(QMapboxGLSettings::FlippedYViewport);
- m_map.reset(new QMapboxGL(nullptr, settings));
+ m_map.reset(new QMapboxGL(nullptr, settings, QSize(256, 256), 1));
}
QQuickMapboxGLRenderer::~QQuickMapboxGLRenderer()
@@ -28,7 +28,7 @@ QQuickMapboxGLRenderer::~QQuickMapboxGLRenderer()
QOpenGLFramebufferObject* QQuickMapboxGLRenderer::createFramebufferObject(const QSize &size)
{
- m_map->resize(size);
+ m_map->resize(size / m_pixelRatio, size);
QOpenGLFramebufferObjectFormat format;
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
@@ -38,7 +38,7 @@ QOpenGLFramebufferObject* QQuickMapboxGLRenderer::createFramebufferObject(const
void QQuickMapboxGLRenderer::render()
{
- m_map->render();
+ m_map->render(framebufferObject());
}
void QQuickMapboxGLRenderer::synchronize(QQuickFramebufferObject *item)
@@ -51,6 +51,12 @@ void QQuickMapboxGLRenderer::synchronize(QQuickFramebufferObject *item)
m_initialized = true;
}
+ if (auto window = quickMap->window()) {
+ m_pixelRatio = window->devicePixelRatio();
+ } else {
+ m_pixelRatio = 1;
+ }
+
auto syncStatus = quickMap->m_syncState;
quickMap->m_syncState = QQuickMapboxGL::NothingNeedsSync;
diff --git a/platform/qt/src/qquickmapboxglrenderer.hpp b/platform/qt/src/qquickmapboxglrenderer.hpp
index e0fc767d58..7adeea0421 100644
--- a/platform/qt/src/qquickmapboxglrenderer.hpp
+++ b/platform/qt/src/qquickmapboxglrenderer.hpp
@@ -29,6 +29,7 @@ signals:
private:
bool m_initialized = false;
+ qreal m_pixelRatio = 1;
QScopedPointer<QMapboxGL> m_map;
};
diff --git a/platform/qt/test/headless_backend_qt.cpp b/platform/qt/test/headless_backend_qt.cpp
new file mode 100644
index 0000000000..3f287ae578
--- /dev/null
+++ b/platform/qt/test/headless_backend_qt.cpp
@@ -0,0 +1,46 @@
+#include <mbgl/platform/default/headless_backend.hpp>
+#include <mbgl/platform/default/headless_display.hpp>
+
+#include <QApplication>
+#include <QGLContext>
+#include <QGLWidget>
+
+#if QT_VERSION >= 0x050000
+#include <QOpenGLContext>
+#endif
+
+namespace mbgl {
+
+gl::glProc HeadlessBackend::initializeExtension(const char* name) {
+#if QT_VERSION >= 0x050000
+ QOpenGLContext* thisContext = QOpenGLContext::currentContext();
+ return thisContext->getProcAddress(name);
+#else
+ const QGLContext* thisContext = QGLContext::currentContext();
+ return reinterpret_cast<mbgl::gl::glProc>(thisContext->getProcAddress(name));
+#endif
+}
+
+void HeadlessBackend::createContext() {
+ static const char* argv[] = { "mbgl" };
+ static int argc = 1;
+ static auto* app = new QApplication(argc, const_cast<char**>(argv));
+
+ Q_UNUSED(app);
+
+ glContext = new QGLWidget;
+}
+
+void HeadlessBackend::destroyContext() {
+ delete glContext;
+}
+
+void HeadlessBackend::activateContext() {
+ glContext->makeCurrent();
+}
+
+void HeadlessBackend::deactivateContext() {
+ glContext->doneCurrent();
+}
+
+} // namespace mbgl
diff --git a/platform/qt/test/headless_view_qt.cpp b/platform/qt/test/headless_view_qt.cpp
deleted file mode 100644
index 03ecb741ab..0000000000
--- a/platform/qt/test/headless_view_qt.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-#include <mbgl/platform/default/headless_display.hpp>
-#include <mbgl/platform/default/headless_view.hpp>
-
-#include <QApplication>
-#include <QGLContext>
-#include <QGLWidget>
-
-#if QT_VERSION >= 0x050000
-#include <QOpenGLContext>
-#endif
-
-namespace mbgl {
-
-gl::glProc HeadlessView::initializeExtension(const char* name) {
-#if QT_VERSION >= 0x050000
- QOpenGLContext* thisContext = QOpenGLContext::currentContext();
- return thisContext->getProcAddress(name);
-#else
- const QGLContext* thisContext = QGLContext::currentContext();
- return reinterpret_cast<mbgl::gl::glProc>(thisContext->getProcAddress(name));
-#endif
-}
-
-void HeadlessView::createContext() {
- static const char* argv[] = { "mbgl" };
- static int argc = 1;
- static auto* app = new QApplication(argc, const_cast<char**>(argv));
-
- Q_UNUSED(app);
-
- glContext = new QGLWidget;
-}
-
-void HeadlessView::destroyContext() {
- delete glContext;
-}
-
-void HeadlessView::resizeFramebuffer() {
- const unsigned int w = dimensions[0] * pixelRatio;
- const unsigned int h = dimensions[1] * pixelRatio;
-
- // Create depth/stencil buffer
- MBGL_CHECK_ERROR(glGenRenderbuffersEXT(1, &fboDepthStencil));
- MBGL_CHECK_ERROR(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fboDepthStencil));
- MBGL_CHECK_ERROR(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, w, h));
- MBGL_CHECK_ERROR(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0));
-
- MBGL_CHECK_ERROR(glGenRenderbuffersEXT(1, &fboColor));
- MBGL_CHECK_ERROR(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fboColor));
- MBGL_CHECK_ERROR(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, w, h));
- MBGL_CHECK_ERROR(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0));
-
- MBGL_CHECK_ERROR(glGenFramebuffersEXT(1, &fbo));
- MBGL_CHECK_ERROR(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo));
-
- MBGL_CHECK_ERROR(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, fboColor));
- MBGL_CHECK_ERROR(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER_EXT, fboDepthStencil));
-
- GLenum status = MBGL_CHECK_ERROR(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT));
-
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
- std::string error("Couldn't create framebuffer: ");
- switch (status) {
- case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: (error += "incomplete attachment"); break;
- case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: error += "incomplete missing attachment"; break;
- case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: error += "incomplete dimensions"; break;
- case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: error += "incomplete formats"; break;
- case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: error += "incomplete draw buffer"; break;
- case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: error += "incomplete read buffer"; break;
- case GL_FRAMEBUFFER_UNSUPPORTED: error += "unsupported"; break;
- default: error += "other"; break;
- }
- throw std::runtime_error(error);
- }
-
- MBGL_CHECK_ERROR(glViewport(0, 0, w, h));
-}
-
-void HeadlessView::clearBuffers() {
- MBGL_CHECK_ERROR(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
-
- if (fbo) {
- MBGL_CHECK_ERROR(glDeleteFramebuffersEXT(1, &fbo));
- fbo = 0;
- }
-
- if (fboColor) {
- MBGL_CHECK_ERROR(glDeleteRenderbuffersEXT(1, &fboColor));
- fboColor = 0;
- }
-
- if (fboDepthStencil) {
- MBGL_CHECK_ERROR(glDeleteRenderbuffersEXT(1, &fboDepthStencil));
- fboDepthStencil = 0;
- }
-}
-
-void HeadlessView::activateContext() {
- glContext->makeCurrent();
-}
-
-void HeadlessView::deactivateContext() {
- glContext->doneCurrent();
-}
-
-} // namespace mbgl
diff --git a/platform/qt/test/qmapboxgl.cpp b/platform/qt/test/qmapboxgl.cpp
index 8bcc485d89..597aef5df3 100644
--- a/platform/qt/test/qmapboxgl.cpp
+++ b/platform/qt/test/qmapboxgl.cpp
@@ -19,7 +19,7 @@ public:
widget.makeCurrent();
QMapbox::initializeGLExtensions();
- map.resize(QSize(512, 512));
+ map.resize(QSize(512, 512), QSize(512, 512));
map.setCoordinateZoom(QMapbox::Coordinate(60.170448, 24.942046), 14);
}
diff --git a/scripts/generate-style-code.js b/scripts/generate-style-code.js
index 77aecbe18c..dcb527e8c9 100644
--- a/scripts/generate-style-code.js
+++ b/scripts/generate-style-code.js
@@ -28,7 +28,7 @@ global.propertyType = function (property) {
if (/-translate-anchor$/.test(property.name)) {
return 'TranslateAnchorType';
}
- if (/-(rotation|pitch)-alignment$/.test(property.name)) {
+ if (/-(rotation|pitch|illumination)-alignment$/.test(property.name)) {
return 'AlignmentType';
}
switch (property.type) {
diff --git a/src/mbgl/actor/mailbox.cpp b/src/mbgl/actor/mailbox.cpp
index ae3c0967af..5f60629833 100644
--- a/src/mbgl/actor/mailbox.cpp
+++ b/src/mbgl/actor/mailbox.cpp
@@ -52,4 +52,10 @@ void Mailbox::receive() {
}
}
+void Mailbox::maybeReceive(std::weak_ptr<Mailbox> mailbox) {
+ if (auto locked = mailbox.lock()) {
+ locked->receive();
+ }
+}
+
} // namespace mbgl
diff --git a/src/mbgl/actor/mailbox.hpp b/src/mbgl/actor/mailbox.hpp
index 5d5e8cb924..cff0de243a 100644
--- a/src/mbgl/actor/mailbox.hpp
+++ b/src/mbgl/actor/mailbox.hpp
@@ -18,6 +18,8 @@ public:
void close();
void receive();
+ static void maybeReceive(std::weak_ptr<Mailbox>);
+
private:
Scheduler& scheduler;
diff --git a/src/mbgl/annotation/symbol_annotation_impl.cpp b/src/mbgl/annotation/symbol_annotation_impl.cpp
index 040de21214..e5ae5f4b91 100644
--- a/src/mbgl/annotation/symbol_annotation_impl.cpp
+++ b/src/mbgl/annotation/symbol_annotation_impl.cpp
@@ -2,6 +2,7 @@
#include <mbgl/annotation/annotation_tile.hpp>
#include <mbgl/tile/tile_id.hpp>
#include <mbgl/math/clamp.hpp>
+#include <mbgl/util/tile_coordinate.hpp>
namespace mbgl {
@@ -14,26 +15,10 @@ void SymbolAnnotationImpl::updateLayer(const CanonicalTileID& tileID, Annotation
std::unordered_map<std::string, std::string> featureProperties;
featureProperties.emplace("sprite", annotation.icon.empty() ? std::string("default_marker") : annotation.icon);
- const Point<double>& p = annotation.geometry;
-
- // Clamp to the latitude limits of Web Mercator.
- const double constrainedLatitude = util::clamp(p.y, -util::LATITUDE_MAX, util::LATITUDE_MAX);
-
- // Project a coordinate into unit space in a square map.
- const double sine = std::sin(constrainedLatitude * util::DEG2RAD);
- const double x = p.x / util::DEGREES_MAX + 0.5;
- const double y = 0.5 - 0.25 * std::log((1.0 + sine) / (1.0 - sine)) / M_PI;
-
- Point<double> projected(x, y);
- projected *= std::pow(2, tileID.z);
- projected.x = std::fmod(projected.x, 1);
- projected.y = std::fmod(projected.y, 1);
- projected *= double(util::EXTENT);
-
- layer.features.emplace_back(id,
- FeatureType::Point,
- GeometryCollection {{ {{ convertPoint<int16_t>(projected) }} }},
- featureProperties);
+ LatLng latLng { annotation.geometry.y, annotation.geometry.x };
+ TileCoordinate coordinate = TileCoordinate::fromLatLng(0, latLng);
+ GeometryCoordinate tilePoint = TileCoordinate::toGeometryCoordinate(UnwrappedTileID(0, tileID), coordinate.p);
+ layer.features.emplace_back(id, FeatureType::Point, GeometryCollection {{ {{ tilePoint }} }}, featureProperties);
}
} // namespace mbgl
diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp
index 2a04fcc18e..23b28a15df 100644
--- a/src/mbgl/gl/context.cpp
+++ b/src/mbgl/gl/context.cpp
@@ -1,3 +1,4 @@
+#include <mbgl/map/view.hpp>
#include <mbgl/gl/context.hpp>
#include <mbgl/gl/gl.hpp>
#include <mbgl/gl/vertex_array.hpp>
@@ -142,6 +143,113 @@ UniqueFramebuffer Context::createFramebuffer() {
return UniqueFramebuffer{ std::move(id), { this } };
}
+UniqueRenderbuffer Context::createRenderbuffer(const RenderbufferType type,
+ const uint16_t width,
+ const uint16_t height) {
+ RenderbufferID id = 0;
+ MBGL_CHECK_ERROR(glGenRenderbuffers(1, &id));
+ UniqueRenderbuffer renderbuffer{ std::move(id), { this } };
+
+ bindRenderbuffer = renderbuffer;
+ MBGL_CHECK_ERROR(
+ glRenderbufferStorage(GL_RENDERBUFFER, static_cast<GLenum>(type), width, height));
+ return renderbuffer;
+}
+
+namespace {
+
+void checkFramebuffer() {
+ GLenum status = MBGL_CHECK_ERROR(glCheckFramebufferStatus(GL_FRAMEBUFFER));
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ switch (status) {
+ case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
+ throw std::runtime_error("Couldn't create framebuffer: incomplete attachment");
+ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
+ throw std::runtime_error("Couldn't create framebuffer: incomplete missing attachment");
+#ifdef GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER
+ case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
+ throw std::runtime_error("Couldn't create framebuffer: incomplete draw buffer");
+#endif
+#ifdef GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER
+ case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
+ throw std::runtime_error("Couldn't create framebuffer: incomplete read buffer");
+#endif
+#ifdef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS
+ case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
+ throw std::runtime_error("Couldn't create framebuffer: incomplete dimensions");
+#endif
+
+ case GL_FRAMEBUFFER_UNSUPPORTED:
+ throw std::runtime_error("Couldn't create framebuffer: unsupported");
+ default:
+ throw std::runtime_error("Couldn't create framebuffer: other");
+ }
+ }
+}
+
+void bindDepthStencilRenderbuffer(
+ const Renderbuffer<RenderbufferType::DepthStencil>& depthStencil) {
+#ifdef GL_DEPTH_STENCIL_ATTACHMENT
+ MBGL_CHECK_ERROR(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER, depthStencil.renderbuffer));
+#else
+ MBGL_CHECK_ERROR(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
+ depthStencil.renderbuffer));
+ MBGL_CHECK_ERROR(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER, depthStencil.renderbuffer));
+#endif
+}
+
+} // namespace
+
+Framebuffer
+Context::createFramebuffer(const Renderbuffer<RenderbufferType::RGBA>& color,
+ const Renderbuffer<RenderbufferType::DepthStencil>& depthStencil) {
+ if (color.size != depthStencil.size) {
+ throw new std::runtime_error("Renderbuffer size mismatch");
+ }
+ auto fbo = createFramebuffer();
+ bindFramebuffer = fbo;
+ MBGL_CHECK_ERROR(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_RENDERBUFFER, color.renderbuffer));
+ bindDepthStencilRenderbuffer(depthStencil);
+ checkFramebuffer();
+ return { color.size, std::move(fbo) };
+}
+
+Framebuffer Context::createFramebuffer(const Renderbuffer<RenderbufferType::RGBA>& color) {
+ auto fbo = createFramebuffer();
+ bindFramebuffer = fbo;
+ MBGL_CHECK_ERROR(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_RENDERBUFFER, color.renderbuffer));
+ checkFramebuffer();
+ return { color.size, std::move(fbo) };
+}
+
+Framebuffer
+Context::createFramebuffer(const Texture& color,
+ const Renderbuffer<RenderbufferType::DepthStencil>& depthStencil) {
+ if (color.size != depthStencil.size) {
+ throw new std::runtime_error("Renderbuffer size mismatch");
+ }
+ auto fbo = createFramebuffer();
+ bindFramebuffer = fbo;
+ MBGL_CHECK_ERROR(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+ color.texture, 0));
+ bindDepthStencilRenderbuffer(depthStencil);
+ checkFramebuffer();
+ return { color.size, std::move(fbo) };
+}
+
+Framebuffer Context::createFramebuffer(const Texture& color) {
+ auto fbo = createFramebuffer();
+ bindFramebuffer = fbo;
+ MBGL_CHECK_ERROR(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+ color.texture, 0));
+ checkFramebuffer();
+ return { color.size, std::move(fbo) };
+}
+
UniqueTexture
Context::createTexture(uint16_t width, uint16_t height, const void* data, TextureUnit unit) {
auto obj = createTexture();
@@ -186,50 +294,37 @@ void Context::reset() {
performCleanup();
}
-namespace {
-
-template <typename Fn>
-void applyStateFunction(Context& context, Fn&& fn) {
- fn(context.stencilFunc);
- fn(context.stencilMask);
- fn(context.stencilTest);
- fn(context.stencilOp);
- fn(context.depthRange);
- fn(context.depthMask);
- fn(context.depthTest);
- fn(context.depthFunc);
- fn(context.blend);
- fn(context.blendFunc);
- fn(context.blendColor);
- fn(context.colorMask);
- fn(context.clearDepth);
- fn(context.clearColor);
- fn(context.clearStencil);
- fn(context.program);
- fn(context.lineWidth);
- fn(context.activeTexture);
- fn(context.bindFramebuffer);
- fn(context.viewport);
+void Context::setDirtyState() {
+ // Note: does not set viewport/bindFramebuffer to dirty since they are handled separately in
+ // the view object.
+ stencilFunc.setDirty();
+ stencilMask.setDirty();
+ stencilTest.setDirty();
+ stencilOp.setDirty();
+ depthRange.setDirty();
+ depthMask.setDirty();
+ depthTest.setDirty();
+ depthFunc.setDirty();
+ blend.setDirty();
+ blendFunc.setDirty();
+ blendColor.setDirty();
+ colorMask.setDirty();
+ clearDepth.setDirty();
+ clearColor.setDirty();
+ clearStencil.setDirty();
+ program.setDirty();
+ lineWidth.setDirty();
+ activeTexture.setDirty();
#if not MBGL_USE_GLES2
- fn(context.pixelZoom);
- fn(context.rasterPos);
+ pixelZoom.setDirty();
+ rasterPos.setDirty();
#endif // MBGL_USE_GLES2
- for (auto& tex : context.texture) {
- fn(tex);
+ for (auto& tex : texture) {
+ tex.setDirty();
}
- fn(context.vertexBuffer);
- fn(context.elementBuffer);
- fn(context.vertexArrayObject);
-}
-
-} // namespace
-
-void Context::resetState() {
- applyStateFunction(*this, [](auto& state) { state.reset(); });
-}
-
-void Context::setDirtyState() {
- applyStateFunction(*this, [](auto& state) { state.setDirty(); });
+ vertexBuffer.setDirty();
+ elementBuffer.setDirty();
+ vertexArrayObject.setDirty();
}
void Context::performCleanup() {
@@ -289,6 +384,12 @@ void Context::performCleanup() {
glDeleteFramebuffers(int(abandonedFramebuffers.size()), abandonedFramebuffers.data()));
abandonedFramebuffers.clear();
}
+
+ if (!abandonedRenderbuffers.empty()) {
+ MBGL_CHECK_ERROR(glDeleteRenderbuffers(int(abandonedRenderbuffers.size()),
+ abandonedRenderbuffers.data()));
+ abandonedRenderbuffers.clear();
+ }
}
} // namespace gl
diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp
index 6a5d44793a..cf8bb2658b 100644
--- a/src/mbgl/gl/context.hpp
+++ b/src/mbgl/gl/context.hpp
@@ -4,6 +4,8 @@
#include <mbgl/gl/state.hpp>
#include <mbgl/gl/value.hpp>
#include <mbgl/gl/texture.hpp>
+#include <mbgl/gl/renderbuffer.hpp>
+#include <mbgl/gl/framebuffer.hpp>
#include <mbgl/gl/vertex_buffer.hpp>
#include <mbgl/gl/index_buffer.hpp>
#include <mbgl/gl/attribute.hpp>
@@ -14,6 +16,9 @@
#include <array>
namespace mbgl {
+
+class View;
+
namespace gl {
constexpr size_t TextureMax = 64;
@@ -27,7 +32,6 @@ public:
UniqueShader createFragmentShader();
UniqueTexture createTexture();
UniqueVertexArray createVertexArray();
- UniqueFramebuffer createFramebuffer();
template <class V>
VertexBuffer<V> createVertexBuffer(std::vector<V>&& v) {
@@ -44,6 +48,20 @@ public:
};
}
+ template <RenderbufferType type>
+ Renderbuffer<type> createRenderbuffer(const std::array<uint16_t, 2>& size) {
+ static_assert(type == RenderbufferType::RGBA || type == RenderbufferType::DepthStencil,
+ "invalid renderbuffer type");
+ return { size, createRenderbuffer(type, size[0], size[1]) };
+ }
+
+ Framebuffer createFramebuffer(const Renderbuffer<RenderbufferType::RGBA>&,
+ const Renderbuffer<RenderbufferType::DepthStencil>&);
+ Framebuffer createFramebuffer(const Renderbuffer<RenderbufferType::RGBA>&);
+ Framebuffer createFramebuffer(const Texture&,
+ const Renderbuffer<RenderbufferType::DepthStencil>&);
+ Framebuffer createFramebuffer(const Texture&);
+
// Create a texture from an image with data.
template <typename Image>
Texture createTexture(const Image& image, TextureUnit unit = 0) {
@@ -87,8 +105,6 @@ public:
&& abandonedFramebuffers.empty();
}
- void resetState();
-
void setDirtyState();
State<value::StencilFunc> stencilFunc;
@@ -111,6 +127,7 @@ public:
State<value::ActiveTexture> activeTexture;
State<value::BindFramebuffer> bindFramebuffer;
State<value::Viewport> viewport;
+ State<value::BindRenderbuffer> bindRenderbuffer;
#if not MBGL_USE_GLES2
State<value::PixelZoom> pixelZoom;
State<value::RasterPos> rasterPos;
@@ -124,6 +141,8 @@ private:
UniqueBuffer createVertexBuffer(const void* data, std::size_t size);
UniqueBuffer createIndexBuffer(const void* data, std::size_t size);
UniqueTexture createTexture(uint16_t width, uint16_t height, const void* data, TextureUnit);
+ UniqueFramebuffer createFramebuffer();
+ UniqueRenderbuffer createRenderbuffer(RenderbufferType, uint16_t width, uint16_t height);
void bindAttribute(const AttributeBinding&, std::size_t stride, const int8_t* offset);
friend detail::ProgramDeleter;
@@ -132,6 +151,7 @@ private:
friend detail::TextureDeleter;
friend detail::VertexArrayDeleter;
friend detail::FramebufferDeleter;
+ friend detail::RenderbufferDeleter;
std::vector<TextureID> pooledTextures;
@@ -141,6 +161,7 @@ private:
std::vector<TextureID> abandonedTextures;
std::vector<VertexArrayID> abandonedVertexArrays;
std::vector<FramebufferID> abandonedFramebuffers;
+ std::vector<RenderbufferID> abandonedRenderbuffers;
};
} // namespace gl
diff --git a/src/mbgl/gl/framebuffer.hpp b/src/mbgl/gl/framebuffer.hpp
new file mode 100644
index 0000000000..880fed159e
--- /dev/null
+++ b/src/mbgl/gl/framebuffer.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+#include <mbgl/gl/object.hpp>
+
+#include <array>
+
+namespace mbgl {
+namespace gl {
+
+class Framebuffer {
+public:
+ std::array<uint16_t, 2> size;
+ gl::UniqueFramebuffer framebuffer;
+};
+
+} // namespace gl
+} // namespace mbgl
diff --git a/src/mbgl/gl/gl.cpp b/src/mbgl/gl/gl.cpp
index 5cef254160..8999468dbd 100644
--- a/src/mbgl/gl/gl.cpp
+++ b/src/mbgl/gl/gl.cpp
@@ -51,6 +51,7 @@ constexpr const char* stringFromError(GLenum err) {
} // namespace
void checkError(const char* cmd, const char* file, int line) {
+// fprintf(stderr, "cmd: %s\n", cmd);
GLenum err = GL_NO_ERROR;
if ((err = glGetError()) != GL_NO_ERROR) {
std::string message = std::string(cmd) + ": Error " + stringFromError(err);
diff --git a/src/mbgl/gl/object.cpp b/src/mbgl/gl/object.cpp
index aee87f8836..e2d476e0c0 100644
--- a/src/mbgl/gl/object.cpp
+++ b/src/mbgl/gl/object.cpp
@@ -41,6 +41,11 @@ void FramebufferDeleter::operator()(FramebufferID id) const {
context->abandonedFramebuffers.push_back(id);
}
+void RenderbufferDeleter::operator()(RenderbufferID id) const {
+ assert(context);
+ context->abandonedRenderbuffers.push_back(id);
+}
+
} // namespace detail
} // namespace gl
} // namespace mbgl
diff --git a/src/mbgl/gl/object.hpp b/src/mbgl/gl/object.hpp
index 1cc1f04a97..1408add65a 100644
--- a/src/mbgl/gl/object.hpp
+++ b/src/mbgl/gl/object.hpp
@@ -41,6 +41,11 @@ struct FramebufferDeleter {
void operator()(FramebufferID) const;
};
+struct RenderbufferDeleter {
+ Context* context;
+ void operator()(RenderbufferID) const;
+};
+
} // namespace detail
using UniqueProgram = std_experimental::unique_resource<ProgramID, detail::ProgramDeleter>;
@@ -49,6 +54,7 @@ using UniqueBuffer = std_experimental::unique_resource<BufferID, detail::BufferD
using UniqueTexture = std_experimental::unique_resource<TextureID, detail::TextureDeleter>;
using UniqueVertexArray = std_experimental::unique_resource<VertexArrayID, detail::VertexArrayDeleter>;
using UniqueFramebuffer = std_experimental::unique_resource<FramebufferID, detail::FramebufferDeleter>;
+using UniqueRenderbuffer = std_experimental::unique_resource<RenderbufferID, detail::RenderbufferDeleter>;
} // namespace gl
} // namespace mbgl
diff --git a/src/mbgl/gl/renderbuffer.hpp b/src/mbgl/gl/renderbuffer.hpp
new file mode 100644
index 0000000000..9e8993bb77
--- /dev/null
+++ b/src/mbgl/gl/renderbuffer.hpp
@@ -0,0 +1,19 @@
+#pragma once
+
+#include <mbgl/gl/object.hpp>
+
+#include <array>
+
+namespace mbgl {
+namespace gl {
+
+template <RenderbufferType renderbufferType>
+class Renderbuffer {
+public:
+ using type = std::integral_constant<RenderbufferType, renderbufferType>;
+ std::array<uint16_t, 2> size;
+ gl::UniqueRenderbuffer renderbuffer;
+};
+
+} // namespace gl
+} // namespace mbgl
diff --git a/src/mbgl/gl/state.hpp b/src/mbgl/gl/state.hpp
index dbb005e77d..efe869e5b9 100644
--- a/src/mbgl/gl/state.hpp
+++ b/src/mbgl/gl/state.hpp
@@ -3,20 +3,6 @@
namespace mbgl {
namespace gl {
-// Helper struct that allows obtaining the default value of a Value class
-template <typename T, typename = void>
-struct DefaultValue {
- static typename T::Type Get() {
- return T::Get();
- }
-};
-template <typename T>
-struct DefaultValue<T, decltype((void)T::Default, void())> {
- static typename T::Type Get() {
- return T::Default;
- }
-};
-
// Wraps a piece of OpenGL state and remember its value to avoid redundant state calls.
// Wrapped types need to implement to the Value class interface:
//
@@ -26,17 +12,12 @@ struct DefaultValue<T, decltype((void)T::Default, void())> {
// static void Set(const Type& value);
// static Type Get();
// };
-//
-// The Get() function is optional, but if it is omitted, you must provide a Default.
-// Default is also optional, but if it is omitted, you must provide a Get() function.
-// If both are present, DefaultValue<T>::Get() will use the Default member.
template <typename T>
class State {
public:
void operator=(const typename T::Type& value) {
if (*this != value) {
- dirty = false;
- currentValue = value;
+ setCurrentValue(value);
T::Set(currentValue);
}
}
@@ -49,9 +30,9 @@ public:
return dirty || currentValue != value;
}
- // Explicitly resets the piece of OpenGL state to its default value.
- void reset() {
- *this = defaultValue;
+ void setCurrentValue(const typename T::Type& value) {
+ dirty = false;
+ currentValue = value;
}
// Mark the state as dirty. This means that the next time we are assigning a value to this
@@ -68,14 +49,9 @@ public:
return dirty;
}
- void setDefaultValue(const typename T::Type& value) {
- defaultValue = value;
- }
-
private:
- typename T::Type defaultValue = DefaultValue<T>::Get();
- typename T::Type currentValue = defaultValue;
- bool dirty = false;
+ typename T::Type currentValue = T::Default;
+ bool dirty = true;
};
// Helper struct that stores the current state and restores it upon destruction. You should not use
diff --git a/src/mbgl/gl/types.hpp b/src/mbgl/gl/types.hpp
index f24674457a..dccc61b03a 100644
--- a/src/mbgl/gl/types.hpp
+++ b/src/mbgl/gl/types.hpp
@@ -48,6 +48,11 @@ enum class BufferType : uint32_t {
Element = 0x8893
};
+enum class RenderbufferType : uint32_t {
+ RGBA = 0x8058,
+ DepthStencil = 0x88F0,
+};
+
enum class TextureMipMap : bool { No = false, Yes = true };
enum class TextureFilter : bool { Nearest = false, Linear = true };
diff --git a/src/mbgl/gl/value.cpp b/src/mbgl/gl/value.cpp
index e78b97ef2e..14cd03efc4 100644
--- a/src/mbgl/gl/value.cpp
+++ b/src/mbgl/gl/value.cpp
@@ -241,6 +241,8 @@ ActiveTexture::Type ActiveTexture::Get() {
return static_cast<Type>(activeTexture - GL_TEXTURE0);
}
+const constexpr Viewport::Type Viewport::Default;
+
void Viewport::Set(const Type& value) {
MBGL_CHECK_ERROR(glViewport(value.x, value.y, value.width, value.height));
}
@@ -252,6 +254,8 @@ Viewport::Type Viewport::Get() {
static_cast<uint16_t>(viewport[2]), static_cast<uint16_t>(viewport[3]) };
}
+const constexpr BindFramebuffer::Type BindFramebuffer::Default;
+
void BindFramebuffer::Set(const Type& value) {
MBGL_CHECK_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, value));
}
@@ -262,6 +266,18 @@ BindFramebuffer::Type BindFramebuffer::Get() {
return binding;
}
+const constexpr BindRenderbuffer::Type BindRenderbuffer::Default;
+
+void BindRenderbuffer::Set(const Type& value) {
+ MBGL_CHECK_ERROR(glBindRenderbuffer(GL_RENDERBUFFER, value));
+}
+
+BindRenderbuffer::Type BindRenderbuffer::Get() {
+ GLint binding;
+ MBGL_CHECK_ERROR(glGetIntegerv(GL_RENDERBUFFER_BINDING, &binding));
+ return binding;
+}
+
const constexpr BindTexture::Type BindTexture::Default;
void BindTexture::Set(const Type& value) {
diff --git a/src/mbgl/gl/value.hpp b/src/mbgl/gl/value.hpp
index 9110b33a16..866ce389a4 100644
--- a/src/mbgl/gl/value.hpp
+++ b/src/mbgl/gl/value.hpp
@@ -180,6 +180,7 @@ struct Viewport {
uint16_t width;
uint16_t height;
};
+ static const constexpr Type Default = { 0, 0, 0, 0 };
static void Set(const Type&);
static Type Get();
};
@@ -190,6 +191,14 @@ constexpr bool operator!=(const Viewport::Type& a, const Viewport::Type& b) {
struct BindFramebuffer {
using Type = FramebufferID;
+ static const constexpr Type Default = 0;
+ static void Set(const Type&);
+ static Type Get();
+};
+
+struct BindRenderbuffer {
+ using Type = RenderbufferID;
+ static const constexpr Type Default = 0;
static void Set(const Type&);
static Type Get();
};
diff --git a/src/mbgl/map/backend.cpp b/src/mbgl/map/backend.cpp
new file mode 100644
index 0000000000..8a06fe2d91
--- /dev/null
+++ b/src/mbgl/map/backend.cpp
@@ -0,0 +1,22 @@
+#include <mbgl/map/backend.hpp>
+#include <mbgl/gl/context.hpp>
+
+#include <cassert>
+
+namespace mbgl {
+
+Backend::Backend() : context(std::make_unique<gl::Context>()) {
+}
+
+gl::Context& Backend::getContext() {
+ return *context;
+}
+
+Backend::~Backend() = default;
+
+void Backend::notifyMapChange(MapChange) {
+ // no-op
+}
+
+
+} // namespace mbgl
diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp
index bf2462e2ab..7b58026386 100644
--- a/src/mbgl/map/map.cpp
+++ b/src/mbgl/map/map.cpp
@@ -1,6 +1,7 @@
#include <mbgl/map/map.hpp>
#include <mbgl/map/camera.hpp>
#include <mbgl/map/view.hpp>
+#include <mbgl/map/backend.hpp>
#include <mbgl/map/transform.hpp>
#include <mbgl/map/transform_state.hpp>
#include <mbgl/annotation/annotation_manager.hpp>
@@ -21,7 +22,7 @@
#include <mbgl/util/async_task.hpp>
#include <mbgl/util/mapbox.hpp>
#include <mbgl/util/tile_coordinate.hpp>
-#include <mbgl/actor/thread_pool.hpp>
+#include <mbgl/actor/scheduler.hpp>
#include <mbgl/platform/log.hpp>
namespace mbgl {
@@ -34,9 +35,25 @@ enum class RenderState : uint8_t {
Fully,
};
+struct StillImageRequest {
+ StillImageRequest(View& view_, Map::StillImageCallback&& callback_)
+ : view(view_), callback(std::move(callback_)) {
+ }
+
+ View& view;
+ Map::StillImageCallback callback;
+};
+
class Map::Impl : public style::Observer {
public:
- Impl(View&, FileSource&, MapMode, GLContextMode, ConstrainMode, ViewportMode);
+ Impl(Backend&,
+ float pixelRatio,
+ FileSource&,
+ Scheduler&,
+ MapMode,
+ GLContextMode,
+ ConstrainMode,
+ ViewportMode);
void onSourceAttributionChanged(style::Source&, const std::string&) override;
void onUpdate(Update) override;
@@ -45,12 +62,13 @@ public:
void onResourceError(std::exception_ptr) override;
void update();
- void render();
+ void render(View&);
void loadStyleJSON(const std::string&);
- View& view;
+ Backend& backend;
FileSource& fileSource;
+ Scheduler& scheduler;
RenderState renderState = RenderState::Never;
Transform transform;
@@ -63,7 +81,6 @@ public:
Update updateFlags = Update::Nothing;
util::AsyncTask asyncUpdate;
- ThreadPool workerThreadPool;
std::unique_ptr<AnnotationManager> annotationManager;
std::unique_ptr<Painter> painter;
@@ -75,39 +92,55 @@ public:
std::unique_ptr<AsyncRequest> styleRequest;
- Map::StillImageCallback callback;
+ std::unique_ptr<StillImageRequest> stillImageRequest;
size_t sourceCacheSize;
TimePoint timePoint;
bool loading = false;
};
-Map::Map(View& view, FileSource& fileSource, MapMode mapMode, GLContextMode contextMode, ConstrainMode constrainMode, ViewportMode viewportMode)
- : impl(std::make_unique<Impl>(view, fileSource, mapMode, contextMode, constrainMode, viewportMode)) {
- view.initialize(this);
- update(Update::Dimensions);
-}
-
-Map::Impl::Impl(View& view_,
+Map::Map(Backend& backend,
+ const std::array<uint16_t, 2> size,
+ const float pixelRatio,
+ FileSource& fileSource,
+ Scheduler& scheduler,
+ MapMode mapMode,
+ GLContextMode contextMode,
+ ConstrainMode constrainMode,
+ ViewportMode viewportMode)
+ : impl(std::make_unique<Impl>(backend,
+ pixelRatio,
+ fileSource,
+ scheduler,
+ mapMode,
+ contextMode,
+ constrainMode,
+ viewportMode)) {
+ impl->transform.resize(size);
+}
+
+Map::Impl::Impl(Backend& backend_,
+ float pixelRatio_,
FileSource& fileSource_,
+ Scheduler& scheduler_,
MapMode mode_,
GLContextMode contextMode_,
ConstrainMode constrainMode_,
ViewportMode viewportMode_)
- : view(view_),
+ : backend(backend_),
fileSource(fileSource_),
- transform([this](MapChange change) { view.notifyMapChange(change); },
+ scheduler(scheduler_),
+ transform([this](MapChange change) { backend.notifyMapChange(change); },
constrainMode_,
viewportMode_),
mode(mode_),
contextMode(contextMode_),
- pixelRatio(view.getPixelRatio()),
+ pixelRatio(pixelRatio_),
asyncUpdate([this] { update(); }),
- workerThreadPool(4),
annotationManager(std::make_unique<AnnotationManager>(pixelRatio)) {
}
Map::~Map() {
- impl->view.activate();
+ impl->backend.activate();
impl->styleRequest = nullptr;
@@ -117,60 +150,56 @@ Map::~Map() {
impl->annotationManager.reset();
impl->painter.reset();
- impl->view.deactivate();
+ impl->backend.deactivate();
}
-void Map::renderStill(StillImageCallback callback) {
+void Map::renderStill(View& view, StillImageCallback callback) {
if (!callback) {
Log::Error(Event::General, "StillImageCallback not set");
return;
}
if (impl->mode != MapMode::Still) {
- callback(std::make_exception_ptr(util::MisuseException("Map is not in still image render mode")), {});
+ callback(std::make_exception_ptr(util::MisuseException("Map is not in still image render mode")));
return;
}
- if (impl->callback) {
- callback(std::make_exception_ptr(util::MisuseException("Map is currently rendering an image")), {});
+ if (impl->stillImageRequest) {
+ callback(std::make_exception_ptr(util::MisuseException("Map is currently rendering an image")));
return;
}
if (!impl->style) {
- callback(std::make_exception_ptr(util::MisuseException("Map doesn't have a style")), {});
+ callback(std::make_exception_ptr(util::MisuseException("Map doesn't have a style")));
return;
}
if (impl->style->getLastError()) {
- callback(impl->style->getLastError(), {});
+ callback(impl->style->getLastError());
return;
}
- impl->callback = callback;
+ impl->stillImageRequest = std::make_unique<StillImageRequest>(view, std::move(callback));
impl->updateFlags |= Update::RenderStill;
impl->asyncUpdate.send();
}
-void Map::update(Update flags) {
- impl->onUpdate(flags);
-}
-
-void Map::render() {
+void Map::render(View& view) {
if (!impl->style) {
return;
}
if (impl->renderState == RenderState::Never) {
- impl->view.notifyMapChange(MapChangeWillStartRenderingMap);
+ impl->backend.notifyMapChange(MapChangeWillStartRenderingMap);
}
- impl->view.notifyMapChange(MapChangeWillStartRenderingFrame);
+ impl->backend.notifyMapChange(MapChangeWillStartRenderingFrame);
const Update flags = impl->transform.updateTransitions(Clock::now());
- impl->render();
+ impl->render(view);
- impl->view.notifyMapChange(isFullyLoaded() ?
+ impl->backend.notifyMapChange(isFullyLoaded() ?
MapChangeDidFinishRenderingFrameFullyRendered :
MapChangeDidFinishRenderingFrame);
@@ -178,26 +207,30 @@ void Map::render() {
impl->renderState = RenderState::Partial;
} else if (impl->renderState != RenderState::Fully) {
impl->renderState = RenderState::Fully;
- impl->view.notifyMapChange(MapChangeDidFinishRenderingMapFullyRendered);
+ impl->backend.notifyMapChange(MapChangeDidFinishRenderingMapFullyRendered);
if (impl->loading) {
impl->loading = false;
- impl->view.notifyMapChange(MapChangeDidFinishLoadingMap);
+ impl->backend.notifyMapChange(MapChangeDidFinishLoadingMap);
}
}
// Triggers an asynchronous update, that eventually triggers a view
// invalidation, causing renderSync to be called again if in transition.
if (flags != Update::Nothing) {
- update(flags);
+ impl->onUpdate(flags);
}
}
+void Map::triggerRepaint() {
+ impl->backend.invalidate();
+}
+
void Map::Impl::update() {
if (!style) {
updateFlags = Update::Nothing;
}
- if (updateFlags == Update::Nothing || (mode == MapMode::Still && !callback)) {
+ if (updateFlags == Update::Nothing || (mode == MapMode::Still && !stillImageRequest)) {
return;
}
@@ -230,7 +263,7 @@ void Map::Impl::update() {
style::UpdateParameters parameters(pixelRatio,
debugOptions,
transform.getState(),
- workerThreadPool,
+ scheduler,
fileSource,
mode,
*annotationManager,
@@ -239,23 +272,23 @@ void Map::Impl::update() {
style->updateTiles(parameters);
if (mode == MapMode::Continuous) {
- view.invalidate();
- } else if (callback && style->isLoaded()) {
- view.activate();
- render();
- view.deactivate();
+ backend.invalidate();
+ } else if (stillImageRequest && style->isLoaded()) {
+ // TODO: determine whether we need activate/deactivate
+ backend.activate();
+ render(stillImageRequest->view);
+ backend.deactivate();
}
updateFlags = Update::Nothing;
}
-void Map::Impl::render() {
+void Map::Impl::render(View& view) {
if (!painter) {
- painter = std::make_unique<Painter>(transform.getState());
+ painter = std::make_unique<Painter>(backend.getContext(), transform.getState());
}
- FrameData frameData { view.getFramebufferSize(),
- timePoint,
+ FrameData frameData { timePoint,
pixelRatio,
mode,
contextMode,
@@ -263,11 +296,12 @@ void Map::Impl::render() {
painter->render(*style,
frameData,
+ view,
annotationManager->getSpriteAtlas());
if (mode == MapMode::Still) {
- callback(nullptr, view.readStillImage());
- callback = nullptr;
+ auto request = std::move(stillImageRequest);
+ request->callback(nullptr);
}
painter->cleanup();
@@ -290,7 +324,7 @@ void Map::setStyleURL(const std::string& url) {
impl->loading = true;
- impl->view.notifyMapChange(MapChangeWillStartLoadingMap);
+ impl->backend.notifyMapChange(MapChangeWillStartLoadingMap);
impl->styleRequest = nullptr;
impl->styleURL = url;
@@ -334,7 +368,7 @@ void Map::setStyleJSON(const std::string& json) {
impl->loading = true;
- impl->view.notifyMapChange(MapChangeWillStartLoadingMap);
+ impl->backend.notifyMapChange(MapChangeWillStartLoadingMap);
impl->styleURL.clear();
impl->styleJSON.clear();
@@ -369,12 +403,12 @@ std::string Map::getStyleJSON() const {
void Map::cancelTransitions() {
impl->transform.cancelTransitions();
- update(Update::Repaint);
+ impl->onUpdate(Update::Repaint);
}
void Map::setGestureInProgress(bool inProgress) {
impl->transform.setGestureInProgress(inProgress);
- update(Update::Repaint);
+ impl->onUpdate(Update::Repaint);
}
bool Map::isGestureInProgress() const {
@@ -401,24 +435,24 @@ CameraOptions Map::getCameraOptions(optional<EdgeInsets> padding) const {
void Map::jumpTo(const CameraOptions& camera) {
impl->transform.jumpTo(camera);
- update(camera.zoom ? Update::RecalculateStyle : Update::Repaint);
+ impl->onUpdate(camera.zoom ? Update::RecalculateStyle : Update::Repaint);
}
void Map::easeTo(const CameraOptions& camera, const AnimationOptions& animation) {
impl->transform.easeTo(camera, animation);
- update(camera.zoom ? Update::RecalculateStyle : Update::Repaint);
+ impl->onUpdate(camera.zoom ? Update::RecalculateStyle : Update::Repaint);
}
void Map::flyTo(const CameraOptions& camera, const AnimationOptions& animation) {
impl->transform.flyTo(camera, animation);
- update(Update::RecalculateStyle);
+ impl->onUpdate(Update::RecalculateStyle);
}
#pragma mark - Position
void Map::moveBy(const ScreenCoordinate& point, const Duration& duration) {
impl->transform.moveBy(point, duration);
- update(Update::Repaint);
+ impl->onUpdate(Update::Repaint);
}
void Map::setLatLng(const LatLng& latLng, const Duration& duration) {
@@ -427,12 +461,12 @@ void Map::setLatLng(const LatLng& latLng, const Duration& duration) {
void Map::setLatLng(const LatLng& latLng, optional<EdgeInsets> padding, const Duration& duration) {
impl->transform.setLatLng(latLng, padding, duration);
- update(Update::Repaint);
+ impl->onUpdate(Update::Repaint);
}
void Map::setLatLng(const LatLng& latLng, optional<ScreenCoordinate> anchor, const Duration& duration) {
impl->transform.setLatLng(latLng, anchor, duration);
- update(Update::Repaint);
+ impl->onUpdate(Update::Repaint);
}
LatLng Map::getLatLng(optional<EdgeInsets> padding) const {
@@ -447,7 +481,7 @@ void Map::resetPosition(optional<EdgeInsets> padding) {
camera.padding = padding;
camera.zoom = 0;
impl->transform.jumpTo(camera);
- update(Update::RecalculateStyle);
+ impl->onUpdate(Update::RecalculateStyle);
}
@@ -455,12 +489,12 @@ void Map::resetPosition(optional<EdgeInsets> padding) {
void Map::scaleBy(double ds, optional<ScreenCoordinate> anchor, const Duration& duration) {
impl->transform.scaleBy(ds, anchor, duration);
- update(Update::RecalculateStyle);
+ impl->onUpdate(Update::RecalculateStyle);
}
void Map::setScale(double scale, optional<ScreenCoordinate> anchor, const Duration& duration) {
impl->transform.setScale(scale, anchor, duration);
- update(Update::RecalculateStyle);
+ impl->onUpdate(Update::RecalculateStyle);
}
double Map::getScale() const {
@@ -473,7 +507,7 @@ void Map::setZoom(double zoom, const Duration& duration) {
void Map::setZoom(double zoom, optional<EdgeInsets> padding, const Duration& duration) {
impl->transform.setZoom(zoom, padding, duration);
- update(Update::RecalculateStyle);
+ impl->onUpdate(Update::RecalculateStyle);
}
double Map::getZoom() const {
@@ -486,7 +520,7 @@ void Map::setLatLngZoom(const LatLng& latLng, double zoom, const Duration& durat
void Map::setLatLngZoom(const LatLng& latLng, double zoom, optional<EdgeInsets> padding, const Duration& duration) {
impl->transform.setLatLngZoom(latLng, zoom, padding, duration);
- update(Update::RecalculateStyle);
+ impl->onUpdate(Update::RecalculateStyle);
}
CameraOptions Map::cameraForLatLngBounds(const LatLngBounds& bounds, optional<EdgeInsets> padding) const {
@@ -583,6 +617,11 @@ double Map::getMaxZoom() const {
#pragma mark - Size
+void Map::setSize(const std::array<uint16_t, 2>& size) {
+ impl->transform.resize(size);
+ impl->onUpdate(Update::Repaint);
+}
+
uint16_t Map::getWidth() const {
return impl->transform.getState().getWidth();
}
@@ -595,7 +634,7 @@ uint16_t Map::getHeight() const {
void Map::rotateBy(const ScreenCoordinate& first, const ScreenCoordinate& second, const Duration& duration) {
impl->transform.rotateBy(first, second, duration);
- update(Update::Repaint);
+ impl->onUpdate(Update::Repaint);
}
void Map::setBearing(double degrees, const Duration& duration) {
@@ -604,12 +643,12 @@ void Map::setBearing(double degrees, const Duration& duration) {
void Map::setBearing(double degrees, optional<ScreenCoordinate> anchor, const Duration& duration) {
impl->transform.setAngle(-degrees * util::DEG2RAD, anchor, duration);
- update(Update::Repaint);
+ impl->onUpdate(Update::Repaint);
}
void Map::setBearing(double degrees, optional<EdgeInsets> padding, const Duration& duration) {
impl->transform.setAngle(-degrees * util::DEG2RAD, padding, duration);
- update(Update::Repaint);
+ impl->onUpdate(Update::Repaint);
}
double Map::getBearing() const {
@@ -618,7 +657,7 @@ double Map::getBearing() const {
void Map::resetNorth(const Duration& duration) {
impl->transform.setAngle(0, duration);
- update(Update::Repaint);
+ impl->onUpdate(Update::Repaint);
}
#pragma mark - Pitch
@@ -629,7 +668,7 @@ void Map::setPitch(double pitch, const Duration& duration) {
void Map::setPitch(double pitch, optional<ScreenCoordinate> anchor, const Duration& duration) {
impl->transform.setPitch(pitch * util::DEG2RAD, anchor, duration);
- update(Update::Repaint);
+ impl->onUpdate(Update::Repaint);
}
double Map::getPitch() const {
@@ -640,7 +679,7 @@ double Map::getPitch() const {
void Map::setNorthOrientation(NorthOrientation orientation) {
impl->transform.setNorthOrientation(orientation);
- update(Update::Repaint);
+ impl->onUpdate(Update::Repaint);
}
NorthOrientation Map::getNorthOrientation() const {
@@ -651,7 +690,7 @@ NorthOrientation Map::getNorthOrientation() const {
void Map::setConstrainMode(mbgl::ConstrainMode mode) {
impl->transform.setConstrainMode(mode);
- update(Update::Repaint);
+ impl->onUpdate(Update::Repaint);
}
ConstrainMode Map::getConstrainMode() const {
@@ -662,7 +701,7 @@ ConstrainMode Map::getConstrainMode() const {
void Map::setViewportMode(mbgl::ViewportMode mode) {
impl->transform.setViewportMode(mode);
- update(Update::Repaint);
+ impl->onUpdate(Update::Repaint);
}
ViewportMode Map::getViewportMode() const {
@@ -707,17 +746,17 @@ double Map::getTopOffsetPixelsForAnnotationIcon(const std::string& name) {
AnnotationID Map::addAnnotation(const Annotation& annotation) {
auto result = impl->annotationManager->addAnnotation(annotation, getMaxZoom());
- update(Update::AnnotationStyle | Update::AnnotationData);
+ impl->onUpdate(Update::AnnotationStyle | Update::AnnotationData);
return result;
}
void Map::updateAnnotation(AnnotationID id, const Annotation& annotation) {
- update(impl->annotationManager->updateAnnotation(id, annotation, getMaxZoom()));
+ impl->onUpdate(impl->annotationManager->updateAnnotation(id, annotation, getMaxZoom()));
}
void Map::removeAnnotation(AnnotationID annotation) {
impl->annotationManager->removeAnnotation(annotation);
- update(Update::AnnotationStyle | Update::AnnotationData);
+ impl->onUpdate(Update::AnnotationStyle | Update::AnnotationData);
}
#pragma mark - Feature query api
@@ -800,12 +839,12 @@ void Map::addLayer(std::unique_ptr<Layer> layer, const optional<std::string>& be
}
impl->styleMutated = true;
- impl->view.activate();
+ impl->backend.activate();
impl->style->addLayer(std::move(layer), before);
- update(Update::Classes);
+ impl->onUpdate(Update::Classes);
- impl->view.deactivate();
+ impl->backend.deactivate();
}
void Map::removeLayer(const std::string& id) {
@@ -814,12 +853,12 @@ void Map::removeLayer(const std::string& id) {
}
impl->styleMutated = true;
- impl->view.activate();
+ impl->backend.activate();
impl->style->removeLayer(id);
- update(Update::Classes);
+ impl->onUpdate(Update::Classes);
- impl->view.deactivate();
+ impl->backend.deactivate();
}
void Map::addImage(const std::string& name, std::unique_ptr<const SpriteImage> image) {
@@ -831,7 +870,7 @@ void Map::addImage(const std::string& name, std::unique_ptr<const SpriteImage> i
impl->style->spriteAtlas->setSprite(name, std::move(image));
impl->style->spriteAtlas->updateDirty();
- update(Update::Repaint);
+ impl->onUpdate(Update::Repaint);
}
void Map::removeImage(const std::string& name) {
@@ -843,7 +882,7 @@ void Map::removeImage(const std::string& name) {
impl->style->spriteAtlas->removeSprite(name);
impl->style->spriteAtlas->updateDirty();
- update(Update::Repaint);
+ impl->onUpdate(Update::Repaint);
}
#pragma mark - Defaults
@@ -887,7 +926,7 @@ double Map::getDefaultPitch() const {
void Map::setDebug(MapDebugOptions debugOptions) {
impl->debugOptions = debugOptions;
- update(Update::Repaint);
+ impl->onUpdate(Update::Repaint);
}
void Map::cycleDebugOptions() {
@@ -911,7 +950,7 @@ void Map::cycleDebugOptions() {
else
impl->debugOptions = MapDebugOptions::TileBorders;
- update(Update::Repaint);
+ impl->onUpdate(Update::Repaint);
}
MapDebugOptions Map::getDebug() const {
@@ -924,20 +963,20 @@ bool Map::isFullyLoaded() const {
void Map::addClass(const std::string& className) {
if (impl->style && impl->style->addClass(className)) {
- update(Update::Classes);
+ impl->onUpdate(Update::Classes);
}
}
void Map::removeClass(const std::string& className) {
if (impl->style && impl->style->removeClass(className)) {
- update(Update::Classes);
+ impl->onUpdate(Update::Classes);
}
}
void Map::setClasses(const std::vector<std::string>& classNames) {
if (impl->style) {
impl->style->setClasses(classNames);
- update(Update::Classes);
+ impl->onUpdate(Update::Classes);
}
}
@@ -970,7 +1009,7 @@ void Map::setSourceTileCacheSize(size_t size) {
impl->sourceCacheSize = size;
if (!impl->style) return;
impl->style->setSourceTileCacheSize(size);
- impl->view.invalidate();
+ impl->backend.invalidate();
}
}
@@ -980,35 +1019,31 @@ void Map::onLowMemory() {
}
if (impl->style) {
impl->style->onLowMemory();
- impl->view.invalidate();
+ impl->backend.invalidate();
}
}
void Map::Impl::onSourceAttributionChanged(style::Source&, const std::string&) {
- view.notifyMapChange(MapChangeSourceDidChange);
+ backend.notifyMapChange(MapChangeSourceDidChange);
}
void Map::Impl::onUpdate(Update flags) {
- if (flags & Update::Dimensions) {
- transform.resize(view.getSize());
- }
-
updateFlags |= flags;
asyncUpdate.send();
}
void Map::Impl::onStyleLoaded() {
- view.notifyMapChange(MapChangeDidFinishLoadingStyle);
+ backend.notifyMapChange(MapChangeDidFinishLoadingStyle);
}
void Map::Impl::onStyleError() {
- view.notifyMapChange(MapChangeDidFailLoadingMap);
+ backend.notifyMapChange(MapChangeDidFailLoadingMap);
}
void Map::Impl::onResourceError(std::exception_ptr error) {
- if (mode == MapMode::Still && callback) {
- callback(error, {});
- callback = nullptr;
+ if (mode == MapMode::Still && stillImageRequest) {
+ auto request = std::move(stillImageRequest);
+ request->callback(error);
}
}
diff --git a/src/mbgl/map/transform.cpp b/src/mbgl/map/transform.cpp
index 41fc36ce27..85805a109d 100644
--- a/src/mbgl/map/transform.cpp
+++ b/src/mbgl/map/transform.cpp
@@ -7,6 +7,7 @@
#include <mbgl/util/unitbezier.hpp>
#include <mbgl/util/interpolate.hpp>
#include <mbgl/util/chrono.hpp>
+#include <mbgl/util/projection.hpp>
#include <mbgl/math/clamp.hpp>
#include <mbgl/platform/log.hpp>
#include <mbgl/platform/platform.hpp>
@@ -112,8 +113,8 @@ void Transform::easeTo(const CameraOptions& camera, const AnimationOptions& anim
// Find the shortest path otherwise.
else startLatLng.unwrapForShortestPath(latLng);
- const Point<double> startPoint = state.project(startLatLng);
- const Point<double> endPoint = state.project(latLng);
+ const Point<double> startPoint = Projection::project(startLatLng, state.scale);
+ const Point<double> endPoint = Projection::project(latLng, state.scale);
ScreenCoordinate center = getScreenCoordinate(padding);
center.y = state.height - center.y;
@@ -131,10 +132,6 @@ void Transform::easeTo(const CameraOptions& camera, const AnimationOptions& anim
Duration duration = animation.duration ? *animation.duration : Duration::zero();
- const double startWorldSize = state.worldSize();
- state.Bc = startWorldSize / util::DEGREES_MAX;
- state.Cc = startWorldSize / util::M2PI;
-
const double startScale = state.scale;
const double startAngle = state.angle;
const double startPitch = state.pitch;
@@ -144,7 +141,7 @@ void Transform::easeTo(const CameraOptions& camera, const AnimationOptions& anim
startTransition(camera, animation, [=](double t) {
Point<double> framePoint = util::interpolate(startPoint, endPoint, t);
- LatLng frameLatLng = state.unproject(framePoint, startWorldSize);
+ LatLng frameLatLng = Projection::unproject(framePoint, startScale);
double frameScale = util::interpolate(startScale, scale, t);
state.setLatLngZoom(frameLatLng, state.scaleZoom(frameScale));
@@ -186,8 +183,8 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima
LatLng startLatLng = getLatLng(padding).wrapped();
startLatLng.unwrapForShortestPath(latLng);
- const Point<double> startPoint = state.project(startLatLng);
- const Point<double> endPoint = state.project(latLng);
+ const Point<double> startPoint = Projection::project(startLatLng, state.scale);
+ const Point<double> endPoint = Projection::project(latLng, state.scale);
ScreenCoordinate center = getScreenCoordinate(padding);
center.y = state.height - center.y;
@@ -291,10 +288,7 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima
return;
}
- const double startWorldSize = state.worldSize();
- state.Bc = startWorldSize / util::DEGREES_MAX;
- state.Cc = startWorldSize / util::M2PI;
-
+ const double startScale = state.scale;
state.panning = true;
state.scaling = true;
state.rotating = angle != startAngle;
@@ -310,7 +304,7 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima
double frameZoom = startZoom + state.scaleZoom(1 / w(s));
// Convert to geographic coordinates and set the new viewpoint.
- LatLng frameLatLng = state.unproject(framePoint, startWorldSize);
+ LatLng frameLatLng = Projection::unproject(framePoint, startScale);
state.setLatLngZoom(frameLatLng, frameZoom);
if (angle != startAngle) {
diff --git a/src/mbgl/map/transform_state.cpp b/src/mbgl/map/transform_state.cpp
index eb66513626..4f6bcecdb6 100644
--- a/src/mbgl/map/transform_state.cpp
+++ b/src/mbgl/map/transform_state.cpp
@@ -17,7 +17,7 @@ TransformState::TransformState(ConstrainMode constrainMode_, ViewportMode viewpo
void TransformState::matrixFor(mat4& matrix, const UnwrappedTileID& tileID) const {
const uint64_t tileScale = 1ull << tileID.canonical.z;
- const double s = worldSize() / tileScale;
+ const double s = Projection::worldSize(scale) / tileScale;
matrix::identity(matrix);
matrix::translate(matrix, matrix,
@@ -108,12 +108,12 @@ LatLng TransformState::getLatLng(LatLng::WrapMode wrapMode) const {
}
double TransformState::pixel_x() const {
- const double center = (width - worldSize()) / 2;
+ const double center = (width - Projection::worldSize(scale)) / 2;
return center + x;
}
double TransformState::pixel_y() const {
- const double center = (height - worldSize()) / 2;
+ const double center = (height - Projection::worldSize(scale)) / 2;
return center + y;
}
@@ -201,22 +201,6 @@ bool TransformState::isGestureInProgress() const {
#pragma mark - Projection
-Point<double> TransformState::project(const LatLng& ll) const {
- return Point<double>(
- (util::LONGITUDE_MAX + ll.longitude),
- (util::LONGITUDE_MAX - util::RAD2DEG * std::log(std::tan(M_PI / 4 + ll.latitude * M_PI / util::DEGREES_MAX)))
- ) * worldSize() / util::DEGREES_MAX;
-}
-
-LatLng TransformState::unproject(const Point<double>& p, double worldSize, LatLng::WrapMode wrapMode) const {
- Point<double> p2 = p * util::DEGREES_MAX / worldSize;
- return LatLng(
- util::DEGREES_MAX / M_PI * std::atan(std::exp((util::LONGITUDE_MAX - p2.y) * util::DEG2RAD)) - 90.0f,
- p2.x - util::LONGITUDE_MAX,
- wrapMode
- );
-}
-
double TransformState::zoomScale(double zoom) const {
return std::pow(2.0f, zoom);
}
@@ -225,10 +209,6 @@ double TransformState::scaleZoom(double s) const {
return util::log2(s);
}
-double TransformState::worldSize() const {
- return scale * util::tileSize;
-}
-
ScreenCoordinate TransformState::latLngToScreenCoordinate(const LatLng& latLng) const {
if (width == 0 || height == 0) {
return {};
@@ -236,7 +216,7 @@ ScreenCoordinate TransformState::latLngToScreenCoordinate(const LatLng& latLng)
mat4 mat = coordinatePointMatrix(getZoom());
vec4 p;
- Point<double> pt = project(latLng) / double(util::tileSize);
+ Point<double> pt = Projection::project(latLng, scale) / double(util::tileSize);
vec4 c = {{ pt.x, pt.y, 0, 1 }};
matrix::transformMat4(p, c, mat);
return { p[0] / p[3], height - p[1] / p[3] };
@@ -278,13 +258,13 @@ LatLng TransformState::screenCoordinateToLatLng(const ScreenCoordinate& point, L
double z1 = coord1[2] / w1;
double t = z0 == z1 ? 0 : (targetZ - z0) / (z1 - z0);
- return unproject(util::interpolate(p0, p1, t), scale, wrapMode);
+ return Projection::unproject(util::interpolate(p0, p1, t), scale / util::tileSize, wrapMode);
}
mat4 TransformState::coordinatePointMatrix(double z) const {
mat4 proj;
getProjMatrix(proj);
- float s = worldSize() / std::pow(2, z);
+ float s = Projection::worldSize(scale) / std::pow(2, z);
matrix::scale(proj, proj, s, s, 1);
matrix::multiply(proj, getPixelMatrix(), proj);
return proj;
@@ -325,10 +305,10 @@ void TransformState::constrain(double& scale_, double& x_, double& y_) const {
}
void TransformState::moveLatLng(const LatLng& latLng, const ScreenCoordinate& anchor) {
- auto centerCoord = project(getLatLng(LatLng::Unwrapped));
- auto latLngCoord = project(latLng);
- auto anchorCoord = project(screenCoordinateToLatLng(anchor));
- setLatLngZoom(unproject(centerCoord + latLngCoord - anchorCoord, worldSize()), getZoom());
+ auto centerCoord = Projection::project(getLatLng(LatLng::Unwrapped), scale);
+ auto latLngCoord = Projection::project(latLng, scale);
+ auto anchorCoord = Projection::project(screenCoordinateToLatLng(anchor), scale);
+ setLatLngZoom(Projection::unproject(centerCoord + latLngCoord - anchorCoord, scale), getZoom());
}
void TransformState::setLatLngZoom(const LatLng &latLng, double zoom) {
@@ -355,8 +335,8 @@ void TransformState::setScalePoint(const double newScale, const ScreenCoordinate
scale = constrainedScale;
x = constrainedPoint.x;
y = constrainedPoint.y;
- Bc = worldSize() / util::DEGREES_MAX;
- Cc = worldSize() / util::M2PI;
+ Bc = Projection::worldSize(scale) / util::DEGREES_MAX;
+ Cc = Projection::worldSize(scale) / util::M2PI;
}
} // namespace mbgl
diff --git a/src/mbgl/map/transform_state.hpp b/src/mbgl/map/transform_state.hpp
index 1e4b2054f7..8a12b62a9e 100644
--- a/src/mbgl/map/transform_state.hpp
+++ b/src/mbgl/map/transform_state.hpp
@@ -4,6 +4,7 @@
#include <mbgl/util/geo.hpp>
#include <mbgl/util/geometry.hpp>
#include <mbgl/util/constants.hpp>
+#include <mbgl/util/projection.hpp>
#include <mbgl/util/mat4.hpp>
#include <cstdint>
@@ -65,13 +66,10 @@ public:
bool isPanning() const;
bool isGestureInProgress() const;
- // Conversion and projection
+ // Conversion
ScreenCoordinate latLngToScreenCoordinate(const LatLng&) const;
LatLng screenCoordinateToLatLng(const ScreenCoordinate&, LatLng::WrapMode = LatLng::Unwrapped) const;
- Point<double> project(const LatLng&) const;
- LatLng unproject(const Point<double>&, double worldSize, LatLng::WrapMode = LatLng::Unwrapped) const;
-
double zoomScale(double zoom) const;
double scaleZoom(double scale) const;
@@ -88,8 +86,6 @@ private:
// logical dimensions
uint16_t width = 0, height = 0;
- double worldSize() const;
-
mat4 coordinatePointMatrix(double z) const;
mat4 getPixelMatrix() const;
@@ -117,8 +113,8 @@ private:
double pitch = 0.0;
// cache values for spherical mercator math
- double Bc = worldSize() / util::DEGREES_MAX;
- double Cc = worldSize() / util::M2PI;
+ double Bc = Projection::worldSize(scale) / util::DEGREES_MAX;
+ double Cc = Projection::worldSize(scale) / util::M2PI;
};
} // namespace mbgl
diff --git a/include/mbgl/map/update.hpp b/src/mbgl/map/update.hpp
index 1da7e3ac92..dc383b819e 100644
--- a/include/mbgl/map/update.hpp
+++ b/src/mbgl/map/update.hpp
@@ -6,7 +6,6 @@ namespace mbgl {
enum class Update {
Nothing = 0,
- Dimensions = 1 << 1,
Classes = 1 << 2,
RecalculateStyle = 1 << 3,
RenderStill = 1 << 4,
diff --git a/src/mbgl/map/view.cpp b/src/mbgl/map/view.cpp
deleted file mode 100644
index 8541753c7a..0000000000
--- a/src/mbgl/map/view.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-#include <mbgl/map/view.hpp>
-#include <mbgl/map/map.hpp>
-
-#include <cassert>
-
-namespace mbgl {
-
-void View::initialize(Map *map_) {
- assert(map_);
- map = map_;
-}
-
-PremultipliedImage View::readStillImage(std::array<uint16_t, 2>) {
- return {};
-}
-
-void View::notifyMapChange(MapChange) {
- // no-op
-}
-
-
-} // namespace mbgl
diff --git a/src/mbgl/renderer/paint_parameters.hpp b/src/mbgl/renderer/paint_parameters.hpp
index 13bf21080d..bd67dc9cfd 100644
--- a/src/mbgl/renderer/paint_parameters.hpp
+++ b/src/mbgl/renderer/paint_parameters.hpp
@@ -3,10 +3,12 @@
namespace mbgl {
class Shaders;
+class View;
class PaintParameters {
public:
Shaders& shaders;
+ View& view;
};
} // namespace mbgl
diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp
index ad0e75cd92..fc61d6e0a0 100644
--- a/src/mbgl/renderer/painter.cpp
+++ b/src/mbgl/renderer/painter.cpp
@@ -5,6 +5,8 @@
#include <mbgl/style/source.hpp>
#include <mbgl/style/source_impl.hpp>
+#include <mbgl/map/view.hpp>
+
#include <mbgl/platform/log.hpp>
#include <mbgl/gl/gl.hpp>
#include <mbgl/gl/debugging.hpp>
@@ -29,6 +31,8 @@
#include <mbgl/util/mat3.hpp>
#include <mbgl/util/string.hpp>
+#include <mbgl/util/offscreen_texture.hpp>
+
#include <cassert>
#include <algorithm>
#include <iostream>
@@ -38,8 +42,9 @@ namespace mbgl {
using namespace style;
-Painter::Painter(const TransformState& state_)
- : state(state_),
+Painter::Painter(gl::Context& context_, const TransformState& state_)
+ : context(context_),
+ state(state_),
tileTriangleVertexBuffer(context.createVertexBuffer(std::vector<FillVertex> {{
{ 0, 0 },
{ util::EXTENT, 0 },
@@ -69,9 +74,6 @@ Painter::Painter(const TransformState& state_)
#ifndef NDEBUG
overdrawShaders = std::make_unique<Shaders>(context, gl::Shader::Overdraw);
#endif
-
- // Reset GL values
- context.setDirtyState();
}
Painter::~Painter() = default;
@@ -90,19 +92,19 @@ void Painter::cleanup() {
context.performCleanup();
}
-void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& annotationSpriteAtlas) {
- if (frame.framebufferSize != frame_.framebufferSize) {
- context.viewport.setDefaultValue(
- { 0, 0, frame_.framebufferSize[0], frame_.framebufferSize[1] });
- }
+void Painter::render(const Style& style, const FrameData& frame_, View& view, SpriteAtlas& annotationSpriteAtlas) {
frame = frame_;
+ if (frame.contextMode == GLContextMode::Shared) {
+ context.setDirtyState();
+ }
PaintParameters parameters {
#ifndef NDEBUG
- paintMode() == PaintMode::Overdraw ? *overdrawShaders : *shaders
+ paintMode() == PaintMode::Overdraw ? *overdrawShaders : *shaders,
#else
- *shaders
+ *shaders,
#endif
+ view
};
glyphAtlas = style.glyphAtlas.get();
@@ -125,12 +127,14 @@ void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& a
frameHistory.record(frame.timePoint, state.getZoom(),
frame.mapMode == MapMode::Continuous ? util::DEFAULT_FADE_DURATION : Milliseconds(0));
+
// - UPLOAD PASS -------------------------------------------------------------------------------
// Uploads all required buffers and images before we do any actual rendering.
{
MBGL_DEBUG_GROUP("upload");
spriteAtlas->upload(context, 0);
+
lineAtlas->upload(context, 0);
glyphAtlas->upload(context, 0);
frameHistory.upload(context, 0);
@@ -148,9 +152,8 @@ void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& a
// tiles whatsoever.
{
MBGL_DEBUG_GROUP("clear");
- context.bindFramebuffer.reset();
- context.viewport.reset();
- context.stencilFunc.reset();
+ view.bind();
+ context.stencilFunc = { gl::StencilTestFunction::Always, 0, ~0u };
context.stencilTest = true;
context.stencilMask = 0xFF;
context.depthTest = false;
@@ -188,7 +191,7 @@ void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& a
#if not MBGL_USE_GLES2 and not defined(NDEBUG)
if (frame.debugOptions & MapDebugOptions::StencilClip) {
- renderClipMasks();
+ renderClipMasks(parameters);
return;
}
#endif
@@ -231,7 +234,7 @@ void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& a
#if not MBGL_USE_GLES2 and not defined(NDEBUG)
if (frame.debugOptions & MapDebugOptions::DepthBuffer) {
- renderDepthBuffer();
+ renderDepthBuffer(parameters);
}
#endif
@@ -247,10 +250,6 @@ void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& a
context.vertexArrayObject = 0;
}
-
- if (frame.contextMode == GLContextMode::Shared) {
- context.setDirtyState();
- }
}
template <class Iterator>
@@ -294,16 +293,21 @@ void Painter::renderPass(PaintParameters& parameters,
renderBackground(parameters, *layer.as<BackgroundLayer>());
} else if (layer.is<CustomLayer>()) {
MBGL_DEBUG_GROUP(layer.baseImpl->id + " - custom");
+
+ // Reset GL state to a known state so the CustomLayer always has a clean slate.
context.vertexArrayObject = 0;
context.depthFunc = gl::DepthTestFunction::LessEqual;
context.depthTest = true;
context.depthMask = false;
context.stencilTest = false;
setDepthSublayer(0);
+
layer.as<CustomLayer>()->impl->render(state);
+
+ // Reset the view back to our original one, just in case the CustomLayer changed
+ // the viewport or Framebuffer.
+ parameters.view.bind();
context.setDirtyState();
- context.bindFramebuffer.reset();
- context.viewport.reset();
} else {
MBGL_DEBUG_GROUP(layer.baseImpl->id + " - " + util::toString(item.tile->id));
if (item.bucket->needsClipping()) {
diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp
index 28aa5aab44..f339ed1aed 100644
--- a/src/mbgl/renderer/painter.hpp
+++ b/src/mbgl/renderer/painter.hpp
@@ -28,6 +28,7 @@ namespace mbgl {
class RenderTile;
class SpriteAtlas;
+class View;
class GlyphAtlas;
class LineAtlas;
struct FrameData;
@@ -58,7 +59,6 @@ class BackgroundLayer;
} // namespace style
struct FrameData {
- std::array<uint16_t, 2> framebufferSize = {{ 0, 0 }};
TimePoint timePoint;
float pixelRatio;
MapMode mapMode;
@@ -68,11 +68,12 @@ struct FrameData {
class Painter : private util::noncopyable {
public:
- Painter(const TransformState&);
+ Painter(gl::Context&, const TransformState&);
~Painter();
void render(const style::Style&,
const FrameData&,
+ View&,
SpriteAtlas& annotationSpriteAtlas);
void cleanup();
@@ -85,9 +86,9 @@ public:
#ifndef NDEBUG
// Renders tile clip boundaries, using stencil buffer to calculate fill color.
- void renderClipMasks();
+ void renderClipMasks(PaintParameters&);
// Renders the depth buffer.
- void renderDepthBuffer();
+ void renderDepthBuffer(PaintParameters&);
#endif
void renderDebugText(Tile&, const mat4&);
@@ -152,6 +153,9 @@ private:
}
#endif
+private:
+ gl::Context& context;
+
mat4 projMatrix;
std::array<float, 2> pixelsToGLUnits;
@@ -168,8 +172,6 @@ private:
int indent = 0;
- gl::Context context;
-
RenderPass pass = RenderPass::Opaque;
int numSublayers = 3;
diff --git a/src/mbgl/renderer/painter_debug.cpp b/src/mbgl/renderer/painter_debug.cpp
index 23a2a8e571..e57bb2205e 100644
--- a/src/mbgl/renderer/painter_debug.cpp
+++ b/src/mbgl/renderer/painter_debug.cpp
@@ -1,6 +1,8 @@
#include <mbgl/renderer/painter.hpp>
#include <mbgl/renderer/debug_bucket.hpp>
#include <mbgl/renderer/render_tile.hpp>
+#include <mbgl/renderer/paint_parameters.hpp>
+#include <mbgl/map/view.hpp>
#include <mbgl/tile/tile.hpp>
#include <mbgl/shader/shaders.hpp>
#include <mbgl/util/string.hpp>
@@ -87,7 +89,7 @@ void Painter::renderDebugFrame(const mat4 &matrix) {
}
#ifndef NDEBUG
-void Painter::renderClipMasks() {
+void Painter::renderClipMasks(PaintParameters&) {
context.stencilTest = false;
context.depthTest = false;
context.program = 0;
@@ -98,13 +100,13 @@ void Painter::renderClipMasks() {
context.rasterPos = { -1, -1, 0, 0 };
// Read the stencil buffer
- const auto& fbSize = frame.framebufferSize;
- auto pixels = std::make_unique<uint8_t[]>(fbSize[0] * fbSize[1]);
+ const auto viewport = context.viewport.getCurrentValue();
+ auto pixels = std::make_unique<uint8_t[]>(viewport.width * viewport.height);
MBGL_CHECK_ERROR(glReadPixels(
- 0, // GLint x
- 0, // GLint y
- fbSize[0], // GLsizei width
- fbSize[1], // GLsizei height
+ viewport.x, // GLint x
+ viewport.y, // GLint y
+ viewport.width, // GLsizei width
+ viewport.height, // GLsizei height
GL_STENCIL_INDEX, // GLenum format
GL_UNSIGNED_BYTE, // GLenum type
pixels.get() // GLvoid * data
@@ -112,20 +114,21 @@ void Painter::renderClipMasks() {
// Scale the Stencil buffer to cover the entire color space.
auto it = pixels.get();
- auto end = it + fbSize[0] * fbSize[1];
+ auto end = it + viewport.width * viewport.height;
const auto factor = 255.0f / *std::max_element(it, end);
for (; it != end; ++it) {
*it *= factor;
}
- MBGL_CHECK_ERROR(glWindowPos2i(0, 0));
- MBGL_CHECK_ERROR(glDrawPixels(fbSize[0], fbSize[1], GL_LUMINANCE, GL_UNSIGNED_BYTE, pixels.get()));
+ MBGL_CHECK_ERROR(glWindowPos2i(viewport.x, viewport.y));
+ MBGL_CHECK_ERROR(glDrawPixels(viewport.width, viewport.height, GL_LUMINANCE, GL_UNSIGNED_BYTE,
+ pixels.get()));
#endif // MBGL_USE_GLES2
}
#endif // NDEBUG
#ifndef NDEBUG
-void Painter::renderDepthBuffer() {
+void Painter::renderDepthBuffer(PaintParameters&) {
context.stencilTest = false;
context.depthTest = false;
context.program = 0;
@@ -136,25 +139,26 @@ void Painter::renderDepthBuffer() {
context.rasterPos = { -1, -1, 0, 0 };
// Read the stencil buffer
- const auto& fbSize = frame.framebufferSize;
- auto pixels = std::make_unique<GLubyte[]>(fbSize[0] * fbSize[1]);
+ const auto viewport = context.viewport.getCurrentValue();
+ auto pixels = std::make_unique<uint8_t[]>(viewport.width * viewport.height);
const double base = 1.0 / (1.0 - depthRangeSize);
glPixelTransferf(GL_DEPTH_SCALE, base);
glPixelTransferf(GL_DEPTH_BIAS, 1.0 - base);
MBGL_CHECK_ERROR(glReadPixels(
- 0, // GLint x
- 0, // GLint y
- fbSize[0], // GLsizei width
- fbSize[1], // GLsizei height
+ viewport.x, // GLint x
+ viewport.y, // GLint y
+ viewport.width, // GLsizei width
+ viewport.height, // GLsizei height
GL_DEPTH_COMPONENT, // GLenum format
GL_UNSIGNED_BYTE, // GLenum type
pixels.get() // GLvoid * data
));
- MBGL_CHECK_ERROR(glWindowPos2i(0, 0));
- MBGL_CHECK_ERROR(glDrawPixels(fbSize[0], fbSize[1], GL_LUMINANCE, GL_UNSIGNED_BYTE, pixels.get()));
+ MBGL_CHECK_ERROR(glWindowPos2i(viewport.x, viewport.y));
+ MBGL_CHECK_ERROR(glDrawPixels(viewport.width, viewport.height, GL_LUMINANCE, GL_UNSIGNED_BYTE,
+ pixels.get()));
#endif // MBGL_USE_GLES2
}
#endif // NDEBUG
diff --git a/src/mbgl/renderer/painter_fill.cpp b/src/mbgl/renderer/painter_fill.cpp
index 50ead900f6..b6606ca40b 100644
--- a/src/mbgl/renderer/painter_fill.cpp
+++ b/src/mbgl/renderer/painter_fill.cpp
@@ -1,6 +1,7 @@
#include <mbgl/renderer/painter.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/gl/gl.hpp>
+#include <mbgl/map/view.hpp>
#include <mbgl/renderer/fill_bucket.hpp>
#include <mbgl/renderer/render_tile.hpp>
@@ -29,7 +30,9 @@ void Painter::renderFill(PaintParameters& parameters,
const bool isOutlineColorDefined = !properties.fillOutlineColor.isUndefined();
Color strokeColor = isOutlineColorDefined? properties.fillOutlineColor : fillColor;
- auto worldSize = util::convert<GLfloat>(frame.framebufferSize);
+ const auto viewport = context.viewport.getCurrentValue();
+ const std::array<GLfloat, 2> worldSize{ { static_cast<GLfloat>(viewport.width),
+ static_cast<GLfloat>(viewport.height) } };
bool pattern = !properties.fillPattern.value.from.empty();
bool outline = properties.fillAntialias && !pattern && isOutlineColorDefined;
diff --git a/src/mbgl/style/source_impl.hpp b/src/mbgl/style/source_impl.hpp
index 608a552835..14ed9cd01c 100644
--- a/src/mbgl/style/source_impl.hpp
+++ b/src/mbgl/style/source_impl.hpp
@@ -86,6 +86,7 @@ protected:
Source& base;
SourceObserver* observer = nullptr;
std::map<OverscaledTileID, std::unique_ptr<Tile>> tiles;
+ TileCache cache;
private:
// TileObserver implementation.
@@ -97,7 +98,6 @@ private:
virtual std::unique_ptr<Tile> createTile(const OverscaledTileID&, const UpdateParameters&) = 0;
std::map<UnwrappedTileID, RenderTile> renderTiles;
- TileCache cache;
};
} // namespace style
diff --git a/src/mbgl/style/source_observer.hpp b/src/mbgl/style/source_observer.hpp
index a6cdab6ba2..dcbcaeabaf 100644
--- a/src/mbgl/style/source_observer.hpp
+++ b/src/mbgl/style/source_observer.hpp
@@ -20,6 +20,9 @@ public:
virtual void onSourceAttributionChanged(Source&, const std::string&) {}
virtual void onSourceError(Source&, std::exception_ptr) {}
+ //Source description needs to be reloaded
+ virtual void onSourceDescriptionChanged(Source&) {}
+
virtual void onTileChanged(Source&, const OverscaledTileID&) {}
virtual void onTileError(Source&, const OverscaledTileID&, std::exception_ptr) {}
};
diff --git a/src/mbgl/style/sources/geojson_source_impl.cpp b/src/mbgl/style/sources/geojson_source_impl.cpp
index 5b7ba4fc77..4800b9c4be 100644
--- a/src/mbgl/style/sources/geojson_source_impl.cpp
+++ b/src/mbgl/style/sources/geojson_source_impl.cpp
@@ -38,15 +38,31 @@ GeoJSONSource::Impl::~Impl() = default;
void GeoJSONSource::Impl::setURL(std::string url_) {
url = std::move(url_);
+
+ //Signal that the source description needs a reload
+ if (loaded || req) {
+ loaded = false;
+ req.reset();
+ observer->onSourceDescriptionChanged(base);
+ }
}
optional<std::string> GeoJSONSource::Impl::getURL() {
return url;
}
+
void GeoJSONSource::Impl::setGeoJSON(const GeoJSON& geoJSON) {
+ req.reset();
+ _setGeoJSON(geoJSON);
+}
+
+//Private implementation
+void GeoJSONSource::Impl::_setGeoJSON(const GeoJSON& geoJSON) {
double scale = util::EXTENT / util::tileSize;
+ cache.clear();
+
if (!options.cluster) {
mapbox::geojsonvt::Options vtOptions;
vtOptions.maxZoom = options.maxzoom;
@@ -65,7 +81,7 @@ void GeoJSONSource::Impl::setGeoJSON(const GeoJSON& geoJSON) {
geoJSONOrSupercluster =
std::make_unique<mapbox::supercluster::Supercluster>(features, clusterOptions);
}
-
+
for (auto const &item : tiles) {
GeoJSONTile* geoJSONTile = static_cast<GeoJSONTile*>(item.second.get());
setTileData(*geoJSONTile, geoJSONTile->id);
@@ -125,9 +141,9 @@ void GeoJSONSource::Impl::loadDescription(FileSource& fileSource) {
geoJSON.error().message.c_str());
// Create an empty GeoJSON VT object to make sure we're not infinitely waiting for
// tiles to load.
- setGeoJSON(GeoJSON{ FeatureCollection{} });
+ _setGeoJSON(GeoJSON{ FeatureCollection{} });
} else {
- setGeoJSON(*geoJSON);
+ _setGeoJSON(*geoJSON);
}
loaded = true;
diff --git a/src/mbgl/style/sources/geojson_source_impl.hpp b/src/mbgl/style/sources/geojson_source_impl.hpp
index 9572355f2c..13994d9078 100644
--- a/src/mbgl/style/sources/geojson_source_impl.hpp
+++ b/src/mbgl/style/sources/geojson_source_impl.hpp
@@ -29,6 +29,8 @@ public:
}
private:
+ void _setGeoJSON(const GeoJSON&);
+
Range<uint8_t> getZoomRange() final;
std::unique_ptr<Tile> createTile(const OverscaledTileID&, const UpdateParameters&) final;
diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp
index 522965b953..e1cbe56bc5 100644
--- a/src/mbgl/style/style.cpp
+++ b/src/mbgl/style/style.cpp
@@ -491,6 +491,13 @@ void Style::onSourceError(Source& source, std::exception_ptr error) {
observer->onResourceError(error);
}
+void Style::onSourceDescriptionChanged(Source& source) {
+ observer->onSourceDescriptionChanged(source);
+ if (!source.baseImpl->loaded) {
+ source.baseImpl->loadDescription(fileSource);
+ }
+}
+
void Style::onTileChanged(Source& source, const OverscaledTileID& tileID) {
observer->onTileChanged(source, tileID);
observer->onUpdate(Update::Repaint);
diff --git a/src/mbgl/style/style.hpp b/src/mbgl/style/style.hpp
index 648bd48030..21b25857d6 100644
--- a/src/mbgl/style/style.hpp
+++ b/src/mbgl/style/style.hpp
@@ -134,6 +134,7 @@ private:
void onSourceLoaded(Source&) override;
void onSourceAttributionChanged(Source&, const std::string&) override;
void onSourceError(Source&, std::exception_ptr) override;
+ void onSourceDescriptionChanged(Source&) override;
void onTileChanged(Source&, const OverscaledTileID&) override;
void onTileError(Source&, const OverscaledTileID&, std::exception_ptr) override;
diff --git a/src/mbgl/text/collision_tile.cpp b/src/mbgl/text/collision_tile.cpp
index d6fc1a6ada..e485fbf36c 100644
--- a/src/mbgl/text/collision_tile.cpp
+++ b/src/mbgl/text/collision_tile.cpp
@@ -3,6 +3,7 @@
#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>
@@ -11,20 +12,7 @@
namespace mbgl {
-auto infinity = std::numeric_limits<float>::infinity();
-
-CollisionTile::CollisionTile(PlacementConfig config_) : config(std::move(config_)),
- edges({{
- // left
- CollisionBox(Point<float>(0, 0), 0, -infinity, 0, infinity, infinity),
- // right
- CollisionBox(Point<float>(util::EXTENT, 0), 0, -infinity, 0, infinity, infinity),
- // top
- CollisionBox(Point<float>(0, 0), -infinity, 0, infinity, 0, infinity),
- // bottom
- CollisionBox(Point<float>(0, util::EXTENT), -infinity, 0, infinity, 0, infinity),
- }}) {
-
+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);
@@ -36,13 +24,12 @@ CollisionTile::CollisionTile(PlacementConfig config_) : config(std::move(config_
// The amount the map is squished depends on the y position.
// Sort of account for this by making all boxes a bit bigger.
- yStretch = std::pow(_yStretch, 1.3);
+ yStretch = std::pow(_yStretch, 1.3f);
}
-float CollisionTile::findPlacementScale(float minPlacementScale, const Point<float>& anchor,
- const CollisionBox& box, const Point<float>& blockingAnchor, const CollisionBox& blocking) {
-
+float CollisionTile::findPlacementScale(const Point<float>& anchor, const CollisionBox& box, 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:
@@ -80,7 +67,18 @@ float CollisionTile::findPlacementScale(float minPlacementScale, const Point<flo
return minPlacementScale;
}
-float CollisionTile::placeFeature(const CollisionFeature& feature, const bool allowOverlap, const bool avoidEdges) {
+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, -infinity, 0, infinity, infinity),
+ // right
+ CollisionBox(Point<float>(util::EXTENT, 0), 0, -infinity, 0, infinity, infinity),
+ // top
+ CollisionBox(Point<float>(0, 0), -infinity, 0, infinity, 0, infinity),
+ // bottom
+ CollisionBox(Point<float>(0, util::EXTENT), -infinity, 0, infinity, 0, infinity)
+ }};
float minPlacementScale = minScale;
@@ -92,20 +90,16 @@ float CollisionTile::placeFeature(const CollisionFeature& feature, const bool al
const CollisionBox& blocking = std::get<1>(*it);
Point<float> blockingAnchor = util::matrixMultiply(rotationMatrix, blocking.anchor);
- minPlacementScale = findPlacementScale(minPlacementScale, anchor, box, blockingAnchor, blocking);
+ minPlacementScale = util::max(minPlacementScale, findPlacementScale(anchor, box, blockingAnchor, blocking));
if (minPlacementScale >= maxScale) return minPlacementScale;
}
}
if (avoidEdges) {
- const Point<float> tl = { box.x1, box.y1 };
- const Point<float> tr = { box.x2, box.y1 };
- const Point<float> bl = { box.x1, box.y2 };
- const Point<float> br = { box.x2, box.y2 };
- const Point<float> rtl = util::matrixMultiply(reverseRotationMatrix, tl);
- const Point<float> rtr = util::matrixMultiply(reverseRotationMatrix, tr);
- const Point<float> rbl = util::matrixMultiply(reverseRotationMatrix, bl);
- const Point<float> rbr = util::matrixMultiply(reverseRotationMatrix, br);
+ 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,
util::min(rtl.x, rtr.x, rbl.x, rbr.x),
util::min(rtl.y, rtr.y, rbl.y, rbr.y),
@@ -114,8 +108,7 @@ float CollisionTile::placeFeature(const CollisionFeature& feature, const bool al
box.maxScale);
for (auto& blocking : edges) {
- minPlacementScale = findPlacementScale(minPlacementScale, box.anchor, rotatedBox, blocking.anchor, blocking);
-
+ minPlacementScale = util::max(minPlacementScale, findPlacementScale(box.anchor, rotatedBox, blocking.anchor, blocking));
if (minPlacementScale >= maxScale) return minPlacementScale;
}
}
@@ -124,7 +117,7 @@ float CollisionTile::placeFeature(const CollisionFeature& feature, const bool al
return minPlacementScale;
}
-void CollisionTile::insertFeature(CollisionFeature& feature, const float minPlacementScale, const bool ignorePlacement) {
+void CollisionTile::insertFeature(CollisionFeature& feature, float minPlacementScale, bool ignorePlacement) {
for (auto& box : feature.boxes) {
box.placementScale = minPlacementScale;
}
@@ -143,7 +136,25 @@ void CollisionTile::insertFeature(CollisionFeature& feature, const float minPlac
}
+// +---------------------------+ 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{
CollisionPoint{
anchor.x + box.x1 / scale,
@@ -156,49 +167,66 @@ Box CollisionTile::getTreeBox(const Point<float>& anchor, const CollisionBox& bo
};
}
-std::vector<IndexedSubfeature> CollisionTile::queryRenderedSymbols(const GeometryCoordinates& queryGeometry, const float scale) {
-
+std::vector<IndexedSubfeature> CollisionTile::queryRenderedSymbols(const GeometryCoordinates& queryGeometry, float scale) {
std::vector<IndexedSubfeature> result;
- if (queryGeometry.empty()) return 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();
+ };
- mapbox::geometry::multi_point<float> rotatedPoints {};
- rotatedPoints.reserve(queryGeometry.size());
- std::transform(queryGeometry.cbegin(), queryGeometry.cend(), std::back_inserter(rotatedPoints),
- [&](const auto& c) { return util::matrixMultiply(rotationMatrix, convertPoint<float>(c)); });
- const auto box = mapbox::geometry::envelope(rotatedPoints);
+ // Account for the rounding done when updating symbol shader variables.
+ const float roundedScale = std::pow(2.0f, std::ceil(util::log2(scale) * 10.0f) / 10.0f);
- const auto& anchor = box.min;
- CollisionBox queryBox(anchor, 0, 0, box.max.x - box.min.x, box.max.y - box.min.y, scale);
- auto predicates = bgi::intersects(getTreeBox(anchor, queryBox));
+ // 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.maxScale;
+ };
- auto fn = [&] (const Tree& tree_, bool ignorePlacement) {
+ // 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 / scale;
+ const int16_t y1 = anchor.y + collisionBox.y1 / scale * yStretch;
+ const int16_t x2 = anchor.x + collisionBox.x2 / scale;
+ const int16_t y2 = anchor.y + collisionBox.y2 / scale * 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 CollisionBox& blocking = std::get<1>(*it);
- const IndexedSubfeature& indexedFeature = std::get<2>(*it);
-
- auto& seenFeatures = sourceLayerFeatures[indexedFeature.sourceLayerName];
- if (seenFeatures.find(indexedFeature.index) == seenFeatures.end()) {
- if (ignorePlacement) {
- seenFeatures.insert(indexedFeature.index);
- result.push_back(indexedFeature);
- } else {
- auto blockingAnchor = util::matrixMultiply(rotationMatrix, blocking.anchor);
- float minPlacementScale = findPlacementScale(minScale, anchor, queryBox, blockingAnchor, blocking);
- if (minPlacementScale >= scale) {
- seenFeatures.insert(indexedFeature.index);
- result.push_back(indexedFeature);
- }
- }
- }
+ const IndexedSubfeature& feature = std::get<2>(*it);
+ auto& seenFeatures = sourceLayerFeatures[feature.sourceLayerName];
+ seenFeatures.insert(feature.index);
+ result.push_back(feature);
}
};
- bool ignorePlacement = false;
- fn(tree, ignorePlacement);
- ignorePlacement = true;
- fn(ignoredTree, ignorePlacement);
+ queryTree(tree);
+ queryTree(ignoredTree);
return result;
}
diff --git a/src/mbgl/text/collision_tile.hpp b/src/mbgl/text/collision_tile.hpp
index dbc23b2a79..186cd19d28 100644
--- a/src/mbgl/text/collision_tile.hpp
+++ b/src/mbgl/text/collision_tile.hpp
@@ -39,10 +39,10 @@ class CollisionTile {
public:
explicit CollisionTile(PlacementConfig);
- float placeFeature(const CollisionFeature&, const bool allowOverlap, const bool avoidEdges);
- void insertFeature(CollisionFeature&, const float minPlacementScale, const bool ignorePlacement);
+ float placeFeature(const CollisionFeature&, bool allowOverlap, bool avoidEdges);
+ void insertFeature(CollisionFeature&, float minPlacementScale, bool ignorePlacement);
- std::vector<IndexedSubfeature> queryRenderedSymbols(const GeometryCoordinates&, const float scale);
+ std::vector<IndexedSubfeature> queryRenderedSymbols(const GeometryCoordinates&, float scale);
const PlacementConfig config;
@@ -52,10 +52,9 @@ public:
std::array<float, 4> rotationMatrix;
std::array<float, 4> reverseRotationMatrix;
- std::array<CollisionBox, 4> edges;
private:
- float findPlacementScale(float minPlacementScale,
+ float findPlacementScale(
const Point<float>& anchor, const CollisionBox& box,
const Point<float>& blockingAnchor, const CollisionBox& blocking);
Box getTreeBox(const Point<float>& anchor, const CollisionBox& box, const float scale = 1.0);
diff --git a/src/mbgl/util/intersection_tests.cpp b/src/mbgl/util/intersection_tests.cpp
index a0feb8ec37..c580357298 100644
--- a/src/mbgl/util/intersection_tests.cpp
+++ b/src/mbgl/util/intersection_tests.cpp
@@ -16,14 +16,6 @@ bool polygonContainsPoint(const GeometryCoordinates& ring, const GeometryCoordin
return c;
}
-bool multiPolygonContainsPoint(const GeometryCollection& rings, const GeometryCoordinate& p) {
- bool c = false;
- for (auto& ring : rings) {
- c = (c != polygonContainsPoint(ring, p));
- }
- return c;
-}
-
// Code from http://stackoverflow.com/a/1501725/331379.
float distToSegmentSquared(const GeometryCoordinate& p, const GeometryCoordinate& v, const GeometryCoordinate& w) {
if (v == w) return util::distSqr<float>(p, v);
@@ -114,23 +106,23 @@ bool polygonIntersectsBufferedMultiLine(const GeometryCoordinates& polygon, cons
return false;
}
-bool polygonIntersectsMultiPolygon(const GeometryCoordinates& polygon, const GeometryCollection& multiPolygon) {
- if (polygon.size() == 1) {
- return multiPolygonContainsPoint(multiPolygon, polygon.at(0));
+bool polygonIntersectsPolygon(const GeometryCoordinates& polygonA, const GeometryCoordinates& polygonB) {
+ for (auto& p : polygonA) {
+ if (polygonContainsPoint(polygonB, p)) return true;
}
- for (auto& ring : multiPolygon) {
- for (auto& p : ring) {
- if (polygonContainsPoint(polygon, p)) return true;
- }
+ for (auto& p : polygonB) {
+ if (polygonContainsPoint(polygonA, p)) return true;
}
- for (auto& p : polygon) {
- if (multiPolygonContainsPoint(multiPolygon, p)) return true;
- }
+ if (lineIntersectsLine(polygonA, polygonB)) return true;
- for (auto& polygonB : multiPolygon) {
- if (lineIntersectsLine(polygon, polygonB)) return true;
+ return false;
+}
+
+bool polygonIntersectsMultiPolygon(const GeometryCoordinates& polygon, const GeometryCollection& multiPolygon) {
+ for (auto& ring : multiPolygon) {
+ if (polygonIntersectsPolygon(polygon, ring)) return true;
}
return false;
diff --git a/src/mbgl/util/intersection_tests.hpp b/src/mbgl/util/intersection_tests.hpp
index 6adb3b5fdf..5bcb29c767 100644
--- a/src/mbgl/util/intersection_tests.hpp
+++ b/src/mbgl/util/intersection_tests.hpp
@@ -7,6 +7,7 @@ namespace util {
bool polygonIntersectsBufferedMultiPoint(const GeometryCoordinates&, const GeometryCollection&, float radius);
bool polygonIntersectsBufferedMultiLine(const GeometryCoordinates&, const GeometryCollection&, float radius);
+bool polygonIntersectsPolygon(const GeometryCoordinates&, const GeometryCoordinates&);
bool polygonIntersectsMultiPolygon(const GeometryCoordinates&, const GeometryCollection&);
} // namespace util
diff --git a/src/mbgl/util/offscreen_texture.cpp b/src/mbgl/util/offscreen_texture.cpp
index 51049f8282..40bb70b70e 100644
--- a/src/mbgl/util/offscreen_texture.cpp
+++ b/src/mbgl/util/offscreen_texture.cpp
@@ -1,70 +1,48 @@
+#include <mbgl/util/offscreen_texture.hpp>
#include <mbgl/gl/context.hpp>
#include <mbgl/gl/gl.hpp>
-#include <mbgl/util/offscreen_texture.hpp>
+#include <cstring>
#include <cassert>
namespace mbgl {
-void OffscreenTexture::bind(gl::Context& context,
- std::array<uint16_t, 2> size) {
+OffscreenTexture::OffscreenTexture(gl::Context& context_, std::array<uint16_t, 2> size_)
+ : context(context_), size(std::move(size_)) {
assert(size[0] > 0 && size[1] > 0);
+}
- if (!texture || texture->size != size) {
- texture = context.createTexture(size);
- }
-
+void OffscreenTexture::bind() {
if (!framebuffer) {
- framebuffer = context.createFramebuffer();
- context.bindFramebuffer = *framebuffer;
- MBGL_CHECK_ERROR(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
- texture->texture, 0));
-
- GLenum status = MBGL_CHECK_ERROR(glCheckFramebufferStatus(GL_FRAMEBUFFER));
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- switch (status) {
- case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
- throw std::runtime_error("Couldn't create framebuffer: incomplete attachment");
- case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
- throw std::runtime_error(
- "Couldn't create framebuffer: incomplete missing attachment");
-#ifdef GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER
- case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
- throw std::runtime_error("Couldn't create framebuffer: incomplete draw buffer");
-#endif
-#ifdef GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER
- case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
- throw std::runtime_error("Couldn't create framebuffer: incomplete read buffer");
-#endif
-#ifdef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS
- case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
- throw std::runtime_error("Couldn't create framebuffer: incomplete dimensions");
-#endif
-
- case GL_FRAMEBUFFER_UNSUPPORTED:
- throw std::runtime_error("Couldn't create framebuffer: unsupported");
- default:
- throw std::runtime_error("Couldn't create framebuffer: other");
- }
- }
+ texture = context.createTexture(size);
+ framebuffer = context.createFramebuffer(*texture);
} else {
- context.bindFramebuffer = *framebuffer;
+ context.bindFramebuffer = framebuffer->framebuffer;
}
context.viewport = { 0, 0, size[0], size[1] };
}
gl::Texture& OffscreenTexture::getTexture() {
+ assert(texture);
return *texture;
}
-std::array<uint16_t, 2> OffscreenTexture::getSize() const {
- if (texture) {
- // Use explicit dereference instead of -> due to clang 3.5 bug
- return (*texture).size;
- } else {
- return {{ 0, 0 }};
+PremultipliedImage OffscreenTexture::readStillImage() {
+ PremultipliedImage image { size[0], size[1] };
+ MBGL_CHECK_ERROR(glReadPixels(0, 0, size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE, image.data.get()));
+
+ const auto stride = image.stride();
+ auto tmp = std::make_unique<uint8_t[]>(stride);
+ uint8_t* rgba = image.data.get();
+ for (int i = 0, j = size[1] - 1; i < j; i++, j--) {
+ std::memcpy(tmp.get(), rgba + i * stride, stride);
+ std::memcpy(rgba + i * stride, rgba + j * stride, stride);
+ std::memcpy(rgba + j * stride, tmp.get(), stride);
}
+
+ return image;
}
+
} // namespace mbgl
diff --git a/src/mbgl/util/offscreen_texture.hpp b/src/mbgl/util/offscreen_texture.hpp
index c71c0e51d9..8928bc2434 100644
--- a/src/mbgl/util/offscreen_texture.hpp
+++ b/src/mbgl/util/offscreen_texture.hpp
@@ -1,6 +1,10 @@
#pragma once
+#include <mbgl/map/view.hpp>
+#include <mbgl/gl/framebuffer.hpp>
#include <mbgl/gl/texture.hpp>
+#include <mbgl/util/optional.hpp>
+#include <mbgl/util/image.hpp>
namespace mbgl {
@@ -8,15 +12,20 @@ namespace gl {
class Context;
} // namespace gl
-class OffscreenTexture {
+class OffscreenTexture : public View {
public:
- void bind(gl::Context&, std::array<uint16_t, 2> size);
+ OffscreenTexture(gl::Context&, std::array<uint16_t, 2> size = {{ 256, 256 }});
+
+ void bind() override;
+
+ PremultipliedImage readStillImage();
gl::Texture& getTexture();
- std::array<uint16_t, 2> getSize() const;
private:
- optional<gl::UniqueFramebuffer> framebuffer;
+ gl::Context& context;
+ std::array<uint16_t, 2> size;
+ optional<gl::Framebuffer> framebuffer;
optional<gl::Texture> texture;
};
diff --git a/src/mbgl/util/tile_coordinate.hpp b/src/mbgl/util/tile_coordinate.hpp
index 194a62ecef..bcd1c8444f 100644
--- a/src/mbgl/util/tile_coordinate.hpp
+++ b/src/mbgl/util/tile_coordinate.hpp
@@ -5,6 +5,7 @@
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/tile/tile_id.hpp>
#include <mbgl/util/geometry.hpp>
+#include <mbgl/util/projection.hpp>
namespace mbgl {
@@ -17,23 +18,25 @@ public:
TileCoordinatePoint p;
double z;
- static TileCoordinate fromLatLng(const TransformState& state, double zoom, const LatLng& latLng) {
- const double scale = std::pow(2, zoom - state.getZoom());
- return { state.project(latLng) * scale / double(util::tileSize), zoom };
+ static TileCoordinate fromLatLng(double zoom, const LatLng& latLng) {
+ const double scale = std::pow(2.0, zoom);
+ return { Projection::project(latLng, scale) / double(util::tileSize), zoom };
}
static TileCoordinate fromScreenCoordinate(const TransformState& state, double zoom, const ScreenCoordinate& screenCoordinate) {
- return fromLatLng(state, zoom, state.screenCoordinateToLatLng(screenCoordinate));
+ return fromLatLng(zoom, state.screenCoordinateToLatLng(screenCoordinate));
}
TileCoordinate zoomTo(double zoom) const {
- return { p * std::pow(2, zoom - z), zoom };
+ const double scaleDiff = std::pow(2.0, zoom - z);
+ return { p * scaleDiff, zoom };
}
static GeometryCoordinate toGeometryCoordinate(const UnwrappedTileID& tileID, const TileCoordinatePoint& point) {
+ const double scale = std::pow(2.0, tileID.canonical.z);
auto zoomed = TileCoordinate { point, 0 }.zoomTo(tileID.canonical.z);
return {
- int16_t(util::clamp<int64_t>((zoomed.p.x - tileID.canonical.x - tileID.wrap * std::pow(2.0, tileID.canonical.z)) * util::EXTENT,
+ int16_t(util::clamp<int64_t>((zoomed.p.x - tileID.canonical.x - tileID.wrap * scale) * util::EXTENT,
std::numeric_limits<int16_t>::min(),
std::numeric_limits<int16_t>::max())),
int16_t(util::clamp<int64_t>((zoomed.p.y - tileID.canonical.y) * util::EXTENT,
diff --git a/src/mbgl/util/tile_cover.cpp b/src/mbgl/util/tile_cover.cpp
index 5487fb269c..c6bf7d362a 100644
--- a/src/mbgl/util/tile_cover.cpp
+++ b/src/mbgl/util/tile_cover.cpp
@@ -147,13 +147,12 @@ std::vector<UnwrappedTileID> tileCover(const LatLngBounds& bounds_, int32_t z) {
{ std::max(bounds_.south(), -util::LATITUDE_MAX), bounds_.west() },
{ std::min(bounds_.north(), util::LATITUDE_MAX), bounds_.east() });
- const TransformState state;
return tileCover(
- TileCoordinate::fromLatLng(state, z, bounds.northwest()).p,
- TileCoordinate::fromLatLng(state, z, bounds.northeast()).p,
- TileCoordinate::fromLatLng(state, z, bounds.southeast()).p,
- TileCoordinate::fromLatLng(state, z, bounds.southwest()).p,
- TileCoordinate::fromLatLng(state, z, bounds.center()).p,
+ TileCoordinate::fromLatLng(z, bounds.northwest()).p,
+ TileCoordinate::fromLatLng(z, bounds.northeast()).p,
+ TileCoordinate::fromLatLng(z, bounds.southeast()).p,
+ TileCoordinate::fromLatLng(z, bounds.southwest()).p,
+ TileCoordinate::fromLatLng(z, bounds.center()).p,
z);
}
diff --git a/test/actor/actor.test.cpp b/test/actor/actor.test.cpp
index 7bb76784d6..c24d0b6c25 100644
--- a/test/actor/actor.test.cpp
+++ b/test/actor/actor.test.cpp
@@ -1,5 +1,5 @@
#include <mbgl/actor/actor.hpp>
-#include <mbgl/actor/thread_pool.hpp>
+#include <mbgl/platform/default/thread_pool.hpp>
#include <mbgl/test/util.hpp>
diff --git a/test/actor/actor_ref.test.cpp b/test/actor/actor_ref.test.cpp
index 655529035f..4be714278e 100644
--- a/test/actor/actor_ref.test.cpp
+++ b/test/actor/actor_ref.test.cpp
@@ -1,5 +1,5 @@
#include <mbgl/actor/actor.hpp>
-#include <mbgl/actor/thread_pool.hpp>
+#include <mbgl/platform/default/thread_pool.hpp>
#include <mbgl/test/util.hpp>
diff --git a/test/api/annotations.test.cpp b/test/api/annotations.test.cpp
index dc4b00170a..2c875796bd 100644
--- a/test/api/annotations.test.cpp
+++ b/test/api/annotations.test.cpp
@@ -1,11 +1,12 @@
#include <mbgl/test/util.hpp>
#include <mbgl/test/stub_file_source.hpp>
+#include <mbgl/platform/default/thread_pool.hpp>
#include <mbgl/annotation/annotation.hpp>
#include <mbgl/sprite/sprite_image.hpp>
#include <mbgl/map/map.hpp>
-#include <mbgl/platform/default/headless_display.hpp>
-#include <mbgl/platform/default/headless_view.hpp>
+#include <mbgl/platform/default/headless_backend.hpp>
+#include <mbgl/platform/default/offscreen_view.hpp>
#include <mbgl/util/io.hpp>
#include <mbgl/util/run_loop.hpp>
#include <mbgl/util/color.hpp>
@@ -22,14 +23,15 @@ std::shared_ptr<SpriteImage> namedMarker(const std::string &name) {
class AnnotationTest {
public:
util::RunLoop loop;
- std::shared_ptr<HeadlessDisplay> display { std::make_shared<HeadlessDisplay>() };
- HeadlessView view { display, 1 };
+ HeadlessBackend backend;
+ OffscreenView view{ backend.getContext() };
StubFileSource fileSource;
- Map map { view, fileSource, MapMode::Still };
+ ThreadPool threadPool { 4 };
+ Map map { backend, view.getSize(), 1, fileSource, threadPool, MapMode::Still };
void checkRendering(const char * name) {
test::checkImage(std::string("test/fixtures/annotations/") + name,
- test::render(map), 0.0002, 0.1);
+ test::render(map, view), 0.0002, 0.1);
}
};
@@ -49,10 +51,7 @@ TEST(Annotations, SymbolAnnotation) {
EXPECT_EQ(features.size(), 1u);
test.map.setZoom(test.map.getMaxZoom());
- // FIXME: https://github.com/mapbox/mapbox-gl-native/issues/5419
- //test.map.setZoom(test.map.getMaxZoom());
- //test.checkRendering("point_annotation");
- test::render(test.map);
+ test.checkRendering("point_annotation");
features = test.map.queryPointAnnotations(screenBox);
EXPECT_EQ(features.size(), 1u);
@@ -163,7 +162,7 @@ TEST(Annotations, AddMultiple) {
test.map.addAnnotationIcon("default_marker", namedMarker("default_marker.png"));
test.map.addAnnotation(SymbolAnnotation { Point<double> { -10, 0 }, "default_marker" });
- test::render(test.map);
+ test::render(test.map, test.view);
test.map.addAnnotation(SymbolAnnotation { Point<double> { 10, 0 }, "default_marker" });
test.checkRendering("add_multiple");
@@ -173,7 +172,7 @@ TEST(Annotations, NonImmediateAdd) {
AnnotationTest test;
test.map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
- test::render(test.map);
+ test::render(test.map, test.view);
Polygon<double> polygon = {{ {{ { 0, 0 }, { 0, 45 }, { 45, 45 }, { 45, 0 } }} }};
FillAnnotation annotation { polygon };
@@ -191,7 +190,7 @@ TEST(Annotations, UpdateSymbolAnnotationGeometry) {
test.map.addAnnotationIcon("flipped_marker", namedMarker("flipped_marker.png"));
AnnotationID point = test.map.addAnnotation(SymbolAnnotation { Point<double> { 0, 0 }, "default_marker" });
- test::render(test.map);
+ test::render(test.map, test.view);
test.map.updateAnnotation(point, SymbolAnnotation { Point<double> { -10, 0 }, "default_marker" });
test.checkRendering("update_point");
@@ -205,7 +204,7 @@ TEST(Annotations, UpdateSymbolAnnotationIcon) {
test.map.addAnnotationIcon("flipped_marker", namedMarker("flipped_marker.png"));
AnnotationID point = test.map.addAnnotation(SymbolAnnotation { Point<double> { 0, 0 }, "default_marker" });
- test::render(test.map);
+ test::render(test.map, test.view);
test.map.updateAnnotation(point, SymbolAnnotation { Point<double> { 0, 0 }, "flipped_marker" });
test.checkRendering("update_icon");
@@ -221,7 +220,7 @@ TEST(Annotations, UpdateLineAnnotationGeometry) {
test.map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
AnnotationID line = test.map.addAnnotation(annotation);
- test::render(test.map);
+ test::render(test.map, test.view);
annotation.geometry = LineString<double> {{ { 0, 0 }, { -45, -45 } }};
test.map.updateAnnotation(line, annotation);
@@ -238,7 +237,7 @@ TEST(Annotations, UpdateLineAnnotationStyle) {
test.map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
AnnotationID line = test.map.addAnnotation(annotation);
- test::render(test.map);
+ test::render(test.map, test.view);
annotation.color = { { 0, 255, 0, 1 } };
annotation.width = { 2 };
@@ -255,7 +254,7 @@ TEST(Annotations, UpdateFillAnnotationGeometry) {
test.map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
AnnotationID fill = test.map.addAnnotation(annotation);
- test::render(test.map);
+ test::render(test.map, test.view);
annotation.geometry = Polygon<double> {{ {{ { 0, 0 }, { 0, 45 }, { 45, 0 } }} }};
test.map.updateAnnotation(fill, annotation);
@@ -272,7 +271,7 @@ TEST(Annotations, UpdateFillAnnotationStyle) {
test.map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
AnnotationID fill = test.map.addAnnotation(annotation);
- test::render(test.map);
+ test::render(test.map, test.view);
annotation.color = { { 0, 255, 0, 1 } };
test.map.updateAnnotation(fill, annotation);
@@ -286,7 +285,7 @@ TEST(Annotations, RemovePoint) {
test.map.addAnnotationIcon("default_marker", namedMarker("default_marker.png"));
AnnotationID point = test.map.addAnnotation(SymbolAnnotation { Point<double> { 0, 0 }, "default_marker" });
- test::render(test.map);
+ test::render(test.map, test.view);
test.map.removeAnnotation(point);
test.checkRendering("remove_point");
@@ -303,7 +302,7 @@ TEST(Annotations, RemoveShape) {
test.map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
AnnotationID shape = test.map.addAnnotation(annotation);
- test::render(test.map);
+ test::render(test.map, test.view);
test.map.removeAnnotation(shape);
test.checkRendering("remove_shape");
@@ -315,7 +314,7 @@ TEST(Annotations, ImmediateRemoveShape) {
test.map.removeAnnotation(test.map.addAnnotation(LineAnnotation { LineString<double>() }));
test.map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
- test::render(test.map);
+ test::render(test.map, test.view);
}
TEST(Annotations, SwitchStyle) {
@@ -325,7 +324,7 @@ TEST(Annotations, SwitchStyle) {
test.map.addAnnotationIcon("default_marker", namedMarker("default_marker.png"));
test.map.addAnnotation(SymbolAnnotation { Point<double> { 0, 0 }, "default_marker" });
- test::render(test.map);
+ test::render(test.map, test.view);
test.map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
test.checkRendering("switch_style");
@@ -339,7 +338,7 @@ TEST(Annotations, QueryRenderedFeatures) {
test.map.addAnnotation(SymbolAnnotation { Point<double> { 0, 0 }, "default_marker" });
test.map.addAnnotation(SymbolAnnotation { Point<double> { 0, 50 }, "default_marker" });
- test::render(test.map);
+ test::render(test.map, test.view);
auto features = test.map.queryRenderedFeatures(test.map.pixelForLatLng({ 0, 0 }));
EXPECT_EQ(features.size(), 1u);
@@ -369,10 +368,17 @@ TEST(Annotations, QueryFractionalZoomLevels) {
}
test.map.setLatLngZoom({ 5, 5 }, 0);
- for (uint16_t zoomSteps = 0; zoomSteps <= 20; ++zoomSteps) {
+ for (uint16_t zoomSteps = 10; zoomSteps <= 20; ++zoomSteps) {
test.map.setZoom(zoomSteps / 10.0);
- test::render(test.map);
+ test::render(test.map, test.view);
auto features = test.map.queryRenderedFeatures(box);
+
+ // Filter out repeated features.
+ // See 'edge-cases/null-island' query-test for reference.
+ auto sortID = [](const Feature& lhs, const Feature& rhs) { return lhs.id < rhs.id; };
+ auto sameID = [](const Feature& lhs, const Feature& rhs) { return lhs.id == rhs.id; };
+ std::sort(features.begin(), features.end(), sortID);
+ features.erase(std::unique(features.begin(), features.end(), sameID), features.end());
EXPECT_EQ(features.size(), ids.size());
}
}
@@ -385,26 +391,31 @@ TEST(Annotations, VisibleFeatures) {
test.map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
test.map.addAnnotationIcon("default_marker", namedMarker("default_marker.png"));
- test.map.setZoom(3);
+ test.map.setLatLngZoom({ 5, 5 }, 3);
std::vector<mbgl::AnnotationID> ids;
- for (int longitude = -5; longitude <= 5; ++longitude) {
- for (int latitude = -5; latitude <= 5; ++latitude) {
+ for (int longitude = 0; longitude < 10; ++longitude) {
+ for (int latitude = 0; latitude <= 10; ++latitude) {
ids.push_back(test.map.addAnnotation(SymbolAnnotation { { double(latitude), double(longitude) }, "default_marker" }));
}
}
- // Change bearing *after* adding annotations cause them to be reordered,
- // and some annotations become occluded by others.
+ // Change bearing *after* adding annotations causes them to be reordered.
test.map.setBearing(45);
- test::render(test.map);
+ test::render(test.map, test.view);
auto features = test.map.queryRenderedFeatures(box);
+ auto sortID = [](const Feature& lhs, const Feature& rhs) { return lhs.id < rhs.id; };
+ auto sameID = [](const Feature& lhs, const Feature& rhs) { return lhs.id == rhs.id; };
+ std::sort(features.begin(), features.end(), sortID);
+ features.erase(std::unique(features.begin(), features.end(), sameID), features.end());
EXPECT_EQ(features.size(), ids.size());
test.map.setBearing(0);
test.map.setZoom(4);
- test::render(test.map);
+ test::render(test.map, test.view);
features = test.map.queryRenderedFeatures(box);
+ std::sort(features.begin(), features.end(), sortID);
+ features.erase(std::unique(features.begin(), features.end(), sameID), features.end());
EXPECT_EQ(features.size(), ids.size());
}
diff --git a/test/api/api_misuse.test.cpp b/test/api/api_misuse.test.cpp
index e9fe307718..eb271b0258 100644
--- a/test/api/api_misuse.test.cpp
+++ b/test/api/api_misuse.test.cpp
@@ -3,8 +3,10 @@
#include <mbgl/test/fixture_log_observer.hpp>
#include <mbgl/map/map.hpp>
-#include <mbgl/platform/default/headless_display.hpp>
+#include <mbgl/platform/default/headless_backend.hpp>
+#include <mbgl/platform/default/offscreen_view.hpp>
#include <mbgl/storage/online_file_source.hpp>
+#include <mbgl/platform/default/thread_pool.hpp>
#include <mbgl/util/exception.hpp>
#include <mbgl/util/run_loop.hpp>
@@ -18,13 +20,14 @@ TEST(API, RenderWithoutCallback) {
util::RunLoop loop;
- auto display = std::make_shared<mbgl::HeadlessDisplay>();
- HeadlessView view(display, 1);
- view.resize(128, 512);
+ HeadlessBackend backend;
+ OffscreenView view(backend.getContext(), {{ 128, 512 }});
StubFileSource fileSource;
+ ThreadPool threadPool(4);
- std::unique_ptr<Map> map = std::make_unique<Map>(view, fileSource, MapMode::Still);
- map->renderStill(nullptr);
+ std::unique_ptr<Map> map =
+ std::make_unique<Map>(backend, view.getSize(), 1, fileSource, threadPool, MapMode::Still);
+ map->renderStill(view, nullptr);
// Force Map thread to join.
map.reset();
@@ -42,15 +45,15 @@ TEST(API, RenderWithoutCallback) {
TEST(API, RenderWithoutStyle) {
util::RunLoop loop;
- auto display = std::make_shared<mbgl::HeadlessDisplay>();
- HeadlessView view(display, 1);
- view.resize(128, 512);
+ HeadlessBackend backend;
+ OffscreenView view(backend.getContext(), {{ 128, 512 }});
StubFileSource fileSource;
+ ThreadPool threadPool(4);
- Map map(view, fileSource, MapMode::Still);
+ Map map(backend, view.getSize(), 1, fileSource, threadPool, MapMode::Still);
std::exception_ptr error;
- map.renderStill([&](std::exception_ptr error_, PremultipliedImage&&) {
+ map.renderStill(view, [&](std::exception_ptr error_) {
error = error_;
loop.stop();
});
diff --git a/test/api/custom_layer.test.cpp b/test/api/custom_layer.test.cpp
index 2dded19256..70de102b80 100644
--- a/test/api/custom_layer.test.cpp
+++ b/test/api/custom_layer.test.cpp
@@ -2,8 +2,9 @@
#include <mbgl/gl/gl.hpp>
#include <mbgl/map/map.hpp>
-#include <mbgl/platform/default/headless_display.hpp>
-#include <mbgl/platform/default/headless_view.hpp>
+#include <mbgl/platform/default/headless_backend.hpp>
+#include <mbgl/platform/default/offscreen_view.hpp>
+#include <mbgl/platform/default/thread_pool.hpp>
#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/style/layers/custom_layer.hpp>
#include <mbgl/style/layers/fill_layer.hpp>
@@ -84,8 +85,8 @@ public:
TEST(CustomLayer, Basic) {
util::RunLoop loop;
- auto display = std::make_shared<mbgl::HeadlessDisplay>();
- HeadlessView view(display, 1);
+ HeadlessBackend backend;
+ OffscreenView view(backend.getContext());
#ifdef MBGL_ASSET_ZIP
// Regenerate with `cd test/fixtures/api/ && zip -r assets.zip assets/`
@@ -94,7 +95,9 @@ TEST(CustomLayer, Basic) {
DefaultFileSource fileSource(":memory:", "test/fixtures/api/assets");
#endif
- Map map(view, fileSource, MapMode::Still);
+ ThreadPool threadPool(4);
+
+ Map map(backend, view.getSize(), 1, fileSource, threadPool, MapMode::Still);
map.setStyleJSON(util::read_file("test/fixtures/api/water.json"));
map.setLatLngZoom({ 37.8, -122.5 }, 10);
map.addLayer(std::make_unique<CustomLayer>(
@@ -114,5 +117,5 @@ TEST(CustomLayer, Basic) {
layer->setFillColor(Color{ 1.0, 1.0, 0.0, 1.0 });
map.addLayer(std::move(layer));
- test::checkImage("test/fixtures/custom_layer/basic", test::render(map), 0.0006, 0.1);
+ test::checkImage("test/fixtures/custom_layer/basic", test::render(map, view), 0.0006, 0.1);
}
diff --git a/test/api/query.test.cpp b/test/api/query.test.cpp
index 7da0f4311c..8e59c19afc 100644
--- a/test/api/query.test.cpp
+++ b/test/api/query.test.cpp
@@ -1,6 +1,7 @@
#include <mbgl/map/map.hpp>
-#include <mbgl/platform/default/headless_display.hpp>
-#include <mbgl/platform/default/headless_view.hpp>
+#include <mbgl/platform/default/headless_backend.hpp>
+#include <mbgl/platform/default/offscreen_view.hpp>
+#include <mbgl/platform/default/thread_pool.hpp>
#include <mbgl/sprite/sprite_image.hpp>
#include <mbgl/test/stub_file_source.hpp>
#include <mbgl/test/util.hpp>
@@ -21,14 +22,15 @@ public:
map.setStyleJSON(util::read_file("test/fixtures/api/query_style.json"));
map.addImage("test-icon", std::move(image));
- test::render(map);
+ test::render(map, view);
}
util::RunLoop loop;
- std::shared_ptr<HeadlessDisplay> display { std::make_shared<HeadlessDisplay>() };
- HeadlessView view { display, 1 };
+ HeadlessBackend backend;
+ OffscreenView view { backend.getContext() };
StubFileSource fileSource;
- Map map { view, fileSource, MapMode::Still };
+ ThreadPool threadPool { 4 };
+ Map map { backend, view.getSize(), 1, fileSource, threadPool, MapMode::Still };
};
} // end namespace
diff --git a/test/api/render_missing.test.cpp b/test/api/render_missing.test.cpp
index 024ebd3729..366d71e67d 100644
--- a/test/api/render_missing.test.cpp
+++ b/test/api/render_missing.test.cpp
@@ -2,8 +2,9 @@
#include <mbgl/test/fixture_log_observer.hpp>
#include <mbgl/map/map.hpp>
-#include <mbgl/platform/default/headless_view.hpp>
-#include <mbgl/platform/default/headless_display.hpp>
+#include <mbgl/platform/default/headless_backend.hpp>
+#include <mbgl/platform/default/offscreen_view.hpp>
+#include <mbgl/platform/default/thread_pool.hpp>
#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/util/image.hpp>
#include <mbgl/util/io.hpp>
@@ -24,8 +25,8 @@ TEST(API, TEST_REQUIRES_SERVER(RenderMissingTile)) {
const auto style = util::read_file("test/fixtures/api/water_missing_tiles.json");
- auto display = std::make_shared<mbgl::HeadlessDisplay>();
- HeadlessView view(display, 1, 256, 512);
+ HeadlessBackend backend;
+ OffscreenView view(backend.getContext(), {{ 256, 512 }});
#ifdef MBGL_ASSET_ZIP
// Regenerate with `cd test/fixtures/api/ && zip -r assets.zip assets/`
DefaultFileSource fileSource(":memory:", "test/fixtures/api/assets.zip");
@@ -33,16 +34,18 @@ TEST(API, TEST_REQUIRES_SERVER(RenderMissingTile)) {
DefaultFileSource fileSource(":memory:", "test/fixtures/api/assets");
#endif
+ ThreadPool threadPool(4);
+
Log::setObserver(std::make_unique<FixtureLogObserver>());
- Map map(view, fileSource, MapMode::Still);
+ Map map(backend, view.getSize(), 1, fileSource, threadPool, MapMode::Still);
std::string message;
// This host does not respond (== connection error).
// Are you seeing this test fail? Make sure you don't have a server running on port 3001!
map.setStyleJSON(style);
- map.renderStill([&](std::exception_ptr err, PremultipliedImage&&) {
+ map.renderStill(view, [&](std::exception_ptr err) {
ASSERT_TRUE(err.operator bool());
try {
std::rethrow_exception(err);
diff --git a/test/api/repeated_render.test.cpp b/test/api/repeated_render.test.cpp
index cf71cb8416..715b49b289 100644
--- a/test/api/repeated_render.test.cpp
+++ b/test/api/repeated_render.test.cpp
@@ -2,8 +2,9 @@
#include <mbgl/test/fixture_log_observer.hpp>
#include <mbgl/map/map.hpp>
-#include <mbgl/platform/default/headless_view.hpp>
-#include <mbgl/platform/default/headless_display.hpp>
+#include <mbgl/platform/default/headless_backend.hpp>
+#include <mbgl/platform/default/offscreen_view.hpp>
+#include <mbgl/platform/default/thread_pool.hpp>
#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/util/image.hpp>
#include <mbgl/util/io.hpp>
@@ -18,8 +19,8 @@ TEST(API, RepeatedRender) {
const auto style = util::read_file("test/fixtures/api/water.json");
- auto display = std::make_shared<mbgl::HeadlessDisplay>();
- HeadlessView view(display, 1, 256, 512);
+ HeadlessBackend backend;
+ OffscreenView view(backend.getContext(), {{ 256, 512 }});
#ifdef MBGL_ASSET_ZIP
// Regenerate with `cd test/fixtures/api/ && zip -r assets.zip assets/`
DefaultFileSource fileSource(":memory:", "test/fixtures/api/assets.zip");
@@ -27,15 +28,17 @@ TEST(API, RepeatedRender) {
DefaultFileSource fileSource(":memory:", "test/fixtures/api/assets");
#endif
+ ThreadPool threadPool(4);
+
Log::setObserver(std::make_unique<FixtureLogObserver>());
- Map map(view, fileSource, MapMode::Still);
+ Map map(backend, view.getSize(), 1, fileSource, threadPool, MapMode::Still);
{
map.setStyleJSON(style);
PremultipliedImage result;
- map.renderStill([&result](std::exception_ptr, PremultipliedImage&& image) {
- result = std::move(image);
+ map.renderStill(view, [&](std::exception_ptr) {
+ result = view.readStillImage();
});
while (!result.size()) {
@@ -52,8 +55,8 @@ TEST(API, RepeatedRender) {
{
map.setStyleJSON(style);
PremultipliedImage result;
- map.renderStill([&result](std::exception_ptr, PremultipliedImage&& image) {
- result = std::move(image);
+ map.renderStill(view, [&](std::exception_ptr) {
+ result = view.readStillImage();
});
while (!result.size()) {
diff --git a/test/gl/object.test.cpp b/test/gl/object.test.cpp
index 1a90cec83b..a3457d28c6 100644
--- a/test/gl/object.test.cpp
+++ b/test/gl/object.test.cpp
@@ -1,7 +1,7 @@
#include <mbgl/test/util.hpp>
-#include <mbgl/platform/default/headless_display.hpp>
-#include <mbgl/platform/default/headless_view.hpp>
+#include <mbgl/platform/default/headless_backend.hpp>
+#include <mbgl/platform/default/offscreen_view.hpp>
#include <mbgl/gl/gl.hpp>
#include <mbgl/gl/context.hpp>
@@ -43,11 +43,8 @@ TEST(GLObject, Value) {
auto object = std::make_unique<mbgl::gl::State<MockGLObject>>();
EXPECT_EQ(object->getCurrentValue(), false);
- EXPECT_FALSE(object->isDirty());
- EXPECT_FALSE(setFlag);
-
- object->setDirty();
EXPECT_TRUE(object->isDirty());
+ EXPECT_FALSE(setFlag);
*object = false;
EXPECT_EQ(object->getCurrentValue(), false);
@@ -59,16 +56,11 @@ TEST(GLObject, Value) {
EXPECT_EQ(object->getCurrentValue(), true);
EXPECT_FALSE(object->isDirty());
EXPECT_TRUE(setFlag);
-
- object->reset();
- EXPECT_EQ(object->getCurrentValue(), false);
- EXPECT_FALSE(object->isDirty());
- EXPECT_TRUE(setFlag);
}
TEST(GLObject, Store) {
- mbgl::HeadlessView view(std::make_shared<mbgl::HeadlessDisplay>(), 1);
- view.activate();
+ mbgl::HeadlessBackend backend;
+ mbgl::OffscreenView view(backend.getContext());
mbgl::gl::Context context;
EXPECT_TRUE(context.empty());
@@ -106,5 +98,5 @@ TEST(GLObject, Store) {
context.reset();
EXPECT_TRUE(context.empty());
- view.deactivate();
+ backend.deactivate();
}
diff --git a/test/map/map.test.cpp b/test/map/map.test.cpp
index 5b66d9b753..97a09e94a0 100644
--- a/test/map/map.test.cpp
+++ b/test/map/map.test.cpp
@@ -4,8 +4,9 @@
#include <mbgl/test/fixture_log_observer.hpp>
#include <mbgl/map/map.hpp>
-#include <mbgl/platform/default/headless_view.hpp>
-#include <mbgl/platform/default/headless_display.hpp>
+#include <mbgl/platform/default/headless_backend.hpp>
+#include <mbgl/platform/default/offscreen_view.hpp>
+#include <mbgl/platform/default/thread_pool.hpp>
#include <mbgl/sprite/sprite_image.hpp>
#include <mbgl/storage/network_status.hpp>
#include <mbgl/storage/default_file_source.hpp>
@@ -21,14 +22,15 @@ using namespace std::literals::string_literals;
struct MapTest {
util::RunLoop runLoop;
- std::shared_ptr<HeadlessDisplay> display { std::make_shared<mbgl::HeadlessDisplay>() };
- HeadlessView view { display, 1 };
+ HeadlessBackend backend;
+ OffscreenView view { backend.getContext() };
StubFileSource fileSource;
+ ThreadPool threadPool { 4 };
};
TEST(Map, LatLngBehavior) {
MapTest test;
- Map map(test.view, test.fileSource, MapMode::Still);
+ Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still);
map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
@@ -62,11 +64,11 @@ TEST(Map, Offline) {
fileSource.put(Resource::glyphs(prefix + "{fontstack}/{range}.pbf", {{"Helvetica"}}, {0, 255}), expiredItem("glyph.pbf"));
NetworkStatus::Set(NetworkStatus::Status::Offline);
- Map map(test.view, fileSource, MapMode::Still);
+ Map map(test.backend, test.view.getSize(), 1, fileSource, test.threadPool, MapMode::Still);
map.setStyleURL(prefix + "style.json");
test::checkImage("test/fixtures/map/offline",
- test::render(map),
+ test::render(map, test.view),
0.0015,
0.1);
@@ -79,14 +81,15 @@ TEST(Map, SetStyleInvalidJSON) {
Log::setObserver(std::make_unique<FixtureLogObserver>());
bool fail = false;
- test.view.setMapChangeCallback([&](MapChange change) {
+ test.backend.setMapChangeCallback([&](MapChange change) {
if (change == mbgl::MapChangeDidFailLoadingMap) {
fail = true;
}
});
{
- Map map(test.view, test.fileSource, MapMode::Still);
+ Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool,
+ MapMode::Still);
map.setStyleJSON("invalid");
}
@@ -111,13 +114,13 @@ TEST(Map, SetStyleInvalidURL) {
return response;
};
- test.view.setMapChangeCallback([&](MapChange change) {
+ test.backend.setMapChangeCallback([&](MapChange change) {
if (change == mbgl::MapChangeDidFailLoadingMap) {
test.runLoop.stop();
}
});
- Map map(test.view, test.fileSource, MapMode::Still);
+ Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still);
map.setStyleURL("mapbox://bar");
test.runLoop.run();
@@ -126,7 +129,7 @@ TEST(Map, SetStyleInvalidURL) {
TEST(Map, DoubleStyleLoad) {
MapTest test;
- Map map(test.view, test.fileSource, MapMode::Still);
+ Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still);
map.setStyleJSON("");
map.setStyleJSON("");
}
@@ -137,7 +140,7 @@ TEST(Map, StyleFresh) {
MapTest test;
FakeFileSource fileSource;
- Map map(test.view, fileSource, MapMode::Still);
+ Map map(test.backend, test.view.getSize(), 1, fileSource, test.threadPool, MapMode::Still);
map.setStyleURL("mapbox://styles/test");
EXPECT_EQ(1u, fileSource.requests.size());
@@ -157,7 +160,7 @@ TEST(Map, StyleExpired) {
MapTest test;
FakeFileSource fileSource;
- Map map(test.view, fileSource, MapMode::Still);
+ Map map(test.backend, test.view.getSize(), 1, fileSource, test.threadPool, MapMode::Still);
map.setStyleURL("mapbox://styles/test");
EXPECT_EQ(1u, fileSource.requests.size());
@@ -184,7 +187,7 @@ TEST(Map, StyleExpiredWithAnnotations) {
MapTest test;
FakeFileSource fileSource;
- Map map(test.view, fileSource, MapMode::Still);
+ Map map(test.backend, test.view.getSize(), 1, fileSource, test.threadPool, MapMode::Still);
map.setStyleURL("mapbox://styles/test");
EXPECT_EQ(1u, fileSource.requests.size());
@@ -208,7 +211,7 @@ TEST(Map, StyleEarlyMutation) {
MapTest test;
FakeFileSource fileSource;
- Map map(test.view, fileSource, MapMode::Still);
+ Map map(test.backend, test.view.getSize(), 1, fileSource, test.threadPool, MapMode::Still);
map.setStyleURL("mapbox://styles/test");
map.addLayer(std::make_unique<style::BackgroundLayer>("bg"));
@@ -222,11 +225,11 @@ TEST(Map, StyleEarlyMutation) {
TEST(Map, StyleLoadedSignal) {
MapTest test;
- Map map(test.view, test.fileSource, MapMode::Still);
-
+ Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still);
+
// The map should emit a signal on style loaded
bool emitted = false;
- test.view.setMapChangeCallback([&](MapChange change) {
+ test.backend.setMapChangeCallback([&](MapChange change) {
if (change == mbgl::MapChangeDidFinishLoadingStyle) {
emitted = true;
}
@@ -243,20 +246,20 @@ TEST(Map, StyleLoadedSignal) {
TEST(Map, AddLayer) {
MapTest test;
- Map map(test.view, test.fileSource, MapMode::Still);
+ Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still);
map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
auto layer = std::make_unique<BackgroundLayer>("background");
- layer->setBackgroundColor({{ 1, 0, 0, 1 }});
+ layer->setBackgroundColor({ { 1, 0, 0, 1 } });
map.addLayer(std::move(layer));
- test::checkImage("test/fixtures/map/add_layer", test::render(map));
+ test::checkImage("test/fixtures/map/add_layer", test::render(map, test.view));
}
TEST(Map, RemoveLayer) {
MapTest test;
- Map map(test.view, test.fileSource, MapMode::Still);
+ Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still);
map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
auto layer = std::make_unique<BackgroundLayer>("background");
@@ -264,7 +267,7 @@ TEST(Map, RemoveLayer) {
map.addLayer(std::move(layer));
map.removeLayer("background");
- test::checkImage("test/fixtures/map/remove_layer", test::render(map));
+ test::checkImage("test/fixtures/map/remove_layer", test::render(map, test.view));
}
TEST(Map, DisabledSources) {
@@ -281,7 +284,7 @@ TEST(Map, DisabledSources) {
return {};
};
- Map map(test.view, test.fileSource, MapMode::Still);
+ Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still);
map.setZoom(1);
// This stylesheet has two raster layers, one that starts at zoom 1, the other at zoom 0.
@@ -323,15 +326,15 @@ TEST(Map, DisabledSources) {
}
)STYLE");
- test::checkImage("test/fixtures/map/disabled_layers/first", test::render(map));
+ test::checkImage("test/fixtures/map/disabled_layers/first", test::render(map, test.view));
map.setZoom(0.5);
- test::checkImage("test/fixtures/map/disabled_layers/second", test::render(map));
+ test::checkImage("test/fixtures/map/disabled_layers/second", test::render(map, test.view));
}
TEST(Map, Classes) {
MapTest test;
- Map map(test.view, test.fileSource, MapMode::Still);
+ Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still);
map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
EXPECT_FALSE(map.getTransitionOptions().duration);
@@ -365,7 +368,7 @@ TEST(Map, Classes) {
TEST(Map, AddImage) {
MapTest test;
- Map map(test.view, test.fileSource, MapMode::Still);
+ Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still);
auto decoded1 = decodeImage(util::read_file("test/fixtures/sprites/default_marker.png"));
auto decoded2 = decodeImage(util::read_file("test/fixtures/sprites/default_marker.png"));
auto image1 = std::make_unique<SpriteImage>(std::move(decoded1), 1.0);
@@ -376,19 +379,18 @@ TEST(Map, AddImage) {
map.setStyleJSON(util::read_file("test/fixtures/api/icon_style.json"));
map.addImage("test-icon", std::move(image2));
- test::checkImage("test/fixtures/map/add_icon", test::render(map));
+ test::checkImage("test/fixtures/map/add_icon", test::render(map, test.view));
}
TEST(Map, RemoveImage) {
MapTest test;
- Map map(test.view, test.fileSource, MapMode::Still);
+ Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still);
auto decoded = decodeImage(util::read_file("test/fixtures/sprites/default_marker.png"));
auto image = std::make_unique<SpriteImage>(std::move(decoded), 1.0);
map.setStyleJSON(util::read_file("test/fixtures/api/icon_style.json"));
map.addImage("test-icon", std::move(image));
map.removeImage("test-icon");
- test::checkImage("test/fixtures/map/remove_icon", test::render(map));
+ test::checkImage("test/fixtures/map/remove_icon", test::render(map, test.view));
}
-
diff --git a/test/src/mbgl/test/stub_style_observer.hpp b/test/src/mbgl/test/stub_style_observer.hpp
index 7189fd8af4..95280565ff 100644
--- a/test/src/mbgl/test/stub_style_observer.hpp
+++ b/test/src/mbgl/test/stub_style_observer.hpp
@@ -38,6 +38,10 @@ public:
if (sourceError) sourceError(source, error);
}
+ void onSourceDescriptionChanged(Source& source) override {
+ if (sourceDescriptionChanged) sourceDescriptionChanged(source);
+ }
+
void onTileChanged(Source& source, const OverscaledTileID& tileID) override {
if (tileChanged) tileChanged(source, tileID);
};
@@ -58,6 +62,7 @@ public:
std::function<void (Source&)> sourceLoaded;
std::function<void (Source&, std::string)> sourceAttributionChanged;
std::function<void (Source&, std::exception_ptr)> sourceError;
+ std::function<void (Source&)> sourceDescriptionChanged;
std::function<void (Source&, const OverscaledTileID&)> tileChanged;
std::function<void (Source&, const OverscaledTileID&, std::exception_ptr)> tileError;
std::function<void (std::exception_ptr)> resourceError;
diff --git a/test/src/mbgl/test/util.cpp b/test/src/mbgl/test/util.cpp
index a674eafeb4..7f98c43dc9 100644
--- a/test/src/mbgl/test/util.cpp
+++ b/test/src/mbgl/test/util.cpp
@@ -1,6 +1,7 @@
#include <mbgl/test/util.hpp>
#include <mbgl/map/map.hpp>
+#include <mbgl/platform/default/offscreen_view.hpp>
#include <mbgl/platform/log.hpp>
#include <mbgl/util/image.hpp>
#include <mbgl/util/io.hpp>
@@ -97,10 +98,10 @@ Server::~Server() {
}
}
-PremultipliedImage render(Map& map) {
+PremultipliedImage render(Map& map, OffscreenView& view) {
PremultipliedImage result;
- map.renderStill([&result](std::exception_ptr, PremultipliedImage&& image) {
- result = std::move(image);
+ map.renderStill(view, [&](std::exception_ptr) {
+ result = view.readStillImage();
});
while (!result.size()) {
diff --git a/test/src/mbgl/test/util.hpp b/test/src/mbgl/test/util.hpp
index ce0069131c..b8ecf175aa 100644
--- a/test/src/mbgl/test/util.hpp
+++ b/test/src/mbgl/test/util.hpp
@@ -52,6 +52,7 @@
namespace mbgl {
class Map;
+class OffscreenView;
namespace test {
@@ -64,7 +65,7 @@ private:
int fd = -1;
};
-PremultipliedImage render(Map&);
+PremultipliedImage render(Map&, OffscreenView&);
void checkImage(const std::string& base,
const PremultipliedImage& actual,
diff --git a/test/style/source.test.cpp b/test/style/source.test.cpp
index 859aa82893..73908a144b 100644
--- a/test/style/source.test.cpp
+++ b/test/style/source.test.cpp
@@ -11,7 +11,7 @@
#include <mbgl/util/string.hpp>
#include <mbgl/util/io.hpp>
#include <mbgl/util/tileset.hpp>
-#include <mbgl/actor/thread_pool.hpp>
+#include <mbgl/platform/default/thread_pool.hpp>
#include <mbgl/platform/log.hpp>
#include <mbgl/map/transform.hpp>
@@ -381,3 +381,37 @@ TEST(Source, RasterTileAttribution) {
test.run();
}
+
+TEST(Source, GeoJSonSourceUrlUpdate) {
+ SourceTest test;
+
+ test.fileSource.sourceResponse = [&] (const Resource& resource) {
+ EXPECT_EQ("url", resource.url);
+ Response response;
+ response.data = std::make_unique<std::string>("{\"geometry\": {\"type\": \"Point\", \"coordinates\": [1.1, 1.1]}, \"type\": \"Feature\", \"properties\": {}}");
+ return response;
+ };
+
+ test.observer.sourceDescriptionChanged = [&] (Source&) {
+ //Should be called (test will hang if it doesn't)
+ test.end();
+ };
+
+ test.observer.tileError = [&] (Source&, const OverscaledTileID&, std::exception_ptr) {
+ FAIL() << "Should never be called";
+ };
+
+ GeoJSONSource source("source");
+ source.baseImpl->setObserver(&test.observer);
+
+ //Load initial, so the source state will be loaded=true
+ source.baseImpl->loadDescription(test.fileSource);
+
+ //Schedule an update
+ test.loop.invoke([&] () {
+ //Update the url
+ source.setURL(std::string("http://source-url.ext"));
+ });
+
+ test.run();
+}
diff --git a/test/tile/raster_tile.test.cpp b/test/tile/raster_tile.test.cpp
index 4e9e907321..2a15fd1b99 100644
--- a/test/tile/raster_tile.test.cpp
+++ b/test/tile/raster_tile.test.cpp
@@ -3,7 +3,7 @@
#include <mbgl/tile/raster_tile.hpp>
#include <mbgl/tile/tile_loader_impl.hpp>
-#include <mbgl/actor/thread_pool.hpp>
+#include <mbgl/platform/default/thread_pool.hpp>
#include <mbgl/util/run_loop.hpp>
#include <mbgl/map/transform.hpp>
#include <mbgl/style/style.hpp>
diff --git a/test/tile/tile_coordinate.test.cpp b/test/tile/tile_coordinate.test.cpp
index f2337c1e7f..740a03894d 100644
--- a/test/tile/tile_coordinate.test.cpp
+++ b/test/tile/tile_coordinate.test.cpp
@@ -41,7 +41,7 @@ TEST(TileCoordinate, FromLatLng) {
for (const auto& pair : edges) {
const auto& latLng = pair.first;
const auto& screenCoordinate = pair.second;
- const auto base = TileCoordinate::fromLatLng(transform.getState(), 0, latLng);
+ const auto base = TileCoordinate::fromLatLng(0, latLng);
// 16 is the maximum zoom level where we actually compute placements.
for (uint8_t integerZoom = 0; integerZoom <= 16; ++integerZoom) {
@@ -52,7 +52,7 @@ TEST(TileCoordinate, FromLatLng) {
latLng.latitude == 0 ? 0.5 : latLng.latitude == -util::LATITUDE_MAX ? 1.0 : 0,
};
- const auto fromLatLng = TileCoordinate::fromLatLng(transform.getState(), zoom, latLng);
+ const auto fromLatLng = TileCoordinate::fromLatLng(zoom, latLng);
ASSERT_DOUBLE_EQ(fromLatLng.z, zoom);
ASSERT_DOUBLE_EQ(fromLatLng.p.x, tilePoint.x * maxTilesPerAxis);
ASSERT_NEAR(fromLatLng.p.y, tilePoint.y * maxTilesPerAxis, 1.0e-7);
diff --git a/test/tile/vector_tile.test.cpp b/test/tile/vector_tile.test.cpp
index fa75e24480..c07db42c3c 100644
--- a/test/tile/vector_tile.test.cpp
+++ b/test/tile/vector_tile.test.cpp
@@ -3,7 +3,7 @@
#include <mbgl/tile/vector_tile.hpp>
#include <mbgl/tile/tile_loader_impl.hpp>
-#include <mbgl/actor/thread_pool.hpp>
+#include <mbgl/platform/default/thread_pool.hpp>
#include <mbgl/util/run_loop.hpp>
#include <mbgl/map/transform.hpp>
#include <mbgl/style/style.hpp>
diff --git a/test/util/memory.test.cpp b/test/util/memory.test.cpp
index d1b9f2412a..a1e47d6c2b 100644
--- a/test/util/memory.test.cpp
+++ b/test/util/memory.test.cpp
@@ -2,8 +2,9 @@
#include <mbgl/test/util.hpp>
#include <mbgl/map/map.hpp>
-#include <mbgl/platform/default/headless_display.hpp>
-#include <mbgl/platform/default/headless_view.hpp>
+#include <mbgl/platform/default/headless_backend.hpp>
+#include <mbgl/platform/default/offscreen_view.hpp>
+#include <mbgl/platform/default/thread_pool.hpp>
#include <mbgl/util/io.hpp>
#include <mbgl/util/run_loop.hpp>
@@ -55,9 +56,10 @@ public:
}
util::RunLoop runLoop;
- std::shared_ptr<HeadlessDisplay> display { std::make_shared<mbgl::HeadlessDisplay>() };
- HeadlessView view { display, 2 };
+ HeadlessBackend backend;
+ OffscreenView view{ backend.getContext(), {{ 512, 512 }} };
StubFileSource fileSource;
+ ThreadPool threadPool { 4 };
private:
Response response(const std::string& path) {
@@ -91,20 +93,20 @@ private:
TEST(Memory, Vector) {
MemoryTest test;
- Map map(test.view, test.fileSource, MapMode::Still);
+ Map map(test.backend, { { 256, 256 } }, 2, test.fileSource, test.threadPool, MapMode::Still);
map.setZoom(16); // more map features
map.setStyleURL("mapbox://streets");
- test::render(map);
+ test::render(map, test.view);
}
TEST(Memory, Raster) {
MemoryTest test;
- Map map(test.view, test.fileSource, MapMode::Still);
+ Map map(test.backend, { { 256, 256 } }, 2, test.fileSource, test.threadPool, MapMode::Still);
map.setStyleURL("mapbox://satellite");
- test::render(map);
+ test::render(map, test.view);
}
// This test will measure the size of a Map object
@@ -119,18 +121,17 @@ TEST(Memory, Footprint) {
MemoryTest test;
- auto renderMap = [](Map* map, const char* style){
- map->setZoom(16);
-
- map->setStyleURL(style);
- test::render(*map);
+ auto renderMap = [&](Map& map, const char* style){
+ map.setZoom(16);
+ map.setStyleURL(style);
+ test::render(map, test.view);
};
// Warm up buffers and cache.
for (unsigned i = 0; i < 10; ++i) {
- Map map(test.view, test.fileSource, MapMode::Still);
- renderMap(&map, "mapbox://streets");
- renderMap(&map, "mapbox://satellite");
+ Map map(test.backend, {{ 256, 256 }}, 2, test.fileSource, test.threadPool, MapMode::Still);
+ renderMap(map, "mapbox://streets");
+ renderMap(map, "mapbox://satellite");
};
// Process close callbacks, mostly needed by
@@ -142,8 +143,9 @@ TEST(Memory, Footprint) {
long vectorInitialRSS = getRSS();
for (unsigned i = 0; i < runs; ++i) {
- auto vector = std::make_unique<Map>(test.view, test.fileSource, MapMode::Still);
- renderMap(vector.get(), "mapbox://streets");
+ auto vector = std::make_unique<Map>(test.backend, std::array<uint16_t, 2>{ { 256, 256 } },
+ 2, test.fileSource, test.threadPool, MapMode::Still);
+ renderMap(*vector, "mapbox://streets");
maps.push_back(std::move(vector));
};
@@ -151,8 +153,9 @@ TEST(Memory, Footprint) {
long rasterInitialRSS = getRSS();
for (unsigned i = 0; i < runs; ++i) {
- auto raster = std::make_unique<Map>(test.view, test.fileSource, MapMode::Still);
- renderMap(raster.get(), "mapbox://satellite");
+ auto raster = std::make_unique<Map>(test.backend, std::array<uint16_t, 2>{ { 256, 256 } },
+ 2, test.fileSource, test.threadPool, MapMode::Still);
+ renderMap(*raster, "mapbox://satellite");
maps.push_back(std::move(raster));
};
diff --git a/test/util/offscreen_texture.test.cpp b/test/util/offscreen_texture.test.cpp
index 301fc2c250..bd4eab69a8 100644
--- a/test/util/offscreen_texture.test.cpp
+++ b/test/util/offscreen_texture.test.cpp
@@ -1,15 +1,18 @@
#include <mbgl/test/util.hpp>
#include <mbgl/gl/context.hpp>
-#include <mbgl/platform/default/headless_view.hpp>
+#include <mbgl/platform/default/headless_backend.hpp>
+#include <mbgl/platform/default/offscreen_view.hpp>
+#include <mbgl/gl/gl.hpp>
#include <mbgl/util/offscreen_texture.hpp>
using namespace mbgl;
TEST(OffscreenTexture, EmptyRed) {
- HeadlessView view(1.0f, 512, 256);
- view.activate();
+ HeadlessBackend backend;
+ OffscreenView view(backend.getContext(), {{ 512, 256 }});
+ view.bind();
MBGL_CHECK_ERROR(glClearColor(1.0f, 0.0f, 0.0f, 1.0f));
MBGL_CHECK_ERROR(glClear(GL_COLOR_BUFFER_BIT));
@@ -64,11 +67,8 @@ struct Buffer {
TEST(OffscreenTexture, RenderToTexture) {
- HeadlessView view(1.0f, 512, 256);
- view.activate();
- gl::Context context;
- context.viewport.setDefaultValue(gl::value::Viewport::Get());
- context.bindFramebuffer.setDefaultValue(gl::value::BindFramebuffer::Get());
+ HeadlessBackend backend;
+ auto& context = backend.getContext();
MBGL_CHECK_ERROR(glEnable(GL_BLEND));
MBGL_CHECK_ERROR(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
@@ -106,14 +106,17 @@ void main() {
// Make sure the texture gets destructed before we call context.reset();
{
+ OffscreenView view(context, {{ 512, 256 }});
+
// First, draw red to the bound FBO.
context.clearColor = { 1, 0, 0, 1 };
+ view.bind();
MBGL_CHECK_ERROR(glClear(GL_COLOR_BUFFER_BIT));
// Then, create a texture, bind it, and render yellow to that texture. This should not
// affect the originally bound FBO.
- OffscreenTexture texture;
- texture.bind(context, {{ 128, 128 }});
+ OffscreenTexture texture(context, {{ 128, 128 }});
+ texture.bind();
context.clearColor = { 0, 0, 0, 0 };
MBGL_CHECK_ERROR(glClear(GL_COLOR_BUFFER_BIT));
@@ -125,11 +128,11 @@ void main() {
glVertexAttribPointer(paintShader.a_pos, 2, GL_FLOAT, GL_FALSE, 0, nullptr));
MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, 3));
- auto image = view.readStillImage(texture.getSize());
+ auto image = texture.readStillImage();
test::checkImage("test/fixtures/offscreen_texture/render-to-texture", image, 0, 0);
// Now reset the FBO back to normal and retrieve the original (restored) framebuffer.
- context.resetState();
+ view.bind();
image = view.readStillImage();
test::checkImage("test/fixtures/offscreen_texture/render-to-fbo", image, 0, 0);