summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Watson <tewatson89@gmail.com>2019-04-03 14:51:13 -0700
committerGitHub <noreply@github.com>2019-04-03 14:51:13 -0700
commit0ff25060dae4858a1b60e2277dbd8921de7a6785 (patch)
treed29d578b9b9d6cfb0999b7a30819d379b85172b7
parentba2b7a74c420856401d344ff15b27771175c9819 (diff)
parent0f416fbbde9b146eb28a4bf88586738d12505007 (diff)
downloadqtlocation-mapboxgl-upstream/friedbunny-external-pr-14135.tar.gz
Merge pull request #1 from mapbox/masterupstream/friedbunny-external-pr-14135
Merge Master
-rw-r--r--.gitmodules3
-rw-r--r--Makefile30
-rw-r--r--benchmark/api/query.benchmark.cpp8
-rw-r--r--benchmark/api/render.benchmark.cpp49
-rw-r--r--bin/offline.cpp2
-rw-r--r--bin/render.cpp14
-rw-r--r--ci.template116
-rw-r--r--circle.yml69
-rw-r--r--cmake/glfw.cmake6
-rw-r--r--cmake/loop-darwin.cmake4
-rw-r--r--cmake/mason-dependencies.cmake3
-rw-r--r--cmake/offline.cmake6
-rw-r--r--cmake/render.cmake6
-rw-r--r--cmake/vendor.cmake1
-rw-r--r--include/mbgl/map/map.hpp28
-rw-r--r--include/mbgl/map/map_observer.hpp2
-rw-r--r--include/mbgl/map/map_options.hpp71
-rw-r--r--include/mbgl/renderer/renderer.hpp2
-rw-r--r--include/mbgl/renderer/renderer_observer.hpp4
-rw-r--r--include/mbgl/storage/default_file_source.hpp2
-rw-r--r--include/mbgl/storage/file_source.hpp12
-rw-r--r--include/mbgl/storage/offline.hpp2
-rw-r--r--include/mbgl/storage/resource_options.hpp122
-rw-r--r--include/mbgl/style/conversion/constant.hpp5
-rw-r--r--include/mbgl/style/layers/symbol_layer.hpp8
-rw-r--r--include/mbgl/style/types.hpp3
-rw-r--r--include/mbgl/util/constants.hpp3
-rw-r--r--platform/android/CHANGELOG.md42
-rw-r--r--platform/android/LICENSE.md36
-rw-r--r--platform/android/MapboxGLAndroidSDK/build.gradle12
-rw-r--r--platform/android/MapboxGLAndroidSDK/gradle.properties2
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java37
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationCameraController.java6
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponent.java16
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentConstants.java32
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationLayerController.java17
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcher.java8
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java103
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java7
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMap.java2
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java9
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Style.java17
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java49
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/glsurfaceview/GLSurfaceViewMapRenderer.java10
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/textureview/TextureViewRenderThread.java1
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/module/telemetry/PerformanceEvent.java94
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/module/telemetry/TelemetryImpl.java5
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java5
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java40
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/SymbolLayer.java32
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/types/Formatted.java8
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/types/FormattedSection.java10
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/BitmapUtils.java3
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_internal.xml4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java11
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationCameraControllerTest.java30
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.java40
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.kt150
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/build.gradle2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/assets/streets.json5331
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/InstrumentationApplication.kt10
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/InstrumentationRunner.kt11
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/BaseIntegrationTest.kt39
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/FragmentBackStackTest.kt52
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/GLSurfaceViewReopenTest.kt30
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/GLSurfaceViewReuseTest.kt31
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/OrientationChangeTest.kt34
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/TextureViewReopenTest.kt33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/TextureViewReuseTest.kt31
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/ViewPagerScrollTest.kt38
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationComponentTest.kt96
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.kt34
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/GLSurfaceViewReopenTest.kt73
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxTest.java3
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/OrientationTest.java41
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/TextureViewReopenTest.kt77
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/VisibleRegionTest.kt80
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/module/telemetry/PerformanceEventTest.java188
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/action/OrientationAction.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/action/OrientationChangeAction.java)18
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/action/WaitAction.java7
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/BaseTest.java126
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/EspressoTest.java18
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/IconTest.java161
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraForTest.java340
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/fragment/MapDialogFragmentTest.kt4
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/geometry/GeoJsonConversionTest.java118
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/StyleLoadTest.kt8
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/AttributionTest.java16
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/CompassViewTest.java3
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/offline/OfflineManagerTest.kt123
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CustomGeometrySourceTest.kt21
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ExpressionTest.java26
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/GeoJsonSourceTests.java2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ImageTest.java46
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ImageTest.kt75
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTests.java13
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java28
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/FinishLoadingStyleIdlingResource.java35
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/LoadStyleIdlingResource.java40
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/MapboxIdlingResource.java46
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/OnMapReadyIdlingResource.java60
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml50
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapboxApplication.java2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/GestureDetectorActivity.java13
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/espresso/PixelTestActivity.kt66
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/MapFragmentActivity.java14
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/SupportMapFragmentActivity.java14
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/ViewPagerActivity.java117
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/ViewPagerActivity.kt109
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/SnapshotActivity.java114
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/SnapshotActivity.kt80
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/GLSurfaceRecyclerViewActivity.kt155
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapInDialogActivity.java34
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/RecyclerViewActivity.kt151
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/TextureRecyclerViewActivity.kt15
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/telemetry/PerformanceMeasurementActivity.java187
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_backstack_fragment.xml1
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_pixel_test.xml16
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_snapshot.xml12
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_viewpager.xml2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/item_map_gl.xml10
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/item_map_texture.xml (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/item_map.xml)0
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/categories.xml2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml4
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml4
-rw-r--r--platform/android/build.gradle1
-rw-r--r--platform/android/gradle/android-nitpick.gradle10
-rw-r--r--platform/android/gradle/dependencies.gradle6
-rw-r--r--platform/android/gradle/jacoco-report.gradle33
-rw-r--r--platform/android/scripts/exclude-activity-gen.json4
-rwxr-xr-xplatform/android/scripts/generate-style-code.js7
-rwxr-xr-xplatform/android/scripts/parse-jacoco-report.py31
-rw-r--r--platform/android/scripts/validate-license.py17
-rw-r--r--platform/android/src/conversion/constant.hpp11
-rw-r--r--platform/android/src/file_source.cpp27
-rw-r--r--platform/android/src/file_source.hpp6
-rw-r--r--platform/android/src/map_renderer.hpp4
-rwxr-xr-xplatform/android/src/native_map_view.cpp13
-rwxr-xr-xplatform/android/src/native_map_view.hpp1
-rw-r--r--platform/android/src/offline/offline_manager.cpp13
-rw-r--r--platform/android/src/offline/offline_manager.hpp8
-rw-r--r--platform/android/src/offline/offline_region.cpp14
-rw-r--r--platform/android/src/offline/offline_region.hpp2
-rw-r--r--platform/android/src/snapshotter/map_snapshotter.cpp10
-rw-r--r--platform/android/src/style/layers/symbol_layer.cpp12
-rw-r--r--platform/android/src/style/layers/symbol_layer.hpp4
m---------platform/android/vendor/mapbox-events-android0
-rw-r--r--platform/darwin/docs/guides/For Style Authors.md.ejs11
-rw-r--r--platform/darwin/docs/guides/Predicates and Expressions.md8
-rw-r--r--platform/darwin/filesource-files.json1
-rwxr-xr-xplatform/darwin/scripts/generate-style-code.js23
-rw-r--r--platform/darwin/src/MGLAttributedExpression.h55
-rw-r--r--platform/darwin/src/MGLAttributedExpression.m23
-rw-r--r--platform/darwin/src/MGLLoggingConfiguration.h2
-rw-r--r--platform/darwin/src/MGLMapSnapshotter.mm15
-rw-r--r--platform/darwin/src/MGLOfflinePack.mm19
-rw-r--r--platform/darwin/src/MGLOfflinePack_Private.h2
-rw-r--r--platform/darwin/src/MGLOfflineStorage.mm29
-rw-r--r--platform/darwin/src/MGLOfflineStorage_Private.h9
-rw-r--r--platform/darwin/src/MGLRendererConfiguration.h8
-rw-r--r--platform/darwin/src/MGLRendererConfiguration.mm4
-rw-r--r--platform/darwin/src/MGLRendererFrontend.h7
-rw-r--r--platform/darwin/src/MGLStyleValue_Private.h24
-rw-r--r--platform/darwin/src/MGLSymbolStyleLayer.h75
-rw-r--r--platform/darwin/src/MGLSymbolStyleLayer.mm37
-rw-r--r--platform/darwin/src/NSBundle+MGLAdditions.m7
-rw-r--r--platform/darwin/src/NSData+MGLAdditions.h13
-rw-r--r--platform/darwin/src/NSData+MGLAdditions.mm23
-rw-r--r--platform/darwin/src/NSExpression+MGLAdditions.mm51
-rw-r--r--platform/darwin/test/MGLAttributionInfoTests.m15
-rw-r--r--platform/darwin/test/MGLDocumentationExampleTests.swift18
-rw-r--r--platform/darwin/test/MGLExpressionTests.mm92
-rw-r--r--platform/darwin/test/MGLOfflineStorageTests.mm9
-rw-r--r--platform/darwin/test/MGLSymbolStyleLayerTests.mm116
-rw-r--r--platform/default/include/mbgl/map/map_snapshotter.hpp9
-rw-r--r--platform/default/src/mbgl/gl/headless_frontend.cpp8
-rw-r--r--platform/default/src/mbgl/map/map_snapshotter.cpp48
-rw-r--r--platform/default/src/mbgl/storage/default_file_source.cpp4
-rw-r--r--platform/default/src/mbgl/storage/file_source.cpp15
-rw-r--r--platform/glfw/glfw_renderer_frontend.cpp7
-rw-r--r--platform/glfw/glfw_view.cpp2
-rw-r--r--platform/glfw/main.cpp37
-rw-r--r--platform/ios/CHANGELOG.md22
-rw-r--r--platform/ios/Integration Tests/Annotation Tests/MGLAnnotationViewIntegrationTests.m1
-rw-r--r--platform/ios/Integration Tests/MGLCameraTransitionTests.mm2
-rw-r--r--platform/ios/Mapbox-iOS-SDK-snapshot-dynamic.podspec2
-rw-r--r--platform/ios/Mapbox-iOS-SDK-stripped.podspec2
-rw-r--r--platform/ios/Mapbox-iOS-SDK.podspec2
-rw-r--r--platform/ios/app/MBXViewController.m20
-rw-r--r--platform/ios/app/missing_icon.json40
-rw-r--r--platform/ios/docs/guides/For Style Authors.md11
-rw-r--r--platform/ios/ios.xcodeproj/project.pbxproj49
-rwxr-xr-xplatform/ios/scripts/package.sh7
-rw-r--r--platform/ios/sdk-files.json6
-rw-r--r--platform/ios/src/MGLMapView.h27
-rw-r--r--platform/ios/src/MGLMapView.mm197
-rw-r--r--platform/ios/src/MGLMapViewDelegate.h2
-rw-r--r--platform/ios/src/UIColor+MGLAdditions.h1
-rw-r--r--platform/ios/test/MGLMapViewDelegateIntegrationTests.swift2
-rw-r--r--platform/ios/test/MGLNSDataAdditionsTests.m48
m---------platform/ios/vendor/mapbox-events-ios0
-rw-r--r--platform/linux/config.cmake9
-rw-r--r--platform/linux/filesource-files.json10
-rw-r--r--platform/macos/CHANGELOG.md7
-rw-r--r--platform/macos/docs/guides/For Style Authors.md11
-rw-r--r--platform/macos/macos.xcodeproj/project.pbxproj1
-rw-r--r--platform/macos/src/MGLMapView.mm13
-rw-r--r--platform/macos/src/NSColor+MGLAdditions.h1
-rw-r--r--platform/macos/src/NSColor+MGLAdditions.mm6
-rw-r--r--platform/node/src/node_map.cpp51
-rw-r--r--platform/node/src/node_map.hpp24
-rw-r--r--platform/node/test/ignores.json21
-rw-r--r--platform/qt/qt.cmake1
-rw-r--r--platform/qt/src/qmapboxgl.cpp104
-rw-r--r--platform/qt/src/qmapboxgl_p.hpp2
-rwxr-xr-xscripts/clang-tools.sh6
-rwxr-xr-xscripts/code-coverage.sh17
-rwxr-xr-xscripts/generate-file-lists.js1
-rwxr-xr-xscripts/generate-shaders.js75
-rwxr-xr-xscripts/generate-style-code.js8
-rwxr-xr-xscripts/publish_core_codecoverage.js170
-rwxr-xr-xscripts/publish_github_stats.js147
-rw-r--r--scripts/style-spec.js7
-rw-r--r--src/core-files.json6
-rw-r--r--src/mbgl/annotation/annotation_manager.cpp1
-rw-r--r--src/mbgl/gfx/attribute.hpp2
-rw-r--r--src/mbgl/gfx/context.hpp24
-rw-r--r--src/mbgl/gl/attribute.hpp42
-rw-r--r--src/mbgl/gl/context.cpp44
-rw-r--r--src/mbgl/gl/context.hpp16
-rw-r--r--src/mbgl/gl/debugging.cpp6
-rw-r--r--src/mbgl/gl/debugging.hpp9
-rw-r--r--src/mbgl/gl/features.hpp3
-rw-r--r--src/mbgl/gl/program.hpp203
-rw-r--r--src/mbgl/gl/texture.hpp10
-rw-r--r--src/mbgl/gl/uniform.hpp11
-rw-r--r--src/mbgl/layout/symbol_instance.cpp79
-rw-r--r--src/mbgl/layout/symbol_instance.hpp30
-rw-r--r--src/mbgl/layout/symbol_layout.cpp220
-rw-r--r--src/mbgl/layout/symbol_layout.hpp7
-rw-r--r--src/mbgl/layout/symbol_projection.cpp6
-rw-r--r--src/mbgl/layout/symbol_projection.hpp5
-rw-r--r--src/mbgl/map/map.cpp70
-rw-r--r--src/mbgl/map/map_impl.cpp62
-rw-r--r--src/mbgl/map/map_impl.hpp29
-rw-r--r--src/mbgl/map/map_options.cpp45
-rw-r--r--src/mbgl/programs/attributes.hpp76
-rw-r--r--src/mbgl/programs/background_program.cpp30
-rw-r--r--src/mbgl/programs/background_program.hpp38
-rw-r--r--src/mbgl/programs/circle_program.hpp16
-rw-r--r--src/mbgl/programs/clipping_mask_program.hpp2
-rw-r--r--src/mbgl/programs/collision_box_program.hpp36
-rw-r--r--src/mbgl/programs/debug_program.hpp6
-rw-r--r--src/mbgl/programs/extrusion_texture_program.hpp10
-rw-r--r--src/mbgl/programs/fill_extrusion_program.cpp28
-rw-r--r--src/mbgl/programs/fill_extrusion_program.hpp46
-rw-r--r--src/mbgl/programs/fill_program.cpp14
-rw-r--r--src/mbgl/programs/fill_program.hpp30
-rw-r--r--src/mbgl/programs/gl/background.cpp25
-rw-r--r--src/mbgl/programs/gl/background_pattern.cpp25
-rw-r--r--src/mbgl/programs/gl/circle.cpp53
-rw-r--r--src/mbgl/programs/gl/clipping_mask.cpp25
-rw-r--r--src/mbgl/programs/gl/collision_box.cpp25
-rw-r--r--src/mbgl/programs/gl/collision_circle.cpp25
-rw-r--r--src/mbgl/programs/gl/debug.cpp25
-rw-r--r--src/mbgl/programs/gl/extrusion_texture.cpp25
-rw-r--r--src/mbgl/programs/gl/fill.cpp33
-rw-r--r--src/mbgl/programs/gl/fill_extrusion.cpp37
-rw-r--r--src/mbgl/programs/gl/fill_extrusion_pattern.cpp37
-rw-r--r--src/mbgl/programs/gl/fill_outline.cpp33
-rw-r--r--src/mbgl/programs/gl/fill_outline_pattern.cpp33
-rw-r--r--src/mbgl/programs/gl/fill_pattern.cpp33
-rw-r--r--src/mbgl/programs/gl/heatmap.cpp33
-rw-r--r--src/mbgl/programs/gl/heatmap_texture.cpp25
-rw-r--r--src/mbgl/programs/gl/hillshade.cpp25
-rw-r--r--src/mbgl/programs/gl/hillshade_prepare.cpp25
-rw-r--r--src/mbgl/programs/gl/line.cpp49
-rw-r--r--src/mbgl/programs/gl/line_gradient.cpp45
-rw-r--r--src/mbgl/programs/gl/line_pattern.cpp49
-rw-r--r--src/mbgl/programs/gl/line_sdf.cpp53
-rw-r--r--src/mbgl/programs/gl/preludes.cpp15
-rw-r--r--src/mbgl/programs/gl/preludes.hpp7
-rw-r--r--src/mbgl/programs/gl/raster.cpp25
-rw-r--r--src/mbgl/programs/gl/shader_source.cpp778
-rw-r--r--src/mbgl/programs/gl/shader_source.hpp3
-rw-r--r--src/mbgl/programs/gl/shaders.cpp24
-rw-r--r--src/mbgl/programs/gl/shaders.hpp7
-rw-r--r--src/mbgl/programs/gl/symbol_icon.cpp29
-rw-r--r--src/mbgl/programs/gl/symbol_sdf_icon.cpp45
-rw-r--r--src/mbgl/programs/gl/symbol_sdf_text.cpp45
-rw-r--r--src/mbgl/programs/heatmap_program.hpp12
-rw-r--r--src/mbgl/programs/heatmap_texture_program.hpp12
-rw-r--r--src/mbgl/programs/hillshade_prepare_program.hpp18
-rw-r--r--src/mbgl/programs/hillshade_program.hpp28
-rw-r--r--src/mbgl/programs/line_program.cpp34
-rw-r--r--src/mbgl/programs/line_program.hpp90
-rw-r--r--src/mbgl/programs/program.hpp30
-rw-r--r--src/mbgl/programs/program_parameters.cpp9
-rw-r--r--src/mbgl/programs/program_parameters.hpp3
-rw-r--r--src/mbgl/programs/raster_program.hpp48
-rw-r--r--src/mbgl/programs/symbol_program.cpp35
-rw-r--r--src/mbgl/programs/symbol_program.hpp143
-rw-r--r--src/mbgl/programs/textures.hpp10
-rw-r--r--src/mbgl/programs/uniforms.hpp96
-rw-r--r--src/mbgl/renderer/buckets/line_bucket.cpp2
-rw-r--r--src/mbgl/renderer/buckets/line_bucket.hpp2
-rw-r--r--src/mbgl/renderer/buckets/symbol_bucket.cpp20
-rw-r--r--src/mbgl/renderer/buckets/symbol_bucket.hpp6
-rw-r--r--src/mbgl/renderer/image_atlas.cpp40
-rw-r--r--src/mbgl/renderer/image_atlas.hpp16
-rw-r--r--src/mbgl/renderer/image_manager.cpp100
-rw-r--r--src/mbgl/renderer/image_manager.hpp20
-rw-r--r--src/mbgl/renderer/image_manager_observer.hpp14
-rw-r--r--src/mbgl/renderer/layers/render_background_layer.cpp9
-rw-r--r--src/mbgl/renderer/layers/render_circle_layer.cpp13
-rw-r--r--src/mbgl/renderer/layers/render_custom_layer.cpp3
-rw-r--r--src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp21
-rw-r--r--src/mbgl/renderer/layers/render_fill_layer.cpp21
-rw-r--r--src/mbgl/renderer/layers/render_heatmap_layer.cpp29
-rw-r--r--src/mbgl/renderer/layers/render_hillshade_layer.cpp27
-rw-r--r--src/mbgl/renderer/layers/render_line_layer.cpp19
-rw-r--r--src/mbgl/renderer/layers/render_line_layer.hpp11
-rw-r--r--src/mbgl/renderer/layers/render_raster_layer.cpp35
-rw-r--r--src/mbgl/renderer/layers/render_symbol_layer.cpp121
-rw-r--r--src/mbgl/renderer/layers/render_symbol_layer.hpp5
-rw-r--r--src/mbgl/renderer/paint_parameters.cpp6
-rw-r--r--src/mbgl/renderer/paint_parameters.hpp13
-rw-r--r--src/mbgl/renderer/paint_property_binder.hpp34
-rw-r--r--src/mbgl/renderer/render_layer.cpp15
-rw-r--r--src/mbgl/renderer/render_layer.hpp5
-rw-r--r--src/mbgl/renderer/render_static_data.cpp4
-rw-r--r--src/mbgl/renderer/render_static_data.hpp5
-rw-r--r--src/mbgl/renderer/render_tile.cpp14
-rw-r--r--src/mbgl/renderer/renderer.cpp4
-rw-r--r--src/mbgl/renderer/renderer_impl.cpp125
-rw-r--r--src/mbgl/renderer/renderer_impl.hpp7
-rw-r--r--src/mbgl/renderer/sources/render_image_source.cpp6
-rw-r--r--src/mbgl/storage/asset_file_source.hpp2
-rw-r--r--src/mbgl/storage/file_source.cpp37
-rw-r--r--src/mbgl/storage/resource_options.cpp80
-rw-r--r--src/mbgl/style/conversion/constant.cpp22
-rw-r--r--src/mbgl/style/conversion/function.cpp2
-rw-r--r--src/mbgl/style/conversion/property_value.cpp1
-rw-r--r--src/mbgl/style/expression/value.cpp8
-rw-r--r--src/mbgl/style/image_impl.hpp1
-rw-r--r--src/mbgl/style/layers/circle_layer_properties.hpp14
-rw-r--r--src/mbgl/style/layers/fill_extrusion_layer_properties.hpp8
-rw-r--r--src/mbgl/style/layers/fill_layer_properties.hpp8
-rw-r--r--src/mbgl/style/layers/heatmap_layer_properties.hpp4
-rw-r--r--src/mbgl/style/layers/layer.cpp.ejs3
-rw-r--r--src/mbgl/style/layers/layer_properties.hpp.ejs10
-rw-r--r--src/mbgl/style/layers/line_layer.cpp1
-rw-r--r--src/mbgl/style/layers/line_layer_properties.hpp20
-rw-r--r--src/mbgl/style/layers/symbol_layer.cpp55
-rw-r--r--src/mbgl/style/layers/symbol_layer_impl.hpp62
-rw-r--r--src/mbgl/style/layers/symbol_layer_properties.hpp32
-rw-r--r--src/mbgl/style/sources/raster_dem_source.cpp3
-rw-r--r--src/mbgl/style/style_impl.cpp1
-rw-r--r--src/mbgl/style/types.cpp3
-rw-r--r--src/mbgl/text/collision_index.cpp9
-rw-r--r--src/mbgl/text/collision_index.hpp1
-rw-r--r--src/mbgl/text/glyph.hpp8
-rw-r--r--src/mbgl/text/placement.cpp264
-rw-r--r--src/mbgl/text/placement.hpp24
-rw-r--r--src/mbgl/text/quads.cpp6
-rw-r--r--src/mbgl/text/quads.hpp1
-rw-r--r--src/mbgl/text/shaping.cpp70
-rw-r--r--src/mbgl/text/shaping.hpp15
-rw-r--r--src/mbgl/tile/geometry_tile.cpp9
-rw-r--r--src/mbgl/tile/geometry_tile.hpp2
-rw-r--r--src/mbgl/tile/geometry_tile_worker.cpp5
-rw-r--r--src/mbgl/tile/geometry_tile_worker.hpp3
-rw-r--r--src/mbgl/tile/raster_dem_tile.cpp1
-rw-r--r--src/mbgl/tile/raster_tile.cpp1
-rw-r--r--src/mbgl/util/literal.hpp67
-rw-r--r--src/mbgl/util/offscreen_texture.cpp10
-rw-r--r--src/mbgl/util/offscreen_texture.hpp9
-rw-r--r--test/api/annotations.test.cpp10
-rw-r--r--test/api/api_misuse.test.cpp13
-rw-r--r--test/api/custom_geometry_source.test.cpp11
-rw-r--r--test/api/custom_layer.test.cpp11
-rw-r--r--test/api/query.test.cpp16
-rw-r--r--test/api/recycle_map.cpp13
-rw-r--r--test/gl/bucket.test.cpp2
-rw-r--r--test/gl/context.test.cpp11
-rw-r--r--test/map/map.test.cpp155
-rw-r--r--test/map/prefetch.test.cpp11
-rw-r--r--test/programs/symbol_program.test.cpp34
-rw-r--r--test/renderer/image_manager.test.cpp17
-rw-r--r--test/src/mbgl/test/map_adapter.hpp21
-rw-r--r--test/style/style_layer.test.cpp12
-rw-r--r--test/test-files.json1
-rw-r--r--test/text/cross_tile_symbol_index.test.cpp24
-rw-r--r--test/text/local_glyph_rasterizer.test.cpp16
-rw-r--r--test/util/memory.test.cpp31
m---------vendor/args0
-rw-r--r--vendor/args-files.json8
-rw-r--r--vendor/args.cmake5
-rw-r--r--vendor/optional.cmake10
402 files changed, 13395 insertions, 4601 deletions
diff --git a/.gitmodules b/.gitmodules
index a36fee4c0e..aeb2663b84 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -91,3 +91,6 @@
[submodule "platform/darwin/docs/theme"]
path = platform/darwin/docs/theme
url = https://github.com/mapbox/jazzy-theme.git
+[submodule "vendor/args"]
+ path = vendor/args
+ url = https://github.com/Taywee/args
diff --git a/Makefile b/Makefile
index ecc4273cff..df476fd677 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,8 @@
export BUILDTYPE ?= Debug
+export IS_LOCAL_DEVELOPMENT ?= true
export WITH_CXX11ABI ?= $(shell scripts/check-cxx11abi.sh)
+export TARGET_BRANCH ?= master
+
ifeq ($(BUILDTYPE), Release)
else ifeq ($(BUILDTYPE), RelWithDebInfo)
@@ -55,6 +58,8 @@ default: test
BUILD_DEPS += Makefile
BUILD_DEPS += CMakeLists.txt
+BUILD_DOCS ?= true
+
#### macOS targets ##############################################################
ifeq ($(HOST_PLATFORM), macos)
@@ -92,7 +97,7 @@ macos: $(MACOS_PROJ_PATH)
.PHONY: xproj
xproj: $(MACOS_PROJ_PATH)
- open $(MACOS_WORK_PATH)
+ xed $(MACOS_WORK_PATH)
.PHONY: test
test: $(MACOS_PROJ_PATH)
@@ -188,12 +193,11 @@ compdb: $(BUILD_DEPS) $(TEST_DEPS) $(MACOS_COMPDB_PATH)/Makefile
.PHONY: tidy
tidy: compdb
- scripts/clang-tools.sh $(MACOS_COMPDB_PATH)
+ scripts/clang-tools.sh $(MACOS_COMPDB_PATH) $(TARGET_BRANCH)
.PHONY: check
check: compdb
- scripts/clang-tools.sh $(MACOS_COMPDB_PATH) --diff
-
+ scripts/clang-tools.sh $(MACOS_COMPDB_PATH) $(TARGET_BRANCH) --diff
endif
#### iOS targets ##############################################################
@@ -234,7 +238,7 @@ ios: $(IOS_PROJ_PATH)
.PHONY: iproj
iproj: $(IOS_PROJ_PATH)
- open $(IOS_WORK_PATH)
+ xed $(IOS_WORK_PATH)
.PHONY: ios-lint
ios-lint:
@@ -272,7 +276,7 @@ ipackage%:
.PHONY: iframework
iframework: $(IOS_PROJ_PATH)
- FORMAT=$(FORMAT) BUILD_DEVICE=$(BUILD_DEVICE) SYMBOLS=$(SYMBOLS) \
+ FORMAT=$(FORMAT) BUILD_DEVICE=$(BUILD_DEVICE) SYMBOLS=$(SYMBOLS) BUILD_DOCS=$(BUILD_DOCS) \
./platform/ios/scripts/package.sh
.PHONY: ideploy
@@ -380,11 +384,11 @@ compdb: $(LINUX_BUILD)
.PHONY: tidy
tidy: compdb
- scripts/clang-tools.sh $(LINUX_OUTPUT_PATH)
+ scripts/clang-tools.sh $(LINUX_OUTPUT_PATH) $(TARGET_BRANCH)
.PHONY: check
check: compdb
- scripts/clang-tools.sh $(LINUX_OUTPUT_PATH) --diff
+ scripts/clang-tools.sh $(LINUX_OUTPUT_PATH) $(TARGET_BRANCH) --diff
endif
@@ -691,6 +695,16 @@ run-android-unit-test: platform/android/gradle/configuration.gradle
run-android-unit-test-%: platform/android/gradle/configuration.gradle
cd platform/android && $(MBGL_ANDROID_GRADLE) -Pmapbox.abis=none :MapboxGLAndroidSDK:testDebugUnitTest --info --tests "$*"
+# Run unit test and build a coverage report from .exec file generated by unit tests and .ec file generated by instrumentation tests
+.PHONY: android-create-jacoco-report
+android-create-jacoco-report: platform/android/gradle/configuration.gradle
+ cd platform/android && $(MBGL_ANDROID_GRADLE) -Pmapbox.abis=none :MapboxGLAndroidSDK:jacocoTestReport
+
+# Parse merged jacoco report and send it to S3
+.PHONY: android-parse-and-send-jacoco-report
+android-parse-and-send-jacoco-report:
+ python platform/android/scripts/parse-jacoco-report.py
+
# Builds a release package of the Android SDK
.PHONY: apackage
apackage: platform/android/gradle/configuration.gradle
diff --git a/benchmark/api/query.benchmark.cpp b/benchmark/api/query.benchmark.cpp
index 47eba7a9fe..9b7c2d7273 100644
--- a/benchmark/api/query.benchmark.cpp
+++ b/benchmark/api/query.benchmark.cpp
@@ -7,7 +7,6 @@
#include <mbgl/renderer/renderer.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/image.hpp>
-#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/storage/network_status.hpp>
#include <mbgl/util/image.hpp>
#include <mbgl/util/io.hpp>
@@ -21,7 +20,6 @@ class QueryBenchmark {
public:
QueryBenchmark() {
NetworkStatus::Set(NetworkStatus::Status::Offline);
- fileSource.setAccessToken("foobar");
map.getStyle().loadJSON(util::read_file("benchmark/fixtures/api/style.json"));
map.jumpTo(CameraOptions().withCenter(LatLng { 40.726989, -73.992857 }).withZoom(15.0)); // Manhattan
@@ -32,11 +30,11 @@ public:
}
util::RunLoop loop;
- DefaultFileSource fileSource{ "benchmark/fixtures/api/cache.db", "." };
ThreadPool threadPool{ 4 };
HeadlessFrontend frontend { { 1000, 1000 }, 1, threadPool };
- Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), 1,
- fileSource, threadPool, MapOptions().withMapMode(MapMode::Static) };
+ Map map { frontend, MapObserver::nullObserver(), threadPool,
+ MapOptions().withMapMode(MapMode::Static).withSize(frontend.getSize()),
+ ResourceOptions().withCachePath("benchmark/fixtures/api/cache.db").withAssetPath(".").withAccessToken("foobar") };
ScreenBox box{{ 0, 0 }, { 1000, 1000 }};
};
diff --git a/benchmark/api/render.benchmark.cpp b/benchmark/api/render.benchmark.cpp
index 9a91e8b3bc..3cff0d9056 100644
--- a/benchmark/api/render.benchmark.cpp
+++ b/benchmark/api/render.benchmark.cpp
@@ -8,7 +8,7 @@
#include <mbgl/renderer/renderer.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/image.hpp>
-#include <mbgl/storage/default_file_source.hpp>
+#include <mbgl/storage/resource_options.hpp>
#include <mbgl/storage/network_status.hpp>
#include <mbgl/util/image.hpp>
#include <mbgl/util/io.hpp>
@@ -18,32 +18,36 @@ using namespace mbgl;
namespace {
+static std::string cachePath { "benchmark/fixtures/api/cache.db" };
+constexpr double pixelRatio { 1.0 };
+constexpr Size size { 1000, 1000 };
+
class RenderBenchmark {
public:
RenderBenchmark() {
NetworkStatus::Set(NetworkStatus::Status::Offline);
- fileSource.setAccessToken("foobar");
}
util::RunLoop loop;
- DefaultFileSource fileSource { "benchmark/fixtures/api/cache.db", "." };
ThreadPool threadPool { 4 };
};
-
+
static void prepare(Map& map, optional<std::string> json = {}) {
map.getStyle().loadJSON(json ? *json : util::read_file("benchmark/fixtures/api/style.json"));
map.jumpTo(CameraOptions().withCenter(LatLng { 40.726989, -73.992857 }).withZoom(15.0)); // Manhattan
- map.getStyle().addImage(std::make_unique<style::Image>("test-icon",
- decodeImage(util::read_file("benchmark/fixtures/api/default_marker.png")), 1.0));
+
+ auto image = decodeImage(util::read_file("benchmark/fixtures/api/default_marker.png"));
+ map.getStyle().addImage(std::make_unique<style::Image>("test-icon", std::move(image), 1.0));
}
-
+
} // end namespace
static void API_renderStill_reuse_map(::benchmark::State& state) {
RenderBenchmark bench;
- HeadlessFrontend frontend { { 1000, 1000 }, 1, bench.threadPool };
- Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), 1,
- bench.fileSource, bench.threadPool, MapOptions().withMapMode(MapMode::Static) };
+ HeadlessFrontend frontend { size, pixelRatio, bench.threadPool };
+ Map map { frontend, MapObserver::nullObserver(), bench.threadPool,
+ MapOptions().withMapMode(MapMode::Static).withSize(size).withPixelRatio(pixelRatio),
+ ResourceOptions().withCachePath(cachePath).withAccessToken("foobar") };
prepare(map);
while (state.KeepRunning()) {
@@ -53,9 +57,10 @@ static void API_renderStill_reuse_map(::benchmark::State& state) {
static void API_renderStill_reuse_map_formatted_labels(::benchmark::State& state) {
RenderBenchmark bench;
- HeadlessFrontend frontend { { 1000, 1000 }, 1, bench.threadPool };
- Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), 1,
- bench.fileSource, bench.threadPool, MapOptions().withMapMode(MapMode::Static) };
+ HeadlessFrontend frontend { size, pixelRatio, bench.threadPool };
+ Map map { frontend, MapObserver::nullObserver(), bench.threadPool,
+ MapOptions().withMapMode(MapMode::Static).withSize(size).withPixelRatio(pixelRatio),
+ ResourceOptions().withCachePath(cachePath).withAccessToken("foobar") };
prepare(map, util::read_file("benchmark/fixtures/api/style_formatted_labels.json"));
while (state.KeepRunning()) {
@@ -65,10 +70,11 @@ static void API_renderStill_reuse_map_formatted_labels(::benchmark::State& state
static void API_renderStill_reuse_map_switch_styles(::benchmark::State& state) {
RenderBenchmark bench;
- HeadlessFrontend frontend { { 1000, 1000 }, 1, bench.threadPool };
- Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), 1,
- bench.fileSource, bench.threadPool, MapOptions().withMapMode(MapMode::Static) };
-
+ HeadlessFrontend frontend { size, pixelRatio, bench.threadPool };
+ Map map { frontend, MapObserver::nullObserver(), bench.threadPool,
+ MapOptions().withMapMode(MapMode::Static).withSize(size).withPixelRatio(pixelRatio),
+ ResourceOptions().withCachePath(cachePath).withAccessToken("foobar") };
+
while (state.KeepRunning()) {
prepare(map, { "{}" });
frontend.render(map);
@@ -79,11 +85,12 @@ static void API_renderStill_reuse_map_switch_styles(::benchmark::State& state) {
static void API_renderStill_recreate_map(::benchmark::State& state) {
RenderBenchmark bench;
-
+
while (state.KeepRunning()) {
- HeadlessFrontend frontend { { 1000, 1000 }, 1, bench.threadPool };
- Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), 1,
- bench.fileSource, bench.threadPool, MapOptions().withMapMode(MapMode::Static) };
+ HeadlessFrontend frontend { size, pixelRatio, bench.threadPool };
+ Map map { frontend, MapObserver::nullObserver(), bench.threadPool,
+ MapOptions().withMapMode(MapMode::Static).withSize(size).withPixelRatio(pixelRatio),
+ ResourceOptions().withCachePath(cachePath).withAccessToken("foobar") };
prepare(map);
frontend.render(map);
}
diff --git a/bin/offline.cpp b/bin/offline.cpp
index e5ce1f75fe..5cd43adfe3 100644
--- a/bin/offline.cpp
+++ b/bin/offline.cpp
@@ -5,7 +5,7 @@
#include <mbgl/storage/default_file_source.hpp>
-#include <args/args.hxx>
+#include <args.hxx>
#include <cstdlib>
#include <iostream>
diff --git a/bin/render.cpp b/bin/render.cpp
index 87a1e670b9..a805953693 100644
--- a/bin/render.cpp
+++ b/bin/render.cpp
@@ -6,10 +6,9 @@
#include <mbgl/gl/headless_frontend.hpp>
#include <mbgl/util/default_thread_pool.hpp>
-#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/style/style.hpp>
-#include <args/args.hxx>
+#include <args.hxx>
#include <cstdlib>
#include <iostream>
@@ -76,17 +75,12 @@ int main(int argc, char *argv[]) {
using namespace mbgl;
util::RunLoop loop;
- DefaultFileSource fileSource(cache_file, asset_root);
-
- // Set access token if present
- if (token.size()) {
- fileSource.setAccessToken(std::string(token));
- }
ThreadPool threadPool(4);
HeadlessFrontend frontend({ width, height }, pixelRatio, threadPool);
- Map map(frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio,
- fileSource, threadPool, MapOptions().withMapMode(MapMode::Static));
+ Map map(frontend, MapObserver::nullObserver(), threadPool,
+ MapOptions().withMapMode(MapMode::Static).withSize(frontend.getSize()).withPixelRatio(pixelRatio),
+ ResourceOptions().withCachePath(cache_file).withAssetPath(asset_root).withAccessToken(std::string(token)));
if (style.find("://") == std::string::npos) {
style = std::string("file://") + style;
diff --git a/ci.template b/ci.template
index f29d8d1608..578ce24c81 100644
--- a/ci.template
+++ b/ci.template
@@ -1,4 +1,3 @@
-
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "mapbox-gl-native travis resources",
@@ -85,35 +84,6 @@
}
},
{
- "PolicyName": "android",
- "PolicyDocument": {
- "Statement": [
- {
- "Effect": "Allow",
- "Action": [
- "ec2:DescribeInstances",
- "ec2:RunInstances",
- "ec2:CreateTags",
- "ec2:GetConsoleOutput"
- ],
- "Resource": [
- "*"
- ]
- },
- {
- "Effect": "Allow",
- "Action": "iam:PassRole",
- "Resource": {
- "Fn::GetAtt": [
- "AndroidRole",
- "Arn"
- ]
- }
- }
- ]
- }
- },
- {
"PolicyName": "cloudwatch-metrics",
"PolicyDocument": {
"Statement": [
@@ -161,7 +131,9 @@
"Resource": [
"arn:aws:s3:::mapbox-loading-dock/raw/mobile.binarysize/*",
"arn:aws:s3:::mapbox-loading-dock/raw/mobile.codecoverage/*",
- "arn:aws:s3:::mapbox-loading-dock/raw/mobile_staging.docs_coverage/*"
+ "arn:aws:s3:::mapbox-loading-dock/raw/mobile_staging.docs_coverage/*",
+ "arn:aws:s3:::mapbox-loading-dock/raw/mobile_staging.codecoverage/*",
+ "arn:aws:s3:::mapbox-loading-dock/raw/mobile_staging.github_stats/*"
]
}
]
@@ -231,72 +203,6 @@
"Ref": "BuildUser"
}
}
- },
- "AndroidRole": {
- "Type": "AWS::IAM::Role",
- "Properties": {
- "AssumeRolePolicyDocument": {
- "Statement": [
- {
- "Effect": "Allow",
- "Principal": {
- "Service": [
- "ec2.amazonaws.com"
- ]
- },
- "Action": [
- "sts:AssumeRole"
- ]
- }
- ]
- },
- "Policies": [
- {
- "PolicyName": "android-testing",
- "PolicyDocument": {
- "Statement": [
- {
- "Effect": "Allow",
- "Action": [
- "s3:PutObject"
- ],
- "Resource": [
- "arn:aws:s3:::mapbox-gl-testing/android/*"
- ]
- }
- ]
- }
- },
- {
- "PolicyName": "android",
- "PolicyDocument": {
- "Statement": [
- {
- "Effect": "Allow",
- "Action": [
- "s3:PutObject"
- ],
- "Resource": [
- "arn:aws:s3:::mapbox/mapbox-gl-native/android/build/*"
- ]
- }
- ]
- }
- }
- ],
- "Path": "/android-gl-build/travis/role/"
- }
- },
- "AndroidInstanceProfile": {
- "Type": "AWS::IAM::InstanceProfile",
- "Properties": {
- "Roles": [
- {
- "Ref": "AndroidRole"
- }
- ],
- "Path": "/android-gl-build/travis/instance-profile/"
- }
}
},
"Outputs": {
@@ -312,22 +218,6 @@
"SecretAccessKey"
]
}
- },
- "AndroidInstanceProfile": {
- "Value": {
- "Fn::GetAtt": [
- "AndroidInstanceProfile",
- "Arn"
- ]
- }
- },
- "AndroidRole": {
- "Value": {
- "Fn::GetAtt": [
- "AndroidRole",
- "Arn"
- ]
- }
}
}
}
diff --git a/circle.yml b/circle.yml
index 6883cd6f5a..21f3c023ca 100644
--- a/circle.yml
+++ b/circle.yml
@@ -15,8 +15,8 @@ workflows:
- android-arm-template:
name: android-gnustl-arm-v7
stl: gnustl_shared
- firebase_device_id: "m0"
- firebase_device_os: "18"
+ firebase_device_id: "htc_m8"
+ firebase_device_os: "19"
image: android-ndk-r17c:1d5db0eb34
abi: arm-v7
- android-release:
@@ -44,6 +44,8 @@ workflows:
- linux-gcc5-debug-coverage
- linux-doxygen
- ios-debug
+ - ios-debug-xcode-102:
+ name: ios-debug-xcode-10.2
- ios-release-template:
name: ios-release
- ios-release-tag:
@@ -64,6 +66,7 @@ workflows:
only:
- master
jobs:
+ - metrics-nightly
- ios-release-template:
name: ios-release-nightly
- ios-sanitize-nightly
@@ -500,7 +503,7 @@ jobs:
command: make compdb
- run:
name: Run Clang checks
- command: make check
+ command: make check TARGET_BRANCH=${CIRCLE_TARGET_BRANCH:master}
no_output_timeout: 20m
- save-dependencies: { ccache: false }
@@ -571,7 +574,16 @@ jobs:
gcloud firebase test android run --type instrumentation \
--app platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk/debug/MapboxGLAndroidSDKTestApp-debug.apk \
--test platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk/androidTest/debug/MapboxGLAndroidSDKTestApp-debug-androidTest.apk \
- --device-ids << parameters.firebase_device_id >> --os-version-ids << parameters.firebase_device_os >> --locales en --orientations portrait --timeout 20m
+ --device-ids << parameters.firebase_device_id >> --os-version-ids << parameters.firebase_device_os >> --locales en --orientations portrait --timeout 20m \
+ --environment-variables coverage=true,coverageFile="/sdcard/coverage.ec" --directories-to-pull /sdcard --results-dir mapbox-android-sdk-${CIRCLE_BUILD_NUM}
+ coverageFile=`gsutil ls gs://test-lab-186672a0qp5bq-ycr70axads3nc/mapbox-android-sdk-${CIRCLE_BUILD_NUM}/**/*.ec | tail -1`
+ gsutil cp $coverageFile $PWD/platform/android/MapboxGLAndroidSDK/build/jacoco | true
+ fi
+ - run:
+ name: Parse and send Jacoco reports
+ command: |
+ if [[ $CIRCLE_BRANCH == master ]]; then
+ make android-create-jacoco-report && make android-parse-and-send-jacoco-report
fi
- store_artifacts:
path: platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk/debug
@@ -838,6 +850,9 @@ jobs:
- build-test
- save-dependencies
- run-unit-tests
+ - run:
+ name: Build offline CLI
+ command: make offline
# ------------------------------------------------------------------------------
linux-gcc5-debug-coverage:
@@ -864,6 +879,12 @@ jobs:
curl -sSfL -o codecov https://codecov.io/bash
chmod +x codecov
./codecov -c
+ - run:
+ name: Upload coverage metrics to s3
+ command: |
+ if [[ $CIRCLE_BRANCH == master ]]; then
+ scripts/publish_core_codecoverage.js -p Linux -s Core
+ fi
# ------------------------------------------------------------------------------
linux-doxygen:
@@ -916,6 +937,46 @@ jobs:
- upload-xcode-build-logs
# ------------------------------------------------------------------------------
+ ios-debug-xcode-102:
+ macos:
+ xcode: "10.2.0"
+ environment:
+ BUILDTYPE: Debug
+ HOMEBREW_NO_AUTO_UPDATE: 1
+ steps:
+ - install-macos-dependencies
+ - install-dependencies
+ - build-ios-test
+ - check-public-symbols
+ - run:
+ name: Check symbol namespacing for mapbox-events-ios
+ command: make ios-check-events-symbols
+ - run:
+ name: Lint plist files
+ command: make ios-lint
+ - run:
+ name: Nitpick Darwin code generation
+ command: scripts/nitpick/generated-code.js darwin
+ - save-dependencies
+ - collect-xcode-build-logs
+ - upload-xcode-build-logs
+
+# ------------------------------------------------------------------------------
+ metrics-nightly:
+ docker:
+ - image: mbgl/linux-gcc-5:54f59e3ac5
+ working_directory: /src
+ environment:
+ LIBSYSCONFCPUS: 2
+ JOBS: 2
+ steps:
+ - install-dependencies
+ - run:
+ name: Collect GitHub statistics
+ command: |
+ scripts/publish_github_stats.js
+
+# ------------------------------------------------------------------------------
ios-sanitize-nightly:
macos:
xcode: "10.1.0"
diff --git a/cmake/glfw.cmake b/cmake/glfw.cmake
index a2adb9fbb5..4ef6890cef 100644
--- a/cmake/glfw.cmake
+++ b/cmake/glfw.cmake
@@ -2,9 +2,6 @@ add_executable(mbgl-glfw
platform/glfw/main.cpp
)
-# args requires RTTI
-set_source_files_properties(platform/glfw/main.cpp PROPERTIES COMPILE_OPTIONS "-frtti")
-
target_sources(mbgl-glfw
PRIVATE platform/glfw/glfw_view.hpp
PRIVATE platform/glfw/glfw_view.cpp
@@ -23,10 +20,9 @@ target_link_libraries(mbgl-glfw
PRIVATE mbgl-core
PRIVATE glfw
PRIVATE cheap-ruler-cpp
+ PRIVATE args
)
-target_add_mason_package(mbgl-glfw PRIVATE args)
-
mbgl_platform_glfw()
create_source_groups(mbgl-glfw)
diff --git a/cmake/loop-darwin.cmake b/cmake/loop-darwin.cmake
index a330375653..46d8f9edc0 100644
--- a/cmake/loop-darwin.cmake
+++ b/cmake/loop-darwin.cmake
@@ -7,6 +7,10 @@ target_include_directories(mbgl-loop-darwin
PRIVATE src
)
+target_link_libraries(mbgl-loop-darwin PUBLIC
+ optional
+)
+
create_source_groups(mbgl-loop-darwin)
set_target_properties(mbgl-loop-darwin PROPERTIES FOLDER "Core")
diff --git a/cmake/mason-dependencies.cmake b/cmake/mason-dependencies.cmake
index 71a94f096f..a6ef7a3a53 100644
--- a/cmake/mason-dependencies.cmake
+++ b/cmake/mason-dependencies.cmake
@@ -8,14 +8,11 @@ elseif(MBGL_PLATFORM STREQUAL "linux")
mason_use(libuv VERSION 1.9.1)
mason_use(libpng VERSION 1.6.25)
mason_use(libjpeg-turbo VERSION 1.5.0)
- mason_use(args VERSION 6.2.0 HEADER_ONLY)
if(WITH_EGL)
mason_use(swiftshader VERSION 2018-05-31)
endif()
elseif(MBGL_PLATFORM STREQUAL "macos")
- mason_use(args VERSION 6.2.0 HEADER_ONLY)
-
if(WITH_EGL)
mason_use(swiftshader VERSION 2018-05-31)
endif()
diff --git a/cmake/offline.cmake b/cmake/offline.cmake
index b751125297..3fa075f07b 100644
--- a/cmake/offline.cmake
+++ b/cmake/offline.cmake
@@ -2,9 +2,6 @@ add_executable(mbgl-offline
bin/offline.cpp
)
-# args requires RTTI
-set_source_files_properties(bin/offline.cpp PROPERTIES COMPILE_OPTIONS "-frtti")
-
target_sources(mbgl-offline
PRIVATE platform/default/include/mbgl/util/default_styles.hpp
)
@@ -15,10 +12,9 @@ target_include_directories(mbgl-offline
target_link_libraries(mbgl-offline
PRIVATE mbgl-core
+ PRIVATE args
)
-target_add_mason_package(mbgl-offline PRIVATE args)
-
mbgl_platform_offline()
create_source_groups(mbgl-offline)
diff --git a/cmake/render.cmake b/cmake/render.cmake
index 776c859bad..a625b3f21f 100644
--- a/cmake/render.cmake
+++ b/cmake/render.cmake
@@ -2,19 +2,15 @@ add_executable(mbgl-render
bin/render.cpp
)
-# args requires RTTI
-set_source_files_properties(bin/render.cpp PROPERTIES COMPILE_OPTIONS "-frtti")
-
target_include_directories(mbgl-render
PRIVATE platform/default/include
)
target_link_libraries(mbgl-render
PRIVATE mbgl-core
+ PRIVATE args
)
-target_add_mason_package(mbgl-render PRIVATE args)
-
mbgl_platform_render()
create_source_groups(mbgl-render)
diff --git a/cmake/vendor.cmake b/cmake/vendor.cmake
index ddeefad76d..7aac53e4cb 100644
--- a/cmake/vendor.cmake
+++ b/cmake/vendor.cmake
@@ -29,5 +29,6 @@ include(${CMAKE_SOURCE_DIR}/vendor/vector-tile.cmake)
include(${CMAKE_SOURCE_DIR}/vendor/wagyu.cmake)
if(MBGL_PLATFORM STREQUAL "linux" OR MBGL_PLATFORM STREQUAL "macos")
+ include(${CMAKE_SOURCE_DIR}/vendor/args.cmake)
include(${CMAKE_SOURCE_DIR}/vendor/glfw.cmake)
endif()
diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp
index b4f60a19ba..2fdd72dcb8 100644
--- a/include/mbgl/map/map.hpp
+++ b/include/mbgl/map/map.hpp
@@ -12,6 +12,7 @@
#include <mbgl/map/camera.hpp>
#include <mbgl/util/geometry.hpp>
#include <mbgl/map/projection_mode.hpp>
+#include <mbgl/storage/resource_options.hpp>
#include <cstdint>
#include <string>
@@ -21,7 +22,6 @@
namespace mbgl {
-class FileSource;
class Scheduler;
class RendererFrontend;
@@ -34,11 +34,9 @@ class Map : private util::noncopyable {
public:
explicit Map(RendererFrontend&,
MapObserver&,
- Size size,
- float pixelRatio,
- FileSource&,
Scheduler&,
- const MapOptions&);
+ const MapOptions&,
+ const ResourceOptions&);
~Map();
// Register a callback that will get called (on the render thread) when all resources have
@@ -87,26 +85,17 @@ public:
/// @}
- // North Orientation
+ // Map Options
void setNorthOrientation(NorthOrientation);
- NorthOrientation getNorthOrientation() const;
-
- // Constrain mode
void setConstrainMode(ConstrainMode);
- ConstrainMode getConstrainMode() const;
-
- // Viewport mode
void setViewportMode(ViewportMode);
- ViewportMode getViewportMode() const;
+ void setSize(Size);
+ MapOptions getMapOptions() const;
//Projection Mode
void setProjectionMode(const ProjectionMode&);
ProjectionMode getProjectionMode() const;
- // Size
- void setSize(Size);
- Size getSize() const;
-
// Projection
ScreenCoordinate pixelForLatLng(const LatLng&) const;
LatLng latLngForPixel(const ScreenCoordinate&) const;
@@ -137,9 +126,12 @@ public:
bool isFullyLoaded() const;
void dumpDebugLogs() const;
-private:
+protected:
class Impl;
const std::unique_ptr<Impl> impl;
+
+ // For testing only.
+ Map(std::unique_ptr<Impl>);
};
} // namespace mbgl
diff --git a/include/mbgl/map/map_observer.hpp b/include/mbgl/map/map_observer.hpp
index 8ad9e93d0b..75e389df9f 100644
--- a/include/mbgl/map/map_observer.hpp
+++ b/include/mbgl/map/map_observer.hpp
@@ -1,6 +1,7 @@
#pragma once
#include <mbgl/style/source.hpp>
+#include <mbgl/style/image.hpp>
#include <cstdint>
#include <string>
@@ -46,6 +47,7 @@ public:
virtual void onDidFinishLoadingStyle() {}
virtual void onSourceChanged(style::Source&) {}
virtual void onDidBecomeIdle() {}
+ virtual void onStyleImageMissing(const std::string&) {}
};
} // namespace mbgl
diff --git a/include/mbgl/map/map_options.hpp b/include/mbgl/map/map_options.hpp
index 13772332a8..fcb8c8f32f 100644
--- a/include/mbgl/map/map_options.hpp
+++ b/include/mbgl/map/map_options.hpp
@@ -1,16 +1,17 @@
#pragma once
#include <mbgl/map/mode.hpp>
+#include <mbgl/util/geo.hpp>
+#include <mbgl/util/size.hpp>
#include <memory>
-#include <string>
namespace mbgl {
/**
* @brief Holds values for Map options.
*/
-class MapOptions {
+class MapOptions final {
public:
/**
* @brief Constructs a MapOptions object with default values.
@@ -18,13 +19,15 @@ public:
MapOptions();
~MapOptions();
+ MapOptions(MapOptions&&) noexcept;
+
/**
* @brief Sets the map rendering mode. By default, it is set to Continuous
* so the map will render as data arrives from the network and react
* immediately to state changes.
*
* @param mode Map rendering mode.
- * @return reference to MapOptions for chaining options together.
+ * @return MapOptions for chaining options together.
*/
MapOptions& withMapMode(MapMode mode);
@@ -41,7 +44,7 @@ public:
* HeightOnly.
*
* @param mode Map constrain mode.
- * @return reference to MapOptions for chaining options together.
+ * @return MapOptions for chaining options together.
*/
MapOptions& withConstrainMode(ConstrainMode mode);
@@ -57,7 +60,7 @@ public:
* orientation of the map as some devices may use inverted orientation.
*
* @param mode Viewport mode.
- * @return reference to MapOptions for chaining options together.
+ * @return MapOptions for chaining options together.
*/
MapOptions& withViewportMode(ViewportMode mode);
@@ -69,71 +72,71 @@ public:
ViewportMode viewportMode() const;
/**
- * @brief Sets the cache path.
+ * @brief Specify whether to enable cross-source symbol collision detection
+ * or not. By default, it is set to true.
*
- * @param path Cache path.
- * @return reference to MapOptions for chaining options together.
+ * @param enableCollisions true to enable, false to disable
+ * @return MapOptions for chaining options together.
*/
- MapOptions& withCachePath(std::string path);
+ MapOptions& withCrossSourceCollisions(bool enableCollisions);
/**
- * @brief Gets the previously set (or default) cache path.
+ * @brief Gets the previously set (or default) crossSourceCollisions value.
*
- * @return cache path
+ * @return true if ecross-source symbol collision detection enabled,
+ * false otherwise.
*/
- const std::string& cachePath() const;
+ bool crossSourceCollisions() const;
/**
- * @brief Sets the asset path, which is the root directory from where
- * the asset:// scheme gets resolved in a style.
+ * @brief Sets the orientation of the Map. By default, it is set to
+ * Upwards.
*
- * @param path Asset path.
+ * @param orientation Orientation of the Map.
* @return reference to MapOptions for chaining options together.
*/
- MapOptions& withAssetRoot(std::string path);
+ MapOptions& withNorthOrientation(NorthOrientation orientation);
/**
- * @brief Gets the previously set (or default) asset path.
+ * @brief Gets the previously set (or default) orientation.
*
- * @return asset path
+ * @return Map orientation.
*/
- const std::string& assetRoot() const;
+ NorthOrientation northOrientation() const;
/**
- * @brief Sets the maximum cache size.
+ * @brief Sets the size to resize the map object and renderer backend.
*
- * @param size Cache maximum size in bytes.
+ * @param size_ A size given in logical pixels.
* @return reference to MapOptions for chaining options together.
*/
- MapOptions& withMaximumCacheSize(uint64_t size);
+ MapOptions& withSize(Size size_);
/**
- * @brief Gets the previously set (or default) maximum allowed cache size.
+ * @brief Gets the previously set size.
*
- * @return maximum allowed cache database size in bytes.
+ * @return Size.
*/
- uint64_t maximumCacheSize() const;
+ Size size() const;
/**
- * @brief Specify whether to enable cross-source symbol collision detection
- * or not. By default, it is set to true.
+ * @brief Sets the custom pixel ratio. By default, it is set to 1.
*
- * @param enableCollisions true to enable, false to disable
+ * @param ratio Pixel ratio value.
* @return reference to MapOptions for chaining options together.
*/
- MapOptions& withCrossSourceCollisions(bool enableCollisions);
+ MapOptions& withPixelRatio(float ratio);
/**
- * @brief Gets the previously set (or default) crossSourceCollisions value.
+ * @brief Gets the previously set (or default) pixel ratio value.
*
- * @return true if ecross-source symbol collision detection enabled,
- * false otherwise.
+ * @return pixel ratio value.
*/
- bool crossSourceCollisions() const;
+ float pixelRatio() const;
private:
class Impl;
- std::shared_ptr<Impl> impl_;
+ std::unique_ptr<Impl> impl_;
};
} // namespace mbgl
diff --git a/include/mbgl/renderer/renderer.hpp b/include/mbgl/renderer/renderer.hpp
index 1d92f9c0cb..0bed4cdaa8 100644
--- a/include/mbgl/renderer/renderer.hpp
+++ b/include/mbgl/renderer/renderer.hpp
@@ -34,6 +34,8 @@ public:
void render(const UpdateParameters&);
+ void flush();
+
// Feature queries
std::vector<Feature> queryRenderedFeatures(const ScreenLineString&, const RenderedQueryOptions& options = {}) const;
std::vector<Feature> queryRenderedFeatures(const ScreenCoordinate& point, const RenderedQueryOptions& options = {}) const;
diff --git a/include/mbgl/renderer/renderer_observer.hpp b/include/mbgl/renderer/renderer_observer.hpp
index 0a76d01ca7..1a9d3ff9bc 100644
--- a/include/mbgl/renderer/renderer_observer.hpp
+++ b/include/mbgl/renderer/renderer_observer.hpp
@@ -31,6 +31,10 @@ public:
// Final frame
virtual void onDidFinishRenderingMap() {}
+
+ // Style is missing an image
+ using StyleImageMissingCallback = std::function<void()>;
+ virtual void onStyleImageMissing(const std::string&, StyleImageMissingCallback done) { done(); }
};
} // namespace mbgl
diff --git a/include/mbgl/storage/default_file_source.hpp b/include/mbgl/storage/default_file_source.hpp
index 5f6999e99f..8f88964acf 100644
--- a/include/mbgl/storage/default_file_source.hpp
+++ b/include/mbgl/storage/default_file_source.hpp
@@ -28,7 +28,7 @@ public:
* of megabytes).
*/
DefaultFileSource(const std::string& cachePath,
- const std::string& assetRoot,
+ const std::string& assetPath,
uint64_t maximumCacheSize = util::DEFAULT_MAX_CACHE_SIZE);
DefaultFileSource(const std::string& cachePath,
std::unique_ptr<FileSource>&& assetFileSource,
diff --git a/include/mbgl/storage/file_source.hpp b/include/mbgl/storage/file_source.hpp
index 0709a1c245..868dbf7347 100644
--- a/include/mbgl/storage/file_source.hpp
+++ b/include/mbgl/storage/file_source.hpp
@@ -1,16 +1,21 @@
#pragma once
+#include <mbgl/actor/actor_ref.hpp>
#include <mbgl/storage/response.hpp>
#include <mbgl/storage/resource.hpp>
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/async_request.hpp>
+#include <mbgl/util/optional.hpp>
#include <functional>
#include <memory>
namespace mbgl {
+class ResourceOptions;
+class ResourceTransform;
+
class FileSource : private util::noncopyable {
public:
virtual ~FileSource() = default;
@@ -31,6 +36,13 @@ public:
virtual bool supportsCacheOnlyRequests() const {
return false;
}
+
+ // Factory for creating a platform-specific file source.
+ static std::shared_ptr<FileSource> createPlatformFileSource(const ResourceOptions&);
+
+ // Singleton for obtaining the shared platform-specific file source. A single instance of a file source is provided
+ // for each unique combination of a Mapbox API base URL, access token, cache path and platform context.
+ static std::shared_ptr<FileSource> getSharedFileSource(const ResourceOptions&);
};
} // namespace mbgl
diff --git a/include/mbgl/storage/offline.hpp b/include/mbgl/storage/offline.hpp
index b3d258a7e3..f884c8b465 100644
--- a/include/mbgl/storage/offline.hpp
+++ b/include/mbgl/storage/offline.hpp
@@ -153,7 +153,7 @@ public:
bool requiredResourceCountIsPrecise = false;
bool complete() const {
- return completedResourceCount == requiredResourceCount;
+ return completedResourceCount >= requiredResourceCount;
}
};
diff --git a/include/mbgl/storage/resource_options.hpp b/include/mbgl/storage/resource_options.hpp
new file mode 100644
index 0000000000..6d603b8cca
--- /dev/null
+++ b/include/mbgl/storage/resource_options.hpp
@@ -0,0 +1,122 @@
+#pragma once
+
+#include <memory>
+#include <string>
+
+namespace mbgl {
+
+/**
+ * @brief Holds values for resource options.
+ */
+class ResourceOptions final {
+public:
+ /**
+ * @brief Constructs a ResourceOptions object with default values.
+ */
+ ResourceOptions();
+ ~ResourceOptions();
+
+ ResourceOptions(ResourceOptions&&) noexcept;
+
+ ResourceOptions clone() const;
+
+ /**
+ * @brief Sets the Mapbox access token - see https://docs.mapbox.com/help/how-mapbox-works/access-tokens/ for details.
+ *
+ * @param token Mapbox access token.
+ * @return ResourceOptions for chaining options together.
+ */
+ ResourceOptions& withAccessToken(std::string token);
+
+ /**
+ * @brief Gets the previously set (or default) Mapbox access token.
+ *
+ * @return const std::string& Mapbox access token.
+ */
+ const std::string& accessToken() const;
+
+ /**
+ * @brief Sets the API base URL. Default is https://api.mapbox.com for Mapbox.
+ *
+ * @param baseURL API base URL.
+ * @return ResourceOptions for chaining options together.
+ */
+ ResourceOptions& withBaseURL(std::string baseURL);
+
+ /**
+ * @brief Gets the previously set (or default) API base URL.
+ *
+ * @return const std::string& API base URL.
+ */
+ const std::string& baseURL() const;
+
+ /**
+ * @brief Sets the cache path.
+ *
+ * @param path Cache path.
+ * @return ResourceOptions for chaining options together.
+ */
+ ResourceOptions& withCachePath(std::string path);
+
+ /**
+ * @brief Gets the previously set (or default) cache path.
+ *
+ * @return cache path
+ */
+ const std::string& cachePath() const;
+
+ /**
+ * @brief Sets the asset path, which is the root directory from where
+ * the asset:// scheme gets resolved in a style.
+ *
+ * @param path Asset path.
+ * @return ResourceOptions for chaining options together.
+ */
+ ResourceOptions& withAssetPath(std::string path);
+
+ /**
+ * @brief Gets the previously set (or default) asset path.
+ *
+ * @return asset path
+ */
+ const std::string& assetPath() const;
+
+ /**
+ * @brief Sets the maximum cache size.
+ *
+ * @param size Cache maximum size in bytes.
+ * @return reference to ResourceOptions for chaining options together.
+ */
+ ResourceOptions& withMaximumCacheSize(uint64_t size);
+
+ /**
+ * @brief Gets the previously set (or default) maximum allowed cache size.
+ *
+ * @return maximum allowed cache database size in bytes.
+ */
+ uint64_t maximumCacheSize() const;
+
+ /**
+ * @brief Sets the platform context. A platform context is usually an object
+ * that assists the creation of a file source.
+ *
+ * @param context Platform context.
+ * @return reference to ResourceOptions for chaining options together.
+ */
+ ResourceOptions& withPlatformContext(void* context);
+
+ /**
+ * @brief Gets the previously set (or default) platform context.
+ *
+ * @return Platform context.
+ */
+ void* platformContext() const;
+
+private:
+ ResourceOptions(const ResourceOptions&);
+
+ class Impl;
+ std::unique_ptr<Impl> impl_;
+};
+
+} // namespace mbgl
diff --git a/include/mbgl/style/conversion/constant.hpp b/include/mbgl/style/conversion/constant.hpp
index 40657528c4..3a5833be64 100644
--- a/include/mbgl/style/conversion/constant.hpp
+++ b/include/mbgl/style/conversion/constant.hpp
@@ -34,6 +34,11 @@ struct Converter<T, typename std::enable_if_t<std::is_enum<T>::value>> {
optional<T> operator()(const Convertible& value, Error& error) const;
};
+template <class T>
+struct Converter<std::vector<T>, typename std::enable_if_t<std::is_enum<T>::value>> {
+ optional<std::vector<T>> operator()(const Convertible& value, Error& error) const;
+};
+
template <>
struct Converter<Color> {
optional<Color> operator()(const Convertible& value, Error& error) const;
diff --git a/include/mbgl/style/layers/symbol_layer.hpp b/include/mbgl/style/layers/symbol_layer.hpp
index 764f1585f6..35fe72e6bf 100644
--- a/include/mbgl/style/layers/symbol_layer.hpp
+++ b/include/mbgl/style/layers/symbol_layer.hpp
@@ -134,6 +134,14 @@ public:
PropertyValue<TextJustifyType> getTextJustify() const;
void setTextJustify(PropertyValue<TextJustifyType>);
+ static PropertyValue<float> getDefaultTextRadialOffset();
+ PropertyValue<float> getTextRadialOffset() const;
+ void setTextRadialOffset(PropertyValue<float>);
+
+ static PropertyValue<std::vector<TextVariableAnchorType>> getDefaultTextVariableAnchor();
+ PropertyValue<std::vector<TextVariableAnchorType>> getTextVariableAnchor() const;
+ void setTextVariableAnchor(PropertyValue<std::vector<TextVariableAnchorType>>);
+
static PropertyValue<SymbolAnchorType> getDefaultTextAnchor();
PropertyValue<SymbolAnchorType> getTextAnchor() const;
void setTextAnchor(PropertyValue<SymbolAnchorType>);
diff --git a/include/mbgl/style/types.hpp b/include/mbgl/style/types.hpp
index ed875733c7..628e0d2395 100644
--- a/include/mbgl/style/types.hpp
+++ b/include/mbgl/style/types.hpp
@@ -81,6 +81,7 @@ enum class AlignmentType : uint8_t {
};
enum class TextJustifyType : uint8_t {
+ Auto,
Center,
Left,
Right
@@ -98,6 +99,8 @@ enum class SymbolAnchorType : uint8_t {
BottomRight
};
+using TextVariableAnchorType = SymbolAnchorType;
+
enum class TextTransformType : uint8_t {
None,
Uppercase,
diff --git a/include/mbgl/util/constants.hpp b/include/mbgl/util/constants.hpp
index b39b3a83e9..f7799a953f 100644
--- a/include/mbgl/util/constants.hpp
+++ b/include/mbgl/util/constants.hpp
@@ -41,6 +41,9 @@ constexpr float MIN_ZOOM_F = MIN_ZOOM;
constexpr float MAX_ZOOM_F = MAX_ZOOM;
constexpr uint8_t DEFAULT_MAX_ZOOM = 22;
+// ONE_EM constant used to go between "em" units used in style spec and "points" used internally for layout.
+constexpr float ONE_EM = 24.0f;
+
constexpr uint8_t DEFAULT_PREFETCH_ZOOM_DELTA = 4;
constexpr uint64_t DEFAULT_MAX_CACHE_SIZE = 50 * 1024 * 1024;
diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md
index 7a117f4b2a..55cfd1a6cd 100644
--- a/platform/android/CHANGELOG.md
+++ b/platform/android/CHANGELOG.md
@@ -4,6 +4,48 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to
## master
+## 7.4.0-alpha.1 - April 3, 2019
+
+### Bugs
+ - Clean up location permissions annotation [#14311](https://github.com/mapbox/mapbox-gl-native/pull/14311)
+ - Clear camera callbacks' message queue when the map is destroyed [#14292](https://github.com/mapbox/mapbox-gl-native/pull/14292)
+ - Use a valid gestures focal point when resetting a manager [#14284](https://github.com/mapbox/mapbox-gl-native/pull/14284)
+ - Disable move gesture detector foreseeing the quickzoom [#14268](https://github.com/mapbox/mapbox-gl-native/pull/14268)
+ - Remove request render from MapboxMap#onStart [#14245](https://github.com/mapbox/mapbox-gl-native/pull/14245)
+ - Use TurfMeasurement#distance in LatLng#distanceTo [#14220](https://github.com/mapbox/mapbox-gl-native/pull/14220)
+
+### Features
+ - Add pixel dimension annotation to public UiSettings methods [#14281](https://github.com/mapbox/mapbox-gl-native/pull/14281)
+ - Add #toString override for formatted sections [#14247](https://github.com/mapbox/mapbox-gl-native/pull/14247)
+ - Harden fetching camera for bounds when padding is excessive [#14221](https://github.com/mapbox/mapbox-gl-native/pull/14221)
+ - Traverse expression tree when checking for property overrides [#14259](https://github.com/mapbox/mapbox-gl-native/pull/14259)
+ - Variable label placement [#14184](https://github.com/mapbox/mapbox-gl-native/pull/14184)
+
+### Build
+ - Disable binary programs until we fix [#14294]((https://github.com/mapbox/mapbox-gl-native/pull/14298)
+ - Disable leak canary during instrumentation tests [#14296](https://github.com/mapbox/mapbox-gl-native/pull/14296)
+ - Remove Android v7 support library [#14265](https://github.com/mapbox/mapbox-gl-native/pull/14265)
+
+## 7.3.0 - March 28, 2019
+
+### Bugs
+ - Fix MapView reuse issues [#14127](https://github.com/mapbox/mapbox-gl-native/pull/14127)
+ - Don't call OnSurfaceCreated from the main thread [#14244](https://github.com/mapbox/mapbox-gl-native/pull/14244)
+
+## 7.3.0-beta.1 - March 20, 2019
+
+### Features
+ - Expose "text-color" option for formatted sections [#14128](https://github.com/mapbox/mapbox-gl-native/pull/14128)
+ - Expose LocationComponent's layer IDs [#14155](https://github.com/mapbox/mapbox-gl-native/pull/14155)
+
+### Bugs
+ - Cache location layer IDs in a set instead of a list [#14141](https://github.com/mapbox/mapbox-gl-native/pull/14141)
+ - Clear the style object when the map is destroyed [#14171](https://github.com/mapbox/mapbox-gl-native/pull/14171)
+ - Cache source/layer only when successfully added [#14171](https://github.com/mapbox/mapbox-gl-native/pull/14171)
+
+### Build
+ - Bump telemetry version to 4.3.0 [#14140](https://github.com/mapbox/mapbox-gl-native/pull/14140)
+
## 7.3.0-alpha.2 - March 13, 2019
### Features
diff --git a/platform/android/LICENSE.md b/platform/android/LICENSE.md
index f69b393541..d6f4e65302 100644
--- a/platform/android/LICENSE.md
+++ b/platform/android/LICENSE.md
@@ -1,11 +1,5 @@
<!-- This file was generated. Use `make android-license` to update. -->
## Additional Mapbox GL licenses
-Mapbox GL uses portions of the Android AppCompat Library v7.
-URL: [http://developer.android.com/tools/extras/support-library.html](http://developer.android.com/tools/extras/support-library.html)
-License: [The Apache Software License](http://www.apache.org/licenses/LICENSE-2.0.txt)
-
-===========================================================================
-
Mapbox GL uses portions of the Android Arch-Common.
URL: [https://developer.android.com/topic/libraries/architecture/index.html](https://developer.android.com/topic/libraries/architecture/index.html)
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
@@ -18,18 +12,6 @@ License: [The Apache Software License, Version 2.0](http://www.apache.org/licens
===========================================================================
-Mapbox GL uses portions of the Android Lifecycle Extensions.
-URL: [https://developer.android.com/topic/libraries/architecture/index.html](https://developer.android.com/topic/libraries/architecture/index.html)
-License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-
-===========================================================================
-
-Mapbox GL uses portions of the Android Lifecycle LiveData.
-URL: [https://developer.android.com/topic/libraries/architecture/index.html](https://developer.android.com/topic/libraries/architecture/index.html)
-License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
-
-===========================================================================
-
Mapbox GL uses portions of the Android Lifecycle LiveData Core.
URL: [https://developer.android.com/topic/libraries/architecture/index.html](https://developer.android.com/topic/libraries/architecture/index.html)
License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
@@ -54,12 +36,6 @@ License: [The Apache Software License, Version 2.0](http://www.apache.org/licens
===========================================================================
-Mapbox GL uses portions of the Android Support AnimatedVectorDrawable.
-URL: [http://developer.android.com/tools/extras/support-library.html](http://developer.android.com/tools/extras/support-library.html)
-License: [The Apache Software License](http://www.apache.org/licenses/LICENSE-2.0.txt)
-
-===========================================================================
-
Mapbox GL uses portions of the Android Support Library Annotations.
URL: [http://developer.android.com/tools/extras/support-library.html](http://developer.android.com/tools/extras/support-library.html)
License: [The Apache Software License](http://www.apache.org/licenses/LICENSE-2.0.txt)
@@ -90,12 +66,6 @@ License: [The Apache Software License](http://www.apache.org/licenses/LICENSE-2.
===========================================================================
-Mapbox GL uses portions of the Android Support VectorDrawable.
-URL: [http://developer.android.com/tools/extras/support-library.html](http://developer.android.com/tools/extras/support-library.html)
-License: [The Apache Software License](http://www.apache.org/licenses/LICENSE-2.0.txt)
-
-===========================================================================
-
Mapbox GL uses portions of the Converter: Gson.
License: [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt)
@@ -157,6 +127,12 @@ License: [Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
===========================================================================
+Mapbox GL uses portions of the ReLinker.
+URL: [https://github.com/KeepSafe/ReLinker](https://github.com/KeepSafe/ReLinker)
+License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt)
+
+===========================================================================
+
Mapbox GL uses portions of the Retrofit.
License: [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt)
diff --git a/platform/android/MapboxGLAndroidSDK/build.gradle b/platform/android/MapboxGLAndroidSDK/build.gradle
index 89937448e9..74c7c4c465 100644
--- a/platform/android/MapboxGLAndroidSDK/build.gradle
+++ b/platform/android/MapboxGLAndroidSDK/build.gradle
@@ -8,7 +8,6 @@ dependencies {
api dependenciesList.mapboxJavaGeoJSON
api dependenciesList.mapboxAndroidGestures
implementation dependenciesList.mapboxJavaTurf
- implementation dependenciesList.supportAppcompatV7
implementation dependenciesList.supportAnnotations
implementation dependenciesList.supportFragmentV4
implementation dependenciesList.okhttp3
@@ -23,10 +22,6 @@ dependencies {
android {
compileSdkVersion androidVersions.compileSdkVersion
- // Roboelectric 4.0 required config
- // http://robolectric.org/migrating/#migrating-to-40
- testOptions.unitTests.includeAndroidResources = true
-
defaultConfig {
minSdkVersion androidVersions.minSdkVersion
targetSdkVersion androidVersions.targetSdkVersion
@@ -134,12 +129,16 @@ android {
testOptions {
unitTests {
returnDefaultValues true
+
+ // Roboelectric 4.0 required config
+ // http://robolectric.org/migrating/#migrating-to-40
includeAndroidResources = true
}
}
buildTypes {
debug {
+ testCoverageEnabled true
jniDebuggable true
}
}
@@ -169,4 +168,5 @@ apply from: "${rootDir}/gradle/gradle-checkstyle.gradle"
apply from: "${rootDir}/gradle/gradle-dependencies-graph.gradle"
apply from: "${rootDir}/gradle/gradle-update-vendor-modules.gradle"
apply from: "${rootDir}/gradle/android-nitpick.gradle"
-apply from: "${rootDir}/gradle/gradle-bintray.gradle" \ No newline at end of file
+apply from: "${rootDir}/gradle/gradle-bintray.gradle"
+apply from: "${rootDir}/gradle/jacoco-report.gradle" \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/gradle.properties b/platform/android/MapboxGLAndroidSDK/gradle.properties
index be4246a903..5f3ea808fa 100644
--- a/platform/android/MapboxGLAndroidSDK/gradle.properties
+++ b/platform/android/MapboxGLAndroidSDK/gradle.properties
@@ -1,4 +1,4 @@
-VERSION_NAME=7.3.0-SNAPSHOT
+VERSION_NAME=7.4.0-SNAPSHOT
# Only build native dependencies for the current ABI
# See https://code.google.com/p/android/issues/detail?id=221098#c20
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java
index 8ae388549e..ce12489b49 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java
@@ -5,10 +5,14 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.FloatRange;
import android.support.annotation.Keep;
-
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
+
+import com.mapbox.geojson.Point;
import com.mapbox.mapboxsdk.constants.GeometryConstants;
+import com.mapbox.turf.TurfMeasurement;
+
+import static com.mapbox.turf.TurfConstants.UNIT_METRES;
/**
@@ -209,7 +213,8 @@ public class LatLng implements Parcelable {
@NonNull
public LatLng wrap() {
return new LatLng(latitude, wrap(longitude,
- GeometryConstants.MIN_WRAP_LONGITUDE, GeometryConstants.MAX_WRAP_LONGITUDE));
+ GeometryConstants.MIN_WRAP_LONGITUDE, GeometryConstants.MAX_WRAP_LONGITUDE)
+ );
}
@@ -218,8 +223,10 @@ public class LatLng implements Parcelable {
* <p>
* Same formula as used in Core GL (wrap.hpp)
* std::fmod((std::fmod((value - min), d) + d), d) + min;
- *
+ * </p>
+ * <p>
* Multiples of max value will be wrapped to max.
+ * </p>
*
* @param value Value to wrap
* @param min Minimum value
@@ -318,24 +325,10 @@ public class LatLng implements Parcelable {
* @return distance in meters
*/
public double distanceTo(@NonNull LatLng other) {
- if (latitude == other.latitude && longitude == other.longitude) {
- // return 0.0 to avoid a NaN
- return 0.0;
- }
-
- final double a1 = Math.toRadians(this.latitude);
- final double a2 = Math.toRadians(this.longitude);
- final double b1 = Math.toRadians(other.getLatitude());
- final double b2 = Math.toRadians(other.getLongitude());
-
- final double cosa1 = Math.cos(a1);
- final double cosb1 = Math.cos(b1);
-
- final double t1 = cosa1 * Math.cos(a2) * cosb1 * Math.cos(b2);
- final double t2 = cosa1 * Math.sin(a2) * cosb1 * Math.sin(b2);
- final double t3 = Math.sin(a1) * Math.sin(b1);
- final double tt = Math.acos(t1 + t2 + t3);
-
- return GeometryConstants.RADIUS_EARTH_METERS * tt;
+ return TurfMeasurement.distance(
+ Point.fromLngLat(longitude, latitude),
+ Point.fromLngLat(other.getLongitude(), other.getLatitude()),
+ UNIT_METRES
+ );
}
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationCameraController.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationCameraController.java
index 4e56c6e9c0..b9aa371a47 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationCameraController.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationCameraController.java
@@ -77,9 +77,11 @@ final class LocationCameraController {
void initializeOptions(LocationComponentOptions options) {
this.options = options;
if (options.trackingGesturesManagement()) {
- mapboxMap.setGesturesManager(internalGesturesManager, true, true);
+ if (mapboxMap.getGesturesManager() != internalGesturesManager) {
+ mapboxMap.setGesturesManager(internalGesturesManager, true, true);
+ }
adjustGesturesThresholds();
- } else {
+ } else if (mapboxMap.getGesturesManager() != initialGesturesManager) {
mapboxMap.setGesturesManager(initialGesturesManager, true, true);
}
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponent.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponent.java
index b97ab75b5e..327ab3c8ed 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponent.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponent.java
@@ -220,7 +220,6 @@ public final class LocationComponent {
* @param style the proxy object for current map style. More info at {@link Style}
* @deprecated use {@link LocationComponentActivationOptions.Builder} instead
*/
- @RequiresPermission(anyOf = {ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION})
@Deprecated
public void activateLocationComponent(@NonNull Context context, @NonNull Style style) {
activateLocationComponent(context, style,
@@ -237,7 +236,6 @@ public final class LocationComponent {
* there should be no location engine initialized
* @deprecated use {@link LocationComponentActivationOptions.Builder} instead
*/
- @RequiresPermission(anyOf = {ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION})
@Deprecated
public void activateLocationComponent(@NonNull Context context, @NonNull Style style,
boolean useDefaultLocationEngine) {
@@ -259,7 +257,6 @@ public final class LocationComponent {
* @param locationEngineRequest the location request
* @deprecated use {@link LocationComponentActivationOptions.Builder} instead
*/
- @RequiresPermission(anyOf = {ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION})
@Deprecated
public void activateLocationComponent(@NonNull Context context, @NonNull Style style,
boolean useDefaultLocationEngine,
@@ -284,7 +281,6 @@ public final class LocationComponent {
* @param options the options
* @deprecated use {@link LocationComponentActivationOptions.Builder} instead
*/
- @RequiresPermission(anyOf = {ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION})
@Deprecated
public void activateLocationComponent(@NonNull Context context, @NonNull Style style,
boolean useDefaultLocationEngine,
@@ -309,7 +305,6 @@ public final class LocationComponent {
* @param styleRes the LocationComponent style res
* @deprecated use {@link LocationComponentActivationOptions.Builder} instead
*/
- @RequiresPermission(anyOf = {ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION})
@Deprecated
public void activateLocationComponent(@NonNull Context context, @NonNull Style style, @StyleRes int styleRes) {
activateLocationComponent(context, style, LocationComponentOptions.createFromAttributes(context, styleRes));
@@ -327,7 +322,6 @@ public final class LocationComponent {
* @param options the options
* @deprecated use {@link LocationComponentActivationOptions.Builder} instead
*/
- @RequiresPermission(anyOf = {ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION})
@Deprecated
public void activateLocationComponent(@NonNull Context context, @NonNull Style style,
@NonNull LocationComponentOptions options) {
@@ -346,7 +340,6 @@ public final class LocationComponent {
* @param styleRes the LocationComponent style res
* @deprecated use {@link LocationComponentActivationOptions.Builder} instead
*/
- @RequiresPermission(anyOf = {ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION})
@Deprecated
public void activateLocationComponent(@NonNull Context context, @NonNull Style style,
@Nullable LocationEngine locationEngine, @StyleRes int styleRes) {
@@ -365,7 +358,6 @@ public final class LocationComponent {
* @param styleRes the LocationComponent style res
* @deprecated use {@link LocationComponentActivationOptions.Builder} instead
*/
- @RequiresPermission(anyOf = {ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION})
@Deprecated
public void activateLocationComponent(@NonNull Context context, @NonNull Style style,
@Nullable LocationEngine locationEngine,
@@ -382,7 +374,6 @@ public final class LocationComponent {
* @param locationEngine the engine
* @deprecated use {@link LocationComponentActivationOptions.Builder} instead
*/
- @RequiresPermission(anyOf = {ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION})
@Deprecated
public void activateLocationComponent(@NonNull Context context, @NonNull Style style,
@Nullable LocationEngine locationEngine) {
@@ -398,7 +389,6 @@ public final class LocationComponent {
* @param locationEngineRequest the location request
* @deprecated use {@link LocationComponentActivationOptions.Builder} instead
*/
- @RequiresPermission(anyOf = {ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION})
@Deprecated
public void activateLocationComponent(@NonNull Context context, @NonNull Style style,
@Nullable LocationEngine locationEngine,
@@ -415,7 +405,6 @@ public final class LocationComponent {
* @param options the options
* @deprecated use {@link LocationComponentActivationOptions.Builder} instead
*/
- @RequiresPermission(anyOf = {ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION})
@Deprecated
public void activateLocationComponent(@NonNull Context context, @NonNull Style style,
@Nullable LocationEngine locationEngine,
@@ -453,8 +442,7 @@ public final class LocationComponent {
*
* @param activationOptions a fully built {@link LocationComponentActivationOptions} object
*/
- public void activateLocationComponent(@NonNull LocationComponentActivationOptions
- activationOptions) {
+ public void activateLocationComponent(@NonNull LocationComponentActivationOptions activationOptions) {
LocationComponentOptions options = activationOptions.locationComponentOptions();
if (options == null) {
int styleRes = activationOptions.styleRes();
@@ -496,6 +484,7 @@ public final class LocationComponent {
*
* @param isEnabled true if the plugin should be visible and listen for location updates, false otherwise.
*/
+ @RequiresPermission(anyOf = {ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION})
public void setLocationComponentEnabled(boolean isEnabled) {
checkActivationState();
if (isEnabled) {
@@ -954,7 +943,6 @@ public final class LocationComponent {
* @return the last known location
*/
@Nullable
- @RequiresPermission(anyOf = {ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION})
public Location getLastKnownLocation() {
checkActivationState();
return lastLocation;
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentConstants.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentConstants.java
index 093c91e799..c0173cb8e8 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentConstants.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentConstants.java
@@ -1,7 +1,7 @@
package com.mapbox.mapboxsdk.location;
/**
- * Contains all the constants being used for the Location layer.
+ * Contains all the constants being used for the {@link LocationComponent}.
*/
final class LocationComponentConstants {
@@ -49,11 +49,31 @@ final class LocationComponentConstants {
static final String PROPERTY_BEARING_ICON = "mapbox-property-shadow-icon";
// Layers
- static final String SHADOW_LAYER = "mapbox-location-shadow";
- static final String FOREGROUND_LAYER = "mapbox-location-layer";
- static final String BACKGROUND_LAYER = "mapbox-location-stroke-layer";
- static final String ACCURACY_LAYER = "mapbox-location-accuracy-layer";
- static final String BEARING_LAYER = "mapbox-location-bearing-layer";
+
+ /**
+ * Layer ID of the location shadow.
+ */
+ public static final String SHADOW_LAYER = "mapbox-location-shadow-layer";
+
+ /**
+ * Layer ID of the location foreground icon.
+ */
+ public static final String FOREGROUND_LAYER = "mapbox-location-foreground-layer";
+
+ /**
+ * Layer ID of the location background icon.
+ */
+ public static final String BACKGROUND_LAYER = "mapbox-location-background-layer";
+
+ /**
+ * Layer ID of the location accuracy.
+ */
+ public static final String ACCURACY_LAYER = "mapbox-location-accuracy-layer";
+
+ /**
+ * Layer ID of the location bearing icon.
+ */
+ public static final String BEARING_LAYER = "mapbox-location-bearing-layer";
// Icons
static final String FOREGROUND_ICON = "mapbox-location-icon";
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationLayerController.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationLayerController.java
index f11acacf31..aa8a82bf6d 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationLayerController.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationLayerController.java
@@ -5,6 +5,7 @@ import android.graphics.PointF;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
+import android.support.annotation.VisibleForTesting;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
@@ -18,7 +19,6 @@ import com.mapbox.mapboxsdk.style.layers.Layer;
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
-import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -70,7 +70,8 @@ final class LocationLayerController {
private LocationComponentOptions options;
private final OnRenderModeChangedListener internalRenderModeChangedListener;
- private final List<String> layerMap = new ArrayList<>();
+ @VisibleForTesting
+ final Set<String> layerSet = new HashSet<>();
private Feature locationFeature;
private GeoJsonSource locationSource;
@@ -112,7 +113,7 @@ final class LocationLayerController {
removeLayers();
addLayers(newLayerBelowOption);
if (isHidden) {
- for (String layerId : layerMap) {
+ for (String layerId : layerSet) {
setLayerVisibility(layerId, false);
}
}
@@ -193,7 +194,7 @@ final class LocationLayerController {
void hide() {
isHidden = true;
- for (String layerId : layerMap) {
+ for (String layerId : layerSet) {
setLayerVisibility(layerId, false);
}
}
@@ -257,14 +258,14 @@ final class LocationLayerController {
private void addLayerToMap(Layer layer, @NonNull String idBelowLayer) {
style.addLayerBelow(layer, idBelowLayer);
- layerMap.add(layer.getId());
+ layerSet.add(layer.getId());
}
private void removeLayers() {
- for (String layerId : layerMap) {
+ for (String layerId : layerSet) {
style.removeLayer(layerId);
}
- layerMap.clear();
+ layerSet.clear();
}
private void setBearingProperty(@NonNull String propertyId, float bearing) {
@@ -351,7 +352,7 @@ final class LocationLayerController {
}
private void styleScaling(@NonNull LocationComponentOptions options) {
- for (String layerId : layerMap) {
+ for (String layerId : layerSet) {
Layer layer = style.getLayer(layerId);
if (layer instanceof SymbolLayer) {
layer.setProperties(
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcher.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcher.java
index b3472ac81e..a1fd4e7e3e 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcher.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcher.java
@@ -142,6 +142,14 @@ class CameraChangeDispatcher implements MapboxMap.OnCameraMoveStartedListener, M
}
}
+ void onDestroy() {
+ handler.removeCallbacksAndMessages(null);
+ onCameraMoveStarted.clear();
+ onCameraMoveCanceled.clear();
+ onCameraMove.clear();
+ onCameraIdle.clear();
+ }
+
private static class CameraChangeHandler extends Handler {
private WeakReference<CameraChangeDispatcher> dispatcherWeakReference;
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java
index c9e6e633aa..9473ea7091 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java
@@ -74,7 +74,7 @@ final class MapGestureDetector {
* User-set focal point.
*/
@Nullable
- private PointF focalPoint;
+ private PointF constantFocalPoint;
private AndroidGesturesManager gesturesManager;
@@ -158,7 +158,7 @@ final class MapGestureDetector {
/**
* Set the gesture focal point.
* <p>
- * this is the center point used for calculate transformations from gestures, value is
+ * This is the center point used for calculate transformations from gestures, value is
* overridden if end user provides his own through {@link UiSettings#setFocalPoint(PointF)}.
* </p>
*
@@ -172,22 +172,7 @@ final class MapGestureDetector {
focalPoint = uiSettings.getFocalPoint();
}
}
- this.focalPoint = focalPoint;
- }
-
- /**
- * Get the current active gesture focal point.
- * <p>
- * This could be either the user provided focal point in
- * {@link UiSettings#setFocalPoint(PointF)}or <code>null</code>.
- * If it's <code>null</code>, gestures will use focal pointed returned by the detector.
- * </p>
- *
- * @return the current active gesture focal point.
- */
- @Nullable
- PointF getFocalPoint() {
- return focalPoint;
+ this.constantFocalPoint = focalPoint;
}
/**
@@ -357,18 +342,25 @@ final class MapGestureDetector {
int action = motionEvent.getActionMasked();
if (action == MotionEvent.ACTION_DOWN) {
executeDoubleTap = true;
+
+ // disable the move detector in preparation for the quickzoom,
+ // so that we don't move the map's center slightly before the quickzoom is started (see #14227)
+ gesturesManager.getMoveGestureDetector().setEnabled(false);
}
if (motionEvent.getActionMasked() == MotionEvent.ACTION_UP) {
+ // re-enabled the move detector
+ gesturesManager.getMoveGestureDetector().setEnabled(true);
+
if (!uiSettings.isZoomGesturesEnabled() || !uiSettings.isDoubleTapGesturesEnabled() || !executeDoubleTap) {
return false;
}
PointF zoomFocalPoint;
// Single finger double tap
- if (focalPoint != null) {
+ if (constantFocalPoint != null) {
// User provided focal point
- zoomFocalPoint = focalPoint;
+ zoomFocalPoint = constantFocalPoint;
} else {
// Zoom in on gesture
zoomFocalPoint = new PointF(motionEvent.getX(), motionEvent.getY());
@@ -468,9 +460,6 @@ final class MapGestureDetector {
private final class ScaleGestureListener extends StandardScaleGestureDetector.SimpleStandardOnScaleGestureListener {
private final float minimumVelocity;
-
- @Nullable
- private PointF scaleFocalPoint;
private boolean quickZoom;
ScaleGestureListener(float minimumVelocity) {
@@ -496,8 +485,6 @@ final class MapGestureDetector {
if (!uiSettings.isQuickZoomGesturesEnabled()) {
return false;
}
- // when quickzoom, disable move gesture
- gesturesManager.getMoveGestureDetector().setEnabled(false);
}
cancelTransitionsIfRequired();
@@ -510,10 +497,7 @@ final class MapGestureDetector {
);
}
- // setting focalPoint in #onScaleBegin() as well, because #onScale() might not get called before #onScaleEnd()
- setScaleFocalPoint(detector);
-
- sendTelemetryEvent(TelemetryConstants.PINCH, scaleFocalPoint);
+ sendTelemetryEvent(TelemetryConstants.PINCH, getScaleFocalPoint(detector));
notifyOnScaleBeginListeners(detector);
@@ -525,11 +509,10 @@ final class MapGestureDetector {
// dispatching camera start event only when the movement actually occurred
cameraChangeDispatcher.onCameraMoveStarted(CameraChangeDispatcher.REASON_API_GESTURE);
- setScaleFocalPoint(detector);
-
float scaleFactor = detector.getScaleFactor();
double zoomBy = getNewZoom(scaleFactor, quickZoom);
- transform.zoomBy(zoomBy, scaleFocalPoint);
+ PointF focalPoint = getScaleFocalPoint(detector);
+ transform.zoomBy(zoomBy, focalPoint);
notifyOnScaleListeners(detector);
@@ -538,11 +521,6 @@ final class MapGestureDetector {
@Override
public void onScaleEnd(@NonNull StandardScaleGestureDetector detector, float velocityX, float velocityY) {
- if (quickZoom) {
- //if quickzoom, re-enabling move gesture detector
- gesturesManager.getMoveGestureDetector().setEnabled(true);
- }
-
if (uiSettings.isIncreaseRotateThresholdWhenScaling()) {
// resetting default angle threshold
gesturesManager.getRotateGestureDetector().setAngleThreshold(
@@ -562,21 +540,23 @@ final class MapGestureDetector {
double zoomAddition = calculateScale(velocityXY, detector.isScalingOut());
double currentZoom = transform.getRawZoom();
+ PointF focalPoint = getScaleFocalPoint(detector);
long animationTime = (long) (Math.abs(zoomAddition) * 1000 / 4);
- scaleAnimator = createScaleAnimator(currentZoom, zoomAddition, scaleFocalPoint, animationTime);
+ scaleAnimator = createScaleAnimator(currentZoom, zoomAddition, focalPoint, animationTime);
scheduleAnimator(scaleAnimator);
}
- private void setScaleFocalPoint(@NonNull StandardScaleGestureDetector detector) {
- if (focalPoint != null) {
+ @NonNull
+ private PointF getScaleFocalPoint(@NonNull StandardScaleGestureDetector detector) {
+ if (constantFocalPoint != null) {
// around user provided focal point
- scaleFocalPoint = focalPoint;
+ return constantFocalPoint;
} else if (quickZoom) {
// around center
- scaleFocalPoint = new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
+ return new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
} else {
// around gesture
- scaleFocalPoint = detector.getFocalPoint();
+ return detector.getFocalPoint();
}
}
@@ -603,14 +583,12 @@ final class MapGestureDetector {
}
private final class RotateGestureListener extends RotateGestureDetector.SimpleOnRotateGestureListener {
- @Nullable
- private PointF rotateFocalPoint;
private final float minimumScaleSpanWhenRotating;
private final float minimumAngularVelocity;
private final float defaultSpanSinceStartThreshold;
- public RotateGestureListener(float minimumScaleSpanWhenRotating, float minimumAngularVelocity,
- float defaultSpanSinceStartThreshold) {
+ RotateGestureListener(float minimumScaleSpanWhenRotating, float minimumAngularVelocity,
+ float defaultSpanSinceStartThreshold) {
this.minimumScaleSpanWhenRotating = minimumScaleSpanWhenRotating;
this.minimumAngularVelocity = minimumAngularVelocity;
this.defaultSpanSinceStartThreshold = defaultSpanSinceStartThreshold;
@@ -631,10 +609,7 @@ final class MapGestureDetector {
gesturesManager.getStandardScaleGestureDetector().interrupt();
}
- // setting in #onRotateBegin() as well, because #onRotate() might not get called before #onRotateEnd()
- setRotateFocalPoint(detector);
-
- sendTelemetryEvent(TelemetryConstants.ROTATION, rotateFocalPoint);
+ sendTelemetryEvent(TelemetryConstants.ROTATION, getRotateFocalPoint(detector));
notifyOnRotateBeginListeners(detector);
@@ -647,13 +622,12 @@ final class MapGestureDetector {
// dispatching camera start event only when the movement actually occurred
cameraChangeDispatcher.onCameraMoveStarted(CameraChangeDispatcher.REASON_API_GESTURE);
- setRotateFocalPoint(detector);
-
// Calculate map bearing value
double bearing = transform.getRawBearing() + rotationDegreesSinceLast;
// Rotate the map
- transform.setBearing(bearing, rotateFocalPoint.x, rotateFocalPoint.y);
+ PointF focalPoint = getRotateFocalPoint(detector);
+ transform.setBearing(bearing, focalPoint.x, focalPoint.y);
notifyOnRotateListeners(detector);
@@ -687,21 +661,24 @@ final class MapGestureDetector {
angularVelocity = -angularVelocity;
}
- rotateAnimator = createRotateAnimator(angularVelocity, animationTime);
+ PointF focalPoint = getRotateFocalPoint(detector);
+ rotateAnimator = createRotateAnimator(angularVelocity, animationTime, focalPoint);
scheduleAnimator(rotateAnimator);
}
- private void setRotateFocalPoint(@NonNull RotateGestureDetector detector) {
- if (focalPoint != null) {
+ @NonNull
+ private PointF getRotateFocalPoint(@NonNull RotateGestureDetector detector) {
+ if (constantFocalPoint != null) {
// User provided focal point
- rotateFocalPoint = focalPoint;
+ return constantFocalPoint;
} else {
// around gesture
- rotateFocalPoint = detector.getFocalPoint();
+ return detector.getFocalPoint();
}
}
- private Animator createRotateAnimator(float angularVelocity, long animationTime) {
+ private Animator createRotateAnimator(float angularVelocity, long animationTime,
+ @NonNull final PointF animationFocalPoint) {
ValueAnimator animator = ValueAnimator.ofFloat(angularVelocity, 0f);
animator.setDuration(animationTime);
animator.setInterpolator(new DecelerateInterpolator());
@@ -710,7 +687,7 @@ final class MapGestureDetector {
public void onAnimationUpdate(@NonNull ValueAnimator animation) {
transform.setBearing(
transform.getRawBearing() + (float) animation.getAnimatedValue(),
- rotateFocalPoint.x, rotateFocalPoint.y,
+ animationFocalPoint.x, animationFocalPoint.y,
0L
);
}
@@ -802,9 +779,9 @@ final class MapGestureDetector {
PointF zoomFocalPoint;
// Single finger double tap
- if (focalPoint != null) {
+ if (constantFocalPoint != null) {
// User provided focal point
- zoomFocalPoint = focalPoint;
+ zoomFocalPoint = constantFocalPoint;
} else {
// Zoom in on gesture
zoomFocalPoint = detector.getFocalPoint();
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 f87c6a854a..23ce2bdef0 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
@@ -911,7 +911,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
/**
* Called when the map has finished rendering.
*
- * @param fully true if map is fully rendered, false if fully rendered
+ * @param fully true if map is fully rendered, false if not fully rendered
*/
void onDidFinishRenderingMap(boolean fully);
}
@@ -1257,4 +1257,4 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
public static void setMapStrictModeEnabled(boolean strictModeEnabled) {
MapStrictMode.setStrictModeEnabled(strictModeEnabled);
}
-} \ No newline at end of file
+}
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 f0155bda58..95d5c29b61 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
@@ -128,7 +128,6 @@ public final class MapboxMap {
* Called when the hosting Activity/Fragment onStart() method is called.
*/
void onStart() {
- nativeMapView.update();
locationComponent.onStart();
}
@@ -174,6 +173,10 @@ public final class MapboxMap {
*/
void onDestroy() {
locationComponent.onDestroy();
+ if (style != null) {
+ style.clear();
+ }
+ cameraChangeDispatcher.onDestroy();
}
/**
@@ -813,7 +816,7 @@ public final class MapboxMap {
public void setStyle(Style.Builder builder, final Style.OnStyleLoaded callback) {
locationComponent.onStartLoadingMap();
if (style != null) {
- style.onWillStartLoadingMap();
+ style.clear();
}
if (callback != null) {
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMap.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMap.java
index cf5961a313..e49126531a 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMap.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMap.java
@@ -29,8 +29,6 @@ interface NativeMap {
// Lifecycle API
//
- void update();
-
void resizeView(int width, int height);
void onLowMemory();
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 10942d521c..a5f8be788c 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
@@ -136,15 +136,6 @@ final class NativeMapView implements NativeMap {
}
@Override
- public void update() {
- if (checkState("update")) {
- return;
- }
-
- mapRenderer.requestRender();
- }
-
- @Override
public void resizeView(int width, int height) {
if (checkState("resizeView")) {
return;
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Style.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Style.java
index f14e034816..5c28b55de8 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Style.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Style.java
@@ -100,8 +100,8 @@ public class Style {
*/
public void addSource(@NonNull Source source) {
validateState("addSource");
- sources.put(source.getId(), source);
nativeMap.addSource(source);
+ sources.put(source.getId(), source);
}
/**
@@ -172,8 +172,8 @@ public class Style {
*/
public void addLayer(@NonNull Layer layer) {
validateState("addLayer");
- layers.put(layer.getId(), layer);
nativeMap.addLayer(layer);
+ layers.put(layer.getId(), layer);
}
/**
@@ -184,8 +184,8 @@ public class Style {
*/
public void addLayerBelow(@NonNull Layer layer, @NonNull String below) {
validateState("addLayerBelow");
- layers.put(layer.getId(), layer);
nativeMap.addLayerBelow(layer, below);
+ layers.put(layer.getId(), layer);
}
/**
@@ -196,8 +196,8 @@ public class Style {
*/
public void addLayerAbove(@NonNull Layer layer, @NonNull String above) {
validateState("addLayerAbove");
- layers.put(layer.getId(), layer);
nativeMap.addLayerAbove(layer, above);
+ layers.put(layer.getId(), layer);
}
/**
@@ -209,8 +209,8 @@ public class Style {
*/
public void addLayerAt(@NonNull Layer layer, @IntRange(from = 0) int index) {
validateState("addLayerAbove");
- layers.put(layer.getId(), layer);
nativeMap.addLayerAt(layer, index);
+ layers.put(layer.getId(), layer);
}
/**
@@ -437,10 +437,11 @@ public class Style {
//
/**
- * Called when the underlying map will start loading a new style. This method will clean up this style
- * by setting the java sources and layers in a detached state and removing them from core.
+ * Called when the underlying map will start loading a new style or the map is destroyed.
+ * This method will clean up this style by setting the java sources and layers
+ * in a detached state and removing them from core.
*/
- void onWillStartLoadingMap() {
+ void clear() {
fullyLoaded = false;
for (Source source : sources.values()) {
if (source != null) {
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 034dc63c35..c671146876 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
@@ -10,6 +10,7 @@ import android.os.Bundle;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
+import android.support.annotation.Px;
import android.support.annotation.UiThread;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.res.ResourcesCompat;
@@ -344,7 +345,7 @@ public final class UiSettings {
}
/**
- * Sets the margins of the compass view. Use this to change the distance of the compass from the
+ * Sets the margins of the compass view in pixels. Use this to change the distance of the compass from the
* map view edge.
*
* @param left The left margin in pixels.
@@ -353,42 +354,46 @@ public final class UiSettings {
* @param bottom The bottom margin in pixels.
*/
@UiThread
- public void setCompassMargins(int left, int top, int right, int bottom) {
+ public void setCompassMargins(@Px int left, @Px int top, @Px int right, @Px int bottom) {
setWidgetMargins(compassView, compassMargins, left, top, right, bottom);
}
/**
- * Returns the left side margin of CompassView
+ * Returns the left side margin of CompassView in pixels.
*
* @return The left margin in pixels
*/
+ @Px
public int getCompassMarginLeft() {
return compassMargins[0];
}
/**
- * Returns the top side margin of CompassView
+ * Returns the top side margin of CompassView in pixels.
*
* @return The top margin in pixels
*/
+ @Px
public int getCompassMarginTop() {
return compassMargins[1];
}
/**
- * Returns the right side margin of CompassView
+ * Returns the right side margin of CompassView in pixels.
*
* @return The right margin in pixels
*/
+ @Px
public int getCompassMarginRight() {
return compassMargins[2];
}
/**
- * Returns the bottom side margin of CompassView
+ * Returns the bottom side margin of CompassView in pixels.
*
* @return The bottom margin in pixels
*/
+ @Px
public int getCompassMarginBottom() {
return compassMargins[3];
}
@@ -456,7 +461,7 @@ public final class UiSettings {
}
/**
- * Sets the margins of the logo view. Use this to change the distance of the Mapbox logo from the
+ * Sets the margins of the logo view in pixels. Use this to change the distance of the Mapbox logo from the
* map view edge.
*
* @param left The left margin in pixels.
@@ -464,42 +469,46 @@ public final class UiSettings {
* @param right The right margin in pixels.
* @param bottom The bottom margin in pixels.
*/
- public void setLogoMargins(int left, int top, int right, int bottom) {
+ public void setLogoMargins(@Px int left, @Px int top, @Px int right, @Px int bottom) {
setWidgetMargins(logoView, logoMargins, left, top, right, bottom);
}
/**
- * Returns the left side margin of the logo
+ * Returns the left side margin of the logo in pixels.
*
* @return The left margin in pixels
*/
+ @Px
public int getLogoMarginLeft() {
return logoMargins[0];
}
/**
- * Returns the top side margin of the logo
+ * Returns the top side margin of the logo in pixels.
*
* @return The top margin in pixels
*/
+ @Px
public int getLogoMarginTop() {
return logoMargins[1];
}
/**
- * Returns the right side margin of the logo
+ * Returns the right side margin of the logo in pixels.
*
* @return The right margin in pixels
*/
+ @Px
public int getLogoMarginRight() {
return logoMargins[2];
}
/**
- * Returns the bottom side margin of the logo
+ * Returns the bottom side margin of the logo in pixels.
*
* @return The bottom margin in pixels
*/
+ @Px
public int getLogoMarginBottom() {
return logoMargins[3];
}
@@ -570,14 +579,14 @@ public final class UiSettings {
}
/**
- * Sets the margins of the attribution view.
+ * Sets the margins of the attribution view in pixels.
*
* @param left The left margin in pixels.
* @param top The top margin in pixels.
* @param right The right margin in pixels.
* @param bottom The bottom margin in pixels.
*/
- public void setAttributionMargins(int left, int top, int right, int bottom) {
+ public void setAttributionMargins(@Px int left, @Px int top, @Px int right, @Px int bottom) {
setWidgetMargins(attributionsView, attributionsMargins, left, top, right, bottom);
}
@@ -599,37 +608,41 @@ public final class UiSettings {
}
/**
- * Returns the left side margin of the attribution view.
+ * Returns the left side margin of the attribution view in pixels.
*
* @return The left margin in pixels
*/
+ @Px
public int getAttributionMarginLeft() {
return attributionsMargins[0];
}
/**
- * Returns the top side margin of the attribution view.
+ * Returns the top side margin of the attribution view in pixels.
*
* @return The top margin in pixels
*/
+ @Px
public int getAttributionMarginTop() {
return attributionsMargins[1];
}
/**
- * Returns the right side margin of the attribution view.
+ * Returns the right side margin of the attribution view in pixels.
*
* @return The right margin in pixels
*/
+ @Px
public int getAttributionMarginRight() {
return attributionsMargins[2];
}
/**
- * Returns the bottom side margin of the logo
+ * Returns the bottom side margin of the logo in pixels.
*
* @return The bottom margin in pixels
*/
+ @Px
public int getAttributionMarginBottom() {
return attributionsMargins[3];
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/glsurfaceview/GLSurfaceViewMapRenderer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/glsurfaceview/GLSurfaceViewMapRenderer.java
index 9d9a7bd2d4..524c1a62ee 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/glsurfaceview/GLSurfaceViewMapRenderer.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/glsurfaceview/GLSurfaceViewMapRenderer.java
@@ -2,10 +2,8 @@ package com.mapbox.mapboxsdk.maps.renderer.glsurfaceview;
import android.content.Context;
import android.opengl.GLSurfaceView;
-
import android.support.annotation.NonNull;
import android.view.SurfaceHolder;
-
import com.mapbox.mapboxsdk.maps.renderer.MapRenderer;
import com.mapbox.mapboxsdk.maps.renderer.egl.EGLConfigChooser;
@@ -25,8 +23,6 @@ public class GLSurfaceViewMapRenderer extends MapRenderer implements GLSurfaceVi
@NonNull
private final GLSurfaceView glSurfaceView;
- private boolean requestDestroy;
-
public GLSurfaceViewMapRenderer(Context context,
GLSurfaceView glSurfaceView,
String localIdeographFontFamily) {
@@ -42,9 +38,8 @@ public class GLSurfaceViewMapRenderer extends MapRenderer implements GLSurfaceVi
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
- requestDestroy = true;
+ onSurfaceDestroyed();
}
-
});
}
@@ -60,9 +55,6 @@ public class GLSurfaceViewMapRenderer extends MapRenderer implements GLSurfaceVi
@Override
public void onDestroy() {
- if (requestDestroy) {
- onSurfaceDestroyed();
- }
super.onDestroy();
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/textureview/TextureViewRenderThread.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/textureview/TextureViewRenderThread.java
index 96d5e9e943..165b15a512 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/textureview/TextureViewRenderThread.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/textureview/TextureViewRenderThread.java
@@ -197,7 +197,6 @@ class TextureViewRenderThread extends Thread implements TextureView.SurfaceTextu
if (destroySurface) {
eglHolder.destroySurface();
destroySurface = false;
- mapRenderer.onSurfaceDestroyed();
break;
}
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 6262418a29..53c0c1c60f 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
@@ -7,10 +7,10 @@ import android.support.annotation.Nullable;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPropertyAnimatorCompat;
import android.support.v4.view.ViewPropertyAnimatorListenerAdapter;
-import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.ImageView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
@@ -23,7 +23,7 @@ import com.mapbox.mapboxsdk.maps.MapboxMap;
* use {@link com.mapbox.mapboxsdk.maps.UiSettings}.
* </p>
*/
-public final class CompassView extends AppCompatImageView implements Runnable {
+public final class CompassView extends ImageView implements Runnable {
public static final long TIME_WAIT_IDLE = 500;
public static final long TIME_MAP_NORTH_ANIMATION = 150;
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/module/telemetry/PerformanceEvent.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/module/telemetry/PerformanceEvent.java
index b88e1885ca..12d1fe46cf 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/module/telemetry/PerformanceEvent.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/module/telemetry/PerformanceEvent.java
@@ -1,20 +1,55 @@
package com.mapbox.mapboxsdk.module.telemetry;
+import com.google.gson.Gson;
+
+import com.google.gson.JsonObject;
+
+import com.google.gson.reflect.TypeToken;
import com.mapbox.android.telemetry.Event;
import android.os.Bundle;
import android.os.Parcel;
+
import java.text.SimpleDateFormat;
+import java.util.ArrayList;
import java.util.Date;
+import java.util.List;
import java.util.Locale;
/**
* Generic Performance Event that can be used for performance measurements.
* Customer measurements can be added to the bundle.
+ *
+ * Bundle is expected to have following properties:
+ * "attributes", "counters", and "metadata" with String values.
+ *
+ * Attributes: a string representing an array of name/string value pair objects.
+ * Counters: a string representing an array of name/number value pair objects.
+ * Metadata is a string representation of a JsonObject with string values.
+ *
+ * Here is an example of a Performance event bundle data:
+ *
+ * "attributes": [{ "name": "style_id", "value": "mapbox://styles/mapbox/streets-v10"}]
+ *
+ * "counters": [{"name": "fps_average", "value": 90.7655486547093},
+ * {"name": "fps_deviation", "value": 29.301809631465574}]
+ * “metadata”: {
+ * “version”: “9”,
+ * “screenSize”: “1080x1794”,
+ * “country”: “US”,
+ * “device”: “Pixel 2”,
+ * “abi”: “arm64-v8a”,
+ * “brand”: “google”,
+ * “ram”: “3834167296”,
+ * “os”: “android”,
+ * “gpu”: “Qualcomm, Adreno (TM) 540, OpenGL ES 3.2 V@313.0 (GIT@7bf2852, Ie32bfa6f6f)“,
+ * “manufacturer”: “Google”
+ * }
*/
public class PerformanceEvent extends Event {
- private static final String PERFORMANCE_TRACE = "performance.trace";
+
+ private static final String PERFORMANCE_TRACE = "mobile.performance_trace";
private final String event;
@@ -22,23 +57,36 @@ public class PerformanceEvent extends Event {
private final String sessionId;
- private final Bundle data;
+ private final List<Attribute<String>> attributes;
+
+ private final List<Attribute<Double>> counters;
+
+ private final JsonObject metadata;
+
private static final SimpleDateFormat DATE_FORMAT =
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US);
- PerformanceEvent(String sessionId, Bundle data) {
+ PerformanceEvent(String sessionId, Bundle bundle) {
+
this.event = PERFORMANCE_TRACE;
this.created = DATE_FORMAT.format(new Date());
this.sessionId = sessionId;
- this.data = data;
+ this.attributes = initList(bundle.getString("attributes"),
+ new TypeToken<ArrayList<Attribute<String>>>() {});
+ this.counters = initList(bundle.getString("counters"),
+ new TypeToken<ArrayList<Attribute<Double>>>() {});
+ this.metadata = initMetaData(bundle.getString("metadata"));
}
private PerformanceEvent(Parcel in) {
this.event = in.readString();
this.created = in.readString();
this.sessionId = in.readString();
- this.data = in.readBundle();
+
+ this.attributes = initList(in.readString(), new TypeToken<ArrayList<Attribute<String>>>() {});
+ this.counters = initList(in.readString(), new TypeToken<ArrayList<Attribute<Double>>>() {});
+ this.metadata = initMetaData(in.readString());
}
@Override
@@ -51,7 +99,30 @@ public class PerformanceEvent extends Event {
parcel.writeString(event);
parcel.writeString(created);
parcel.writeString(sessionId);
- parcel.writeBundle(data);
+
+ Gson gson = new Gson();
+
+ parcel.writeString(gson.toJson(attributes));
+ parcel.writeString(gson.toJson(counters));
+
+ if (metadata != null) {
+ parcel.writeString(metadata.toString());
+ }
+ }
+
+ private <T> ArrayList<Attribute<T>> initList(String fromString, TypeToken typeToken) {
+ if (fromString == null || fromString.isEmpty()) {
+ return new ArrayList<>();
+ }
+ return new Gson().fromJson(fromString, typeToken.getType());
+ }
+
+ private JsonObject initMetaData(String fromString) {
+ if (fromString == null) {
+ return new JsonObject();
+ } else {
+ return new Gson().fromJson(fromString, JsonObject.class);
+ }
}
public static final Creator<PerformanceEvent> CREATOR = new Creator<PerformanceEvent>() {
@@ -65,4 +136,15 @@ public class PerformanceEvent extends Event {
return new PerformanceEvent[size];
}
};
+
+
+ private class Attribute<T> {
+ private final String name;
+ private final T value;
+
+ Attribute(String name, T value) {
+ this.name = name;
+ this.value = value;
+ }
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/module/telemetry/TelemetryImpl.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/module/telemetry/TelemetryImpl.java
index 5e021f961e..697a51286f 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/module/telemetry/TelemetryImpl.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/module/telemetry/TelemetryImpl.java
@@ -111,8 +111,9 @@ public class TelemetryImpl implements TelemetryDefinition {
@Override
public void onPerformanceEvent(Bundle data) {
- if (data != null && !data.isEmpty()) {
- telemetry.push(new PerformanceEvent(UUID.randomUUID().toString(), data));
+ if (data == null) {
+ data = new Bundle();
}
+ telemetry.push(new PerformanceEvent(UUID.randomUUID().toString(), data));
}
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java
index 01ac098d16..8684d7c6f1 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java
@@ -26,7 +26,11 @@ import java.nio.channels.FileChannel;
/**
* The offline manager is the main entry point for offline-related functionality.
+ * <p>
* It'll help you list and create offline regions.
+ * </p>
+ *
+ * @see <a href="https://docs.mapbox.com/help/troubleshooting/mobile-offline/">Offline Maps Information/</a>
*/
public class OfflineManager {
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java
index 1c87b9004b..57cf6271c9 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java
@@ -323,6 +323,10 @@ public final class Property {
// TEXT_JUSTIFY: Text justification options.
/**
+ * The text is aligned towards the anchor position.
+ */
+ public static final String TEXT_JUSTIFY_AUTO = "auto";
+ /**
* The text is aligned to the left.
*/
public static final String TEXT_JUSTIFY_LEFT = "left";
@@ -339,6 +343,7 @@ public final class Property {
* Text justification options.
*/
@StringDef({
+ TEXT_JUSTIFY_AUTO,
TEXT_JUSTIFY_LEFT,
TEXT_JUSTIFY_CENTER,
TEXT_JUSTIFY_RIGHT,
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java
index 3d8b921a79..01908b1b0b 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java
@@ -2276,6 +2276,46 @@ public class PropertyFactory {
}
/**
+ * Radial offset of text, in the direction of the symbol's anchor. Useful in combination with {@link PropertyFactory#textVariableAnchor}, which doesn't support the two-dimensional {@link PropertyFactory#textOffset}.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static PropertyValue<Float> textRadialOffset(Float value) {
+ return new LayoutPropertyValue<>("text-radial-offset", value);
+ }
+
+ /**
+ * Radial offset of text, in the direction of the symbol's anchor. Useful in combination with {@link PropertyFactory#textVariableAnchor}, which doesn't support the two-dimensional {@link PropertyFactory#textOffset}.
+ *
+ * @param value a Float value
+ * @return property wrapper around Float
+ */
+ public static PropertyValue<Expression> textRadialOffset(Expression value) {
+ return new LayoutPropertyValue<>("text-radial-offset", value);
+ }
+
+ /**
+ * To increase the chance of placing high-priority labels on the map, you can provide an array of {@link Property.TEXT_ANCHOR} locations: the render will attempt to place the label at each location, in order, before moving onto the next label. Use `text-justify: auto` to choose justification based on anchor position. To apply an offset, use the {@link PropertyFactory#textRadialOffset} instead of the two-dimensional {@link PropertyFactory#textOffset}.
+ *
+ * @param value a String[] value
+ * @return property wrapper around String[]
+ */
+ public static PropertyValue<String[]> textVariableAnchor(String[] value) {
+ return new LayoutPropertyValue<>("text-variable-anchor", value);
+ }
+
+ /**
+ * To increase the chance of placing high-priority labels on the map, you can provide an array of {@link Property.TEXT_ANCHOR} locations: the render will attempt to place the label at each location, in order, before moving onto the next label. Use `text-justify: auto` to choose justification based on anchor position. To apply an offset, use the {@link PropertyFactory#textRadialOffset} instead of the two-dimensional {@link PropertyFactory#textOffset}.
+ *
+ * @param value a String[] value
+ * @return property wrapper around String[]
+ */
+ public static PropertyValue<Expression> textVariableAnchor(Expression value) {
+ return new LayoutPropertyValue<>("text-variable-anchor", value);
+ }
+
+ /**
* Part of the text placed closest to the anchor.
*
* @param value a String value
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/SymbolLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/SymbolLayer.java
index ab45cb04f2..75473f0f30 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/SymbolLayer.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/SymbolLayer.java
@@ -470,6 +470,30 @@ public class SymbolLayer extends Layer {
}
/**
+ * Get the TextRadialOffset property
+ *
+ * @return property wrapper value around Float
+ */
+ @NonNull
+ @SuppressWarnings("unchecked")
+ public PropertyValue<Float> getTextRadialOffset() {
+ checkThread();
+ return (PropertyValue<Float>) new PropertyValue("text-radial-offset", nativeGetTextRadialOffset());
+ }
+
+ /**
+ * Get the TextVariableAnchor property
+ *
+ * @return property wrapper value around String[]
+ */
+ @NonNull
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String[]> getTextVariableAnchor() {
+ checkThread();
+ return (PropertyValue<String[]>) new PropertyValue("text-variable-anchor", nativeGetTextVariableAnchor());
+ }
+
+ /**
* Get the TextAnchor property
*
* @return property wrapper value around String
@@ -1187,6 +1211,14 @@ public class SymbolLayer extends Layer {
@NonNull
@Keep
+ private native Object nativeGetTextRadialOffset();
+
+ @NonNull
+ @Keep
+ private native Object nativeGetTextVariableAnchor();
+
+ @NonNull
+ @Keep
private native Object nativeGetTextAnchor();
@NonNull
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/types/Formatted.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/types/Formatted.java
index fb2d361bfc..b76e4f4417 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/types/Formatted.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/types/Formatted.java
@@ -58,4 +58,12 @@ public class Formatted {
public int hashCode() {
return Arrays.hashCode(formattedSections);
}
+
+ @Override
+ public String toString() {
+ return "Formatted{"
+ + "formattedSections="
+ + Arrays.toString(formattedSections)
+ + '}';
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/types/FormattedSection.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/types/FormattedSection.java
index a5b0dfbfe8..859fcff378 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/types/FormattedSection.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/types/FormattedSection.java
@@ -228,4 +228,14 @@ public class FormattedSection {
params.put("text-color", textColor);
return new Object[] {text, params};
}
+
+ @Override
+ public String toString() {
+ return "FormattedSection{"
+ + "text='" + text + '\''
+ + ", fontScale=" + fontScale
+ + ", fontStack=" + Arrays.toString(fontStack)
+ + ", textColor='" + textColor + '\''
+ + '}';
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/BitmapUtils.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/BitmapUtils.java
index 3ef8e93cae..3570aa2c0b 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/BitmapUtils.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/BitmapUtils.java
@@ -13,7 +13,6 @@ import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
-import android.support.v7.content.res.AppCompatResources;
import android.view.View;
import java.io.ByteArrayOutputStream;
@@ -152,7 +151,7 @@ public class BitmapUtils {
@Nullable
public static Drawable getDrawableFromRes(@NonNull Context context, @DrawableRes int drawableRes,
@Nullable @ColorInt Integer tintColor) {
- Drawable drawable = AppCompatResources.getDrawable(context, drawableRes);
+ Drawable drawable = context.getResources().getDrawable(drawableRes);
if (drawable == null) {
return null;
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_internal.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_internal.xml
index 1adbe7e769..e5cde7e441 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_internal.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_internal.xml
@@ -7,14 +7,14 @@
android:layout_height="wrap_content"
android:contentDescription="@string/mapbox_compassContentDescription"/>
- <android.support.v7.widget.AppCompatImageView
+ <ImageView
android:visibility="gone"
android:id="@+id/logoView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"/>
- <android.support.v7.widget.AppCompatImageView
+ <ImageView
android:visibility="gone"
android:id="@+id/attributionView"
android:layout_width="wrap_content"
diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java
index 8e47f069c3..862c56a526 100644
--- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java
+++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java
@@ -175,7 +175,7 @@ public class LatLngTest {
LatLng latLng2 = new LatLng(1.0, 1.0);
assertEquals("distances should match",
latLng1.distanceTo(latLng2),
- 157425.53710839353, DELTA);
+ 157298.7453847275, DELTA);
}
@Test
@@ -186,6 +186,15 @@ public class LatLngTest {
assertEquals("distance should match", 0.0, distance, DELTA);
}
+ // Regression test for #14216
+ @Test
+ public void testDistanceToClosePointNotNaN() {
+ LatLng latLng = new LatLng(40.00599, -105.29261);
+ LatLng other = new LatLng(40.005990000000025, -105.29260999999997);
+ double distance = latLng.distanceTo(other);
+ assertNotEquals(distance, Double.NaN);
+ }
+
@Test
public void testLocationProvider() {
double latitude = 1.2;
diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationCameraControllerTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationCameraControllerTest.java
index 56a8f276a7..a3d54fe221 100644
--- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationCameraControllerTest.java
+++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationCameraControllerTest.java
@@ -408,6 +408,7 @@ public class LocationCameraControllerTest {
MapboxMap mapboxMap = mock(MapboxMap.class);
AndroidGesturesManager initialGesturesManager = mock(AndroidGesturesManager.class);
AndroidGesturesManager internalGesturesManager = mock(AndroidGesturesManager.class);
+ when(mapboxMap.getGesturesManager()).thenReturn(initialGesturesManager);
LocationCameraController camera = buildCamera(mapboxMap, initialGesturesManager, internalGesturesManager);
LocationComponentOptions options = mock(LocationComponentOptions.class);
when(options.trackingGesturesManagement()).thenReturn(true);
@@ -421,6 +422,7 @@ public class LocationCameraControllerTest {
MapboxMap mapboxMap = mock(MapboxMap.class);
AndroidGesturesManager initialGesturesManager = mock(AndroidGesturesManager.class);
AndroidGesturesManager internalGesturesManager = mock(AndroidGesturesManager.class);
+ when(mapboxMap.getGesturesManager()).thenReturn(internalGesturesManager);
LocationCameraController camera = buildCamera(mapboxMap, initialGesturesManager, internalGesturesManager);
LocationComponentOptions options = mock(LocationComponentOptions.class);
when(options.trackingGesturesManagement()).thenReturn(false);
@@ -430,6 +432,34 @@ public class LocationCameraControllerTest {
}
@Test
+ public void gesturesManagement_optionNotChangedInitial() {
+ MapboxMap mapboxMap = mock(MapboxMap.class);
+ AndroidGesturesManager initialGesturesManager = mock(AndroidGesturesManager.class);
+ AndroidGesturesManager internalGesturesManager = mock(AndroidGesturesManager.class);
+ when(mapboxMap.getGesturesManager()).thenReturn(initialGesturesManager);
+ LocationCameraController camera = buildCamera(mapboxMap, initialGesturesManager, internalGesturesManager);
+ LocationComponentOptions options = mock(LocationComponentOptions.class);
+ when(options.trackingGesturesManagement()).thenReturn(false);
+ camera.initializeOptions(options);
+
+ verify(mapboxMap, times(0)).setGesturesManager(initialGesturesManager, true, true);
+ }
+
+ @Test
+ public void gesturesManagement_optionNotChangedInternal() {
+ MapboxMap mapboxMap = mock(MapboxMap.class);
+ AndroidGesturesManager initialGesturesManager = mock(AndroidGesturesManager.class);
+ AndroidGesturesManager internalGesturesManager = mock(AndroidGesturesManager.class);
+ when(mapboxMap.getGesturesManager()).thenReturn(internalGesturesManager);
+ LocationCameraController camera = buildCamera(mapboxMap, initialGesturesManager, internalGesturesManager);
+ LocationComponentOptions options = mock(LocationComponentOptions.class);
+ when(options.trackingGesturesManagement()).thenReturn(true);
+ camera.initializeOptions(options);
+
+ verify(mapboxMap, times(0)).setGesturesManager(internalGesturesManager, true, true);
+ }
+
+ @Test
public void onMove_notCancellingTransitionWhileNone() {
MapboxMap mapboxMap = mock(MapboxMap.class);
when(mapboxMap.getUiSettings()).thenReturn(mock(UiSettings.class));
diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.java
index 10553700b3..6a44cf1f79 100644
--- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.java
+++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.java
@@ -39,6 +39,7 @@ import static com.mapbox.mapboxsdk.location.MapboxAnimator.ANIMATOR_LAYER_ACCURA
import static com.mapbox.mapboxsdk.location.MapboxAnimator.ANIMATOR_LAYER_COMPASS_BEARING;
import static com.mapbox.mapboxsdk.location.MapboxAnimator.ANIMATOR_LAYER_GPS_BEARING;
import static com.mapbox.mapboxsdk.location.MapboxAnimator.ANIMATOR_LAYER_LATLNG;
+import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
@@ -160,6 +161,24 @@ public class LocationLayerControllerTest {
}
@Test
+ public void onInitialization_numberOfCachedLayerIdsIsConstant() {
+ OnRenderModeChangedListener internalRenderModeChangedListener = mock(OnRenderModeChangedListener.class);
+ LayerSourceProvider sourceProvider = buildLayerProvider();
+ GeoJsonSource locationSource = mock(GeoJsonSource.class);
+ when(sourceProvider.generateSource(any(Feature.class))).thenReturn(locationSource);
+ LayerBitmapProvider bitmapProvider = mock(LayerBitmapProvider.class);
+ LocationComponentOptions options = mock(LocationComponentOptions.class);
+
+ LocationLayerController controller =
+ new LocationLayerController(mapboxMap, mapboxMap.getStyle(), sourceProvider, buildFeatureProvider(options),
+ bitmapProvider, options, internalRenderModeChangedListener);
+
+ controller.initializeComponents(mapboxMap.getStyle(), options);
+
+ assertEquals(5, controller.layerSet.size());
+ }
+
+ @Test
public void applyStyle_styleShadowWithValidElevation() {
OnRenderModeChangedListener internalRenderModeChangedListener = mock(OnRenderModeChangedListener.class);
LayerSourceProvider sourceProvider = buildLayerProvider();
@@ -300,22 +319,6 @@ public class LocationLayerControllerTest {
LayerSourceProvider sourceProvider = buildLayerProvider();
when(sourceProvider.generateSource(any(Feature.class))).thenReturn(mock(GeoJsonSource.class));
- Layer bearingLayer = mock(Layer.class);
- when(bearingLayer.getId()).thenReturn(BEARING_LAYER);
- when(sourceProvider.generateLayer(BEARING_LAYER)).thenReturn(bearingLayer);
- Layer foregroundLayer = mock(Layer.class);
- when(foregroundLayer.getId()).thenReturn(FOREGROUND_LAYER);
- when(sourceProvider.generateLayer(FOREGROUND_LAYER)).thenReturn(foregroundLayer);
- Layer backgroundLayer = mock(Layer.class);
- when(backgroundLayer.getId()).thenReturn(BACKGROUND_LAYER);
- when(sourceProvider.generateLayer(BACKGROUND_LAYER)).thenReturn(backgroundLayer);
- Layer shadowLayer = mock(Layer.class);
- when(shadowLayer.getId()).thenReturn(SHADOW_LAYER);
- when(sourceProvider.generateLayer(SHADOW_LAYER)).thenReturn(shadowLayer);
- Layer accuracyLayer = mock(Layer.class);
- when(accuracyLayer.getId()).thenReturn(ACCURACY_LAYER);
- when(sourceProvider.generateAccuracyLayer()).thenReturn(accuracyLayer);
-
LocationComponentOptions options = mock(LocationComponentOptions.class);
LayerBitmapProvider bitmapProvider = mock(LayerBitmapProvider.class);
Bitmap bitmap = mock(Bitmap.class);
@@ -606,18 +609,23 @@ public class LocationLayerControllerTest {
LayerSourceProvider layerSourceProvider = mock(LayerSourceProvider.class);
Layer shadowLayer = mock(Layer.class);
+ when(shadowLayer.getId()).thenReturn(SHADOW_LAYER);
when(layerSourceProvider.generateLayer(SHADOW_LAYER)).thenReturn(shadowLayer);
Layer backgroundLayer = mock(Layer.class);
+ when(backgroundLayer.getId()).thenReturn(BACKGROUND_LAYER);
when(layerSourceProvider.generateLayer(BACKGROUND_LAYER)).thenReturn(backgroundLayer);
Layer foregroundLayer = mock(Layer.class);
+ when(foregroundLayer.getId()).thenReturn(FOREGROUND_LAYER);
when(layerSourceProvider.generateLayer(FOREGROUND_LAYER)).thenReturn(foregroundLayer);
Layer bearingLayer = mock(Layer.class);
+ when(bearingLayer.getId()).thenReturn(BEARING_LAYER);
when(layerSourceProvider.generateLayer(BEARING_LAYER)).thenReturn(bearingLayer);
Layer accuracyLayer = mock(Layer.class);
+ when(accuracyLayer.getId()).thenReturn(ACCURACY_LAYER);
when(layerSourceProvider.generateAccuracyLayer()).thenReturn(accuracyLayer);
return layerSourceProvider;
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.kt b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.kt
index a0873e97ff..2d68612c70 100644
--- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.kt
+++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.kt
@@ -15,31 +15,33 @@ import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class MapboxMapTest {
- private lateinit var mapboxMap: MapboxMap
-
- private lateinit var nativeMapView: NativeMapView
-
- private lateinit var transform: Transform
-
- @Before
- fun setup() {
- val cameraChangeDispatcher = spyk<CameraChangeDispatcher>()
- nativeMapView = mockk(relaxed = true)
- transform = mockk(relaxed = true)
- mapboxMap = MapboxMap(nativeMapView, transform, mockk(relaxed = true), null, null, cameraChangeDispatcher)
- every { nativeMapView.isDestroyed } returns false
- every { nativeMapView.nativePtr } returns 5
- mapboxMap.injectLocationComponent(spyk())
- mapboxMap.setStyle(Style.MAPBOX_STREETS)
- mapboxMap.onFinishLoadingStyle()
- }
-
- @Test
- fun testTransitionOptions() {
- val expected = TransitionOptions(100, 200)
- mapboxMap.style?.transition = expected
- verify { nativeMapView.transitionOptions = expected }
- }
+ private lateinit var mapboxMap: MapboxMap
+
+ private lateinit var nativeMapView: NativeMapView
+
+ private lateinit var transform: Transform
+
+ private lateinit var cameraChangeDispatcher: CameraChangeDispatcher
+
+ @Before
+ fun setup() {
+ cameraChangeDispatcher = spyk()
+ nativeMapView = mockk(relaxed = true)
+ transform = mockk(relaxed = true)
+ mapboxMap = MapboxMap(nativeMapView, transform, mockk(relaxed = true), null, null, cameraChangeDispatcher)
+ every { nativeMapView.isDestroyed } returns false
+ every { nativeMapView.nativePtr } returns 5
+ mapboxMap.injectLocationComponent(spyk())
+ mapboxMap.setStyle(Style.MAPBOX_STREETS)
+ mapboxMap.onFinishLoadingStyle()
+ }
+
+ @Test
+ fun testTransitionOptions() {
+ val expected = TransitionOptions(100, 200)
+ mapboxMap.style?.transition = expected
+ verify { nativeMapView.transitionOptions = expected }
+ }
@Test
fun testMoveCamera() {
@@ -51,52 +53,52 @@ class MapboxMapTest {
verify { transform.moveCamera(mapboxMap, update, callback) }
}
- @Test
- fun testMinZoom() {
- mapboxMap.setMinZoomPreference(10.0)
- verify { transform.minZoom = 10.0 }
- }
-
- @Test
- fun testMaxZoom() {
- mapboxMap.setMaxZoomPreference(10.0)
- verify { transform.maxZoom = 10.0 }
- }
-
- @Test
- fun testFpsListener() {
- val fpsChangedListener = mockk<MapboxMap.OnFpsChangedListener>()
- mapboxMap.onFpsChangedListener = fpsChangedListener
- assertEquals("Listener should match", fpsChangedListener, mapboxMap.onFpsChangedListener)
- }
-
- @Test
- fun testTilePrefetch() {
- mapboxMap.prefetchesTiles = true
- verify { nativeMapView.prefetchTiles = true }
- }
-
- @Test
- fun testCameraForLatLngBounds() {
- val bounds = LatLngBounds.Builder().include(LatLng()).include(LatLng(1.0, 1.0)).build()
- mapboxMap.setLatLngBoundsForCameraTarget(bounds)
- verify { nativeMapView.setLatLngBounds(bounds) }
- }
-
- @Test(expected = IllegalArgumentException::class)
- fun testAnimateCameraChecksDurationPositive() {
- mapboxMap.animateCamera(CameraUpdateFactory.newLatLng(LatLng(30.0, 30.0)), 0, null)
- }
-
- @Test(expected = IllegalArgumentException::class)
- fun testEaseCameraChecksDurationPositive() {
- mapboxMap.easeCamera(CameraUpdateFactory.newLatLng(LatLng(30.0, 30.0)), 0, null)
- }
-
- @Test
- fun testGetNativeMapPtr() {
- assertEquals(5, mapboxMap.nativeMapPtr)
- }
+ @Test
+ fun testMinZoom() {
+ mapboxMap.setMinZoomPreference(10.0)
+ verify { transform.minZoom = 10.0 }
+ }
+
+ @Test
+ fun testMaxZoom() {
+ mapboxMap.setMaxZoomPreference(10.0)
+ verify { transform.maxZoom = 10.0 }
+ }
+
+ @Test
+ fun testFpsListener() {
+ val fpsChangedListener = mockk<MapboxMap.OnFpsChangedListener>()
+ mapboxMap.onFpsChangedListener = fpsChangedListener
+ assertEquals("Listener should match", fpsChangedListener, mapboxMap.onFpsChangedListener)
+ }
+
+ @Test
+ fun testTilePrefetch() {
+ mapboxMap.prefetchesTiles = true
+ verify { nativeMapView.prefetchTiles = true }
+ }
+
+ @Test
+ fun testCameraForLatLngBounds() {
+ val bounds = LatLngBounds.Builder().include(LatLng()).include(LatLng(1.0, 1.0)).build()
+ mapboxMap.setLatLngBoundsForCameraTarget(bounds)
+ verify { nativeMapView.setLatLngBounds(bounds) }
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ fun testAnimateCameraChecksDurationPositive() {
+ mapboxMap.animateCamera(CameraUpdateFactory.newLatLng(LatLng(30.0, 30.0)), 0, null)
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ fun testEaseCameraChecksDurationPositive() {
+ mapboxMap.easeCamera(CameraUpdateFactory.newLatLng(LatLng(30.0, 30.0)), 0, null)
+ }
+
+ @Test
+ fun testGetNativeMapPtr() {
+ assertEquals(5, mapboxMap.nativeMapPtr)
+ }
@Test
fun testNativeMapIsNotCalledOnStateSave() {
@@ -104,4 +106,10 @@ class MapboxMapTest {
mapboxMap.onSaveInstanceState(mockk(relaxed = true))
verify { nativeMapView wasNot Called }
}
+
+ @Test
+ fun testCameraChangeDispatcherCleared() {
+ mapboxMap.onDestroy()
+ verify { cameraChangeDispatcher.onDestroy() }
+ }
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/build.gradle b/platform/android/MapboxGLAndroidSDKTestApp/build.gradle
index 22222b0f50..190c279e03 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/build.gradle
+++ b/platform/android/MapboxGLAndroidSDKTestApp/build.gradle
@@ -9,7 +9,7 @@ android {
targetSdkVersion androidVersions.targetSdkVersion
versionCode 13
versionName "6.0.0"
- testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ testInstrumentationRunner "com.mapbox.mapboxsdk.InstrumentationRunner"
}
compileOptions {
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/assets/streets.json b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/assets/streets.json
new file mode 100644
index 0000000000..5ab289344a
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/assets/streets.json
@@ -0,0 +1,5331 @@
+{
+ "version": 8,
+ "name": "mapbox-gl-native-test-style",
+ "metadata": {
+ "mapbox:autocomposite": true,
+ "mapbox:type": "default",
+ "mapbox:origin": "streets-v10",
+ "mapbox:groups": {
+ "1444934828655.3389": {"name": "Aeroways", "collapsed": true},
+ "1444933322393.2852": {
+ "name": "POI labels (scalerank 1)",
+ "collapsed": true
+ },
+ "1444855786460.0557": {"name": "Roads", "collapsed": true},
+ "1444933575858.6992": {
+ "name": "Highway shields",
+ "collapsed": true
+ },
+ "1444934295202.7542": {
+ "name": "Admin boundaries",
+ "collapsed": true
+ },
+ "1444856151690.9143": {"name": "State labels", "collapsed": true},
+ "1444933721429.3076": {"name": "Road labels", "collapsed": true},
+ "1444933358918.2366": {
+ "name": "POI labels (scalerank 2)",
+ "collapsed": true
+ },
+ "1444933808272.805": {"name": "Water labels", "collapsed": true},
+ "1444933372896.5967": {
+ "name": "POI labels (scalerank 3)",
+ "collapsed": true
+ },
+ "1444855799204.86": {"name": "Bridges", "collapsed": true},
+ "1444856087950.3635": {"name": "Marine labels", "collapsed": true},
+ "1456969573402.7817": {"name": "Hillshading", "collapsed": true},
+ "1444862510685.128": {"name": "City labels", "collapsed": true},
+ "1444855769305.6016": {"name": "Tunnels", "collapsed": true},
+ "1456970288113.8113": {"name": "Landcover", "collapsed": true},
+ "1444856144497.7825": {"name": "Country labels", "collapsed": true},
+ "1444933456003.5437": {
+ "name": "POI labels (scalerank 4)",
+ "collapsed": true
+ }
+ },
+ "mapbox:sdk-support": {
+ "js": "0.49.0",
+ "android": "6.5.0",
+ "ios": "4.4.0"
+ }
+ },
+ "center": [0.0, 0.0],
+ "zoom": 0,
+ "bearing": 0,
+ "pitch": 0,
+ "sources": {
+ "composite": {
+ "url": "mapbox://mapbox.mapbox-terrain-v2,mapbox.mapbox-streets-v7",
+ "type": "vector"
+ }
+ },
+ "sprite": "mapbox://sprites/lukaspaczos/cjnkdt02b0b2p2ss40skwpvs1",
+ "glyphs": "mapbox://fonts/lukaspaczos/{fontstack}/{range}.pbf",
+ "layers": [
+ {
+ "id": "background",
+ "type": "background",
+ "layout": {},
+ "paint": {
+ "background-color": {
+ "base": 1,
+ "stops": [
+ [11, "hsl(35, 32%, 91%)"],
+ [13, "hsl(35, 12%, 89%)"]
+ ]
+ }
+ }
+ },
+ {
+ "id": "landcover_snow",
+ "type": "fill",
+ "metadata": {"mapbox:group": "1456970288113.8113"},
+ "source": "composite",
+ "source-layer": "landcover",
+ "filter": ["==", "class", "snow"],
+ "layout": {},
+ "paint": {
+ "fill-color": "hsl(0, 0%, 100%)",
+ "fill-opacity": 0.2,
+ "fill-antialias": false
+ }
+ },
+ {
+ "id": "landcover_wood",
+ "type": "fill",
+ "metadata": {"mapbox:group": "1456970288113.8113"},
+ "source": "composite",
+ "source-layer": "landcover",
+ "maxzoom": 14,
+ "filter": ["==", "class", "wood"],
+ "layout": {},
+ "paint": {
+ "fill-color": "hsl(75, 62%, 81%)",
+ "fill-opacity": {"base": 1.5, "stops": [[2, 0.3], [7, 0]]},
+ "fill-antialias": false
+ }
+ },
+ {
+ "id": "landcover_scrub",
+ "type": "fill",
+ "metadata": {"mapbox:group": "1456970288113.8113"},
+ "source": "composite",
+ "source-layer": "landcover",
+ "maxzoom": 14,
+ "filter": ["==", "class", "scrub"],
+ "layout": {},
+ "paint": {
+ "fill-color": "hsl(75, 62%, 81%)",
+ "fill-opacity": {"base": 1.5, "stops": [[2, 0.3], [7, 0]]},
+ "fill-antialias": false
+ }
+ },
+ {
+ "id": "landcover_grass",
+ "type": "fill",
+ "metadata": {"mapbox:group": "1456970288113.8113"},
+ "source": "composite",
+ "source-layer": "landcover",
+ "maxzoom": 14,
+ "filter": ["==", "class", "grass"],
+ "layout": {},
+ "paint": {
+ "fill-color": "hsl(75, 62%, 81%)",
+ "fill-opacity": {"base": 1.5, "stops": [[2, 0.3], [7, 0]]},
+ "fill-antialias": false
+ }
+ },
+ {
+ "id": "landcover_crop",
+ "type": "fill",
+ "metadata": {"mapbox:group": "1456970288113.8113"},
+ "source": "composite",
+ "source-layer": "landcover",
+ "maxzoom": 14,
+ "filter": ["==", "class", "crop"],
+ "layout": {},
+ "paint": {
+ "fill-color": "hsl(75, 62%, 81%)",
+ "fill-opacity": {"base": 1.5, "stops": [[2, 0.3], [7, 0]]},
+ "fill-antialias": false
+ }
+ },
+ {
+ "id": "national_park",
+ "type": "fill",
+ "source": "composite",
+ "source-layer": "landuse_overlay",
+ "filter": ["==", "class", "national_park"],
+ "layout": {},
+ "paint": {
+ "fill-color": "hsl(100, 58%, 76%)",
+ "fill-opacity": {"base": 1, "stops": [[5, 0], [6, 0.5]]}
+ }
+ },
+ {
+ "id": "hospital",
+ "type": "fill",
+ "source": "composite",
+ "source-layer": "landuse",
+ "filter": ["==", "class", "hospital"],
+ "layout": {},
+ "paint": {
+ "fill-color": {
+ "base": 1,
+ "stops": [
+ [15.5, "hsl(340, 37%, 87%)"],
+ [16, "hsl(340, 63%, 89%)"]
+ ]
+ }
+ }
+ },
+ {
+ "id": "school",
+ "type": "fill",
+ "source": "composite",
+ "source-layer": "landuse",
+ "filter": ["==", "class", "school"],
+ "layout": {},
+ "paint": {
+ "fill-color": {
+ "base": 1,
+ "stops": [
+ [15.5, "hsl(50, 47%, 81%)"],
+ [16, "hsl(50, 63%, 84%)"]
+ ]
+ }
+ }
+ },
+ {
+ "id": "park",
+ "type": "fill",
+ "source": "composite",
+ "source-layer": "landuse",
+ "filter": ["==", "class", "park"],
+ "layout": {},
+ "paint": {
+ "fill-color": "hsl(100, 58%, 76%)",
+ "fill-opacity": {"base": 1, "stops": [[5, 0], [6, 1]]}
+ }
+ },
+ {
+ "id": "pitch",
+ "type": "fill",
+ "source": "composite",
+ "source-layer": "landuse",
+ "filter": ["==", "class", "pitch"],
+ "layout": {},
+ "paint": {"fill-color": "hsl(100, 57%, 72%)"}
+ },
+ {
+ "id": "pitch-line",
+ "type": "line",
+ "source": "composite",
+ "source-layer": "landuse",
+ "minzoom": 15,
+ "filter": ["==", "class", "pitch"],
+ "layout": {"line-join": "miter"},
+ "paint": {"line-color": "hsl(75, 57%, 84%)"}
+ },
+ {
+ "id": "cemetery",
+ "type": "fill",
+ "source": "composite",
+ "source-layer": "landuse",
+ "filter": ["==", "class", "cemetery"],
+ "layout": {},
+ "paint": {"fill-color": "hsl(75, 37%, 81%)"}
+ },
+ {
+ "id": "industrial",
+ "type": "fill",
+ "source": "composite",
+ "source-layer": "landuse",
+ "filter": ["==", "class", "industrial"],
+ "layout": {},
+ "paint": {
+ "fill-color": {
+ "base": 1,
+ "stops": [
+ [15.5, "hsl(230, 15%, 86%)"],
+ [16, "hsl(230, 29%, 89%)"]
+ ]
+ }
+ }
+ },
+ {
+ "id": "sand",
+ "type": "fill",
+ "source": "composite",
+ "source-layer": "landuse",
+ "filter": ["==", "class", "sand"],
+ "layout": {},
+ "paint": {"fill-color": "hsl(60, 46%, 87%)"}
+ },
+ {
+ "id": "hillshade_highlight_bright",
+ "type": "fill",
+ "metadata": {"mapbox:group": "1456969573402.7817"},
+ "source": "composite",
+ "source-layer": "hillshade",
+ "maxzoom": 16,
+ "filter": ["==", "level", 94],
+ "layout": {},
+ "paint": {
+ "fill-color": "hsl(0, 0%, 100%)",
+ "fill-opacity": {"stops": [[14, 0.12], [16, 0]]},
+ "fill-antialias": false
+ }
+ },
+ {
+ "id": "hillshade_highlight_med",
+ "type": "fill",
+ "metadata": {"mapbox:group": "1456969573402.7817"},
+ "source": "composite",
+ "source-layer": "hillshade",
+ "maxzoom": 16,
+ "filter": ["==", "level", 90],
+ "layout": {},
+ "paint": {
+ "fill-color": "hsl(0, 0%, 100%)",
+ "fill-opacity": {"stops": [[14, 0.12], [16, 0]]},
+ "fill-antialias": false
+ }
+ },
+ {
+ "id": "hillshade_shadow_faint",
+ "type": "fill",
+ "metadata": {"mapbox:group": "1456969573402.7817"},
+ "source": "composite",
+ "source-layer": "hillshade",
+ "maxzoom": 16,
+ "filter": ["==", "level", 89],
+ "layout": {},
+ "paint": {
+ "fill-color": "hsl(56, 59%, 22%)",
+ "fill-opacity": {"stops": [[14, 0.05], [16, 0]]},
+ "fill-antialias": false
+ }
+ },
+ {
+ "id": "hillshade_shadow_med",
+ "type": "fill",
+ "metadata": {"mapbox:group": "1456969573402.7817"},
+ "source": "composite",
+ "source-layer": "hillshade",
+ "maxzoom": 16,
+ "filter": ["==", "level", 78],
+ "layout": {},
+ "paint": {
+ "fill-color": "hsl(56, 59%, 22%)",
+ "fill-opacity": {"stops": [[14, 0.05], [16, 0]]},
+ "fill-antialias": false
+ }
+ },
+ {
+ "id": "hillshade_shadow_dark",
+ "type": "fill",
+ "metadata": {"mapbox:group": "1456969573402.7817"},
+ "source": "composite",
+ "source-layer": "hillshade",
+ "maxzoom": 16,
+ "filter": ["==", "level", 67],
+ "layout": {},
+ "paint": {
+ "fill-color": "hsl(56, 59%, 22%)",
+ "fill-opacity": {"stops": [[14, 0.06], [16, 0]]},
+ "fill-antialias": false
+ }
+ },
+ {
+ "id": "hillshade_shadow_extreme",
+ "type": "fill",
+ "metadata": {"mapbox:group": "1456969573402.7817"},
+ "source": "composite",
+ "source-layer": "hillshade",
+ "maxzoom": 16,
+ "filter": ["==", "level", 56],
+ "layout": {},
+ "paint": {
+ "fill-color": "hsl(56, 59%, 22%)",
+ "fill-opacity": {"stops": [[14, 0.06], [16, 0]]},
+ "fill-antialias": false
+ }
+ },
+ {
+ "id": "waterway-river-canal",
+ "type": "line",
+ "source": "composite",
+ "source-layer": "waterway",
+ "minzoom": 8,
+ "filter": ["in", "class", "canal", "river"],
+ "layout": {
+ "line-cap": {"base": 1, "stops": [[0, "butt"], [11, "round"]]},
+ "line-join": "round"
+ },
+ "paint": {
+ "line-color": "hsl(205, 87%, 76%)",
+ "line-width": {"base": 1.3, "stops": [[8.5, 0.1], [20, 8]]},
+ "line-opacity": {"base": 1, "stops": [[8, 0], [8.5, 1]]}
+ }
+ },
+ {
+ "id": "waterway-small",
+ "type": "line",
+ "source": "composite",
+ "source-layer": "waterway",
+ "minzoom": 13,
+ "filter": ["!in", "class", "canal", "river"],
+ "layout": {"line-join": "round", "line-cap": "round"},
+ "paint": {
+ "line-color": "hsl(205, 87%, 76%)",
+ "line-width": {"base": 1.35, "stops": [[13.5, 0.1], [20, 3]]},
+ "line-opacity": {"base": 1, "stops": [[13, 0], [13.5, 1]]}
+ }
+ },
+ {
+ "id": "water-shadow",
+ "type": "fill",
+ "source": "composite",
+ "source-layer": "water",
+ "layout": {},
+ "paint": {
+ "fill-color": "hsl(215, 84%, 69%)",
+ "fill-translate": {
+ "base": 1.2,
+ "stops": [[7, [0, 0]], [16, [-1, -1]]]
+ },
+ "fill-translate-anchor": "viewport",
+ "fill-opacity": 1
+ }
+ },
+ {
+ "id": "water",
+ "type": "fill",
+ "source": "composite",
+ "source-layer": "water",
+ "layout": {},
+ "paint": {"fill-color": "hsl(196, 80%, 70%)"}
+ },
+ {
+ "id": "barrier_line-land-polygon",
+ "type": "fill",
+ "source": "composite",
+ "source-layer": "barrier_line",
+ "filter": [
+ "all",
+ ["==", "$type", "Polygon"],
+ ["==", "class", "land"]
+ ],
+ "layout": {},
+ "paint": {"fill-color": "hsl(35, 12%, 89%)"}
+ },
+ {
+ "id": "barrier_line-land-line",
+ "type": "line",
+ "source": "composite",
+ "source-layer": "barrier_line",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ ["==", "class", "land"]
+ ],
+ "layout": {"line-cap": "round"},
+ "paint": {
+ "line-width": {"base": 1.99, "stops": [[14, 0.75], [20, 40]]},
+ "line-color": "hsl(35, 12%, 89%)"
+ }
+ },
+ {
+ "id": "aeroway-polygon",
+ "type": "fill",
+ "metadata": {"mapbox:group": "1444934828655.3389"},
+ "source": "composite",
+ "source-layer": "aeroway",
+ "minzoom": 11,
+ "filter": [
+ "all",
+ ["!=", "type", "apron"],
+ ["==", "$type", "Polygon"]
+ ],
+ "layout": {},
+ "paint": {
+ "fill-color": {
+ "base": 1,
+ "stops": [
+ [15, "hsl(230, 23%, 82%)"],
+ [16, "hsl(230, 37%, 84%)"]
+ ]
+ },
+ "fill-opacity": {"base": 1, "stops": [[11, 0], [11.5, 1]]}
+ }
+ },
+ {
+ "id": "aeroway-runway",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444934828655.3389"},
+ "source": "composite",
+ "source-layer": "aeroway",
+ "minzoom": 9,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ ["==", "type", "runway"]
+ ],
+ "layout": {},
+ "paint": {
+ "line-color": {
+ "base": 1,
+ "stops": [
+ [15, "hsl(230, 23%, 82%)"],
+ [16, "hsl(230, 37%, 84%)"]
+ ]
+ },
+ "line-width": {"base": 1.5, "stops": [[9, 1], [18, 80]]}
+ }
+ },
+ {
+ "id": "aeroway-taxiway",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444934828655.3389"},
+ "source": "composite",
+ "source-layer": "aeroway",
+ "minzoom": 9,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ ["==", "type", "taxiway"]
+ ],
+ "layout": {},
+ "paint": {
+ "line-color": {
+ "base": 1,
+ "stops": [
+ [15, "hsl(230, 23%, 82%)"],
+ [16, "hsl(230, 37%, 84%)"]
+ ]
+ },
+ "line-width": {"base": 1.5, "stops": [[10, 0.5], [18, 20]]}
+ }
+ },
+ {
+ "id": "building-line",
+ "type": "line",
+ "source": "composite",
+ "source-layer": "building",
+ "minzoom": 15,
+ "filter": [
+ "all",
+ ["!=", "type", "building:part"],
+ ["==", "underground", "false"]
+ ],
+ "layout": {},
+ "paint": {
+ "line-color": "hsl(35, 6%, 79%)",
+ "line-width": {"base": 1.5, "stops": [[15, 0.75], [20, 3]]},
+ "line-opacity": {"base": 1, "stops": [[15.5, 0], [16, 1]]}
+ }
+ },
+ {
+ "id": "building",
+ "type": "fill",
+ "source": "composite",
+ "source-layer": "building",
+ "minzoom": 15,
+ "filter": [
+ "all",
+ ["!=", "type", "building:part"],
+ ["==", "underground", "false"]
+ ],
+ "layout": {},
+ "paint": {
+ "fill-color": {
+ "base": 1,
+ "stops": [
+ [15, "hsl(35, 11%, 88%)"],
+ [16, "hsl(35, 8%, 85%)"]
+ ]
+ },
+ "fill-opacity": {"base": 1, "stops": [[15.5, 0], [16, 1]]},
+ "fill-outline-color": "hsl(35, 6%, 79%)"
+ }
+ },
+ {
+ "id": "tunnel-street-low",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855769305.6016"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 11,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "street"],
+ ["==", "structure", "tunnel"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[12.5, 0.5], [14, 2], [18, 18]]
+ },
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-opacity": {
+ "stops": [[11.5, 0], [12, 1], [14, 1], [14.01, 0]]
+ }
+ }
+ },
+ {
+ "id": "tunnel-street_limited-low",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855769305.6016"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 11,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "street_limited"],
+ ["==", "structure", "tunnel"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[12.5, 0.5], [14, 2], [18, 18]]
+ },
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-opacity": {
+ "stops": [[11.5, 0], [12, 1], [14, 1], [14.01, 0]]
+ }
+ }
+ },
+ {
+ "id": "tunnel-service-link-track-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855769305.6016"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 14,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!=", "type", "trunk_link"],
+ ["==", "structure", "tunnel"],
+ ["in", "class", "link", "service", "track"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[12, 0.75], [20, 2]]},
+ "line-color": "hsl(230, 19%, 75%)",
+ "line-gap-width": {"base": 1.5, "stops": [[14, 0.5], [18, 12]]},
+ "line-dasharray": [3, 3]
+ }
+ },
+ {
+ "id": "tunnel-street_limited-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855769305.6016"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 11,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "street_limited"],
+ ["==", "structure", "tunnel"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[12, 0.75], [20, 2]]},
+ "line-color": "hsl(230, 19%, 75%)",
+ "line-gap-width": {
+ "base": 1.5,
+ "stops": [[13, 0], [14, 2], [18, 18]]
+ },
+ "line-dasharray": [3, 3],
+ "line-opacity": {"base": 1, "stops": [[13.99, 0], [14, 1]]}
+ }
+ },
+ {
+ "id": "tunnel-street-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855769305.6016"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 11,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "street"],
+ ["==", "structure", "tunnel"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[12, 0.75], [20, 2]]},
+ "line-color": "hsl(230, 19%, 75%)",
+ "line-gap-width": {
+ "base": 1.5,
+ "stops": [[13, 0], [14, 2], [18, 18]]
+ },
+ "line-dasharray": [3, 3],
+ "line-opacity": {"base": 1, "stops": [[13.99, 0], [14, 1]]}
+ }
+ },
+ {
+ "id": "tunnel-secondary-tertiary-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855769305.6016"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "structure", "tunnel"],
+ ["in", "class", "secondary", "tertiary"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.2, "stops": [[10, 0.75], [18, 2]]},
+ "line-dasharray": [3, 3],
+ "line-gap-width": {
+ "base": 1.5,
+ "stops": [[8.5, 0.5], [10, 0.75], [18, 26]]
+ },
+ "line-color": "hsl(230, 19%, 75%)"
+ }
+ },
+ {
+ "id": "tunnel-primary-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855769305.6016"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "primary"],
+ ["==", "structure", "tunnel"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[10, 1], [16, 2]]},
+ "line-dasharray": [3, 3],
+ "line-gap-width": {"base": 1.5, "stops": [[5, 0.75], [18, 32]]},
+ "line-color": "hsl(230, 19%, 75%)"
+ }
+ },
+ {
+ "id": "tunnel-trunk_link-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855769305.6016"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 13,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "structure", "tunnel"],
+ ["==", "type", "trunk_link"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[12, 0.75], [20, 2]]},
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-gap-width": {
+ "base": 1.5,
+ "stops": [[12, 0.5], [14, 2], [18, 18]]
+ },
+ "line-dasharray": [3, 3]
+ }
+ },
+ {
+ "id": "tunnel-motorway_link-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855769305.6016"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 13,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "motorway_link"],
+ ["==", "structure", "tunnel"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[12, 0.75], [20, 2]]},
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-gap-width": {
+ "base": 1.5,
+ "stops": [[12, 0.5], [14, 2], [18, 18]]
+ },
+ "line-dasharray": [3, 3]
+ }
+ },
+ {
+ "id": "tunnel-trunk-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855769305.6016"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ ["all", ["==", "structure", "tunnel"], ["==", "type", "trunk"]]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[10, 1], [16, 2]]},
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-gap-width": {"base": 1.5, "stops": [[5, 0.75], [18, 32]]},
+ "line-opacity": 1,
+ "line-dasharray": [3, 3]
+ }
+ },
+ {
+ "id": "tunnel-motorway-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855769305.6016"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "motorway"],
+ ["==", "structure", "tunnel"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[10, 1], [16, 2]]},
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-gap-width": {"base": 1.5, "stops": [[5, 0.75], [18, 32]]},
+ "line-opacity": 1,
+ "line-dasharray": [3, 3]
+ }
+ },
+ {
+ "id": "tunnel-construction",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855769305.6016"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 14,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "construction"],
+ ["==", "structure", "tunnel"]
+ ]
+ ],
+ "layout": {"line-join": "miter"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[12.5, 0.5], [14, 2], [18, 18]]
+ },
+ "line-color": "hsl(230, 24%, 87%)",
+ "line-opacity": {"base": 1, "stops": [[13.99, 0], [14, 1]]},
+ "line-dasharray": {
+ "base": 1,
+ "stops": [
+ [14, [0.4, 0.8]],
+ [15, [0.3, 0.6]],
+ [16, [0.2, 0.3]],
+ [17, [0.2, 0.25]],
+ [18, [0.15, 0.15]]
+ ]
+ }
+ }
+ },
+ {
+ "id": "tunnel-path",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855769305.6016"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!=", "type", "steps"],
+ ["==", "class", "path"],
+ ["==", "structure", "tunnel"]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[15, 1], [18, 4]]},
+ "line-dasharray": {
+ "base": 1,
+ "stops": [
+ [14, [1, 0]],
+ [15, [1.75, 1]],
+ [16, [1, 0.75]],
+ [17, [1, 0.5]]
+ ]
+ },
+ "line-color": "hsl(35, 26%, 95%)",
+ "line-opacity": {"base": 1, "stops": [[14, 0], [14.25, 1]]}
+ }
+ },
+ {
+ "id": "tunnel-steps",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855769305.6016"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ ["all", ["==", "structure", "tunnel"], ["==", "type", "steps"]]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[15, 1], [16, 1.6], [18, 6]]
+ },
+ "line-color": "hsl(35, 26%, 95%)",
+ "line-dasharray": {
+ "base": 1,
+ "stops": [
+ [14, [1, 0]],
+ [15, [1.75, 1]],
+ [16, [1, 0.75]],
+ [17, [0.3, 0.3]]
+ ]
+ },
+ "line-opacity": {"base": 1, "stops": [[14, 0], [14.25, 1]]}
+ }
+ },
+ {
+ "id": "tunnel-trunk_link",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855769305.6016"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 13,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "structure", "tunnel"],
+ ["==", "type", "trunk_link"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[12, 0.5], [14, 2], [18, 18]]
+ },
+ "line-color": "hsl(46, 77%, 78%)",
+ "line-opacity": 1,
+ "line-dasharray": [1, 0]
+ }
+ },
+ {
+ "id": "tunnel-motorway_link",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855769305.6016"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 13,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "motorway_link"],
+ ["==", "structure", "tunnel"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[12, 0.5], [14, 2], [18, 18]]
+ },
+ "line-color": "hsl(26, 100%, 78%)",
+ "line-opacity": 1,
+ "line-dasharray": [1, 0]
+ }
+ },
+ {
+ "id": "tunnel-pedestrian",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855769305.6016"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 13,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "pedestrian"],
+ ["==", "structure", "tunnel"]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[14, 0.5], [18, 12]]},
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-opacity": 1,
+ "line-dasharray": {
+ "base": 1,
+ "stops": [[14, [1, 0]], [15, [1.5, 0.4]], [16, [1, 0.2]]]
+ }
+ }
+ },
+ {
+ "id": "tunnel-service-link-track",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855769305.6016"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 14,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!=", "type", "trunk_link"],
+ ["==", "structure", "tunnel"],
+ ["in", "class", "link", "service", "track"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[14, 0.5], [18, 12]]},
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-dasharray": [1, 0]
+ }
+ },
+ {
+ "id": "tunnel-street_limited",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855769305.6016"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 11,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "street_limited"],
+ ["==", "structure", "tunnel"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[12.5, 0.5], [14, 2], [18, 18]]
+ },
+ "line-color": "hsl(35, 14%, 93%)",
+ "line-opacity": {"base": 1, "stops": [[13.99, 0], [14, 1]]}
+ }
+ },
+ {
+ "id": "tunnel-street",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855769305.6016"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 11,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "street"],
+ ["==", "structure", "tunnel"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[12.5, 0.5], [14, 2], [18, 18]]
+ },
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-opacity": {"base": 1, "stops": [[13.99, 0], [14, 1]]}
+ }
+ },
+ {
+ "id": "tunnel-secondary-tertiary",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855769305.6016"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "structure", "tunnel"],
+ ["in", "class", "secondary", "tertiary"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[8.5, 0.5], [10, 0.75], [18, 26]]
+ },
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-opacity": 1,
+ "line-dasharray": [1, 0],
+ "line-blur": 0
+ }
+ },
+ {
+ "id": "tunnel-primary",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855769305.6016"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "primary"],
+ ["==", "structure", "tunnel"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[5, 0.75], [18, 32]]},
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-opacity": 1,
+ "line-dasharray": [1, 0],
+ "line-blur": 0
+ }
+ },
+ {
+ "id": "tunnel-oneway-arrows-blue-minor",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444855769305.6016"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 16,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!=", "type", "trunk_link"],
+ ["==", "oneway", "true"],
+ ["==", "structure", "tunnel"],
+ [
+ "in",
+ "class",
+ "link",
+ "path",
+ "pedestrian",
+ "service",
+ "track"
+ ]
+ ]
+ ],
+ "layout": {
+ "symbol-placement": "line",
+ "icon-image": {
+ "base": 1,
+ "stops": [[17, "oneway-small"], [18, "oneway-large"]]
+ },
+ "symbol-spacing": 200,
+ "icon-padding": 2
+ },
+ "paint": {}
+ },
+ {
+ "id": "tunnel-oneway-arrows-blue-major",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444855769305.6016"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 15,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!=", "type", "trunk_link"],
+ ["==", "oneway", "true"],
+ ["==", "structure", "tunnel"],
+ [
+ "in",
+ "class",
+ "primary",
+ "secondary",
+ "street",
+ "street_limited",
+ "tertiary"
+ ]
+ ]
+ ],
+ "layout": {
+ "symbol-placement": "line",
+ "icon-image": {
+ "base": 1,
+ "stops": [[16, "oneway-small"], [17, "oneway-large"]]
+ },
+ "symbol-spacing": 200,
+ "icon-padding": 2
+ },
+ "paint": {}
+ },
+ {
+ "id": "tunnel-trunk",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855769305.6016"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ ["all", ["==", "class", "trunk"], ["==", "structure", "tunnel"]]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[5, 0.75], [18, 32]]},
+ "line-color": "hsl(46, 77%, 78%)"
+ }
+ },
+ {
+ "id": "tunnel-motorway",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855769305.6016"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "motorway"],
+ ["==", "structure", "tunnel"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[5, 0.75], [18, 32]]},
+ "line-dasharray": [1, 0],
+ "line-opacity": 1,
+ "line-color": "hsl(26, 100%, 78%)",
+ "line-blur": 0
+ }
+ },
+ {
+ "id": "tunnel-oneway-arrows-white",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444855769305.6016"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 16,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ [
+ "!in",
+ "type",
+ "primary_link",
+ "secondary_link",
+ "tertiary_link"
+ ],
+ ["==", "oneway", "true"],
+ ["==", "structure", "tunnel"],
+ [
+ "in",
+ "class",
+ "link",
+ "motorway",
+ "motorway_link",
+ "trunk"
+ ]
+ ]
+ ],
+ "layout": {
+ "symbol-placement": "line",
+ "icon-image": {
+ "base": 1,
+ "stops": [
+ [16, "oneway-white-small"],
+ [17, "oneway-white-large"]
+ ]
+ },
+ "symbol-spacing": 200,
+ "icon-padding": 2
+ },
+ "paint": {}
+ },
+ {
+ "id": "ferry",
+ "type": "line",
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ ["==", "type", "ferry"]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-color": {
+ "base": 1,
+ "stops": [
+ [15, "hsl(205, 73%, 63%)"],
+ [17, "hsl(230, 73%, 63%)"]
+ ]
+ },
+ "line-opacity": 1,
+ "line-width": {"base": 1.5, "stops": [[14, 0.5], [20, 1]]},
+ "line-dasharray": {
+ "base": 1,
+ "stops": [[12, [1, 0]], [13, [12, 4]]]
+ }
+ }
+ },
+ {
+ "id": "ferry_auto",
+ "type": "line",
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ ["==", "type", "ferry_auto"]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-color": {
+ "base": 1,
+ "stops": [
+ [15, "hsl(205, 73%, 63%)"],
+ [17, "hsl(230, 73%, 63%)"]
+ ]
+ },
+ "line-opacity": 1,
+ "line-width": {"base": 1.5, "stops": [[14, 0.5], [20, 1]]}
+ }
+ },
+ {
+ "id": "road-path-bg",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!in", "structure", "bridge", "tunnel"],
+ ["!in", "type", "crossing", "sidewalk", "steps"],
+ ["==", "class", "path"]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[15, 2], [18, 7]]},
+ "line-dasharray": [1, 0],
+ "line-color": "hsl(230, 17%, 82%)",
+ "line-blur": 0,
+ "line-opacity": {"base": 1, "stops": [[14, 0], [14.25, 0.75]]}
+ }
+ },
+ {
+ "id": "road-steps-bg",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!in", "structure", "bridge", "tunnel"],
+ ["==", "type", "steps"]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[15, 2], [17, 4.6], [18, 7]]
+ },
+ "line-color": "hsl(230, 17%, 82%)",
+ "line-dasharray": [1, 0],
+ "line-opacity": {"base": 1, "stops": [[14, 0], [14.25, 0.75]]}
+ }
+ },
+ {
+ "id": "road-sidewalk-bg",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 16,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!in", "structure", "bridge", "tunnel"],
+ ["in", "type", "crossing", "sidewalk"]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[15, 2], [18, 7]]},
+ "line-dasharray": [1, 0],
+ "line-color": "hsl(230, 17%, 82%)",
+ "line-blur": 0,
+ "line-opacity": {"base": 1, "stops": [[16, 0], [16.25, 0.75]]}
+ }
+ },
+ {
+ "id": "turning-features-outline",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 15,
+ "filter": [
+ "all",
+ ["==", "$type", "Point"],
+ ["in", "class", "turning_circle", "turning_loop"]
+ ],
+ "layout": {
+ "icon-image": "turning-circle-outline",
+ "icon-size": {
+ "base": 1.5,
+ "stops": [[14, 0.122], [18, 0.969], [20, 1]]
+ },
+ "icon-allow-overlap": true,
+ "icon-ignore-placement": true,
+ "icon-padding": 0,
+ "icon-rotation-alignment": "map"
+ },
+ "paint": {}
+ },
+ {
+ "id": "road-pedestrian-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 12,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "pedestrian"],
+ ["==", "structure", "none"]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[14, 2], [18, 14.5]]},
+ "line-color": "hsl(230, 24%, 87%)",
+ "line-gap-width": 0,
+ "line-opacity": {"base": 1, "stops": [[13.99, 0], [14, 1]]}
+ }
+ },
+ {
+ "id": "road-street-low",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 11,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ ["all", ["==", "class", "street"], ["==", "structure", "none"]]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[12.5, 0.5], [14, 2], [18, 18]]
+ },
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-opacity": {
+ "stops": [[11, 0], [11.25, 1], [14, 1], [14.01, 0]]
+ }
+ }
+ },
+ {
+ "id": "road-street_limited-low",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 11,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "street_limited"],
+ ["==", "structure", "none"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[12.5, 0.5], [14, 2], [18, 18]]
+ },
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-opacity": {
+ "stops": [[11, 0], [11.25, 1], [14, 1], [14.01, 0]]
+ }
+ }
+ },
+ {
+ "id": "road-service-link-track-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 14,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!=", "type", "trunk_link"],
+ ["!in", "structure", "bridge", "tunnel"],
+ ["in", "class", "link", "service", "track"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[12, 0.75], [20, 2]]},
+ "line-color": "hsl(230, 24%, 87%)",
+ "line-gap-width": {"base": 1.5, "stops": [[14, 0.5], [18, 12]]}
+ }
+ },
+ {
+ "id": "road-street_limited-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 11,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "street_limited"],
+ ["==", "structure", "none"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[12, 0.75], [20, 2]]},
+ "line-color": "hsl(230, 24%, 87%)",
+ "line-gap-width": {
+ "base": 1.5,
+ "stops": [[13, 0], [14, 2], [18, 18]]
+ },
+ "line-opacity": {"base": 1, "stops": [[13.99, 0], [14, 1]]}
+ }
+ },
+ {
+ "id": "road-street-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 11,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ ["all", ["==", "class", "street"], ["==", "structure", "none"]]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[12, 0.75], [20, 2]]},
+ "line-color": "hsl(230, 24%, 87%)",
+ "line-gap-width": {
+ "base": 1.5,
+ "stops": [[13, 0], [14, 2], [18, 18]]
+ },
+ "line-opacity": {"base": 1, "stops": [[13.99, 0], [14, 1]]}
+ }
+ },
+ {
+ "id": "road-secondary-tertiary-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!in", "structure", "bridge", "tunnel"],
+ ["in", "class", "secondary", "tertiary"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.2, "stops": [[10, 0.75], [18, 2]]},
+ "line-color": "hsl(230, 24%, 87%)",
+ "line-gap-width": {
+ "base": 1.5,
+ "stops": [[8.5, 0.5], [10, 0.75], [18, 26]]
+ },
+ "line-opacity": {"base": 1, "stops": [[9.99, 0], [10, 1]]}
+ }
+ },
+ {
+ "id": "road-primary-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!in", "structure", "bridge", "tunnel"],
+ ["==", "class", "primary"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[10, 1], [16, 2]]},
+ "line-color": "hsl(230, 24%, 87%)",
+ "line-gap-width": {"base": 1.5, "stops": [[5, 0.75], [18, 32]]},
+ "line-opacity": {"base": 1, "stops": [[9.99, 0], [10, 1]]}
+ }
+ },
+ {
+ "id": "road-motorway_link-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 10,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!in", "structure", "bridge", "tunnel"],
+ ["==", "class", "motorway_link"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[12, 0.75], [20, 2]]},
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-gap-width": {
+ "base": 1.5,
+ "stops": [[12, 0.5], [14, 2], [18, 18]]
+ },
+ "line-opacity": {"base": 1, "stops": [[10.99, 0], [11, 1]]}
+ }
+ },
+ {
+ "id": "road-trunk_link-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 11,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!in", "structure", "bridge", "tunnel"],
+ ["==", "type", "trunk_link"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[12, 0.75], [20, 2]]},
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-gap-width": {
+ "base": 1.5,
+ "stops": [[12, 0.5], [14, 2], [18, 18]]
+ },
+ "line-opacity": {"base": 1, "stops": [[10.99, 0], [11, 1]]}
+ }
+ },
+ {
+ "id": "road-trunk-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!in", "structure", "bridge", "tunnel"],
+ ["==", "class", "trunk"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[10, 1], [16, 2]]},
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-gap-width": {"base": 1.5, "stops": [[5, 0.75], [18, 32]]},
+ "line-opacity": {"base": 1, "stops": [[6, 0], [6.1, 1]]}
+ }
+ },
+ {
+ "id": "road-motorway-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!in", "structure", "bridge", "tunnel"],
+ ["==", "class", "motorway"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[10, 1], [16, 2]]},
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-gap-width": {"base": 1.5, "stops": [[5, 0.75], [18, 32]]}
+ }
+ },
+ {
+ "id": "road-construction",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 14,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "construction"],
+ ["==", "structure", "none"]
+ ]
+ ],
+ "layout": {"line-join": "miter"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[12.5, 0.5], [14, 2], [18, 18]]
+ },
+ "line-color": "hsl(230, 24%, 87%)",
+ "line-opacity": {"base": 1, "stops": [[13.99, 0], [14, 1]]},
+ "line-dasharray": {
+ "base": 1,
+ "stops": [
+ [14, [0.4, 0.8]],
+ [15, [0.3, 0.6]],
+ [16, [0.2, 0.3]],
+ [17, [0.2, 0.25]],
+ [18, [0.15, 0.15]]
+ ]
+ }
+ }
+ },
+ {
+ "id": "road-sidewalks",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 16,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!in", "structure", "bridge", "tunnel"],
+ ["in", "type", "crossing", "sidewalk"]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[15, 1], [18, 4]]},
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-dasharray": {
+ "base": 1,
+ "stops": [
+ [14, [1, 0]],
+ [15, [1.75, 1]],
+ [16, [1, 0.75]],
+ [17, [1, 0.5]]
+ ]
+ },
+ "line-opacity": {"base": 1, "stops": [[16, 0], [16.25, 1]]}
+ }
+ },
+ {
+ "id": "road-path",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!in", "structure", "bridge", "tunnel"],
+ ["!in", "type", "crossing", "sidewalk", "steps"],
+ ["==", "class", "path"]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[15, 1], [18, 4]]},
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-dasharray": {
+ "base": 1,
+ "stops": [
+ [14, [1, 0]],
+ [15, [1.75, 1]],
+ [16, [1, 0.75]],
+ [17, [1, 0.5]]
+ ]
+ },
+ "line-opacity": {"base": 1, "stops": [[14, 0], [14.25, 1]]}
+ }
+ },
+ {
+ "id": "road-steps",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!in", "structure", "bridge", "tunnel"],
+ ["==", "type", "steps"]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[15, 1], [16, 1.6], [18, 6]]
+ },
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-dasharray": {
+ "base": 1,
+ "stops": [
+ [14, [1, 0]],
+ [15, [1.75, 1]],
+ [16, [1, 0.75]],
+ [17, [0.3, 0.3]]
+ ]
+ },
+ "line-opacity": {"base": 1, "stops": [[14, 0], [14.25, 1]]}
+ }
+ },
+ {
+ "id": "road-trunk_link",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 11,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!in", "structure", "bridge", "tunnel"],
+ ["==", "type", "trunk_link"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[12, 0.5], [14, 2], [18, 18]]
+ },
+ "line-color": "hsl(46, 85%, 67%)",
+ "line-opacity": 1
+ }
+ },
+ {
+ "id": "road-motorway_link",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 10,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!in", "structure", "bridge", "tunnel"],
+ ["==", "class", "motorway_link"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[12, 0.5], [14, 2], [18, 18]]
+ },
+ "line-color": "hsl(26, 100%, 68%)",
+ "line-opacity": 1
+ }
+ },
+ {
+ "id": "road-pedestrian",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 12,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "pedestrian"],
+ ["==", "structure", "none"]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[14, 0.5], [18, 12]]},
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-opacity": 1,
+ "line-dasharray": {
+ "base": 1,
+ "stops": [[14, [1, 0]], [15, [1.5, 0.4]], [16, [1, 0.2]]]
+ }
+ }
+ },
+ {
+ "id": "road-pedestrian-polygon-fill",
+ "type": "fill",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 12,
+ "filter": [
+ "all",
+ ["==", "$type", "Polygon"],
+ [
+ "all",
+ ["==", "structure", "none"],
+ ["in", "class", "path", "pedestrian"]
+ ]
+ ],
+ "layout": {},
+ "paint": {
+ "fill-color": {
+ "base": 1,
+ "stops": [
+ [16, "hsl(230, 16%, 94%)"],
+ [16.25, "hsl(230, 50%, 98%)"]
+ ]
+ },
+ "fill-outline-color": "hsl(230, 26%, 88%)",
+ "fill-opacity": 1
+ }
+ },
+ {
+ "id": "road-pedestrian-polygon-pattern",
+ "type": "fill",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 12,
+ "filter": [
+ "all",
+ ["==", "$type", "Polygon"],
+ [
+ "all",
+ ["==", "structure", "none"],
+ ["in", "class", "path", "pedestrian"]
+ ]
+ ],
+ "layout": {},
+ "paint": {
+ "fill-color": "hsl(0, 0%, 100%)",
+ "fill-outline-color": "hsl(35, 10%, 83%)",
+ "fill-pattern": "pedestrian-polygon",
+ "fill-opacity": {"base": 1, "stops": [[16, 0], [16.25, 1]]}
+ }
+ },
+ {
+ "id": "road-polygon",
+ "type": "fill",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 12,
+ "filter": [
+ "all",
+ ["==", "$type", "Polygon"],
+ [
+ "all",
+ ["!in", "class", "motorway", "path", "pedestrian", "trunk"],
+ ["!in", "structure", "bridge", "tunnel"]
+ ]
+ ],
+ "layout": {},
+ "paint": {
+ "fill-color": "hsl(0, 0%, 100%)",
+ "fill-outline-color": "#d6d9e6"
+ }
+ },
+ {
+ "id": "road-service-link-track",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 14,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!=", "type", "trunk_link"],
+ ["!in", "structure", "bridge", "tunnel"],
+ ["in", "class", "link", "service", "track"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[14, 0.5], [18, 12]]},
+ "line-color": "hsl(0, 0%, 100%)"
+ }
+ },
+ {
+ "id": "road-street_limited",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 11,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "street_limited"],
+ ["==", "structure", "none"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[12.5, 0.5], [14, 2], [18, 18]]
+ },
+ "line-color": "hsl(35, 14%, 93%)",
+ "line-opacity": {"base": 1, "stops": [[13.99, 0], [14, 1]]}
+ }
+ },
+ {
+ "id": "road-street",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 11,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ ["all", ["==", "class", "street"], ["==", "structure", "none"]]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[12.5, 0.5], [14, 2], [18, 18]]
+ },
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-opacity": {"base": 1, "stops": [[13.99, 0], [14, 1]]}
+ }
+ },
+ {
+ "id": "road-secondary-tertiary",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!in", "structure", "bridge", "tunnel"],
+ ["in", "class", "secondary", "tertiary"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[8.5, 0.5], [10, 0.75], [18, 26]]
+ },
+ "line-color": {
+ "base": 1,
+ "stops": [[5, "hsl(35, 32%, 91%)"], [8, "hsl(0, 0%, 100%)"]]
+ },
+ "line-opacity": {"base": 1.2, "stops": [[5, 0], [5.5, 1]]}
+ }
+ },
+ {
+ "id": "road-primary",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!in", "structure", "bridge", "tunnel"],
+ ["==", "class", "primary"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[5, 0.75], [18, 32]]},
+ "line-color": {
+ "base": 1,
+ "stops": [[5, "hsl(35, 32%, 91%)"], [7, "hsl(0, 0%, 100%)"]]
+ },
+ "line-opacity": 1
+ }
+ },
+ {
+ "id": "road-oneway-arrows-blue-minor",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 16,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!=", "type", "trunk_link"],
+ ["!in", "structure", "bridge", "tunnel"],
+ ["==", "oneway", "true"],
+ [
+ "in",
+ "class",
+ "link",
+ "path",
+ "pedestrian",
+ "service",
+ "track"
+ ]
+ ]
+ ],
+ "layout": {
+ "symbol-placement": "line",
+ "icon-image": {
+ "base": 1,
+ "stops": [[17, "oneway-small"], [18, "oneway-large"]]
+ },
+ "icon-rotation-alignment": "map",
+ "icon-padding": 2,
+ "symbol-spacing": 200
+ },
+ "paint": {}
+ },
+ {
+ "id": "road-oneway-arrows-blue-major",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 15,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!=", "type", "trunk_link"],
+ ["!in", "structure", "bridge", "tunnel"],
+ ["==", "oneway", "true"],
+ [
+ "in",
+ "class",
+ "primary",
+ "secondary",
+ "street",
+ "street_limited",
+ "tertiary"
+ ]
+ ]
+ ],
+ "layout": {
+ "symbol-placement": "line",
+ "icon-image": {
+ "base": 1,
+ "stops": [[16, "oneway-small"], [17, "oneway-large"]]
+ },
+ "icon-rotation-alignment": "map",
+ "icon-padding": 2,
+ "symbol-spacing": 200
+ },
+ "paint": {}
+ },
+ {
+ "id": "road-trunk",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!in", "structure", "bridge", "tunnel"],
+ ["==", "class", "trunk"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[5, 0.75], [18, 32]]},
+ "line-color": {
+ "base": 1,
+ "stops": [
+ [6, "hsl(0, 0%, 100%)"],
+ [6.1, "hsl(46, 80%, 60%)"],
+ [9, "hsl(46, 85%, 67%)"]
+ ]
+ }
+ }
+ },
+ {
+ "id": "road-motorway",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!in", "structure", "bridge", "tunnel"],
+ ["==", "class", "motorway"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[5, 0.75], [18, 32]]},
+ "line-color": {
+ "base": 1,
+ "stops": [
+ [8, "hsl(26, 87%, 62%)"],
+ [9, "hsl(26, 100%, 68%)"]
+ ]
+ }
+ }
+ },
+ {
+ "id": "road-rail",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 13,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!in", "structure", "bridge", "tunnel"],
+ ["in", "class", "major_rail", "minor_rail"]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-color": {
+ "stops": [
+ [13, "hsl(50, 17%, 82%)"],
+ [16, "hsl(230, 10%, 74%)"]
+ ]
+ },
+ "line-width": {"base": 1.5, "stops": [[14, 0.5], [20, 1]]}
+ }
+ },
+ {
+ "id": "road-rail-tracks",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 13,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!in", "structure", "bridge", "tunnel"],
+ ["in", "class", "major_rail", "minor_rail"]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-color": {
+ "stops": [
+ [13, "hsl(50, 17%, 82%)"],
+ [16, "hsl(230, 10%, 74%)"]
+ ]
+ },
+ "line-width": {"base": 1.5, "stops": [[14, 4], [20, 8]]},
+ "line-dasharray": [0.1, 15],
+ "line-opacity": {"base": 1, "stops": [[13.75, 0], [14, 1]]}
+ }
+ },
+ {
+ "id": "level-crossings",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 16,
+ "filter": [
+ "all",
+ ["==", "$type", "Point"],
+ ["==", "class", "level_crossing"]
+ ],
+ "layout": {
+ "icon-size": 1,
+ "icon-image": "level-crossing",
+ "icon-allow-overlap": true
+ },
+ "paint": {}
+ },
+ {
+ "id": "road-oneway-arrows-white",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 16,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!in", "structure", "bridge", "tunnel"],
+ [
+ "!in",
+ "type",
+ "primary_link",
+ "secondary_link",
+ "tertiary_link"
+ ],
+ ["==", "oneway", "true"],
+ [
+ "in",
+ "class",
+ "link",
+ "motorway",
+ "motorway_link",
+ "trunk"
+ ]
+ ]
+ ],
+ "layout": {
+ "symbol-placement": "line",
+ "icon-image": {
+ "base": 1,
+ "stops": [
+ [16, "oneway-white-small"],
+ [17, "oneway-white-large"]
+ ]
+ },
+ "icon-padding": 2,
+ "symbol-spacing": 200
+ },
+ "paint": {}
+ },
+ {
+ "id": "turning-features",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444855786460.0557"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 15,
+ "filter": [
+ "all",
+ ["==", "$type", "Point"],
+ ["in", "class", "turning_circle", "turning_loop"]
+ ],
+ "layout": {
+ "icon-image": "turning-circle",
+ "icon-size": {"base": 1.5, "stops": [[14, 0.095], [18, 1]]},
+ "icon-allow-overlap": true,
+ "icon-ignore-placement": true,
+ "icon-padding": 0,
+ "icon-rotation-alignment": "map"
+ },
+ "paint": {}
+ },
+ {
+ "id": "bridge-path-bg",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!=", "type", "steps"],
+ ["==", "class", "path"],
+ ["==", "structure", "bridge"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[15, 2], [18, 7]]},
+ "line-dasharray": [1, 0],
+ "line-color": "hsl(230, 17%, 82%)",
+ "line-blur": 0,
+ "line-opacity": {"base": 1, "stops": [[15, 0], [15.25, 1]]}
+ }
+ },
+ {
+ "id": "bridge-steps-bg",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ ["all", ["==", "structure", "bridge"], ["==", "type", "steps"]]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[15, 2], [17, 4.6], [18, 7]]
+ },
+ "line-color": "hsl(230, 17%, 82%)",
+ "line-dasharray": [1, 0],
+ "line-opacity": {"base": 1, "stops": [[14, 0], [14.25, 0.75]]}
+ }
+ },
+ {
+ "id": "bridge-pedestrian-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 13,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "pedestrian"],
+ ["==", "structure", "bridge"]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[14, 2], [18, 14.5]]},
+ "line-color": "hsl(230, 24%, 87%)",
+ "line-gap-width": 0,
+ "line-opacity": {"base": 1, "stops": [[13.99, 0], [14, 1]]}
+ }
+ },
+ {
+ "id": "bridge-street-low",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 11,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "street"],
+ ["==", "structure", "bridge"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[12.5, 0.5], [14, 2], [18, 18]]
+ },
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-opacity": {
+ "stops": [[11.5, 0], [12, 1], [14, 1], [14.01, 0]]
+ }
+ }
+ },
+ {
+ "id": "bridge-street_limited-low",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 11,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "street_limited"],
+ ["==", "structure", "bridge"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[12.5, 0.5], [14, 2], [18, 18]]
+ },
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-opacity": {
+ "stops": [[11.5, 0], [12, 1], [14, 1], [14.01, 0]]
+ }
+ }
+ },
+ {
+ "id": "bridge-service-link-track-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 14,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!=", "type", "trunk_link"],
+ ["==", "structure", "bridge"],
+ ["in", "class", "link", "service", "track"]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[12, 0.75], [20, 2]]},
+ "line-color": "hsl(230, 24%, 87%)",
+ "line-gap-width": {"base": 1.5, "stops": [[14, 0.5], [18, 12]]}
+ }
+ },
+ {
+ "id": "bridge-street_limited-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 11,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "street_limited"],
+ ["==", "structure", "bridge"]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[12, 0.75], [20, 2]]},
+ "line-color": "hsl(230, 24%, 87%)",
+ "line-gap-width": {
+ "base": 1.5,
+ "stops": [[13, 0], [14, 2], [18, 18]]
+ }
+ }
+ },
+ {
+ "id": "bridge-street-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 11,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "street"],
+ ["==", "structure", "bridge"]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[12, 0.75], [20, 2]]},
+ "line-color": "hsl(230, 24%, 87%)",
+ "line-opacity": {"base": 1, "stops": [[13.99, 0], [14, 1]]},
+ "line-gap-width": {
+ "base": 1.5,
+ "stops": [[13, 0], [14, 2], [18, 18]]
+ }
+ }
+ },
+ {
+ "id": "bridge-secondary-tertiary-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "structure", "bridge"],
+ ["in", "class", "secondary", "tertiary"]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.2, "stops": [[10, 0.75], [18, 2]]},
+ "line-color": "hsl(230, 24%, 87%)",
+ "line-gap-width": {
+ "base": 1.5,
+ "stops": [[8.5, 0.5], [10, 0.75], [18, 26]]
+ },
+ "line-translate": [0, 0]
+ }
+ },
+ {
+ "id": "bridge-primary-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "primary"],
+ ["==", "structure", "bridge"]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[10, 1], [16, 2]]},
+ "line-color": "hsl(230, 24%, 87%)",
+ "line-gap-width": {"base": 1.5, "stops": [[5, 0.75], [18, 32]]},
+ "line-translate": [0, 0]
+ }
+ },
+ {
+ "id": "bridge-trunk_link-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 13,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!in", "layer", 2, 3, 4, 5],
+ ["==", "structure", "bridge"],
+ ["==", "type", "trunk_link"]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[12, 0.75], [20, 2]]},
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-gap-width": {
+ "base": 1.5,
+ "stops": [[12, 0.5], [14, 2], [18, 18]]
+ },
+ "line-opacity": {"base": 1, "stops": [[10.99, 0], [11, 1]]}
+ }
+ },
+ {
+ "id": "bridge-motorway_link-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 13,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!in", "layer", 2, 3, 4, 5],
+ ["==", "class", "motorway_link"],
+ ["==", "structure", "bridge"]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[12, 0.75], [20, 2]]},
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-gap-width": {
+ "base": 1.5,
+ "stops": [[12, 0.5], [14, 2], [18, 18]]
+ },
+ "line-opacity": 1
+ }
+ },
+ {
+ "id": "bridge-trunk-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!in", "layer", 2, 3, 4, 5],
+ ["==", "class", "trunk"],
+ ["==", "structure", "bridge"]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[10, 1], [16, 2]]},
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-gap-width": {"base": 1.5, "stops": [[5, 0.75], [18, 32]]}
+ }
+ },
+ {
+ "id": "bridge-motorway-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!in", "layer", 2, 3, 4, 5],
+ ["==", "class", "motorway"],
+ ["==", "structure", "bridge"]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[10, 1], [16, 2]]},
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-gap-width": {"base": 1.5, "stops": [[5, 0.75], [18, 32]]}
+ }
+ },
+ {
+ "id": "bridge-construction",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 14,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "construction"],
+ ["==", "structure", "bridge"]
+ ]
+ ],
+ "layout": {"line-join": "miter"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[12.5, 0.5], [14, 2], [18, 18]]
+ },
+ "line-color": "hsl(230, 24%, 87%)",
+ "line-opacity": {"base": 1, "stops": [[13.99, 0], [14, 1]]},
+ "line-dasharray": {
+ "base": 1,
+ "stops": [
+ [14, [0.4, 0.8]],
+ [15, [0.3, 0.6]],
+ [16, [0.2, 0.3]],
+ [17, [0.2, 0.25]],
+ [18, [0.15, 0.15]]
+ ]
+ }
+ }
+ },
+ {
+ "id": "bridge-path",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!=", "type", "steps"],
+ ["==", "class", "path"],
+ ["==", "structure", "bridge"]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[15, 1], [18, 4]]},
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-dasharray": {
+ "base": 1,
+ "stops": [
+ [14, [1, 0]],
+ [15, [1.75, 1]],
+ [16, [1, 0.75]],
+ [17, [1, 0.5]]
+ ]
+ },
+ "line-opacity": {"base": 1, "stops": [[14, 0], [14.25, 1]]}
+ }
+ },
+ {
+ "id": "bridge-steps",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ ["all", ["==", "structure", "bridge"], ["==", "type", "steps"]]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[15, 1], [16, 1.6], [18, 6]]
+ },
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-dasharray": {
+ "base": 1,
+ "stops": [
+ [14, [1, 0]],
+ [15, [1.75, 1]],
+ [16, [1, 0.75]],
+ [17, [0.3, 0.3]]
+ ]
+ },
+ "line-opacity": {"base": 1, "stops": [[14, 0], [14.25, 1]]}
+ }
+ },
+ {
+ "id": "bridge-trunk_link",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 13,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!in", "layer", 2, 3, 4, 5],
+ ["==", "structure", "bridge"],
+ ["==", "type", "trunk_link"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[12, 0.5], [14, 2], [18, 18]]
+ },
+ "line-color": "hsl(46, 85%, 67%)"
+ }
+ },
+ {
+ "id": "bridge-motorway_link",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 13,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!in", "layer", 2, 3, 4, 5],
+ ["==", "class", "motorway_link"],
+ ["==", "structure", "bridge"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[12, 0.5], [14, 2], [18, 18]]
+ },
+ "line-color": "hsl(26, 100%, 68%)"
+ }
+ },
+ {
+ "id": "bridge-pedestrian",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 13,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "pedestrian"],
+ ["==", "structure", "bridge"]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[14, 0.5], [18, 12]]},
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-opacity": 1,
+ "line-dasharray": {
+ "base": 1,
+ "stops": [[14, [1, 0]], [15, [1.5, 0.4]], [16, [1, 0.2]]]
+ }
+ }
+ },
+ {
+ "id": "bridge-service-link-track",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 14,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!=", "type", "trunk_link"],
+ ["==", "structure", "bridge"],
+ ["in", "class", "link", "service", "track"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[14, 0.5], [18, 12]]},
+ "line-color": "hsl(0, 0%, 100%)"
+ }
+ },
+ {
+ "id": "bridge-street_limited",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 11,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "street_limited"],
+ ["==", "structure", "bridge"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[12.5, 0.5], [14, 2], [18, 18]]
+ },
+ "line-color": "hsl(35, 14%, 93%)",
+ "line-opacity": {"base": 1, "stops": [[13.99, 0], [14, 1]]}
+ }
+ },
+ {
+ "id": "bridge-street",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 11,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "street"],
+ ["==", "structure", "bridge"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[12.5, 0.5], [14, 2], [18, 18]]
+ },
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-opacity": {"base": 1, "stops": [[13.99, 0], [14, 1]]}
+ }
+ },
+ {
+ "id": "bridge-secondary-tertiary",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "structure", "bridge"],
+ ["in", "type", "secondary", "tertiary"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[8.5, 0.5], [10, 0.75], [18, 26]]
+ },
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-opacity": {"base": 1.2, "stops": [[5, 0], [5.5, 1]]}
+ }
+ },
+ {
+ "id": "bridge-primary",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "structure", "bridge"],
+ ["==", "type", "primary"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[5, 0.75], [18, 32]]},
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-opacity": 1
+ }
+ },
+ {
+ "id": "bridge-oneway-arrows-blue-minor",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 16,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "oneway", "true"],
+ ["==", "structure", "bridge"],
+ [
+ "in",
+ "class",
+ "link",
+ "path",
+ "pedestrian",
+ "service",
+ "track"
+ ]
+ ]
+ ],
+ "layout": {
+ "symbol-placement": "line",
+ "icon-image": {
+ "base": 1,
+ "stops": [[17, "oneway-small"], [18, "oneway-large"]]
+ },
+ "symbol-spacing": 200,
+ "icon-rotation-alignment": "map",
+ "icon-padding": 2
+ },
+ "paint": {}
+ },
+ {
+ "id": "bridge-oneway-arrows-blue-major",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 15,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "oneway", "true"],
+ ["==", "structure", "bridge"],
+ [
+ "in",
+ "class",
+ "primary",
+ "secondary",
+ "street",
+ "street_limited",
+ "tertiary"
+ ]
+ ]
+ ],
+ "layout": {
+ "symbol-placement": "line",
+ "icon-image": {
+ "base": 1,
+ "stops": [[16, "oneway-small"], [17, "oneway-large"]]
+ },
+ "symbol-spacing": 200,
+ "icon-rotation-alignment": "map",
+ "icon-padding": 2
+ },
+ "paint": {}
+ },
+ {
+ "id": "bridge-trunk",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!in", "layer", 2, 3, 4, 5],
+ ["==", "class", "trunk"],
+ ["==", "structure", "bridge"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[5, 0.75], [18, 32]]},
+ "line-color": "hsl(46, 85%, 67%)"
+ }
+ },
+ {
+ "id": "bridge-motorway",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["!in", "layer", 2, 3, 4, 5],
+ ["==", "class", "motorway"],
+ ["==", "structure", "bridge"]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[5, 0.75], [18, 32]]},
+ "line-color": "hsl(26, 100%, 68%)"
+ }
+ },
+ {
+ "id": "bridge-rail",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 13,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "structure", "bridge"],
+ ["in", "class", "major_rail", "minor_rail"]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-color": {
+ "stops": [
+ [13, "hsl(50, 17%, 82%)"],
+ [16, "hsl(230, 10%, 74%)"]
+ ]
+ },
+ "line-width": {"base": 1.5, "stops": [[14, 0.5], [20, 1]]}
+ }
+ },
+ {
+ "id": "bridge-rail-tracks",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 13,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "structure", "bridge"],
+ ["in", "class", "major_rail", "minor_rail"]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-color": {
+ "stops": [
+ [13, "hsl(50, 17%, 82%)"],
+ [16, "hsl(230, 10%, 74%)"]
+ ]
+ },
+ "line-width": {"base": 1.5, "stops": [[14, 4], [20, 8]]},
+ "line-dasharray": [0.1, 15],
+ "line-opacity": {"base": 1, "stops": [[13.75, 0], [20, 1]]}
+ }
+ },
+ {
+ "id": "bridge-trunk_link-2-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 13,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "structure", "bridge"],
+ ["==", "type", "trunk_link"],
+ [">=", "layer", 2]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[12, 0.75], [20, 2]]},
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-gap-width": {
+ "base": 1.5,
+ "stops": [[12, 0.5], [14, 2], [18, 18]]
+ },
+ "line-opacity": {"base": 1, "stops": [[10.99, 0], [11, 1]]}
+ }
+ },
+ {
+ "id": "bridge-motorway_link-2-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 13,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "motorway_link"],
+ ["==", "structure", "bridge"],
+ [">=", "layer", 2]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[12, 0.75], [20, 2]]},
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-gap-width": {
+ "base": 1.5,
+ "stops": [[12, 0.5], [14, 2], [18, 18]]
+ },
+ "line-opacity": 1
+ }
+ },
+ {
+ "id": "bridge-trunk-2-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "trunk"],
+ ["==", "structure", "bridge"],
+ [">=", "layer", 2]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[10, 1], [16, 2]]},
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-gap-width": {"base": 1.5, "stops": [[5, 0.75], [18, 32]]}
+ }
+ },
+ {
+ "id": "bridge-motorway-2-case",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "motorway"],
+ ["==", "structure", "bridge"],
+ [">=", "layer", 2]
+ ]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[10, 1], [16, 2]]},
+ "line-color": "hsl(0, 0%, 100%)",
+ "line-gap-width": {"base": 1.5, "stops": [[5, 0.75], [18, 32]]}
+ }
+ },
+ {
+ "id": "bridge-trunk_link-2",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 13,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "structure", "bridge"],
+ ["==", "type", "trunk_link"],
+ [">=", "layer", 2]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[12, 0.5], [14, 2], [18, 18]]
+ },
+ "line-color": "hsl(46, 85%, 67%)"
+ }
+ },
+ {
+ "id": "bridge-motorway_link-2",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 13,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "motorway_link"],
+ ["==", "structure", "bridge"],
+ [">=", "layer", 2]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {
+ "base": 1.5,
+ "stops": [[12, 0.5], [14, 2], [18, 18]]
+ },
+ "line-color": "hsl(26, 100%, 68%)"
+ }
+ },
+ {
+ "id": "bridge-trunk-2",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "trunk"],
+ ["==", "structure", "bridge"],
+ [">=", "layer", 2]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[5, 0.75], [18, 32]]},
+ "line-color": "hsl(46, 85%, 67%)"
+ }
+ },
+ {
+ "id": "bridge-motorway-2",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ ["==", "class", "motorway"],
+ ["==", "structure", "bridge"],
+ [">=", "layer", 2]
+ ]
+ ],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-width": {"base": 1.5, "stops": [[5, 0.75], [18, 32]]},
+ "line-color": "hsl(26, 100%, 68%)"
+ }
+ },
+ {
+ "id": "bridge-oneway-arrows-white",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444855799204.86"},
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 16,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "all",
+ [
+ "!in",
+ "type",
+ "primary_link",
+ "secondary_link",
+ "tertiary_link"
+ ],
+ ["==", "oneway", "true"],
+ ["==", "structure", "bridge"],
+ [
+ "in",
+ "class",
+ "link",
+ "motorway",
+ "motorway_link",
+ "trunk"
+ ]
+ ]
+ ],
+ "layout": {
+ "symbol-placement": "line",
+ "icon-image": {
+ "base": 1,
+ "stops": [
+ [16, "oneway-white-small"],
+ [17, "oneway-white-large"]
+ ]
+ },
+ "symbol-spacing": 200,
+ "icon-padding": 2
+ },
+ "paint": {}
+ },
+ {
+ "id": "aerialway",
+ "type": "line",
+ "source": "composite",
+ "source-layer": "road",
+ "minzoom": 13,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ ["==", "class", "aerialway"]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-color": "hsl(230, 10%, 74%)",
+ "line-width": {"base": 1.5, "stops": [[14, 0.5], [20, 1]]}
+ }
+ },
+ {
+ "id": "admin-3-4-boundaries-bg",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444934295202.7542"},
+ "source": "composite",
+ "source-layer": "admin",
+ "filter": ["all", ["==", "maritime", 0], [">=", "admin_level", 3]],
+ "layout": {"line-join": "bevel"},
+ "paint": {
+ "line-color": {
+ "base": 1,
+ "stops": [
+ [8, "hsl(35, 12%, 89%)"],
+ [16, "hsl(230, 49%, 90%)"]
+ ]
+ },
+ "line-width": {"base": 1, "stops": [[7, 3.75], [12, 5.5]]},
+ "line-opacity": {"base": 1, "stops": [[7, 0], [8, 0.75]]},
+ "line-dasharray": [1, 0],
+ "line-translate": [0, 0],
+ "line-blur": {"base": 1, "stops": [[3, 0], [8, 3]]}
+ }
+ },
+ {
+ "id": "admin-2-boundaries-bg",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444934295202.7542"},
+ "source": "composite",
+ "source-layer": "admin",
+ "minzoom": 1,
+ "filter": ["all", ["==", "admin_level", 2], ["==", "maritime", 0]],
+ "layout": {"line-join": "miter"},
+ "paint": {
+ "line-width": {"base": 1, "stops": [[3, 3.5], [10, 8]]},
+ "line-color": {
+ "base": 1,
+ "stops": [
+ [6, "hsl(35, 12%, 89%)"],
+ [8, "hsl(230, 49%, 90%)"]
+ ]
+ },
+ "line-opacity": {"base": 1, "stops": [[3, 0], [4, 0.5]]},
+ "line-translate": [0, 0],
+ "line-blur": {"base": 1, "stops": [[3, 0], [10, 2]]}
+ }
+ },
+ {
+ "id": "admin-3-4-boundaries",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444934295202.7542"},
+ "source": "composite",
+ "source-layer": "admin",
+ "filter": ["all", ["==", "maritime", 0], [">=", "admin_level", 3]],
+ "layout": {"line-join": "round", "line-cap": "round"},
+ "paint": {
+ "line-dasharray": {
+ "base": 1,
+ "stops": [[6, [2, 0]], [7, [2, 2, 6, 2]]]
+ },
+ "line-width": {"base": 1, "stops": [[7, 0.75], [12, 1.5]]},
+ "line-opacity": {"base": 1, "stops": [[2, 0], [3, 1]]},
+ "line-color": {
+ "base": 1,
+ "stops": [
+ [3, "hsl(230, 14%, 77%)"],
+ [7, "hsl(230, 8%, 62%)"]
+ ]
+ }
+ }
+ },
+ {
+ "id": "admin-2-boundaries",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444934295202.7542"},
+ "source": "composite",
+ "source-layer": "admin",
+ "minzoom": 1,
+ "filter": [
+ "all",
+ ["==", "admin_level", 2],
+ ["==", "disputed", 0],
+ ["==", "maritime", 0]
+ ],
+ "layout": {"line-join": "round", "line-cap": "round"},
+ "paint": {
+ "line-color": "hsl(230, 8%, 51%)",
+ "line-width": {"base": 1, "stops": [[3, 0.5], [10, 2]]}
+ }
+ },
+ {
+ "id": "admin-2-boundaries-dispute",
+ "type": "line",
+ "metadata": {"mapbox:group": "1444934295202.7542"},
+ "source": "composite",
+ "source-layer": "admin",
+ "minzoom": 1,
+ "filter": [
+ "all",
+ ["==", "admin_level", 2],
+ ["==", "disputed", 1],
+ ["==", "maritime", 0]
+ ],
+ "layout": {"line-join": "round"},
+ "paint": {
+ "line-dasharray": [1.5, 1.5],
+ "line-color": "hsl(230, 8%, 51%)",
+ "line-width": {"base": 1, "stops": [[3, 0.5], [10, 2]]}
+ }
+ },
+ {
+ "id": "housenum-label",
+ "type": "symbol",
+ "source": "composite",
+ "source-layer": "housenum_label",
+ "minzoom": 17,
+ "layout": {
+ "text-field": "{house_num}",
+ "text-font": [
+ "DIN Offc Pro Italic",
+ "Arial Unicode MS Regular"
+ ],
+ "text-padding": 4,
+ "text-max-width": 7,
+ "text-size": 9.5
+ },
+ "paint": {
+ "text-color": "hsl(35, 2%, 69%)",
+ "text-halo-color": "hsl(35, 8%, 85%)",
+ "text-halo-width": 0.5,
+ "text-halo-blur": 0
+ }
+ },
+ {
+ "id": "waterway-label",
+ "type": "symbol",
+ "source": "composite",
+ "source-layer": "waterway_label",
+ "minzoom": 12,
+ "filter": ["in", "class", "canal", "river"],
+ "layout": {
+ "text-field": "{name_en}",
+ "text-font": [
+ "DIN Offc Pro Italic",
+ "Arial Unicode MS Regular"
+ ],
+ "symbol-placement": "line",
+ "text-pitch-alignment": "viewport",
+ "text-max-angle": 30,
+ "text-size": {"base": 1, "stops": [[13, 12], [18, 16]]}
+ },
+ "paint": {
+ "text-halo-width": 0.5,
+ "text-halo-color": "hsl(196, 80%, 70%)",
+ "text-color": "hsl(230, 48%, 44%)",
+ "text-halo-blur": 0.5
+ }
+ },
+ {
+ "id": "poi-scalerank4-l15",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444933456003.5437"},
+ "source": "composite",
+ "source-layer": "poi_label",
+ "minzoom": 17,
+ "filter": [
+ "all",
+ [
+ "!in",
+ "maki",
+ "campsite",
+ "cemetery",
+ "dog-park",
+ "garden",
+ "golf",
+ "park",
+ "picnic-site",
+ "playground",
+ "zoo"
+ ],
+ ["==", "scalerank", 4],
+ [">=", "localrank", 15]
+ ],
+ "layout": {
+ "text-line-height": 1.1,
+ "text-size": {"base": 1, "stops": [[16, 11], [20, 13]]},
+ "icon-image": "{maki}-11",
+ "text-max-angle": 38,
+ "symbol-spacing": 250,
+ "text-font": [
+ "DIN Offc Pro Medium",
+ "Arial Unicode MS Regular"
+ ],
+ "text-padding": 2,
+ "text-offset": [0, 0.65],
+ "text-rotation-alignment": "viewport",
+ "text-anchor": "top",
+ "text-field": "{name_en}",
+ "text-letter-spacing": 0.01,
+ "text-max-width": 8
+ },
+ "paint": {
+ "text-color": "hsl(26, 25%, 32%)",
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 0.5,
+ "text-halo-blur": 0.5
+ }
+ },
+ {
+ "id": "poi-scalerank4-l1",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444933456003.5437"},
+ "source": "composite",
+ "source-layer": "poi_label",
+ "minzoom": 15,
+ "filter": [
+ "all",
+ [
+ "!in",
+ "maki",
+ "campsite",
+ "cemetery",
+ "dog-park",
+ "garden",
+ "golf",
+ "park",
+ "picnic-site",
+ "playground",
+ "zoo"
+ ],
+ ["<=", "localrank", 14],
+ ["==", "scalerank", 4]
+ ],
+ "layout": {
+ "text-line-height": 1.1,
+ "text-size": {"base": 1, "stops": [[16, 11], [20, 13]]},
+ "icon-image": "{maki}-11",
+ "text-max-angle": 38,
+ "symbol-spacing": 250,
+ "text-font": [
+ "DIN Offc Pro Medium",
+ "Arial Unicode MS Regular"
+ ],
+ "text-padding": 1,
+ "text-offset": [0, 0.65],
+ "text-rotation-alignment": "viewport",
+ "text-anchor": "top",
+ "text-field": "{name_en}",
+ "text-letter-spacing": 0.01,
+ "text-max-width": 8
+ },
+ "paint": {
+ "text-color": "hsl(26, 25%, 32%)",
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 0.5,
+ "text-halo-blur": 0.5
+ }
+ },
+ {
+ "id": "poi-parks_scalerank4",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444933456003.5437"},
+ "source": "composite",
+ "source-layer": "poi_label",
+ "minzoom": 15,
+ "filter": [
+ "all",
+ ["==", "scalerank", 4],
+ [
+ "in",
+ "maki",
+ "campsite",
+ "cemetery",
+ "dog-park",
+ "garden",
+ "golf",
+ "park",
+ "picnic-site",
+ "playground",
+ "zoo"
+ ]
+ ],
+ "layout": {
+ "text-line-height": 1.1,
+ "text-size": {"base": 1, "stops": [[16, 11], [20, 13]]},
+ "icon-image": "{maki}-11",
+ "text-max-angle": 38,
+ "symbol-spacing": 250,
+ "text-font": [
+ "DIN Offc Pro Medium",
+ "Arial Unicode MS Regular"
+ ],
+ "text-padding": 1,
+ "text-offset": [0, 0.65],
+ "text-rotation-alignment": "viewport",
+ "text-anchor": "top",
+ "text-field": "{name_en}",
+ "text-letter-spacing": 0.01,
+ "text-max-width": 8
+ },
+ "paint": {
+ "text-color": "hsl(100, 100%, 20%)",
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 0.5,
+ "text-halo-blur": 0.5
+ }
+ },
+ {
+ "id": "poi-scalerank3",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444933372896.5967"},
+ "source": "composite",
+ "source-layer": "poi_label",
+ "filter": [
+ "all",
+ [
+ "!in",
+ "maki",
+ "campsite",
+ "cemetery",
+ "dog-park",
+ "garden",
+ "golf",
+ "park",
+ "picnic-site",
+ "playground",
+ "zoo"
+ ],
+ ["==", "scalerank", 3]
+ ],
+ "layout": {
+ "text-line-height": 1.1,
+ "text-size": {"base": 1, "stops": [[16, 11], [20, 13]]},
+ "icon-image": "{maki}-11",
+ "text-max-angle": 38,
+ "symbol-spacing": 250,
+ "text-font": [
+ "DIN Offc Pro Medium",
+ "Arial Unicode MS Regular"
+ ],
+ "text-padding": 1,
+ "text-offset": [0, 0.65],
+ "text-rotation-alignment": "viewport",
+ "text-anchor": "top",
+ "text-field": "{name_en}",
+ "text-letter-spacing": 0.01,
+ "text-max-width": 8
+ },
+ "paint": {
+ "text-color": "hsl(26, 25%, 32%)",
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 0.5,
+ "text-halo-blur": 0.5
+ }
+ },
+ {
+ "id": "poi-parks-scalerank3",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444933372896.5967"},
+ "source": "composite",
+ "source-layer": "poi_label",
+ "filter": [
+ "all",
+ ["==", "scalerank", 3],
+ [
+ "in",
+ "maki",
+ "campsite",
+ "cemetery",
+ "dog-park",
+ "garden",
+ "golf",
+ "park",
+ "picnic-site",
+ "playground",
+ "zoo"
+ ]
+ ],
+ "layout": {
+ "text-line-height": 1.1,
+ "text-size": {"base": 1, "stops": [[16, 11], [20, 13]]},
+ "icon-image": "{maki}-11",
+ "text-max-angle": 38,
+ "symbol-spacing": 250,
+ "text-font": [
+ "DIN Offc Pro Medium",
+ "Arial Unicode MS Regular"
+ ],
+ "text-padding": 2,
+ "text-offset": [0, 0.65],
+ "text-rotation-alignment": "viewport",
+ "text-anchor": "top",
+ "text-field": "{name_en}",
+ "text-letter-spacing": 0.01,
+ "text-max-width": 8
+ },
+ "paint": {
+ "text-color": "hsl(100, 100%, 20%)",
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 0.5,
+ "text-halo-blur": 0.5
+ }
+ },
+ {
+ "id": "road-label-small",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444933721429.3076"},
+ "source": "composite",
+ "source-layer": "road_label",
+ "minzoom": 15,
+ "filter": [
+ "all",
+ [
+ "!in",
+ "class",
+ "golf",
+ "link",
+ "motorway",
+ "pedestrian",
+ "primary",
+ "secondary",
+ "street",
+ "street_limited",
+ "tertiary",
+ "trunk"
+ ],
+ ["==", "$type", "LineString"]
+ ],
+ "layout": {
+ "text-size": {"base": 1, "stops": [[15, 10], [20, 13]]},
+ "text-max-angle": 30,
+ "symbol-spacing": 250,
+ "text-font": [
+ "DIN Offc Pro Regular",
+ "Arial Unicode MS Regular"
+ ],
+ "symbol-placement": "line",
+ "text-padding": 1,
+ "text-rotation-alignment": "map",
+ "text-pitch-alignment": "viewport",
+ "text-field": "{name_en}",
+ "text-letter-spacing": 0.01
+ },
+ "paint": {
+ "text-color": "hsl(0, 0%, 0%)",
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 1.25,
+ "text-halo-blur": 1
+ }
+ },
+ {
+ "id": "road-label-medium",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444933721429.3076"},
+ "source": "composite",
+ "source-layer": "road_label",
+ "minzoom": 11,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [
+ "in",
+ "class",
+ "link",
+ "pedestrian",
+ "street",
+ "street_limited"
+ ]
+ ],
+ "layout": {
+ "text-size": {"base": 1, "stops": [[11, 10], [20, 14]]},
+ "text-max-angle": 30,
+ "symbol-spacing": 250,
+ "text-font": [
+ "DIN Offc Pro Regular",
+ "Arial Unicode MS Regular"
+ ],
+ "symbol-placement": "line",
+ "text-padding": 1,
+ "text-rotation-alignment": "map",
+ "text-pitch-alignment": "viewport",
+ "text-field": "{name_en}",
+ "text-letter-spacing": 0.01
+ },
+ "paint": {
+ "text-color": "hsl(0, 0%, 0%)",
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 1
+ }
+ },
+ {
+ "id": "road-label-large",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444933721429.3076"},
+ "source": "composite",
+ "source-layer": "road_label",
+ "filter": [
+ "in",
+ "class",
+ "motorway",
+ "primary",
+ "secondary",
+ "tertiary",
+ "trunk"
+ ],
+ "layout": {
+ "text-size": {"base": 1, "stops": [[9, 10], [20, 16]]},
+ "text-max-angle": 30,
+ "symbol-spacing": 250,
+ "text-font": [
+ "DIN Offc Pro Regular",
+ "Arial Unicode MS Regular"
+ ],
+ "symbol-placement": "line",
+ "text-padding": 1,
+ "text-rotation-alignment": "map",
+ "text-pitch-alignment": "viewport",
+ "text-field": "{name_en}",
+ "text-letter-spacing": 0.01
+ },
+ "paint": {
+ "text-color": "hsl(0, 0%, 0%)",
+ "text-halo-color": "hsla(0, 0%, 100%, 0.75)",
+ "text-halo-width": 1,
+ "text-halo-blur": 1
+ }
+ },
+ {
+ "id": "road-shields-black",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444933575858.6992"},
+ "source": "composite",
+ "source-layer": "road_label",
+ "filter": [
+ "all",
+ [
+ "!in",
+ "shield",
+ "at-expressway",
+ "at-motorway",
+ "at-state-b",
+ "bg-motorway",
+ "bg-national",
+ "ch-main",
+ "ch-motorway",
+ "cz-motorway",
+ "cz-road",
+ "de-motorway",
+ "e-road",
+ "fi-main",
+ "gr-motorway",
+ "gr-national",
+ "hr-motorway",
+ "hr-state",
+ "hu-main",
+ "hu-motorway",
+ "nz-state",
+ "pl-expressway",
+ "pl-motorway",
+ "pl-national",
+ "ro-county",
+ "ro-motorway",
+ "ro-national",
+ "rs-motorway",
+ "rs-state-1b",
+ "se-main",
+ "si-expressway",
+ "si-motorway",
+ "sk-highway",
+ "sk-road",
+ "us-interstate",
+ "us-interstate-business",
+ "us-interstate-duplex",
+ "us-interstate-truck",
+ "za-metropolitan",
+ "za-national",
+ "za-provincial",
+ "za-regional"
+ ],
+ ["<=", "reflen", 6]
+ ],
+ "layout": {
+ "text-size": 9,
+ "icon-image": "{shield}-{reflen}",
+ "icon-rotation-alignment": "viewport",
+ "text-max-angle": 38,
+ "symbol-spacing": {"base": 1, "stops": [[11, 150], [14, 200]]},
+ "text-font": ["DIN Offc Pro Bold", "Arial Unicode MS Bold"],
+ "symbol-placement": {
+ "base": 1,
+ "stops": [[10, "point"], [11, "line"]]
+ },
+ "text-padding": 2,
+ "text-rotation-alignment": "viewport",
+ "text-field": "{ref}",
+ "text-letter-spacing": 0.05,
+ "icon-padding": 2
+ },
+ "paint": {
+ "text-color": "hsl(0, 0%, 7%)",
+ "icon-halo-color": "rgba(0, 0, 0, 1)",
+ "icon-halo-width": 1,
+ "text-opacity": 1,
+ "icon-color": "white",
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 0
+ }
+ },
+ {
+ "id": "road-shields-white",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444933575858.6992"},
+ "source": "composite",
+ "source-layer": "road_label",
+ "filter": [
+ "all",
+ ["<=", "reflen", 6],
+ [
+ "in",
+ "shield",
+ "at-expressway",
+ "at-motorway",
+ "at-state-b",
+ "bg-motorway",
+ "bg-national",
+ "ch-main",
+ "ch-motorway",
+ "cz-motorway",
+ "cz-road",
+ "de-motorway",
+ "e-road",
+ "fi-main",
+ "gr-motorway",
+ "gr-national",
+ "hr-motorway",
+ "hr-state",
+ "hu-main",
+ "hu-motorway",
+ "nz-state",
+ "pl-expressway",
+ "pl-motorway",
+ "pl-national",
+ "ro-county",
+ "ro-motorway",
+ "ro-national",
+ "rs-motorway",
+ "rs-state-1b",
+ "se-main",
+ "si-expressway",
+ "si-motorway",
+ "sk-highway",
+ "sk-road",
+ "us-interstate",
+ "us-interstate-business",
+ "us-interstate-duplex",
+ "us-interstate-truck",
+ "za-metropolitan",
+ "za-national",
+ "za-provincial",
+ "za-regional"
+ ]
+ ],
+ "layout": {
+ "text-size": 9,
+ "icon-image": "{shield}-{reflen}",
+ "icon-rotation-alignment": "viewport",
+ "text-max-angle": 38,
+ "symbol-spacing": {"base": 1, "stops": [[11, 150], [14, 200]]},
+ "text-font": ["DIN Offc Pro Bold", "Arial Unicode MS Bold"],
+ "symbol-placement": {
+ "base": 1,
+ "stops": [[10, "point"], [11, "line"]]
+ },
+ "text-padding": 2,
+ "text-rotation-alignment": "viewport",
+ "text-field": "{ref}",
+ "text-letter-spacing": 0.05,
+ "icon-padding": 2
+ },
+ "paint": {
+ "text-color": "hsl(0, 0%, 100%)",
+ "icon-halo-color": "rgba(0, 0, 0, 1)",
+ "icon-halo-width": 1,
+ "text-opacity": 1,
+ "icon-color": "white",
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 0
+ }
+ },
+ {
+ "id": "motorway-junction",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444933575858.6992"},
+ "source": "composite",
+ "source-layer": "motorway_junction",
+ "minzoom": 14,
+ "filter": ["all", ["<=", "reflen", 9], [">", "reflen", 0]],
+ "layout": {
+ "text-field": "{ref}",
+ "text-size": 9,
+ "icon-image": "motorway-exit-{reflen}",
+ "text-font": ["DIN Offc Pro Bold", "Arial Unicode MS Bold"]
+ },
+ "paint": {
+ "text-color": "hsl(0, 0%, 100%)",
+ "text-translate": [0, 0]
+ }
+ },
+ {
+ "id": "poi-scalerank2",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444933358918.2366"},
+ "source": "composite",
+ "source-layer": "poi_label",
+ "filter": [
+ "all",
+ [
+ "!in",
+ "maki",
+ "campsite",
+ "cemetery",
+ "dog-park",
+ "garden",
+ "golf",
+ "park",
+ "picnic-site",
+ "playground",
+ "zoo"
+ ],
+ ["==", "scalerank", 2]
+ ],
+ "layout": {
+ "text-line-height": 1.1,
+ "text-size": {"base": 1, "stops": [[14, 11], [20, 14]]},
+ "icon-image": {"stops": [[14, "{maki}-11"], [15, "{maki}-15"]]},
+ "text-max-angle": 38,
+ "symbol-spacing": 250,
+ "text-font": [
+ "DIN Offc Pro Medium",
+ "Arial Unicode MS Regular"
+ ],
+ "text-padding": 2,
+ "text-offset": [0, 0.65],
+ "text-rotation-alignment": "viewport",
+ "text-anchor": "top",
+ "text-field": "{name_en}",
+ "text-letter-spacing": 0.01,
+ "text-max-width": 8
+ },
+ "paint": {
+ "text-color": "hsl(26, 25%, 32%)",
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 0.5,
+ "text-halo-blur": 0.5
+ }
+ },
+ {
+ "id": "poi-parks-scalerank2",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444933358918.2366"},
+ "source": "composite",
+ "source-layer": "poi_label",
+ "filter": [
+ "all",
+ ["==", "scalerank", 2],
+ [
+ "in",
+ "maki",
+ "campsite",
+ "cemetery",
+ "dog-park",
+ "garden",
+ "golf",
+ "park",
+ "picnic-site",
+ "playground",
+ "zoo"
+ ]
+ ],
+ "layout": {
+ "text-line-height": 1.1,
+ "text-size": {"base": 1, "stops": [[14, 11], [20, 14]]},
+ "icon-image": {"stops": [[14, "{maki}-11"], [15, "{maki}-15"]]},
+ "text-max-angle": 38,
+ "symbol-spacing": 250,
+ "text-font": [
+ "DIN Offc Pro Medium",
+ "Arial Unicode MS Regular"
+ ],
+ "text-padding": 2,
+ "text-offset": [0, 0.65],
+ "text-rotation-alignment": "viewport",
+ "text-anchor": "top",
+ "text-field": "{name_en}",
+ "text-letter-spacing": 0.01,
+ "text-max-width": 8
+ },
+ "paint": {
+ "text-color": "hsl(100, 100%, 20%)",
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 0.5,
+ "text-halo-blur": 0.5
+ }
+ },
+ {
+ "id": "rail-label",
+ "type": "symbol",
+ "source": "composite",
+ "source-layer": "rail_station_label",
+ "minzoom": 12,
+ "filter": ["!=", "maki", "entrance"],
+ "layout": {
+ "text-line-height": 1.1,
+ "text-size": {"base": 1, "stops": [[16, 11], [20, 13]]},
+ "icon-image": "{network}",
+ "symbol-spacing": 250,
+ "text-font": [
+ "DIN Offc Pro Medium",
+ "Arial Unicode MS Regular"
+ ],
+ "text-offset": [0, 0.85],
+ "text-rotation-alignment": "viewport",
+ "text-anchor": "top",
+ "text-field": {
+ "base": 1,
+ "stops": [[0, ""], [13, "{name_en}"]]
+ },
+ "text-letter-spacing": 0.01,
+ "icon-padding": 0,
+ "text-max-width": 7
+ },
+ "paint": {
+ "text-color": "hsl(230, 48%, 44%)",
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 0.5,
+ "icon-halo-width": 4,
+ "icon-halo-color": "#fff",
+ "text-opacity": {"base": 1, "stops": [[13.99, 0], [14, 1]]},
+ "text-halo-blur": 0.5
+ }
+ },
+ {
+ "id": "water-label-sm",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444933808272.805"},
+ "source": "composite",
+ "source-layer": "water_label",
+ "minzoom": 15,
+ "filter": ["<=", "area", 10000],
+ "layout": {
+ "text-field": "{name_en}",
+ "text-font": [
+ "DIN Offc Pro Italic",
+ "Arial Unicode MS Regular"
+ ],
+ "text-max-width": 7,
+ "text-size": {"base": 1, "stops": [[16, 13], [20, 16]]}
+ },
+ "paint": {"text-color": "hsl(230, 48%, 44%)"}
+ },
+ {
+ "id": "water-label",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444933808272.805"},
+ "source": "composite",
+ "source-layer": "water_label",
+ "minzoom": 5,
+ "filter": [">", "area", 10000],
+ "layout": {
+ "text-field": "{name_en}",
+ "text-font": [
+ "DIN Offc Pro Italic",
+ "Arial Unicode MS Regular"
+ ],
+ "text-max-width": 7,
+ "text-size": {"base": 1, "stops": [[13, 13], [18, 18]]}
+ },
+ "paint": {"text-color": "hsl(230, 48%, 44%)"}
+ },
+ {
+ "id": "place-residential",
+ "type": "symbol",
+ "source": "composite",
+ "source-layer": "place_label",
+ "maxzoom": 18,
+ "filter": [
+ "all",
+ ["all", ["<=", "localrank", 10], ["==", "type", "residential"]],
+ ["in", "$type", "LineString", "Point", "Polygon"]
+ ],
+ "layout": {
+ "text-line-height": 1.2,
+ "text-size": {"base": 1, "stops": [[10, 11], [18, 14]]},
+ "text-max-angle": 38,
+ "symbol-spacing": 250,
+ "text-font": [
+ "DIN Offc Pro Regular",
+ "Arial Unicode MS Regular"
+ ],
+ "text-padding": 2,
+ "text-offset": [0, 0],
+ "text-rotation-alignment": "viewport",
+ "text-field": "{name_en}",
+ "text-max-width": 7
+ },
+ "paint": {
+ "text-color": "hsl(26, 25%, 32%)",
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 1,
+ "text-halo-blur": 0.5
+ }
+ },
+ {
+ "id": "poi-parks-scalerank1",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444933322393.2852"},
+ "source": "composite",
+ "source-layer": "poi_label",
+ "filter": [
+ "all",
+ ["<=", "scalerank", 1],
+ [
+ "in",
+ "maki",
+ "campsite",
+ "cemetery",
+ "dog-park",
+ "garden",
+ "golf",
+ "park",
+ "picnic-site",
+ "playground",
+ "zoo"
+ ]
+ ],
+ "layout": {
+ "text-line-height": 1.1,
+ "text-size": {"base": 1, "stops": [[10, 11], [18, 14]]},
+ "icon-image": {"stops": [[13, "{maki}-11"], [14, "{maki}-15"]]},
+ "text-max-angle": 38,
+ "symbol-spacing": 250,
+ "text-font": [
+ "DIN Offc Pro Medium",
+ "Arial Unicode MS Regular"
+ ],
+ "text-padding": 2,
+ "text-offset": [0, 0.65],
+ "text-rotation-alignment": "viewport",
+ "text-anchor": "top",
+ "text-field": "{name_en}",
+ "text-letter-spacing": 0.01,
+ "text-max-width": 8
+ },
+ "paint": {
+ "text-color": "hsl(100, 100%, 20%)",
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 0.5,
+ "text-halo-blur": 0.5
+ }
+ },
+ {
+ "id": "poi-scalerank1",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444933322393.2852"},
+ "source": "composite",
+ "source-layer": "poi_label",
+ "filter": [
+ "all",
+ [
+ "!in",
+ "maki",
+ "campsite",
+ "cemetery",
+ "dog-park",
+ "garden",
+ "golf",
+ "park",
+ "picnic-site",
+ "playground",
+ "zoo"
+ ],
+ ["<=", "scalerank", 1]
+ ],
+ "layout": {
+ "text-line-height": 1.1,
+ "text-size": {"base": 1, "stops": [[10, 11], [18, 14]]},
+ "icon-image": {"stops": [[13, "{maki}-11"], [14, "{maki}-15"]]},
+ "text-max-angle": 38,
+ "symbol-spacing": 250,
+ "text-font": [
+ "DIN Offc Pro Medium",
+ "Arial Unicode MS Regular"
+ ],
+ "text-padding": 2,
+ "text-offset": [0, 0.65],
+ "text-rotation-alignment": "viewport",
+ "text-anchor": "top",
+ "text-field": "{name_en}",
+ "text-letter-spacing": 0.01,
+ "text-max-width": 8
+ },
+ "paint": {
+ "text-color": "hsl(26, 25%, 32%)",
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 0.5,
+ "text-halo-blur": 0.5
+ }
+ },
+ {
+ "id": "airport-label",
+ "type": "symbol",
+ "source": "composite",
+ "source-layer": "airport_label",
+ "minzoom": 9,
+ "filter": ["<=", "scalerank", 2],
+ "layout": {
+ "text-line-height": 1.1,
+ "text-size": {"base": 1, "stops": [[10, 12], [18, 18]]},
+ "icon-image": {"stops": [[12, "{maki}-11"], [13, "{maki}-15"]]},
+ "symbol-spacing": 250,
+ "text-font": [
+ "DIN Offc Pro Medium",
+ "Arial Unicode MS Regular"
+ ],
+ "text-padding": 2,
+ "text-offset": [0, 0.75],
+ "text-rotation-alignment": "viewport",
+ "text-anchor": "top",
+ "text-field": {"stops": [[11, "{ref}"], [12, "{name_en}"]]},
+ "text-letter-spacing": 0.01,
+ "text-max-width": 9
+ },
+ "paint": {
+ "text-color": "hsl(230, 48%, 44%)",
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 0.5,
+ "text-halo-blur": 0.5
+ }
+ },
+ {
+ "id": "place-islet-archipelago-aboriginal",
+ "type": "symbol",
+ "source": "composite",
+ "source-layer": "place_label",
+ "maxzoom": 16,
+ "filter": [
+ "in",
+ "type",
+ "aboriginal_lands",
+ "archipelago",
+ "islet"
+ ],
+ "layout": {
+ "text-line-height": 1.2,
+ "text-size": {"base": 1, "stops": [[10, 11], [18, 16]]},
+ "text-max-angle": 38,
+ "symbol-spacing": 250,
+ "text-font": [
+ "DIN Offc Pro Regular",
+ "Arial Unicode MS Regular"
+ ],
+ "text-padding": 2,
+ "text-offset": [0, 0],
+ "text-rotation-alignment": "viewport",
+ "text-field": "{name_en}",
+ "text-letter-spacing": 0.01,
+ "text-max-width": 8
+ },
+ "paint": {
+ "text-color": "hsl(230, 29%, 35%)",
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 1
+ }
+ },
+ {
+ "id": "place-neighbourhood",
+ "type": "symbol",
+ "source": "composite",
+ "source-layer": "place_label",
+ "minzoom": 10,
+ "maxzoom": 16,
+ "filter": ["==", "type", "neighbourhood"],
+ "layout": {
+ "text-field": "{name_en}",
+ "text-transform": "uppercase",
+ "text-letter-spacing": 0.1,
+ "text-max-width": 7,
+ "text-font": [
+ "DIN Offc Pro Regular",
+ "Arial Unicode MS Regular"
+ ],
+ "text-padding": 3,
+ "text-size": {"base": 1, "stops": [[12, 11], [16, 16]]}
+ },
+ "paint": {
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 1,
+ "text-color": "hsl(230, 29%, 35%)",
+ "text-halo-blur": 0.5
+ }
+ },
+ {
+ "id": "place-suburb",
+ "type": "symbol",
+ "source": "composite",
+ "source-layer": "place_label",
+ "minzoom": 10,
+ "maxzoom": 16,
+ "filter": ["==", "type", "suburb"],
+ "layout": {
+ "text-field": "{name_en}",
+ "text-transform": "uppercase",
+ "text-font": [
+ "DIN Offc Pro Regular",
+ "Arial Unicode MS Regular"
+ ],
+ "text-letter-spacing": 0.15,
+ "text-max-width": 7,
+ "text-padding": 3,
+ "text-size": {"base": 1, "stops": [[11, 11], [15, 18]]}
+ },
+ "paint": {
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 1,
+ "text-color": "hsl(230, 29%, 35%)",
+ "text-halo-blur": 0.5
+ }
+ },
+ {
+ "id": "place-hamlet",
+ "type": "symbol",
+ "source": "composite",
+ "source-layer": "place_label",
+ "minzoom": 10,
+ "maxzoom": 16,
+ "filter": ["==", "type", "hamlet"],
+ "layout": {
+ "text-field": "{name_en}",
+ "text-font": [
+ "DIN Offc Pro Regular",
+ "Arial Unicode MS Regular"
+ ],
+ "text-size": {"base": 1, "stops": [[12, 11.5], [15, 16]]}
+ },
+ "paint": {
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 1.25,
+ "text-color": "hsl(0, 0%, 0%)"
+ }
+ },
+ {
+ "id": "place-village",
+ "type": "symbol",
+ "source": "composite",
+ "source-layer": "place_label",
+ "minzoom": 8,
+ "maxzoom": 15,
+ "filter": ["==", "type", "village"],
+ "layout": {
+ "text-field": "{name_en}",
+ "text-font": [
+ "DIN Offc Pro Regular",
+ "Arial Unicode MS Regular"
+ ],
+ "text-max-width": 7,
+ "text-size": {"base": 1, "stops": [[10, 11.5], [16, 18]]}
+ },
+ "paint": {
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 1.25,
+ "text-color": "hsl(0, 0%, 0%)"
+ }
+ },
+ {
+ "id": "place-town",
+ "type": "symbol",
+ "source": "composite",
+ "source-layer": "place_label",
+ "minzoom": 6,
+ "maxzoom": 15,
+ "filter": ["==", "type", "town"],
+ "layout": {
+ "icon-image": "dot-9",
+ "text-font": {
+ "base": 1,
+ "stops": [
+ [
+ 11,
+ ["DIN Offc Pro Regular", "Arial Unicode MS Regular"]
+ ],
+ [
+ 12,
+ ["DIN Offc Pro Medium", "Arial Unicode MS Regular"]
+ ]
+ ]
+ },
+ "text-offset": {
+ "base": 1,
+ "stops": [[7, [0, -0.15]], [8, [0, 0]]]
+ },
+ "text-anchor": {
+ "base": 1,
+ "stops": [[7, "bottom"], [8, "center"]]
+ },
+ "text-field": "{name_en}",
+ "text-max-width": 7,
+ "text-size": {"base": 1, "stops": [[7, 11.5], [15, 20]]}
+ },
+ "paint": {
+ "text-color": "hsl(0, 0%, 0%)",
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 1.25,
+ "icon-opacity": {"base": 1, "stops": [[7.99, 1], [8, 0]]}
+ }
+ },
+ {
+ "id": "place-island",
+ "type": "symbol",
+ "source": "composite",
+ "source-layer": "place_label",
+ "maxzoom": 16,
+ "filter": ["==", "type", "island"],
+ "layout": {
+ "text-line-height": 1.2,
+ "text-size": {"base": 1, "stops": [[10, 11], [18, 16]]},
+ "text-max-angle": 38,
+ "symbol-spacing": 250,
+ "text-font": [
+ "DIN Offc Pro Regular",
+ "Arial Unicode MS Regular"
+ ],
+ "text-padding": 2,
+ "text-offset": [0, 0],
+ "text-rotation-alignment": "viewport",
+ "text-field": "{name_en}",
+ "text-letter-spacing": 0.01,
+ "text-max-width": 7
+ },
+ "paint": {
+ "text-color": "hsl(230, 29%, 35%)",
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 1
+ }
+ },
+ {
+ "id": "place-city-sm",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444862510685.128"},
+ "source": "composite",
+ "source-layer": "place_label",
+ "maxzoom": 14,
+ "filter": [
+ "all",
+ ["!in", "scalerank", 0, 1, 2, 3, 4, 5],
+ ["==", "type", "city"]
+ ],
+ "layout": {
+ "text-size": {"base": 1, "stops": [[6, 12], [14, 22]]},
+ "icon-image": "dot-9",
+ "text-font": {
+ "base": 1,
+ "stops": [
+ [
+ 7,
+ ["DIN Offc Pro Regular", "Arial Unicode MS Regular"]
+ ],
+ [8, ["DIN Offc Pro Medium", "Arial Unicode MS Regular"]]
+ ]
+ },
+ "text-offset": {
+ "base": 1,
+ "stops": [[7.99, [0, -0.2]], [8, [0, 0]]]
+ },
+ "text-anchor": {
+ "base": 1,
+ "stops": [[7, "bottom"], [8, "center"]]
+ },
+ "text-field": "{name_en}",
+ "text-max-width": 7
+ },
+ "paint": {
+ "text-color": "hsl(0, 0%, 0%)",
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 1.25,
+ "icon-opacity": {"base": 1, "stops": [[7.99, 1], [8, 0]]}
+ }
+ },
+ {
+ "id": "place-city-md-s",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444862510685.128"},
+ "source": "composite",
+ "source-layer": "place_label",
+ "maxzoom": 14,
+ "filter": [
+ "all",
+ ["==", "type", "city"],
+ ["in", "ldir", "E", "S", "SE", "SW"],
+ ["in", "scalerank", 3, 4, 5]
+ ],
+ "layout": {
+ "text-field": "{name_en}",
+ "icon-image": "dot-10",
+ "text-anchor": {
+ "base": 1,
+ "stops": [[7, "top"], [8, "center"]]
+ },
+ "text-offset": {
+ "base": 1,
+ "stops": [[7.99, [0, 0.1]], [8, [0, 0]]]
+ },
+ "text-font": {
+ "base": 1,
+ "stops": [
+ [
+ 7,
+ ["DIN Offc Pro Regular", "Arial Unicode MS Regular"]
+ ],
+ [8, ["DIN Offc Pro Medium", "Arial Unicode MS Regular"]]
+ ]
+ },
+ "text-size": {"base": 0.9, "stops": [[5, 12], [12, 22]]}
+ },
+ "paint": {
+ "text-halo-width": 1,
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-color": "hsl(0, 0%, 0%)",
+ "text-halo-blur": 1,
+ "icon-opacity": {"base": 1, "stops": [[7.99, 1], [8, 0]]}
+ }
+ },
+ {
+ "id": "place-city-md-n",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444862510685.128"},
+ "source": "composite",
+ "source-layer": "place_label",
+ "maxzoom": 14,
+ "filter": [
+ "all",
+ ["==", "type", "city"],
+ ["in", "ldir", "N", "NE", "NW", "W"],
+ ["in", "scalerank", 3, 4, 5]
+ ],
+ "layout": {
+ "icon-image": "dot-10",
+ "text-font": {
+ "base": 1,
+ "stops": [
+ [
+ 7,
+ ["DIN Offc Pro Regular", "Arial Unicode MS Regular"]
+ ],
+ [8, ["DIN Offc Pro Medium", "Arial Unicode MS Regular"]]
+ ]
+ },
+ "text-offset": {
+ "base": 1,
+ "stops": [[7.99, [0, -0.25]], [8, [0, 0]]]
+ },
+ "text-anchor": {
+ "base": 1,
+ "stops": [[7, "bottom"], [8, "center"]]
+ },
+ "text-field": "{name_en}",
+ "text-max-width": 7,
+ "text-size": {"base": 0.9, "stops": [[5, 12], [12, 22]]}
+ },
+ "paint": {
+ "text-color": "hsl(0, 0%, 0%)",
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 1,
+ "icon-opacity": {"base": 1, "stops": [[7.99, 1], [8, 0]]},
+ "text-halo-blur": 1
+ }
+ },
+ {
+ "id": "place-city-lg-s",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444862510685.128"},
+ "source": "composite",
+ "source-layer": "place_label",
+ "minzoom": 1,
+ "maxzoom": 14,
+ "filter": [
+ "all",
+ ["<=", "scalerank", 2],
+ ["==", "type", "city"],
+ ["in", "ldir", "E", "S", "SE", "SW"]
+ ],
+ "layout": {
+ "icon-image": "dot-11",
+ "text-font": {
+ "base": 1,
+ "stops": [
+ [
+ 7,
+ ["DIN Offc Pro Regular", "Arial Unicode MS Regular"]
+ ],
+ [8, ["DIN Offc Pro Medium", "Arial Unicode MS Regular"]]
+ ]
+ },
+ "text-offset": {
+ "base": 1,
+ "stops": [[7.99, [0, 0.15]], [8, [0, 0]]]
+ },
+ "text-anchor": {
+ "base": 1,
+ "stops": [[7, "top"], [8, "center"]]
+ },
+ "text-field": "{name_en}",
+ "text-max-width": 7,
+ "text-size": {"base": 0.9, "stops": [[4, 12], [10, 22]]}
+ },
+ "paint": {
+ "text-color": "hsl(0, 0%, 0%)",
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 1,
+ "icon-opacity": {"base": 1, "stops": [[7.99, 1], [8, 0]]},
+ "text-halo-blur": 1
+ }
+ },
+ {
+ "id": "place-city-lg-n",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444862510685.128"},
+ "source": "composite",
+ "source-layer": "place_label",
+ "minzoom": 1,
+ "maxzoom": 14,
+ "filter": [
+ "all",
+ ["<=", "scalerank", 2],
+ ["==", "type", "city"],
+ ["in", "ldir", "N", "NE", "NW", "W"]
+ ],
+ "layout": {
+ "icon-image": "dot-11",
+ "text-font": {
+ "base": 1,
+ "stops": [
+ [
+ 7,
+ ["DIN Offc Pro Regular", "Arial Unicode MS Regular"]
+ ],
+ [8, ["DIN Offc Pro Medium", "Arial Unicode MS Regular"]]
+ ]
+ },
+ "text-offset": {
+ "base": 1,
+ "stops": [[7.99, [0, -0.25]], [8, [0, 0]]]
+ },
+ "text-anchor": {
+ "base": 1,
+ "stops": [[7, "bottom"], [8, "center"]]
+ },
+ "text-field": "{name_en}",
+ "text-max-width": 7,
+ "text-size": {"base": 0.9, "stops": [[4, 12], [10, 22]]}
+ },
+ "paint": {
+ "text-color": "hsl(0, 0%, 0%)",
+ "text-opacity": 1,
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 1,
+ "icon-opacity": {"base": 1, "stops": [[7.99, 1], [8, 0]]},
+ "text-halo-blur": 1
+ }
+ },
+ {
+ "id": "marine-label-sm-ln",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444856087950.3635"},
+ "source": "composite",
+ "source-layer": "marine_label",
+ "minzoom": 3,
+ "maxzoom": 10,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ [">=", "labelrank", 4]
+ ],
+ "layout": {
+ "text-line-height": 1.1,
+ "text-size": {"base": 1, "stops": [[3, 12], [6, 16]]},
+ "symbol-spacing": {"base": 1, "stops": [[4, 100], [6, 400]]},
+ "text-font": [
+ "DIN Offc Pro Italic",
+ "Arial Unicode MS Regular"
+ ],
+ "symbol-placement": "line",
+ "text-pitch-alignment": "viewport",
+ "text-field": "{name_en}",
+ "text-letter-spacing": 0.1,
+ "text-max-width": 5
+ },
+ "paint": {"text-color": "hsl(205, 83%, 88%)"}
+ },
+ {
+ "id": "marine-label-sm-pt",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444856087950.3635"},
+ "source": "composite",
+ "source-layer": "marine_label",
+ "minzoom": 3,
+ "maxzoom": 10,
+ "filter": ["all", ["==", "$type", "Point"], [">=", "labelrank", 4]],
+ "layout": {
+ "text-field": "{name_en}",
+ "text-max-width": 5,
+ "text-letter-spacing": 0.1,
+ "text-line-height": 1.5,
+ "text-font": [
+ "DIN Offc Pro Italic",
+ "Arial Unicode MS Regular"
+ ],
+ "text-size": {"base": 1, "stops": [[3, 12], [6, 16]]}
+ },
+ "paint": {"text-color": "hsl(205, 83%, 88%)"}
+ },
+ {
+ "id": "marine-label-md-ln",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444856087950.3635"},
+ "source": "composite",
+ "source-layer": "marine_label",
+ "minzoom": 2,
+ "maxzoom": 8,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ ["in", "labelrank", 2, 3]
+ ],
+ "layout": {
+ "text-line-height": 1.1,
+ "text-size": {"base": 1.1, "stops": [[2, 12], [5, 20]]},
+ "symbol-spacing": 250,
+ "text-font": [
+ "DIN Offc Pro Italic",
+ "Arial Unicode MS Regular"
+ ],
+ "symbol-placement": "line",
+ "text-pitch-alignment": "viewport",
+ "text-field": "{name_en}",
+ "text-letter-spacing": 0.15,
+ "text-max-width": 5
+ },
+ "paint": {"text-color": "hsl(205, 83%, 88%)"}
+ },
+ {
+ "id": "marine-label-md-pt",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444856087950.3635"},
+ "source": "composite",
+ "source-layer": "marine_label",
+ "minzoom": 2,
+ "maxzoom": 8,
+ "filter": [
+ "all",
+ ["==", "$type", "Point"],
+ ["in", "labelrank", 2, 3]
+ ],
+ "layout": {
+ "text-field": "{name_en}",
+ "text-max-width": 5,
+ "text-letter-spacing": 0.15,
+ "text-line-height": 1.5,
+ "text-font": [
+ "DIN Offc Pro Italic",
+ "Arial Unicode MS Regular"
+ ],
+ "text-size": {"base": 1.1, "stops": [[2, 14], [5, 20]]}
+ },
+ "paint": {"text-color": "hsl(205, 83%, 88%)"}
+ },
+ {
+ "id": "marine-label-lg-ln",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444856087950.3635"},
+ "source": "composite",
+ "source-layer": "marine_label",
+ "minzoom": 1,
+ "maxzoom": 4,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ ["==", "labelrank", 1]
+ ],
+ "layout": {
+ "text-field": "{name_en}",
+ "text-max-width": 4,
+ "text-letter-spacing": 0.25,
+ "text-line-height": 1.1,
+ "symbol-placement": "line",
+ "text-pitch-alignment": "viewport",
+ "text-font": [
+ "DIN Offc Pro Italic",
+ "Arial Unicode MS Regular"
+ ],
+ "text-size": {"base": 1, "stops": [[1, 14], [4, 30]]}
+ },
+ "paint": {"text-color": "hsl(205, 83%, 88%)"}
+ },
+ {
+ "id": "marine-label-lg-pt",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444856087950.3635"},
+ "source": "composite",
+ "source-layer": "marine_label",
+ "minzoom": 1,
+ "maxzoom": 4,
+ "filter": ["all", ["==", "$type", "Point"], ["==", "labelrank", 1]],
+ "layout": {
+ "text-field": "{name_en}",
+ "text-max-width": 4,
+ "text-letter-spacing": 0.25,
+ "text-line-height": 1.5,
+ "text-font": [
+ "DIN Offc Pro Italic",
+ "Arial Unicode MS Regular"
+ ],
+ "text-size": {"base": 1, "stops": [[1, 14], [4, 30]]}
+ },
+ "paint": {"text-color": "hsl(205, 83%, 88%)"}
+ },
+ {
+ "id": "state-label-sm",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444856151690.9143"},
+ "source": "composite",
+ "source-layer": "state_label",
+ "minzoom": 3,
+ "maxzoom": 9,
+ "filter": ["<", "area", 20000],
+ "layout": {
+ "text-size": {"base": 1, "stops": [[6, 10], [9, 14]]},
+ "text-transform": "uppercase",
+ "text-font": ["DIN Offc Pro Bold", "Arial Unicode MS Bold"],
+ "text-field": {
+ "base": 1,
+ "stops": [[0, "{abbr}"], [6, "{name_en}"]]
+ },
+ "text-letter-spacing": 0.15,
+ "text-max-width": 5
+ },
+ "paint": {
+ "text-opacity": 1,
+ "text-color": "hsl(0, 0%, 0%)",
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 1
+ }
+ },
+ {
+ "id": "state-label-md",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444856151690.9143"},
+ "source": "composite",
+ "source-layer": "state_label",
+ "minzoom": 3,
+ "maxzoom": 8,
+ "filter": ["all", ["<", "area", 80000], [">=", "area", 20000]],
+ "layout": {
+ "text-size": {"base": 1, "stops": [[5, 10], [8, 16]]},
+ "text-transform": "uppercase",
+ "text-font": ["DIN Offc Pro Bold", "Arial Unicode MS Bold"],
+ "text-field": {
+ "base": 1,
+ "stops": [[0, "{abbr}"], [5, "{name_en}"]]
+ },
+ "text-letter-spacing": 0.15,
+ "text-max-width": 6
+ },
+ "paint": {
+ "text-opacity": 1,
+ "text-color": "hsl(0, 0%, 0%)",
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 1
+ }
+ },
+ {
+ "id": "state-label-lg",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444856151690.9143"},
+ "source": "composite",
+ "source-layer": "state_label",
+ "minzoom": 3,
+ "maxzoom": 7,
+ "filter": [">=", "area", 80000],
+ "layout": {
+ "text-size": {"base": 1, "stops": [[4, 10], [7, 18]]},
+ "text-transform": "uppercase",
+ "text-font": ["DIN Offc Pro Bold", "Arial Unicode MS Bold"],
+ "text-padding": 1,
+ "text-field": {
+ "base": 1,
+ "stops": [[0, "{abbr}"], [4, "{name_en}"]]
+ },
+ "text-letter-spacing": 0.15,
+ "text-max-width": 6
+ },
+ "paint": {
+ "text-opacity": 1,
+ "text-color": "hsl(0, 0%, 0%)",
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 1
+ }
+ },
+ {
+ "id": "country-label-sm",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444856144497.7825"},
+ "source": "composite",
+ "source-layer": "country_label",
+ "minzoom": 1,
+ "maxzoom": 10,
+ "filter": [">=", "scalerank", 5],
+ "layout": {
+ "text-field": "{name_en}",
+ "text-max-width": 6,
+ "text-font": [
+ "DIN Offc Pro Medium",
+ "Arial Unicode MS Regular"
+ ],
+ "text-size": {"base": 0.9, "stops": [[5, 14], [9, 22]]}
+ },
+ "paint": {
+ "text-color": "hsl(0, 0%, 0%)",
+ "text-halo-color": {
+ "base": 1,
+ "stops": [
+ [2, "rgba(255,255,255,0.75)"],
+ [3, "hsl(0, 0%, 100%)"]
+ ]
+ },
+ "text-halo-width": 1.25
+ }
+ },
+ {
+ "id": "country-label-md",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444856144497.7825"},
+ "source": "composite",
+ "source-layer": "country_label",
+ "minzoom": 1,
+ "maxzoom": 8,
+ "filter": ["in", "scalerank", 3, 4],
+ "layout": {
+ "text-field": {
+ "base": 1,
+ "stops": [[0, "{code}"], [2, "{name_en}"]]
+ },
+ "text-max-width": 6,
+ "text-font": [
+ "DIN Offc Pro Medium",
+ "Arial Unicode MS Regular"
+ ],
+ "text-size": {"base": 1, "stops": [[3, 10], [8, 24]]}
+ },
+ "paint": {
+ "text-color": "hsl(0, 0%, 0%)",
+ "text-halo-color": {
+ "base": 1,
+ "stops": [
+ [2, "rgba(255,255,255,0.75)"],
+ [3, "hsl(0, 0%, 100%)"]
+ ]
+ },
+ "text-halo-width": 1.25
+ }
+ },
+ {
+ "id": "country-label-lg",
+ "type": "symbol",
+ "metadata": {"mapbox:group": "1444856144497.7825"},
+ "source": "composite",
+ "source-layer": "country_label",
+ "minzoom": 1,
+ "maxzoom": 7,
+ "filter": ["in", "scalerank", 1, 2],
+ "layout": {
+ "text-field": "{name_en}",
+ "text-max-width": {"base": 1, "stops": [[0, 5], [3, 6]]},
+ "text-font": [
+ "DIN Offc Pro Medium",
+ "Arial Unicode MS Regular"
+ ],
+ "text-size": {"base": 1, "stops": [[1, 10], [6, 24]]}
+ },
+ "paint": {
+ "text-color": "hsl(0, 0%, 0%)",
+ "text-halo-color": {
+ "base": 1,
+ "stops": [
+ [2, "rgba(255,255,255,0.75)"],
+ [3, "hsl(0, 0%, 100%)"]
+ ]
+ },
+ "text-halo-width": 1.25
+ }
+ }
+ ],
+ "created": "2018-10-22T14:13:43.210Z",
+ "id": "cjnkdt02b0b2p2ss40skwpvs1",
+ "modified": "2018-10-22T14:14:35.211Z",
+ "owner": "lukaspaczos",
+ "visibility": "public",
+ "draft": false
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/InstrumentationApplication.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/InstrumentationApplication.kt
new file mode 100644
index 0000000000..ea48bdc00f
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/InstrumentationApplication.kt
@@ -0,0 +1,10 @@
+package com.mapbox.mapboxsdk
+
+import com.mapbox.mapboxsdk.testapp.MapboxApplication
+
+class InstrumentationApplication : MapboxApplication() {
+ override fun initializeLeakCanary(): Boolean {
+ // do not initialize leak canary during instrumentation tests
+ return true
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/InstrumentationRunner.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/InstrumentationRunner.kt
new file mode 100644
index 0000000000..6873b33262
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/InstrumentationRunner.kt
@@ -0,0 +1,11 @@
+package com.mapbox.mapboxsdk
+
+import android.app.Application
+import android.content.Context
+import android.support.test.runner.AndroidJUnitRunner
+
+class InstrumentationRunner : AndroidJUnitRunner() {
+ override fun newApplication(cl: ClassLoader?, className: String?, context: Context?): Application {
+ return super.newApplication(cl, InstrumentationApplication::class.java.name, context)
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/BaseIntegrationTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/BaseIntegrationTest.kt
new file mode 100644
index 0000000000..aeb8863790
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/BaseIntegrationTest.kt
@@ -0,0 +1,39 @@
+package com.mapbox.mapboxsdk.integration
+
+import android.content.Context
+import android.content.Intent
+import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
+import android.support.test.InstrumentationRegistry
+import android.support.test.uiautomator.*
+import org.junit.Before
+
+const val TIMEOUT_UI_SEARCH_WAIT = 5000L
+
+abstract class BaseIntegrationTest {
+
+ protected lateinit var device: UiDevice
+
+ @Before
+ open fun beforeTest() {
+ device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
+ }
+}
+
+/**
+ * Launches an activity with FLAG_ACTIVITY_NEW_TASK.
+ * <p>
+ * To resume an activity, you need to add a single instance launchmode to your manifest configuration.
+ * <p>
+ */
+fun UiDevice.launchActivity(context: Context, clazz: Class<*>) {
+ val applicationPackage = InstrumentationRegistry.getTargetContext().packageName
+ val intent = Intent(context, clazz)
+ intent.addFlags(FLAG_ACTIVITY_NEW_TASK)
+ InstrumentationRegistry.getContext().startActivity(intent)
+ wait(Until.hasObject(By.pkg(applicationPackage).depth(0)), TIMEOUT_UI_SEARCH_WAIT)
+}
+
+fun UiDevice.scrollRecyclerViewTo(recycleItem: String) {
+ val appView = UiScrollable(UiSelector().scrollable(true))
+ appView.scrollIntoView(UiSelector().text(recycleItem))
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/FragmentBackStackTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/FragmentBackStackTest.kt
new file mode 100644
index 0000000000..b0f6436bdd
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/FragmentBackStackTest.kt
@@ -0,0 +1,52 @@
+package com.mapbox.mapboxsdk.integration
+
+import android.support.test.filters.LargeTest
+import android.support.test.rule.ActivityTestRule
+import android.support.test.runner.AndroidJUnit4
+import android.support.test.uiautomator.By
+import android.support.test.uiautomator.SearchCondition
+import android.support.test.uiautomator.UiSelector
+import android.support.test.uiautomator.Until
+import com.mapbox.mapboxsdk.testapp.R
+import com.mapbox.mapboxsdk.testapp.activity.fragment.FragmentBackStackActivity
+import com.mapbox.mapboxsdk.testapp.activity.maplayout.SimpleMapActivity
+import kotlinx.android.synthetic.main.activity_backstack_fragment.view.*
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Regression test that validates MapFragment integration on the backstack
+ */
+@RunWith(AndroidJUnit4::class)
+class FragmentBackStackTest : BaseIntegrationTest() {
+
+ @get:Rule
+ var activityRule: ActivityTestRule<FragmentBackStackActivity> = ActivityTestRule(FragmentBackStackActivity::class.java)
+
+ @Test
+ @LargeTest
+ fun backPressedOnBackStackResumed() {
+ device.waitForIdle()
+ clickReplaceFragmentButton()
+ device.pressHome()
+ device.waitForIdle()
+ device.launchActivity(activityRule.activity.applicationContext, FragmentBackStackActivity::class.java)
+ backPressBackStack()
+ device.waitForIdle()
+ }
+
+ private fun clickReplaceFragmentButton() {
+ device.findObject(UiSelector().description(textDescription)).click()
+ }
+
+ private fun backPressBackStack() {
+ device.pressBack() // pops fragment, showing map
+ device.pressBack() // finish activity
+ }
+
+ private companion object {
+ const val textDescription = "btn_change_fragment"
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/GLSurfaceViewReopenTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/GLSurfaceViewReopenTest.kt
new file mode 100644
index 0000000000..f22b5f7c9d
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/GLSurfaceViewReopenTest.kt
@@ -0,0 +1,30 @@
+package com.mapbox.mapboxsdk.integration
+
+import android.support.test.filters.LargeTest
+import android.support.test.rule.ActivityTestRule
+import android.support.test.runner.AndroidJUnit4
+import com.mapbox.mapboxsdk.testapp.activity.maplayout.SimpleMapActivity
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+
+/**
+ * Regression test that validates reopening an Activity with a GLSurfaceView
+ */
+@RunWith(AndroidJUnit4::class)
+class GLSurfaceViewReopenTest : BaseIntegrationTest() {
+
+ @get:Rule
+ var activityRule: ActivityTestRule<SimpleMapActivity> = ActivityTestRule(SimpleMapActivity::class.java)
+
+ @Test
+ @LargeTest
+ fun reopenSimpleMapActivity() {
+ device.waitForIdle()
+ device.pressHome()
+ device.waitForIdle()
+ device.launchActivity(activityRule.activity, SimpleMapActivity::class.java)
+ device.waitForIdle()
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/GLSurfaceViewReuseTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/GLSurfaceViewReuseTest.kt
new file mode 100644
index 0000000000..945fac677e
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/GLSurfaceViewReuseTest.kt
@@ -0,0 +1,31 @@
+package com.mapbox.mapboxsdk.integration
+
+import android.support.test.filters.LargeTest
+import android.support.test.rule.ActivityTestRule
+import android.support.test.runner.AndroidJUnit4
+import com.mapbox.mapboxsdk.testapp.activity.maplayout.GLSurfaceRecyclerViewActivity
+import com.mapbox.mapboxsdk.testapp.activity.maplayout.SimpleMapActivity
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Regression test that validates if a GLSurfaceView surface can be recreated without crashing.
+ */
+@RunWith(AndroidJUnit4::class)
+class GLSurfaceViewReuseTest : BaseIntegrationTest() {
+
+ @get:Rule
+ var activityRule: ActivityTestRule<GLSurfaceRecyclerViewActivity> = ActivityTestRule(GLSurfaceRecyclerViewActivity::class.java)
+
+ @Test
+ @LargeTest
+ fun scrollRecyclerView() {
+ device.waitForIdle()
+ device.scrollRecyclerViewTo("Twenty-one")
+ device.waitForIdle()
+ device.scrollRecyclerViewTo("One")
+ device.waitForIdle()
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/OrientationChangeTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/OrientationChangeTest.kt
new file mode 100644
index 0000000000..941b7ea8dc
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/OrientationChangeTest.kt
@@ -0,0 +1,34 @@
+package com.mapbox.mapboxsdk.integration
+
+import android.support.test.filters.LargeTest
+import android.support.test.rule.ActivityTestRule
+import android.support.test.runner.AndroidJUnit4
+import com.mapbox.mapboxsdk.testapp.activity.maplayout.GLSurfaceRecyclerViewActivity
+import com.mapbox.mapboxsdk.testapp.activity.maplayout.SimpleMapActivity
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class OrientationChangeTest : BaseIntegrationTest() {
+
+ @get:Rule
+ var activityRule: ActivityTestRule<SimpleMapActivity> = ActivityTestRule(SimpleMapActivity::class.java)
+
+ @Test
+ @LargeTest
+ fun rotateSimpleMap() {
+ device.setOrientationLeft()
+ device.waitForIdle()
+ device.setOrientationNatural()
+ device.waitForIdle()
+ device.setOrientationRight()
+ device.waitForIdle()
+ device.setOrientationNatural()
+ device.setOrientationLeft()
+ device.setOrientationNatural()
+ device.setOrientationRight()
+ device.setOrientationNatural()
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/TextureViewReopenTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/TextureViewReopenTest.kt
new file mode 100644
index 0000000000..44da557904
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/TextureViewReopenTest.kt
@@ -0,0 +1,33 @@
+package com.mapbox.mapboxsdk.integration
+
+import android.support.test.filters.LargeTest
+import android.support.test.rule.ActivityTestRule
+import android.support.test.runner.AndroidJUnit4
+import com.mapbox.mapboxsdk.testapp.activity.maplayout.GLSurfaceRecyclerViewActivity
+import com.mapbox.mapboxsdk.testapp.activity.maplayout.SimpleMapActivity
+import com.mapbox.mapboxsdk.testapp.activity.textureview.TextureViewDebugModeActivity
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.lang.Thread.sleep
+
+/**
+ * Regression test that validates reopening an Activity with a TextureView
+ */
+@RunWith(AndroidJUnit4::class)
+class TextureViewReopenTest : BaseIntegrationTest() {
+
+ @get:Rule
+ var activityRule: ActivityTestRule<TextureViewDebugModeActivity> = ActivityTestRule(TextureViewDebugModeActivity::class.java)
+
+ @Test
+ @LargeTest
+ fun reopenTextureViewDebugActivity() {
+ device.waitForIdle()
+ device.pressHome()
+ device.waitForIdle()
+ device.launchActivity(activityRule.activity, TextureViewDebugModeActivity::class.java)
+ device.waitForIdle()
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/TextureViewReuseTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/TextureViewReuseTest.kt
new file mode 100644
index 0000000000..5c3d66c462
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/TextureViewReuseTest.kt
@@ -0,0 +1,31 @@
+package com.mapbox.mapboxsdk.integration
+
+import android.support.test.filters.LargeTest
+import android.support.test.rule.ActivityTestRule
+import android.support.test.runner.AndroidJUnit4
+import com.mapbox.mapboxsdk.testapp.activity.maplayout.GLSurfaceRecyclerViewActivity
+import com.mapbox.mapboxsdk.testapp.activity.maplayout.TextureRecyclerViewActivity
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Regression test that validates if a GLSurfaceView surface can be recreated without crashing.
+ */
+@RunWith(AndroidJUnit4::class)
+class TextureViewReuseTest : BaseIntegrationTest() {
+
+ @get:Rule
+ var activityRule: ActivityTestRule<TextureRecyclerViewActivity> = ActivityTestRule(TextureRecyclerViewActivity::class.java)
+
+ @Test
+ @LargeTest
+ fun scrollRecyclerView() {
+ device.waitForIdle()
+ device.scrollRecyclerViewTo("Twenty-one")
+ device.waitForIdle()
+ device.scrollRecyclerViewTo("One")
+ device.waitForIdle()
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/ViewPagerScrollTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/ViewPagerScrollTest.kt
new file mode 100644
index 0000000000..b918801296
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/integration/ViewPagerScrollTest.kt
@@ -0,0 +1,38 @@
+package com.mapbox.mapboxsdk.integration
+
+import android.support.test.filters.LargeTest
+import android.support.test.rule.ActivityTestRule
+import android.support.test.runner.AndroidJUnit4
+import android.support.test.uiautomator.UiSelector
+import com.mapbox.mapboxsdk.testapp.activity.fragment.ViewPagerActivity
+import com.mapbox.mapboxsdk.testapp.activity.maplayout.GLSurfaceRecyclerViewActivity
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Regression test that validates MapFragment integration with a ViewPager
+ */
+@RunWith(AndroidJUnit4::class)
+class ViewPagerScrollTest : BaseIntegrationTest() {
+
+ @get:Rule
+ var activityRule: ActivityTestRule<ViewPagerActivity> = ActivityTestRule(ViewPagerActivity::class.java)
+
+ @Test
+ @LargeTest
+ fun scrollViewPager() {
+ for (i in 1..4) {
+ clickTab(i)
+ }
+
+ for (i in 3 downTo 0) {
+ clickTab(i)
+ }
+ }
+
+ private fun clickTab(index: Int) {
+ device.findObject(UiSelector().text("Page $index")).click()
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationComponentTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationComponentTest.kt
index dde03d8a14..f9827c767e 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationComponentTest.kt
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationComponentTest.kt
@@ -82,7 +82,7 @@ class LocationComponentTest : EspressoTest() {
val locationEngine = component.locationEngine
assertThat(locationEngine, notNullValue())
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
}
}
@@ -118,7 +118,7 @@ class LocationComponentTest : EspressoTest() {
assertThat(locationEngine, notNullValue())
assertThat(componentOptions, notNullValue())
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertThat(componentOptions?.accuracyAlpha(), `is`(.5f))
assertThat(componentOptions?.accuracyColor(), `is`(Color.BLUE))
}
@@ -157,7 +157,7 @@ class LocationComponentTest : EspressoTest() {
assertThat(locationEngine, nullValue())
assertThat(componentOptions, notNullValue())
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertThat(componentOptions?.accuracyAlpha(), `is`(.5f))
assertThat(componentOptions?.accuracyColor(), `is`(Color.BLUE))
}
@@ -205,7 +205,7 @@ class LocationComponentTest : EspressoTest() {
// Force the first location update
component.forceLocationUpdate(location)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
// Check if the puck is visible
assertThat(mapboxMap.queryRenderedFeatures(location, FOREGROUND_LAYER).isEmpty(), `is`(false))
@@ -240,7 +240,7 @@ class LocationComponentTest : EspressoTest() {
component.isLocationComponentEnabled = true
component.forceLocationUpdate(location)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
uiController.loopMainThreadForAtLeast(300) // waiting for stale state
mapboxMap.querySourceFeatures(LOCATION_SOURCE).also { feature ->
@@ -287,7 +287,7 @@ class LocationComponentTest : EspressoTest() {
}
component.forceLocationUpdate(location)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
val feature = mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0]
assertThat(mapboxMap.queryRenderedFeatures(location, FOREGROUND_LAYER).isEmpty(), `is`(false))
@@ -329,7 +329,7 @@ class LocationComponentTest : EspressoTest() {
mapboxMap.addImageFromDrawable("custom-foreground-bitmap", it)
mapboxMap.addImageFromDrawable("custom-gps-bitmap", it)
}
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
val foregroundId = mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getStringProperty(PROPERTY_FOREGROUND_ICON)
assertThat(foregroundId, `is`(equalTo("custom-gps-bitmap")))
@@ -360,13 +360,13 @@ class LocationComponentTest : EspressoTest() {
component.renderMode = RenderMode.GPS
component.forceLocationUpdate(location)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
val foregroundId = mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getStringProperty(PROPERTY_FOREGROUND_ICON)
assertThat(foregroundId, `is`(equalTo("custom-gps-bitmap")))
component.applyStyle(LocationComponentOptions.builder(context).build())
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertEquals(FOREGROUND_ICON, mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getStringProperty(PROPERTY_FOREGROUND_ICON))
}
@@ -395,13 +395,13 @@ class LocationComponentTest : EspressoTest() {
component.renderMode = RenderMode.GPS
component.forceLocationUpdate(location)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
val foregroundId = mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getStringProperty(PROPERTY_FOREGROUND_ICON)
assertThat(foregroundId, `is`(equalTo("custom-gps-bitmap")))
component.renderMode = RenderMode.NORMAL
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertEquals(FOREGROUND_ICON, mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getStringProperty(PROPERTY_FOREGROUND_ICON))
}
@@ -430,14 +430,14 @@ class LocationComponentTest : EspressoTest() {
component.isLocationComponentEnabled = true
component.forceLocationUpdate(location)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
uiController.loopMainThreadForAtLeast(250) // engaging stale state
assertThat(mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getBooleanProperty(PROPERTY_LOCATION_STALE), `is`(true))
component.onStop()
component.onStart()
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertThat(mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getBooleanProperty(PROPERTY_LOCATION_STALE), `is`(true))
assertThat(mapboxMap.isLayerVisible(ACCURACY_LAYER), `is`(false))
@@ -461,13 +461,13 @@ class LocationComponentTest : EspressoTest() {
component.isLocationComponentEnabled = true
component.forceLocationUpdate(location)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertThat(mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getBooleanProperty(PROPERTY_LOCATION_STALE), `is`(false))
component.onStop()
component.onStart()
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertThat(mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getBooleanProperty(PROPERTY_LOCATION_STALE), `is`(false))
assertThat(mapboxMap.isLayerVisible(ACCURACY_LAYER), `is`(true))
@@ -499,7 +499,7 @@ class LocationComponentTest : EspressoTest() {
component.isLocationComponentEnabled = true
component.forceLocationUpdate(location)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
mapboxMap.querySourceFeatures(LOCATION_SOURCE).also { feature ->
feature.forEach {
@@ -526,7 +526,7 @@ class LocationComponentTest : EspressoTest() {
component.isLocationComponentEnabled = true
component.forceLocationUpdate(location)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
val point: Point = mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].geometry() as Point
assertThat(component.locationEngine, nullValue())
@@ -550,14 +550,14 @@ class LocationComponentTest : EspressoTest() {
.build())
component.isLocationComponentEnabled = true
component.forceLocationUpdate(location)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
val point: Point = mapboxMap.queryRenderedFeatures(location, FOREGROUND_LAYER)[0].geometry() as Point
assertEquals(point.latitude(), location.latitude, 0.1)
assertEquals(point.longitude(), location.longitude, 0.1)
component.isLocationComponentEnabled = false
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertThat(mapboxMap.queryRenderedFeatures(location, FOREGROUND_LAYER).isEmpty(), `is`(true))
}
}
@@ -580,7 +580,7 @@ class LocationComponentTest : EspressoTest() {
component.isLocationComponentEnabled = false
mapboxMap.setStyle(Style.Builder().fromUrl(Style.LIGHT))
component.isLocationComponentEnabled = true
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertThat(mapboxMap.isLayerVisible(FOREGROUND_LAYER), `is`(true))
}
@@ -675,7 +675,7 @@ class LocationComponentTest : EspressoTest() {
component.onStart()
mapboxMap.setStyle(Style.Builder().fromUrl(Style.DARK))
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
}
}
executeComponentTest(componentAction)
@@ -695,7 +695,7 @@ class LocationComponentTest : EspressoTest() {
mapboxMap.setStyle(Style.Builder().fromUrl(Style.DARK))
component.onStop()
component.onStart()
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
}
}
executeComponentTest(componentAction)
@@ -714,7 +714,7 @@ class LocationComponentTest : EspressoTest() {
component.isLocationComponentEnabled = true
component.onStop()
component.forceLocationUpdate(location)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertThat(mapboxMap.querySourceFeatures(LOCATION_SOURCE).isEmpty(), `is`(true))
}
@@ -736,7 +736,7 @@ class LocationComponentTest : EspressoTest() {
component.onStop()
component.forceLocationUpdate(location)
component.onStart()
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
val point: Point = mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].geometry() as Point
assertEquals(point.latitude(), location.latitude, 0.1)
@@ -760,9 +760,9 @@ class LocationComponentTest : EspressoTest() {
component.forceLocationUpdate(location)
mapboxMap.setStyle(Style.Builder().fromUrl(Style.LIGHT))
component.onStop()
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
component.onStart()
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
val point: Point = mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].geometry() as Point
assertEquals(point.latitude(), location.latitude, 0.1)
@@ -797,7 +797,7 @@ class LocationComponentTest : EspressoTest() {
component.applyStyle(options)
}
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
}
}
executeComponentTest(componentAction)
@@ -823,7 +823,7 @@ class LocationComponentTest : EspressoTest() {
component.forceLocationUpdate(location)
}
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
}
}
executeComponentTest(componentAction)
@@ -839,7 +839,7 @@ class LocationComponentTest : EspressoTest() {
override fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap,
style: Style, uiController: UiController, context: Context) {
styleChangeIdlingResource.waitForStyle(mapboxMap, MAPBOX_HEAVY_STYLE)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
locationComponentActivationOptions = LocationComponentActivationOptions
.builder(context, mapboxMap.style!!)
@@ -878,13 +878,13 @@ class LocationComponentTest : EspressoTest() {
component.renderMode = RenderMode.GPS
location.bearing = 77f
component.forceLocationUpdate(location)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
uiController.loopMainThreadForAtLeast(MAX_ANIMATION_DURATION_MS)
assertEquals(77f, mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getNumberProperty(PROPERTY_GPS_BEARING).toFloat(), 0.1f)
location.bearing = 92f
component.forceLocationUpdate(location)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
uiController.loopMainThreadForAtLeast(MAX_ANIMATION_DURATION_MS) // Waiting for the animation to finish
assertEquals(92.0f, mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getNumberProperty(PROPERTY_GPS_BEARING).toFloat(), 0.1f)
}
@@ -906,7 +906,7 @@ class LocationComponentTest : EspressoTest() {
component.cameraMode = CameraMode.TRACKING_GPS
location.bearing = 77f
component.forceLocationUpdate(location)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
uiController.loopMainThreadForAtLeast(MAX_ANIMATION_DURATION_MS)
assertEquals(77.0, mapboxMap.cameraPosition.bearing, 0.1)
@@ -917,7 +917,7 @@ class LocationComponentTest : EspressoTest() {
location.latitude = 30.0
location.longitude = 35.0
component.forceLocationUpdate(location)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
uiController.loopMainThreadForAtLeast(MAX_ANIMATION_DURATION_MS) // Waiting for the animation to finish
assertEquals(92.0, mapboxMap.cameraPosition.bearing, 0.1)
@@ -945,7 +945,7 @@ class LocationComponentTest : EspressoTest() {
location.bearing = 77f
component.forceLocationUpdate(location)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
uiController.loopMainThreadForAtLeast(MAX_ANIMATION_DURATION_MS)
assertEquals(77.0, mapboxMap.cameraPosition.bearing, 0.1)
@@ -956,7 +956,7 @@ class LocationComponentTest : EspressoTest() {
location.latitude = 30.0
location.longitude = 35.0
component.forceLocationUpdate(location)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
uiController.loopMainThreadForAtLeast(MAX_ANIMATION_DURATION_MS)
assertEquals(92.0, mapboxMap.cameraPosition.bearing, 0.1)
@@ -985,7 +985,7 @@ class LocationComponentTest : EspressoTest() {
location.bearing = 77f
component.forceLocationUpdate(location)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
uiController.loopMainThreadForAtLeast(MAX_ANIMATION_DURATION_MS)
assertEquals(bearing, mapboxMap.cameraPosition.bearing, 0.1)
@@ -996,7 +996,7 @@ class LocationComponentTest : EspressoTest() {
location.latitude = 30.0
location.longitude = 35.0
component.forceLocationUpdate(location)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
uiController.loopMainThreadForAtLeast(MAX_ANIMATION_DURATION_MS)
assertEquals(bearing, mapboxMap.cameraPosition.bearing, 0.1)
@@ -1021,7 +1021,7 @@ class LocationComponentTest : EspressoTest() {
component.cameraMode = CameraMode.TRACKING
component.cameraMode = CameraMode.NONE
component.forceLocationUpdate(location)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertThat(mapboxMap.uiSettings.focalPoint, nullValue())
}
@@ -1044,7 +1044,7 @@ class LocationComponentTest : EspressoTest() {
val zoom = mapboxMap.cameraPosition.zoom
component.zoomWhileTracking(10.0)
uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_ZOOM_ANIM_DURATION)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertEquals(zoom, mapboxMap.cameraPosition.zoom, 0.1)
}
@@ -1066,7 +1066,7 @@ class LocationComponentTest : EspressoTest() {
component.cameraMode = CameraMode.TRACKING
component.zoomWhileTracking(10.0)
uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_ZOOM_ANIM_DURATION)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertEquals(10.0, mapboxMap.cameraPosition.zoom, 0.1)
}
@@ -1091,7 +1091,7 @@ class LocationComponentTest : EspressoTest() {
uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_ZOOM_ANIM_DURATION / 2)
component.cameraMode = CameraMode.NONE
uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_ZOOM_ANIM_DURATION / 2)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertEquals(15.0 / 2.0, mapboxMap.cameraPosition.zoom, 3.0)
}
@@ -1117,7 +1117,7 @@ class LocationComponentTest : EspressoTest() {
component.onStop()
component.zoomWhileTracking(10.0)
uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_ZOOM_ANIM_DURATION)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertEquals(zoom, mapboxMap.cameraPosition.zoom, 0.1)
}
@@ -1142,7 +1142,7 @@ class LocationComponentTest : EspressoTest() {
uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_ZOOM_ANIM_DURATION / 2)
component.cancelZoomWhileTrackingAnimation()
uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_ZOOM_ANIM_DURATION / 2)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertEquals(15.0 / 2.0, mapboxMap.cameraPosition.zoom, 3.0)
}
@@ -1165,7 +1165,7 @@ class LocationComponentTest : EspressoTest() {
val tilt = mapboxMap.cameraPosition.tilt
component.tiltWhileTracking(30.0)
uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_TILT_ANIM_DURATION)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertEquals(tilt, mapboxMap.cameraPosition.tilt, 0.1)
}
@@ -1187,7 +1187,7 @@ class LocationComponentTest : EspressoTest() {
component.cameraMode = CameraMode.TRACKING
component.tiltWhileTracking(30.0)
uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_TILT_ANIM_DURATION)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertEquals(30.0, mapboxMap.cameraPosition.tilt, 0.1)
}
@@ -1212,7 +1212,7 @@ class LocationComponentTest : EspressoTest() {
uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_TILT_ANIM_DURATION / 2)
component.cameraMode = CameraMode.NONE
uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_TILT_ANIM_DURATION / 2)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertEquals(30.0 / 2.0, mapboxMap.cameraPosition.tilt, 3.0)
}
@@ -1237,7 +1237,7 @@ class LocationComponentTest : EspressoTest() {
component.onStop()
component.tiltWhileTracking(30.0)
uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_TILT_ANIM_DURATION)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertEquals(tilt, mapboxMap.cameraPosition.tilt, 0.1)
}
@@ -1286,7 +1286,7 @@ class LocationComponentTest : EspressoTest() {
mapboxMap.moveCamera(CameraUpdateFactory.newLatLng(LatLng(51.0, 17.0)))
mapboxMap.moveCamera(CameraUpdateFactory.bearingTo(90.0))
component.isLocationComponentEnabled = true
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
uiController.loopMainThreadForAtLeast(MAX_ANIMATION_DURATION_MS)
assertEquals(location.bearing.toDouble(), mapboxMap.cameraPosition.bearing, 0.1)
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.kt
index 37b3e8b802..fb450de527 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.kt
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.kt
@@ -75,7 +75,7 @@ class LocationLayerControllerTest : EspressoTest() {
.build())
component.isLocationComponentEnabled = true
component.renderMode = RenderMode.NORMAL
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertThat(style.getSource(LOCATION_SOURCE), notNullValue())
}
@@ -99,7 +99,7 @@ class LocationLayerControllerTest : EspressoTest() {
component.isLocationComponentEnabled = true
component.renderMode = RenderMode.NORMAL
component.forceLocationUpdate(location)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertThat(mapboxMap.isLayerVisible(FOREGROUND_LAYER), `is`(true))
assertThat(mapboxMap.isLayerVisible(BACKGROUND_LAYER), `is`(true))
@@ -123,7 +123,7 @@ class LocationLayerControllerTest : EspressoTest() {
component.isLocationComponentEnabled = true
component.renderMode = RenderMode.COMPASS
component.forceLocationUpdate(location)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertThat(mapboxMap.isLayerVisible(FOREGROUND_LAYER), `is`(true))
assertThat(mapboxMap.isLayerVisible(BACKGROUND_LAYER), `is`(true))
@@ -147,7 +147,7 @@ class LocationLayerControllerTest : EspressoTest() {
component.isLocationComponentEnabled = true
component.renderMode = RenderMode.GPS
component.forceLocationUpdate(location)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertThat(mapboxMap.isLayerVisible(FOREGROUND_LAYER), `is`(true))
assertThat(mapboxMap.isLayerVisible(BACKGROUND_LAYER), `is`(true))
@@ -171,7 +171,7 @@ class LocationLayerControllerTest : EspressoTest() {
component.isLocationComponentEnabled = true
component.forceLocationUpdate(location)
component.isLocationComponentEnabled = false
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
component.renderMode = RenderMode.GPS
assertThat(mapboxMap.isLayerVisible(FOREGROUND_LAYER), `is`(false))
@@ -197,7 +197,7 @@ class LocationLayerControllerTest : EspressoTest() {
component.renderMode = RenderMode.NORMAL
component.forceLocationUpdate(location)
component.isLocationComponentEnabled = false
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
// Check that all layers visibilities are set to none
assertThat(mapboxMap.isLayerVisible(FOREGROUND_LAYER), `is`(false))
@@ -223,7 +223,7 @@ class LocationLayerControllerTest : EspressoTest() {
component.renderMode = RenderMode.NORMAL
component.forceLocationUpdate(location)
styleChangeIdlingResource.waitForStyle(mapboxMap, Style.LIGHT)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertThat(component.renderMode, `is`(equalTo(RenderMode.NORMAL)))
@@ -254,13 +254,13 @@ class LocationLayerControllerTest : EspressoTest() {
component.isLocationComponentEnabled = true
component.applyStyle(LocationComponentOptions.builder(context).staleStateTimeout(100).build())
component.forceLocationUpdate(location)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
uiController.loopMainThreadForAtLeast(150)
assertThat(mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getBooleanProperty(PROPERTY_LOCATION_STALE), `is`(true))
mapboxMap.setStyle(Style.Builder().fromUrl(Style.LIGHT))
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertThat(mapboxMap.querySourceFeatures(LOCATION_SOURCE)[0].getBooleanProperty(PROPERTY_LOCATION_STALE), `is`(true))
}
@@ -279,9 +279,9 @@ class LocationLayerControllerTest : EspressoTest() {
.build())
component.isLocationComponentEnabled = true
component.forceLocationUpdate(location)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
component.isLocationComponentEnabled = false
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertThat(mapboxMap.queryRenderedFeatures(location, FOREGROUND_LAYER).isEmpty(), `is`(true))
val options =
@@ -291,7 +291,7 @@ class LocationLayerControllerTest : EspressoTest() {
.build()
component.applyStyle(options)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertThat(mapboxMap.queryRenderedFeatures(location, FOREGROUND_LAYER).isEmpty(), `is`(true))
}
}
@@ -338,7 +338,7 @@ class LocationLayerControllerTest : EspressoTest() {
show = !show
}
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
}
}
executeComponentTest(componentAction)
@@ -359,7 +359,7 @@ class LocationLayerControllerTest : EspressoTest() {
component.isLocationComponentEnabled = true
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(location), 16.0))
component.forceLocationUpdate(location)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
uiController.loopMainThreadForAtLeast(ACCURACY_RADIUS_ANIMATION_DURATION)
assertEquals(Utils.calculateZoomLevelRadius(mapboxMap, location) /*meters projected to radius on zoom 16*/,
@@ -386,7 +386,7 @@ class LocationLayerControllerTest : EspressoTest() {
val zoom = 16.0
mapboxMap.easeCamera(CameraUpdateFactory.newLatLngZoom(target, zoom), 300)
uiController.loopMainThreadForAtLeast(300)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertThat(Math.abs(zoom - mapboxMap.cameraPosition.zoom) < 0.1
@@ -418,7 +418,7 @@ class LocationLayerControllerTest : EspressoTest() {
val target = LatLng(location)
val zoom = 16.0
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(target, zoom))
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
assertThat(Math.abs(zoom - mapboxMap.cameraPosition.zoom) < 0.1
&& Math.abs(target.latitude - mapboxMap.cameraPosition.target.latitude) < 0.1
@@ -445,7 +445,7 @@ class LocationLayerControllerTest : EspressoTest() {
.build())
component.isLocationComponentEnabled = true
component.forceLocationUpdate(location)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
component.applyStyle(LocationComponentOptions.builder(context).layerBelow("road-label").build())
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/GLSurfaceViewReopenTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/GLSurfaceViewReopenTest.kt
deleted file mode 100644
index 98b251027f..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/GLSurfaceViewReopenTest.kt
+++ /dev/null
@@ -1,73 +0,0 @@
-package com.mapbox.mapboxsdk.maps
-
-import android.content.Intent
-import android.support.test.InstrumentationRegistry
-import android.support.test.filters.SdkSuppress
-import android.support.test.runner.AndroidJUnit4
-import android.support.test.uiautomator.*
-import org.hamcrest.CoreMatchers.notNullValue
-import org.hamcrest.MatcherAssert.assertThat
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import java.lang.Thread.sleep
-
-private const val BASIC_SAMPLE_PACKAGE = "com.mapbox.mapboxsdk.testapp"
-private const val LAUNCH_TIMEOUT = 5000L
-
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = 18)
-class GLSurfaceViewReopenTest {
-
- private lateinit var device: UiDevice
-
- @Before
- fun startSimpleMapActivityFromHomeScreen() {
- // Initialize UiDevice instance
- device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
-
- // Start from the home screen
- device.pressHome()
-
- // Wait for launcher
- val launcherPackage: String = device.launcherPackageName
- assertThat(launcherPackage, notNullValue())
- device.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT)
-
- // Launch the app
- val context = InstrumentationRegistry.getInstrumentation().context
- val intent = context.packageManager.getLaunchIntentForPackage(BASIC_SAMPLE_PACKAGE).apply {
- // Clear out any previous instances
- addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
- }
- context.startActivity(intent)
-
- // Wait for the app to appear
- device.wait(
- Until.hasObject(By.pkg(BASIC_SAMPLE_PACKAGE).depth(0)),
- LAUNCH_TIMEOUT
- )
-
- // open SimpleMapActivity
- device.findObject(UiSelector().text("Simple Map")).clickAndWaitForNewWindow()
-
- // wait for idle
- device.waitForIdle(LAUNCH_TIMEOUT)
- }
-
- @Test
- fun reopenSimpleMapActivity() {
- // return to home screen
- device.pressHome()
-
- // press recents apps button
- device.pressRecentApps()
-
- // click to reopen app
- device.findObject(UiSelector().description("Mapbox Android SDK TestApp")).click()
-
- // wait for idle
- device.waitForIdle(LAUNCH_TIMEOUT)
- sleep(LAUNCH_TIMEOUT)
- }
-} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxTest.java
index b56d267b81..c8737e2802 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxTest.java
@@ -1,5 +1,6 @@
package com.mapbox.mapboxsdk.maps;
+import android.support.test.annotation.UiThreadTest;
import android.support.test.runner.AndroidJUnit4;
import com.mapbox.mapboxsdk.Mapbox;
import org.junit.Test;
@@ -16,6 +17,7 @@ public class MapboxTest {
private static final String ACCESS_TOKEN_2 = "pk.0000000002";
@Test
+ @UiThreadTest
public void testConnected() {
assertTrue(Mapbox.isConnected());
@@ -31,6 +33,7 @@ public class MapboxTest {
}
@Test
+ @UiThreadTest
public void setAccessToken() {
String realToken = Mapbox.getAccessToken();
Mapbox.setAccessToken(ACCESS_TOKEN);
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/OrientationTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/OrientationTest.java
deleted file mode 100644
index 14a2c3bdbf..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/OrientationTest.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.mapbox.mapboxsdk.maps;
-
-import com.mapbox.mapboxsdk.testapp.activity.BaseTest;
-import com.mapbox.mapboxsdk.testapp.activity.camera.CameraAnimationTypeActivity;
-import org.junit.Test;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.matcher.ViewMatchers.isRoot;
-import static com.mapbox.mapboxsdk.testapp.action.OrientationChangeAction.orientationLandscape;
-import static com.mapbox.mapboxsdk.testapp.action.OrientationChangeAction.orientationLandscapeReverse;
-import static com.mapbox.mapboxsdk.testapp.action.OrientationChangeAction.orientationPortrait;
-import static com.mapbox.mapboxsdk.testapp.action.OrientationChangeAction.orientationPortraitReverse;
-
-public class OrientationTest extends BaseTest {
-
- @Test
- public void testChangeDeviceOrientation() {
- onView(isRoot()).perform(orientationLandscape());
- waitAction(2200);
- onView(isRoot()).perform(orientationPortrait());
- waitAction(2500);
- onView(isRoot()).perform(orientationLandscapeReverse());
- waitAction(500);
- onView(isRoot()).perform(orientationPortraitReverse());
- waitAction(1250);
- onView(isRoot()).perform(orientationLandscape());
- waitAction(750);
- onView(isRoot()).perform(orientationPortrait());
- waitAction(950);
- onView(isRoot()).perform(orientationLandscapeReverse());
- onView(isRoot()).perform(orientationPortraitReverse());
- onView(isRoot()).perform(orientationLandscape());
- onView(isRoot()).perform(orientationPortrait());
- }
-
- @Override
- protected Class getActivityClass() {
- return CameraAnimationTypeActivity.class;
- }
-
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/TextureViewReopenTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/TextureViewReopenTest.kt
deleted file mode 100644
index cd139ccc40..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/TextureViewReopenTest.kt
+++ /dev/null
@@ -1,77 +0,0 @@
-package com.mapbox.mapboxsdk.maps
-
-import android.content.Intent
-import android.support.test.InstrumentationRegistry
-import android.support.test.filters.SdkSuppress
-import android.support.test.runner.AndroidJUnit4
-import android.support.test.uiautomator.*
-import org.hamcrest.CoreMatchers.notNullValue
-import org.hamcrest.MatcherAssert.assertThat
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import java.lang.Thread.sleep
-import android.support.test.uiautomator.UiSelector
-import android.support.test.uiautomator.UiScrollable
-
-private const val BASIC_SAMPLE_PACKAGE = "com.mapbox.mapboxsdk.testapp"
-private const val LAUNCH_TIMEOUT = 5000L
-
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = 18)
-class TextureViewReopenTest {
-
- private lateinit var device: UiDevice
-
- @Before
- fun startSimpleMapActivityFromHomeScreen() {
- // Initialize UiDevice instance
- device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
-
- // Start from the home screen
- device.pressHome()
-
- // Wait for launcher
- val launcherPackage: String = device.launcherPackageName
- assertThat(launcherPackage, notNullValue())
- device.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT)
-
- // Launch the app
- val context = InstrumentationRegistry.getInstrumentation().context
- val intent = context.packageManager.getLaunchIntentForPackage(BASIC_SAMPLE_PACKAGE).apply {
- // Clear out any previous instances
- addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
- }
- context.startActivity(intent)
-
- // Wait for the app to appear
- device.wait(
- Until.hasObject(By.pkg(BASIC_SAMPLE_PACKAGE).depth(0)),
- LAUNCH_TIMEOUT
- )
-
- // open TextureView debug activity
- val appView = UiScrollable(UiSelector().scrollable(true))
- appView.scrollIntoView(UiSelector().text("TextureView debug"))
- device.findObject(UiSelector().text("TextureView debug")).clickAndWaitForNewWindow()
-
- // wait for idle
- device.waitForIdle(LAUNCH_TIMEOUT)
- }
-
- @Test
- fun reopenTextureViewDebugActivity() {
- // return to home screen
- device.pressHome()
-
- // press recent apps button
- device.pressRecentApps()
-
- // click to reopen app
- device.findObject(UiSelector().description("Mapbox Android SDK TestApp")).click()
-
- // wait for idle
- device.waitForIdle(LAUNCH_TIMEOUT)
- sleep(LAUNCH_TIMEOUT)
- }
-} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/VisibleRegionTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/VisibleRegionTest.kt
index 4866812e67..139695461d 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/VisibleRegionTest.kt
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/VisibleRegionTest.kt
@@ -1,25 +1,27 @@
-package com.mapbox.mapboxsdk.testapp.maps
+package com.mapbox.mapboxsdk.maps
import android.graphics.PointF
import android.support.test.espresso.UiController
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory
import com.mapbox.mapboxsdk.geometry.LatLng
-import com.mapbox.mapboxsdk.maps.MapView
-import com.mapbox.mapboxsdk.maps.MapboxMap
import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke
-import com.mapbox.mapboxsdk.testapp.activity.EspressoTest
-import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseTest
+import com.mapbox.mapboxsdk.testapp.activity.espresso.PixelTestActivity
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
-class VisibleRegionTest : EspressoTest() {
+class VisibleRegionTest : BaseTest() {
- private lateinit var mapView: MapView
+ override fun getActivityClass(): Class<*> {
+ return PixelTestActivity::class.java
+ }
- override fun beforeTest() {
+ override
+ fun beforeTest() {
super.beforeTest()
- mapView = (rule.activity as EspressoTestActivity).mapView
+ mapView = (rule.activity as PixelTestActivity).mapView
}
@Test
@@ -263,9 +265,9 @@ class VisibleRegionTest : EspressoTest() {
@Test
fun paddedTopVisibleRegionOverDatelineTest() {
validateTestSetup()
- invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
+ invoke(mapboxMap) { ui: UiController, mapboxMap: MapboxMap ->
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 180.0), 8.0))
-
+ ui.loopMainThreadForAtLeast(5000)
val latLngs = listOf(
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
@@ -299,7 +301,7 @@ class VisibleRegionTest : EspressoTest() {
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f)
- .also { it.longitude += 360 },
+ .also { it.longitude += 360 },
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f)
.also { it.longitude += 360 },
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat())
@@ -355,11 +357,11 @@ class VisibleRegionTest : EspressoTest() {
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 0.0), 8.0))
val d = Math.min(mapboxMap.width, mapboxMap.height) / 4;
val latLngs = listOf(
- mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f),
- mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f - d / 2f, mapView.height / 2f),
- mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f + d / 2f, mapView.height / 2f),
- mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f - d / 2f),
- mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f + d / 2f)
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f - d / 2f, mapView.height / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f + d / 2f, mapView.height / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f - d / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f + d / 2f)
)
@@ -371,29 +373,29 @@ class VisibleRegionTest : EspressoTest() {
}
}
- @Test
- fun visibleRotatedRegionOverDatelineTest() {
- validateTestSetup()
- invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
- mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 180.0), 8.0))
- val d = Math.min(mapboxMap.width, mapboxMap.height) / 4;
- val latLngs = listOf(
- mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f),
- mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f - d / 2f, mapView.height / 2f),
- mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f + d / 2f, mapView.height / 2f)
- .also { it.longitude += 360 },
- mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f - d / 2f),
- mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f + d / 2f)
- )
-
-
- for (bearing in 45 until 360 step 45) {
- mapboxMap.moveCamera(CameraUpdateFactory.bearingTo(bearing.toDouble()));
- val visibleRegion = mapboxMap.projection.visibleRegion
- assertTrue(latLngs.all { visibleRegion.latLngBounds.contains(it) })
- }
- }
+ @Test
+ fun visibleRotatedRegionOverDatelineTest() {
+ validateTestSetup()
+ invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 180.0), 8.0))
+ val d = Math.min(mapboxMap.width, mapboxMap.height) / 4;
+ val latLngs = listOf(
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f - d / 2f, mapView.height / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f + d / 2f, mapView.height / 2f)
+ .also { it.longitude += 360 },
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f - d / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f + d / 2f)
+ )
+
+
+ for (bearing in 45 until 360 step 45) {
+ mapboxMap.moveCamera(CameraUpdateFactory.bearingTo(bearing.toDouble()));
+ val visibleRegion = mapboxMap.projection.visibleRegion
+ assertTrue(latLngs.all { visibleRegion.latLngBounds.contains(it) })
+ }
}
+ }
private fun MapboxMap.getLatLngFromScreenCoords(x: Float, y: Float): LatLng {
return this.projection.fromScreenLocation(PointF(x, y))
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/module/telemetry/PerformanceEventTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/module/telemetry/PerformanceEventTest.java
new file mode 100644
index 0000000000..6f256b4e56
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/module/telemetry/PerformanceEventTest.java
@@ -0,0 +1,188 @@
+package com.mapbox.mapboxsdk.module.telemetry;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.DisplayMetrics;
+import android.view.Display;
+import android.view.WindowManager;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import com.mapbox.mapboxsdk.Mapbox;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.UUID;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+@RunWith(AndroidJUnit4.class)
+public class PerformanceEventTest {
+
+ @Test
+ public void checksPerformanceEventWithMetaData() throws Exception {
+ PerformanceEvent event = obtainPerformanceEvent();
+ assertNotNull(event);
+
+ Parcel parcel = Parcel.obtain();
+
+ event.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+
+ PerformanceEvent newPerfEvent = PerformanceEvent.CREATOR.createFromParcel(parcel);
+ assertNotNull(newPerfEvent);
+
+ compare(event, newPerfEvent, "attributes", "style_id");
+ compare(event, newPerfEvent, "counters", "int_value");
+ compare(event, newPerfEvent, "counters", "long_value");
+ compare(event, newPerfEvent, "counters", "double_value");
+ assertEquals(getMetadata(event), getMetadata(newPerfEvent));
+ }
+
+ @Test
+ public void checksPerformanceEventOnlyRequiredData() throws Exception {
+ Bundle bundle = new Bundle();
+ bundle.putString("property ignored", "value will be ignored");
+ PerformanceEvent event = new PerformanceEvent(UUID.randomUUID().toString(), bundle);
+ assertNotNull(event);
+
+ Parcel parcel = Parcel.obtain();
+ event.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+
+ PerformanceEvent newPerfEvent = PerformanceEvent.CREATOR.createFromParcel(parcel);
+ assertNotNull(newPerfEvent);
+
+ assertEquals(getAttributes(event).size(), 0);
+ assertEquals(getCounters(event).size(), 0);
+ assertEquals(getAttributes(newPerfEvent).size(), 0);
+ assertEquals(getCounters(newPerfEvent).size(), 0);
+ assertEquals(getMetadata(event), getMetadata(newPerfEvent));
+ }
+
+
+ private PerformanceEvent obtainPerformanceEvent() {
+ String styleStr = "mapbox://styles/mapbox/streets-v11";
+ boolean testPerfEvent = true;
+ Double doubleValue = 40.5;
+ Long longValue = 40L;
+ Integer intValue = 40;
+
+ List<Attribute<String>> attributes = new ArrayList<>();
+ attributes.add(
+ new Attribute<>("style_id", styleStr));
+ attributes.add(
+ new Attribute<>("test_perf_event", String.valueOf(testPerfEvent)));
+
+ List<Attribute<? extends Number>> counters = new ArrayList();
+ counters.add(new Attribute<>("long_value", longValue));
+ counters.add(new Attribute<>("double_value", doubleValue));
+ counters.add(new Attribute<>("int_value", intValue));
+
+ Gson gson = new Gson();
+
+ Bundle bundle = new Bundle();
+ bundle.putString("attributes", gson.toJson(attributes));
+ bundle.putString("counters", gson.toJson(counters));
+
+ JsonObject metaData = new JsonObject();
+ metaData.addProperty("os", "android");
+ metaData.addProperty("manufacturer", Build.MANUFACTURER);
+ metaData.addProperty("brand", Build.BRAND);
+ metaData.addProperty("device", Build.MODEL);
+ metaData.addProperty("version", Build.VERSION.RELEASE);
+ metaData.addProperty("abi", Build.CPU_ABI);
+ metaData.addProperty("country", Locale.getDefault().getISO3Country());
+ metaData.addProperty("ram", getRam());
+ metaData.addProperty("screenSize", getWindowSize());
+ bundle.putString("metadata", metaData.toString());
+
+ return new PerformanceEvent(UUID.randomUUID().toString(), bundle);
+ }
+
+ private void compare(PerformanceEvent event1, PerformanceEvent event2, String listFieldName, String name)
+ throws NoSuchFieldException, IllegalAccessException {
+ Object value1 = getValue(event1, listFieldName, name);
+ Object value2 = getValue(event2, listFieldName, name);
+
+ if (value1 instanceof Double && value2 instanceof Double) {
+ assertEquals((Double)value1, (Double)value2, 0.00006);
+ } else {
+ assertEquals(value1, value2);
+ }
+ }
+
+ private Object getPrivateFieldValue(Object object, String fieldName)
+ throws NoSuchFieldException, IllegalAccessException {
+ Field field = object.getClass().getDeclaredField(fieldName);
+ field.setAccessible(true);
+ return field.get(object);
+ }
+
+ private Object getValue(PerformanceEvent event, String listFieldName, String name)
+ throws NoSuchFieldException, IllegalAccessException {
+ ArrayList list = (ArrayList)getPrivateFieldValue(event, listFieldName);
+ for (Object element : list) {
+ Object elementName = getPrivateFieldValue(element, "name");
+ if (elementName != null && elementName.equals((String)name)) {
+ return getPrivateFieldValue(element, "value");
+ }
+ }
+ return null;
+ }
+
+ private JsonObject getMetadata(PerformanceEvent event)
+ throws NoSuchFieldException, IllegalAccessException {
+ return (JsonObject)getPrivateFieldValue(event, "metadata");
+ }
+
+ private ArrayList getAttributes(PerformanceEvent event)
+ throws NoSuchFieldException, IllegalAccessException {
+ return (ArrayList)getPrivateFieldValue(event, "attributes");
+ }
+
+ private ArrayList getCounters(PerformanceEvent event)
+ throws NoSuchFieldException, IllegalAccessException {
+ return (ArrayList)getPrivateFieldValue(event, "counters");
+ }
+
+ private static String getRam() {
+ ActivityManager actManager =
+ (ActivityManager) Mapbox.getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
+ ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo();
+ actManager.getMemoryInfo(memInfo);
+ return String.valueOf(memInfo.totalMem);
+ }
+
+ private static String getWindowSize() {
+ WindowManager windowManager =
+ (WindowManager) Mapbox.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
+ Display display = windowManager.getDefaultDisplay();
+ DisplayMetrics metrics = new DisplayMetrics();
+ display.getMetrics(metrics);
+ int width = metrics.widthPixels;
+ int height = metrics.heightPixels;
+
+ return "{" + width + "," + height + "}";
+ }
+
+ private class Attribute<T> {
+ private String name;
+ private T value;
+
+ Attribute(String name, T value) {
+ this.name = name;
+ this.value = value;
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/action/OrientationChangeAction.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/action/OrientationAction.java
index 7f73d6a7f3..1bf5a87970 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/action/OrientationChangeAction.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/action/OrientationAction.java
@@ -1,6 +1,5 @@
package com.mapbox.mapboxsdk.testapp.action;
-
import android.app.Activity;
import android.content.Context;
import android.content.ContextWrapper;
@@ -11,30 +10,31 @@ import android.view.View;
import android.view.ViewGroup;
import org.hamcrest.Matcher;
+import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.matcher.ViewMatchers.isRoot;
-public class OrientationChangeAction implements ViewAction {
+public class OrientationAction implements ViewAction {
private final int orientation;
- private OrientationChangeAction(int orientation) {
+ private OrientationAction(int orientation) {
this.orientation = orientation;
}
public static ViewAction orientationLandscape() {
- return new OrientationChangeAction(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+ return new OrientationAction(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
public static ViewAction orientationPortrait() {
- return new OrientationChangeAction(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ return new OrientationAction(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
public static ViewAction orientationLandscapeReverse() {
- return new OrientationChangeAction(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
+ return new OrientationAction(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
}
public static ViewAction orientationPortraitReverse() {
- return new OrientationChangeAction(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
+ return new OrientationAction(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
}
@Override
@@ -61,6 +61,10 @@ public class OrientationChangeAction implements ViewAction {
activity.setRequestedOrientation(orientation);
}
+ public static void invoke(ViewAction action) {
+ onView(isRoot()).perform(action);
+ }
+
private Activity getActivity(Context context) {
while (context instanceof ContextWrapper) {
if (context instanceof Activity) {
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/action/WaitAction.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/action/WaitAction.java
index 5d98ccb7f8..e3741f3d42 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/action/WaitAction.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/action/WaitAction.java
@@ -3,10 +3,11 @@ package com.mapbox.mapboxsdk.testapp.action;
import android.support.test.espresso.UiController;
import android.support.test.espresso.ViewAction;
import android.view.View;
-
import org.hamcrest.Matcher;
+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.isRoot;
public final class WaitAction implements ViewAction {
@@ -30,5 +31,9 @@ public final class WaitAction implements ViewAction {
public void perform(UiController uiController, View view) {
uiController.loopMainThreadForAtLeast(loopTime);
}
+
+ public static void invoke(long loopTime) {
+ onView(isRoot()).perform(new WaitAction(loopTime));
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/BaseTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/BaseTest.java
index ea69f8adae..c91afe9b60 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/BaseTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/BaseTest.java
@@ -1,116 +1,96 @@
package com.mapbox.mapboxsdk.testapp.activity;
-import android.app.Activity;
-import android.support.test.espresso.Espresso;
-import android.support.test.espresso.IdlingRegistry;
-import android.support.test.espresso.IdlingResource;
-import android.support.test.espresso.IdlingResourceTimeoutException;
-import android.support.test.espresso.ViewInteraction;
+import android.support.annotation.CallSuper;
+import android.support.annotation.UiThread;
import android.support.test.rule.ActivityTestRule;
-
import com.mapbox.mapboxsdk.Mapbox;
+import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
-import com.mapbox.mapboxsdk.testapp.action.WaitAction;
-import com.mapbox.mapboxsdk.testapp.utils.FinishLoadingStyleIdlingResource;
-
-import com.mapbox.mapboxsdk.testapp.utils.MapboxIdlingResource;
-import junit.framework.Assert;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.TestName;
-
import timber.log.Timber;
-import static android.support.test.espresso.Espresso.onView;
-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;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static junit.framework.TestCase.assertNotNull;
+import static junit.framework.TestCase.assertTrue;
/**
* Base class for all Activity test hooking into an existing Activity that will load style.
*/
public abstract class BaseTest {
+ private static final int WAIT_TIMEOUT = 30; //seconds
+
@Rule
- public ActivityTestRule<Activity> rule = new ActivityTestRule<>(getActivityClass());
+ public ActivityTestRule rule = new ActivityTestRule<>(getActivityClass());
@Rule
- public TestName testNameRule = new TestName();
+ public TestName testName = new TestName();
protected MapboxMap mapboxMap;
- protected MapboxIdlingResource idlingResource;
+ protected MapView mapView;
+ private final CountDownLatch latch = new CountDownLatch(1);
@Before
+ @CallSuper
public void beforeTest() {
- try {
- Timber.e(String.format(
- "%s - %s - %s",
- getClass().getSimpleName(),
- testNameRule.getMethodName(),
- "@Before test: register idle resource"
- ));
- idlingResource = (MapboxIdlingResource) generateIdlingResource();
- IdlingRegistry.getInstance().register(idlingResource);
- Espresso.onIdle();
- mapboxMap = idlingResource.getMapboxMap();
- } catch (IdlingResourceTimeoutException idlingResourceTimeoutException) {
- throw new RuntimeException(
- String.format(
- "Could not start %s test for %s.",
- testNameRule.getMethodName(),
- getActivityClass().getSimpleName()
- )
- );
- }
+ initialiseMap();
+ holdTestRunnerForStyleLoad();
}
- protected IdlingResource generateIdlingResource() {
- return new FinishLoadingStyleIdlingResource(rule.getActivity());
+ @After
+ @CallSuper
+ public void afterTest() {
+ // override to add logic
+ }
+
+ @UiThread
+ @CallSuper
+ protected void initMap(MapboxMap mapboxMap) {
+ this.mapboxMap = mapboxMap;
+ mapboxMap.getStyle(style -> latch.countDown());
}
protected void validateTestSetup() {
if (!Mapbox.isConnected()) {
Timber.e("Not connected to the internet while running test");
}
-
- checkViewIsDisplayed(R.id.mapView);
- Assert.assertNotNull(mapboxMap);
- }
-
- protected MapboxMap getMapboxMap() {
- return mapboxMap;
+ assertNotNull("MapView isn't initialised", mapView);
+ assertNotNull("MapboxMap isn't initialised", mapboxMap);
+ assertNotNull("Style isn't initialised", mapboxMap.getStyle());
+ assertTrue("Style isn't fully loaded", mapboxMap.getStyle().isFullyLoaded());
}
protected abstract Class getActivityClass();
- protected void checkViewIsDisplayed(int id) {
- onView(withId(id)).check(matches(isDisplayed()));
- }
-
- protected void waitAction() {
- waitAction(500);
- }
-
- protected void waitAction(long waitTime) {
- onView(withId(R.id.mapView)).perform(new WaitAction(waitTime));
- }
-
- protected ViewInteraction onMapView() {
- return onView(withId(R.id.mapView));
+ private void initialiseMap() {
+ try {
+ rule.runOnUiThread(() -> {
+ mapView = rule.getActivity().findViewById(R.id.mapView);
+ mapView.getMapAsync(this::initMap);
+ });
+ } catch (Throwable throwable) {
+ throwable.printStackTrace();
+ }
}
- protected MapboxMapAction getMapboxMapAction(MapboxMapAction.OnInvokeActionListener onInvokeActionListener) {
- return new MapboxMapAction(onInvokeActionListener, mapboxMap);
- }
+ private void holdTestRunnerForStyleLoad() {
+ boolean interrupted;
+ try {
+ interrupted = latch.await(WAIT_TIMEOUT, TimeUnit.SECONDS);
+ } catch (InterruptedException ignore) {
+ interrupted = true;
+ }
- @After
- public void afterTest() {
- Timber.e(String.format("%s - %s", testNameRule.getMethodName(), "@After test: unregister idle resource"));
- IdlingRegistry.getInstance().unregister(idlingResource);
+ if (!interrupted) {
+ Timber.e("Timeout occurred for %s", testName.getMethodName());
+ validateTestSetup();
+ }
}
-}
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/EspressoTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/EspressoTest.java
index dfb4a46180..97a73ba1cb 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/EspressoTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/EspressoTest.java
@@ -1,24 +1,28 @@
package com.mapbox.mapboxsdk.testapp.activity;
-import android.support.test.espresso.IdlingResource;
+import android.support.annotation.UiThread;
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
-import com.mapbox.mapboxsdk.testapp.utils.LoadStyleIdlingResource;
+
/**
* Base class for all tests using EspressoTestActivity as wrapper.
* <p>
- * Uses {@link LoadStyleIdlingResource} to load "assets/streets.json" as style.
+ * Loads "assets/streets.json" as style.
* </p>
*/
public class EspressoTest extends BaseTest {
@Override
- protected IdlingResource generateIdlingResource() {
- return new LoadStyleIdlingResource(rule.getActivity());
+ protected final Class getActivityClass() {
+ return EspressoTestActivity.class;
}
+ @UiThread
@Override
- protected final Class getActivityClass() {
- return EspressoTestActivity.class;
+ protected void initMap(MapboxMap mapboxMap) {
+ mapboxMap.setStyle(new Style.Builder().fromUrl("asset://streets.json"));
+ super.initMap(mapboxMap);
}
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/IconTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/IconTest.java
index 9fb823a377..559213af3d 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/IconTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/IconTest.java
@@ -1,6 +1,7 @@
package com.mapbox.mapboxsdk.testapp.annotations;
import android.app.Activity;
+import android.support.test.annotation.UiThreadTest;
import android.support.v4.content.res.ResourcesCompat;
import com.mapbox.mapboxsdk.annotations.Icon;
import com.mapbox.mapboxsdk.annotations.IconFactory;
@@ -31,117 +32,107 @@ public class IconTest extends EspressoTest {
@Before
public void beforeTest() {
super.beforeTest();
- iconMap = new IconManagerResolver(getMapboxMap()).getIconMap();
- }
-
- @Test
- public void testEmpty() {
- assertTrue(iconMap.isEmpty());
+ iconMap = new IconManagerResolver(mapboxMap).getIconMap();
}
@Test
+ @UiThreadTest
public void testAddSameIconMarker() {
validateTestSetup();
- onMapView().perform(getMapboxMapAction((uiController, mapboxMap) -> {
- Icon defaultMarker = IconFactory.getInstance(rule.getActivity()).defaultMarker();
- mapboxMap.addMarker(new MarkerOptions().position(new LatLng()));
- mapboxMap.addMarker(new MarkerOptions().position(new LatLng(1, 1)));
- assertEquals(1, iconMap.size());
- assertEquals(2, iconMap.get(defaultMarker), 0);
- }));
+ Icon defaultMarker = IconFactory.getInstance(rule.getActivity()).defaultMarker();
+ mapboxMap.addMarker(new MarkerOptions().position(new LatLng()));
+ mapboxMap.addMarker(new MarkerOptions().position(new LatLng(1, 1)));
+ assertEquals(1, iconMap.size());
+ assertEquals(2, iconMap.get(defaultMarker), 0);
}
@Test
+ @UiThreadTest
public void testAddDifferentIconMarker() {
validateTestSetup();
- onMapView().perform(getMapboxMapAction((uiController, mapboxMap) -> {
- Icon icon = IconFactory.getInstance(rule.getActivity()).fromResource(R.drawable.mapbox_logo_icon);
- getMapboxMap().addMarker(new MarkerOptions().icon(icon).position(new LatLng()));
- getMapboxMap().addMarker(new MarkerOptions().position(new LatLng(1, 1)));
- assertEquals(iconMap.size(), 2);
- assertTrue(iconMap.containsKey(icon));
- assertTrue(iconMap.get(icon) == 1);
- }));
+ Icon icon = IconFactory.getInstance(rule.getActivity()).fromResource(R.drawable.mapbox_logo_icon);
+ mapboxMap.addMarker(new MarkerOptions().icon(icon).position(new LatLng()));
+ mapboxMap.addMarker(new MarkerOptions().position(new LatLng(1, 1)));
+ assertEquals(iconMap.size(), 2);
+ assertTrue(iconMap.containsKey(icon));
+ assertTrue(iconMap.get(icon) == 1);
}
@Test
+ @UiThreadTest
public void testAddRemoveIconMarker() {
validateTestSetup();
- onMapView().perform(getMapboxMapAction((uiController, mapboxMap) -> {
- Icon icon = IconFactory.getInstance(rule.getActivity()).fromResource(R.drawable.mapbox_logo_icon);
- Marker marker = mapboxMap.addMarker(new MarkerOptions().icon(icon).position(new LatLng()));
- mapboxMap.addMarker(new MarkerOptions().position(new LatLng(1, 1)));
- assertEquals(iconMap.size(), 2);
- assertTrue(iconMap.containsKey(icon));
- assertTrue(iconMap.get(icon) == 1);
-
- mapboxMap.removeMarker(marker);
- assertEquals(iconMap.size(), 1);
- assertFalse(iconMap.containsKey(icon));
- }));
+ Icon icon = IconFactory.getInstance(rule.getActivity()).fromResource(R.drawable.mapbox_logo_icon);
+ Marker marker = mapboxMap.addMarker(new MarkerOptions().icon(icon).position(new LatLng()));
+ mapboxMap.addMarker(new MarkerOptions().position(new LatLng(1, 1)));
+ assertEquals(iconMap.size(), 2);
+ assertTrue(iconMap.containsKey(icon));
+ assertTrue(iconMap.get(icon) == 1);
+
+ mapboxMap.removeMarker(marker);
+ assertEquals(iconMap.size(), 1);
+ assertFalse(iconMap.containsKey(icon));
}
@Test
+ @UiThreadTest
public void testAddRemoveDefaultMarker() {
validateTestSetup();
- onMapView().perform(getMapboxMapAction((uiController, mapboxMap) -> {
- Marker marker = mapboxMap.addMarker(new MarkerOptions().position(new LatLng(1, 1)));
- assertEquals(iconMap.size(), 1);
+ Marker marker = mapboxMap.addMarker(new MarkerOptions().position(new LatLng(1, 1)));
+ assertEquals(iconMap.size(), 1);
- mapboxMap.removeMarker(marker);
- assertEquals(iconMap.size(), 0);
+ mapboxMap.removeMarker(marker);
+ assertEquals(iconMap.size(), 0);
- mapboxMap.addMarker(new MarkerOptions().position(new LatLng()));
- assertEquals(iconMap.size(), 1);
- }));
+ mapboxMap.addMarker(new MarkerOptions().position(new LatLng()));
+ assertEquals(iconMap.size(), 1);
}
@Test
+ @UiThreadTest
public void testAddRemoveMany() {
validateTestSetup();
- onMapView().perform(getMapboxMapAction((uiController, mapboxMap) -> {
- Activity activity = rule.getActivity();
- IconFactory iconFactory = IconFactory.getInstance(activity);
-
- // add 2 default icon markers
- Marker defaultMarkerOne = mapboxMap.addMarker(new MarkerOptions().position(new LatLng(1, 1)));
- Marker defaultMarkerTwo = mapboxMap.addMarker(new MarkerOptions().position(new LatLng(2, 1)));
-
- // add 4 unique icon markers
- mapboxMap.addMarker(new MarkerOptions()
- .icon(iconFactory.fromResource(R.drawable.mapbox_logo_icon))
- .position(new LatLng(3, 1))
- );
- mapboxMap.addMarker(new MarkerOptions()
- .icon(iconFactory.fromResource(R.drawable.mapbox_compass_icon))
- .position(new LatLng(4, 1))
- );
- mapboxMap.addMarker(new MarkerOptions()
- .icon(IconUtils.drawableToIcon(activity, R.drawable.ic_stars,
- ResourcesCompat.getColor(activity.getResources(),
- R.color.blueAccent, activity.getTheme())))
- .position(new LatLng(5, 1))
- );
- mapboxMap.addMarker(new MarkerOptions()
- .icon(iconFactory.fromResource(R.drawable.ic_android))
- .position(new LatLng(6, 1))
- );
-
- assertEquals("Amount of icons should match 5", 5, iconMap.size());
- assertEquals("Refcounter of default marker should match 2", 2, iconMap.get(iconFactory.defaultMarker()), 0);
-
- mapboxMap.removeMarker(defaultMarkerOne);
-
- assertEquals("Amount of icons should match 5", 5, iconMap.size());
- assertEquals("Refcounter of default marker should match 1", 1, iconMap.get(iconFactory.defaultMarker()), 0);
-
- mapboxMap.removeMarker(defaultMarkerTwo);
-
- assertEquals("Amount of icons should match 4", 4, iconMap.size());
- assertNull("DefaultMarker shouldn't exist anymore", iconMap.get(iconFactory.defaultMarker()));
-
- mapboxMap.clear();
- assertEquals("Amount of icons should match 0", 0, iconMap.size());
- }));
+ Activity activity = rule.getActivity();
+ IconFactory iconFactory = IconFactory.getInstance(activity);
+
+ // add 2 default icon markers
+ Marker defaultMarkerOne = mapboxMap.addMarker(new MarkerOptions().position(new LatLng(1, 1)));
+ Marker defaultMarkerTwo = mapboxMap.addMarker(new MarkerOptions().position(new LatLng(2, 1)));
+
+ // add 4 unique icon markers
+ mapboxMap.addMarker(new MarkerOptions()
+ .icon(iconFactory.fromResource(R.drawable.mapbox_logo_icon))
+ .position(new LatLng(3, 1))
+ );
+ mapboxMap.addMarker(new MarkerOptions()
+ .icon(iconFactory.fromResource(R.drawable.mapbox_compass_icon))
+ .position(new LatLng(4, 1))
+ );
+ mapboxMap.addMarker(new MarkerOptions()
+ .icon(IconUtils.drawableToIcon(activity, R.drawable.ic_stars,
+ ResourcesCompat.getColor(activity.getResources(),
+ R.color.blueAccent, activity.getTheme())))
+ .position(new LatLng(5, 1))
+ );
+ mapboxMap.addMarker(new MarkerOptions()
+ .icon(iconFactory.fromResource(R.drawable.ic_android))
+ .position(new LatLng(6, 1))
+ );
+
+ assertEquals("Amount of icons should match 5", 5, iconMap.size());
+ assertEquals("Refcounter of default marker should match 2", 2, iconMap.get(iconFactory.defaultMarker()), 0);
+
+ mapboxMap.removeMarker(defaultMarkerOne);
+
+ assertEquals("Amount of icons should match 5", 5, iconMap.size());
+ assertEquals("Refcounter of default marker should match 1", 1, iconMap.get(iconFactory.defaultMarker()), 0);
+
+ mapboxMap.removeMarker(defaultMarkerTwo);
+
+ assertEquals("Amount of icons should match 4", 4, iconMap.size());
+ assertNull("DefaultMarker shouldn't exist anymore", iconMap.get(iconFactory.defaultMarker()));
+
+ mapboxMap.clear();
+ assertEquals("Amount of icons should match 0", 0, iconMap.size());
}
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraForTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraForTest.java
index eb38bddf84..4365ea95ff 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraForTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraForTest.java
@@ -1,6 +1,7 @@
package com.mapbox.mapboxsdk.testapp.camera;
import android.support.annotation.NonNull;
+import android.support.test.annotation.UiThreadTest;
import com.mapbox.geojson.Point;
import com.mapbox.geojson.Polygon;
import com.mapbox.mapboxsdk.camera.CameraPosition;
@@ -18,123 +19,117 @@ import static org.junit.Assert.assertEquals;
public class CameraForTest extends BaseTest {
@Test
+ @UiThreadTest
public void testGetCameraForLatLngBounds() {
validateTestSetup();
- onMapView().perform(getMapboxMapAction((uiController, mapboxMap) -> {
- CameraPosition actualPosition = mapboxMap.getCameraForLatLngBounds(
- LatLngBounds.from(10, 10, -10, -10));
- CameraPosition expectedPosition = new CameraPosition.Builder()
- .target(new LatLng()).zoom(4.16).tilt(0).bearing(0).build();
- assertEquals("Latitude should match",
- expectedPosition.target.getLatitude(), actualPosition.target.getLatitude(), 0.00001f);
- assertEquals("Longitude should match",
- expectedPosition.target.getLongitude(), actualPosition.target.getLongitude(), 0.00001f);
- assertEquals("Bearing should match",
- expectedPosition.zoom, actualPosition.zoom, 0.01f);
- assertEquals("Tilt should match", expectedPosition.tilt, actualPosition.tilt, 0.01f);
- }));
+ CameraPosition actualPosition = mapboxMap.getCameraForLatLngBounds(
+ LatLngBounds.from(10, 10, -10, -10));
+ CameraPosition expectedPosition = new CameraPosition.Builder()
+ .target(new LatLng()).zoom(4.16).tilt(0).bearing(0).build();
+ assertEquals("Latitude should match",
+ expectedPosition.target.getLatitude(), actualPosition.target.getLatitude(), 0.00001f);
+ assertEquals("Longitude should match",
+ expectedPosition.target.getLongitude(), actualPosition.target.getLongitude(), 0.00001f);
+ assertEquals("Bearing should match",
+ expectedPosition.zoom, actualPosition.zoom, 0.01f);
+ assertEquals("Tilt should match", expectedPosition.tilt, actualPosition.tilt, 0.01f);
}
@Test
+ @UiThreadTest
public void testGetCameraForLatLngBoundsPadding() {
validateTestSetup();
- onMapView().perform(getMapboxMapAction((uiController, mapboxMap) -> {
- CameraPosition actualPosition = mapboxMap.getCameraForLatLngBounds(
- LatLngBounds.from(10, 10, -10, -10), new int[] {5, 5, 5, 5});
- CameraPosition expectedPosition = new CameraPosition.Builder()
- .target(new LatLng()).zoom(4.13).tilt(0).bearing(0).build();
- assertEquals("Latitude should match",
- expectedPosition.target.getLatitude(), actualPosition.target.getLatitude(), 0.00001f);
- assertEquals("Longitude should match",
- expectedPosition.target.getLongitude(), actualPosition.target.getLongitude(), 0.00001f);
- assertEquals("Zoom should match",
- expectedPosition.zoom, actualPosition.zoom, 0.01f);
- assertEquals("Tilt should match",
- expectedPosition.tilt, actualPosition.tilt, 0.01f);
- assertEquals("Bearing should match",
- expectedPosition.bearing, actualPosition.bearing, 0.01f);
- }));
+ CameraPosition actualPosition = mapboxMap.getCameraForLatLngBounds(
+ LatLngBounds.from(10, 10, -10, -10), new int[] {5, 5, 5, 5});
+ CameraPosition expectedPosition = new CameraPosition.Builder()
+ .target(new LatLng()).zoom(4.13).tilt(0).bearing(0).build();
+ assertEquals("Latitude should match",
+ expectedPosition.target.getLatitude(), actualPosition.target.getLatitude(), 0.00001f);
+ assertEquals("Longitude should match",
+ expectedPosition.target.getLongitude(), actualPosition.target.getLongitude(), 0.00001f);
+ assertEquals("Zoom should match",
+ expectedPosition.zoom, actualPosition.zoom, 0.01f);
+ assertEquals("Tilt should match",
+ expectedPosition.tilt, actualPosition.tilt, 0.01f);
+ assertEquals("Bearing should match",
+ expectedPosition.bearing, actualPosition.bearing, 0.01f);
}
@Test
+ @UiThreadTest
public void testGetCameraForLatLngBoundsBearing() {
validateTestSetup();
- onMapView().perform(getMapboxMapAction((uiController, mapboxMap) -> {
- CameraPosition actualPosition = mapboxMap.getCameraForLatLngBounds(
- LatLngBounds.from(10, 10, -10, -10), 45, 0);
- CameraPosition expectedPosition = new CameraPosition.Builder()
- .target(new LatLng()).zoom(3.66).tilt(0).bearing(45).build();
- assertEquals("Latitude should match",
- expectedPosition.target.getLatitude(), actualPosition.target.getLatitude(), 0.00001f);
- assertEquals("Longitude should match",
- expectedPosition.target.getLongitude(), actualPosition.target.getLongitude(), 0.00001f);
- assertEquals("Zoom should match",
- expectedPosition.zoom, actualPosition.zoom, 0.01f);
- assertEquals("Tilt should match",
- expectedPosition.tilt, actualPosition.tilt, 0.01f);
- assertEquals("Bearing should match",
- expectedPosition.bearing, actualPosition.bearing, 0.01f);
- }));
+ CameraPosition actualPosition = mapboxMap.getCameraForLatLngBounds(
+ LatLngBounds.from(10, 10, -10, -10), 45, 0);
+ CameraPosition expectedPosition = new CameraPosition.Builder()
+ .target(new LatLng()).zoom(3.66).tilt(0).bearing(45).build();
+ assertEquals("Latitude should match",
+ expectedPosition.target.getLatitude(), actualPosition.target.getLatitude(), 0.00001f);
+ assertEquals("Longitude should match",
+ expectedPosition.target.getLongitude(), actualPosition.target.getLongitude(), 0.00001f);
+ assertEquals("Zoom should match",
+ expectedPosition.zoom, actualPosition.zoom, 0.01f);
+ assertEquals("Tilt should match",
+ expectedPosition.tilt, actualPosition.tilt, 0.01f);
+ assertEquals("Bearing should match",
+ expectedPosition.bearing, actualPosition.bearing, 0.01f);
}
@Test
+ @UiThreadTest
public void testGetCameraForLatLngBoundsTilt() {
validateTestSetup();
- onMapView().perform(getMapboxMapAction((uiController, mapboxMap) -> {
- CameraPosition actualPosition = mapboxMap.getCameraForLatLngBounds(
- LatLngBounds.from(10, 10, -10, -10), 0, 45);
- CameraPosition expectedPosition = new CameraPosition.Builder()
- .target(new LatLng(-0.264576975267, 0)).zoom(4.13).tilt(45).bearing(0).build();
- assertEquals("Latitude should match",
- expectedPosition.target.getLatitude(), actualPosition.target.getLatitude(), 0.00001f);
- assertEquals("Longitude should match",
- expectedPosition.target.getLongitude(), actualPosition.target.getLongitude(), 0.00001f);
- assertEquals("Zoom should match",
- expectedPosition.zoom, actualPosition.zoom, 0.01f);
- assertEquals("Tilt should match",
- expectedPosition.tilt, actualPosition.tilt, 0.01f);
- assertEquals("Bearing should match",
- expectedPosition.bearing, actualPosition.bearing, 0.01f);
- }));
+ CameraPosition actualPosition = mapboxMap.getCameraForLatLngBounds(
+ LatLngBounds.from(10, 10, -10, -10), 0, 45);
+ CameraPosition expectedPosition = new CameraPosition.Builder()
+ .target(new LatLng(-0.264576975267, 0)).zoom(4.13).tilt(45).bearing(0).build();
+ assertEquals("Latitude should match",
+ expectedPosition.target.getLatitude(), actualPosition.target.getLatitude(), 0.00001f);
+ assertEquals("Longitude should match",
+ expectedPosition.target.getLongitude(), actualPosition.target.getLongitude(), 0.00001f);
+ assertEquals("Zoom should match",
+ expectedPosition.zoom, actualPosition.zoom, 0.01f);
+ assertEquals("Tilt should match",
+ expectedPosition.tilt, actualPosition.tilt, 0.01f);
+ assertEquals("Bearing should match",
+ expectedPosition.bearing, actualPosition.bearing, 0.01f);
}
@Test
+ @UiThreadTest
public void testGetCameraForLatLngBoundsAll() {
validateTestSetup();
- onMapView().perform(getMapboxMapAction((uiController, mapboxMap) -> {
- CameraPosition actualPosition = mapboxMap.getCameraForLatLngBounds(
- LatLngBounds.from(10, 10, -10, -10), new int[] {5, 5, 5, 5}, 45, 45);
- CameraPosition expectedPosition = new CameraPosition.Builder()
- .target(new LatLng(-0.3732134634, -0.3713191053)).zoom(3.63).tilt(45).bearing(45).build();
- assertEquals("Latitude should match",
- expectedPosition.target.getLatitude(), actualPosition.target.getLatitude(), 0.00001f);
- assertEquals("Longitude should match",
- expectedPosition.target.getLongitude(), actualPosition.target.getLongitude(), 0.00001f);
- assertEquals("Zoom should match",
- expectedPosition.zoom, actualPosition.zoom, 0.01f);
- assertEquals("Tilt should match",
- expectedPosition.tilt, actualPosition.tilt, 0.01f);
- assertEquals("Bearing should match",
- expectedPosition.bearing, actualPosition.bearing, 0.01f);
- }));
+ CameraPosition actualPosition = mapboxMap.getCameraForLatLngBounds(
+ LatLngBounds.from(10, 10, -10, -10), new int[] {5, 5, 5, 5}, 45, 45);
+ CameraPosition expectedPosition = new CameraPosition.Builder()
+ .target(new LatLng(-0.3732134634, -0.3713191053)).zoom(3.63).tilt(45).bearing(45).build();
+ assertEquals("Latitude should match",
+ expectedPosition.target.getLatitude(), actualPosition.target.getLatitude(), 0.00001f);
+ assertEquals("Longitude should match",
+ expectedPosition.target.getLongitude(), actualPosition.target.getLongitude(), 0.00001f);
+ assertEquals("Zoom should match",
+ expectedPosition.zoom, actualPosition.zoom, 0.01f);
+ assertEquals("Tilt should match",
+ expectedPosition.tilt, actualPosition.tilt, 0.01f);
+ assertEquals("Bearing should match",
+ expectedPosition.bearing, actualPosition.bearing, 0.01f);
}
@Test
+ @UiThreadTest
public void testGetCameraForGeometry() {
validateTestSetup();
- onMapView().perform(getMapboxMapAction((uiController, mapboxMap) -> {
- List<List<Point>> polygonDefinition = getPolygonDefinition();
- CameraPosition actualPosition = mapboxMap.getCameraForGeometry(Polygon.fromLngLats(polygonDefinition));
- CameraPosition expectedPosition = new CameraPosition.Builder()
- .target(new LatLng()).zoom(4.16).tilt(0).bearing(0).build();
- assertEquals("Latitude should match",
- expectedPosition.target.getLatitude(), actualPosition.target.getLatitude(), 0.00001f);
- assertEquals("Longitude should match",
- expectedPosition.target.getLongitude(), actualPosition.target.getLongitude(), 0.00001f);
- assertEquals("Bearing should match",
- expectedPosition.zoom, actualPosition.zoom, 0.01f);
- assertEquals("Tilt should match", expectedPosition.tilt, actualPosition.tilt, 0.01f);
- }));
+ List<List<Point>> polygonDefinition = getPolygonDefinition();
+ CameraPosition actualPosition = mapboxMap.getCameraForGeometry(Polygon.fromLngLats(polygonDefinition));
+ CameraPosition expectedPosition = new CameraPosition.Builder()
+ .target(new LatLng()).zoom(4.16).tilt(0).bearing(0).build();
+ assertEquals("Latitude should match",
+ expectedPosition.target.getLatitude(), actualPosition.target.getLatitude(), 0.00001f);
+ assertEquals("Longitude should match",
+ expectedPosition.target.getLongitude(), actualPosition.target.getLongitude(), 0.00001f);
+ assertEquals("Bearing should match",
+ expectedPosition.zoom, actualPosition.zoom, 0.01f);
+ assertEquals("Tilt should match", expectedPosition.tilt, actualPosition.tilt, 0.01f);
}
@NonNull
@@ -154,113 +149,108 @@ public class CameraForTest extends BaseTest {
}
@Test
+ @UiThreadTest
public void testGetCameraForGeometryPadding() {
validateTestSetup();
- onMapView().perform(getMapboxMapAction((uiController, mapboxMap) -> {
- List<List<Point>> polygonDefinition = getPolygonDefinition();
- CameraPosition actualPosition = mapboxMap.getCameraForGeometry(Polygon.fromLngLats(polygonDefinition),
- new int[] {5, 5, 5, 5});
- CameraPosition expectedPosition = new CameraPosition.Builder()
- .target(new LatLng()).zoom(4.13).tilt(0).bearing(0).build();
- assertEquals("Latitude should match",
- expectedPosition.target.getLatitude(), actualPosition.target.getLatitude(), 0.00001f);
- assertEquals("Longitude should match",
- expectedPosition.target.getLongitude(), actualPosition.target.getLongitude(), 0.00001f);
- assertEquals("Zoom should match",
- expectedPosition.zoom, actualPosition.zoom, 0.01f);
- assertEquals("Tilt should match",
- expectedPosition.tilt, actualPosition.tilt, 0.01f);
- assertEquals("Bearing should match",
- expectedPosition.bearing, actualPosition.bearing, 0.01f);
- }));
+ List<List<Point>> polygonDefinition = getPolygonDefinition();
+ CameraPosition actualPosition = mapboxMap.getCameraForGeometry(Polygon.fromLngLats(polygonDefinition),
+ new int[] {5, 5, 5, 5});
+ CameraPosition expectedPosition = new CameraPosition.Builder()
+ .target(new LatLng()).zoom(4.13).tilt(0).bearing(0).build();
+ assertEquals("Latitude should match",
+ expectedPosition.target.getLatitude(), actualPosition.target.getLatitude(), 0.00001f);
+ assertEquals("Longitude should match",
+ expectedPosition.target.getLongitude(), actualPosition.target.getLongitude(), 0.00001f);
+ assertEquals("Zoom should match",
+ expectedPosition.zoom, actualPosition.zoom, 0.01f);
+ assertEquals("Tilt should match",
+ expectedPosition.tilt, actualPosition.tilt, 0.01f);
+ assertEquals("Bearing should match",
+ expectedPosition.bearing, actualPosition.bearing, 0.01f);
}
@Test
+ @UiThreadTest
public void testGetCameraForGeometryBearing() {
validateTestSetup();
- onMapView().perform(getMapboxMapAction((uiController, mapboxMap) -> {
- List<List<Point>> polygonDefinition = getPolygonDefinition();
- CameraPosition actualPosition = mapboxMap.getCameraForGeometry(Polygon.fromLngLats(polygonDefinition), 45, 0);
- CameraPosition expectedPosition = new CameraPosition.Builder()
- .target(new LatLng()).zoom(3.66).tilt(0).bearing(45).build();
- assertEquals("Latitude should match",
- expectedPosition.target.getLatitude(), actualPosition.target.getLatitude(), 0.00001f);
- assertEquals("Longitude should match",
- expectedPosition.target.getLongitude(), actualPosition.target.getLongitude(), 0.00001f);
- assertEquals("Zoom should match",
- expectedPosition.zoom, actualPosition.zoom, 0.01f);
- assertEquals("Tilt should match",
- expectedPosition.tilt, actualPosition.tilt, 0.01f);
- assertEquals("Bearing should match",
- expectedPosition.bearing, actualPosition.bearing, 0.01f);
- }));
+ List<List<Point>> polygonDefinition = getPolygonDefinition();
+ CameraPosition actualPosition = mapboxMap.getCameraForGeometry(Polygon.fromLngLats(polygonDefinition), 45, 0);
+ CameraPosition expectedPosition = new CameraPosition.Builder()
+ .target(new LatLng()).zoom(3.66).tilt(0).bearing(45).build();
+ assertEquals("Latitude should match",
+ expectedPosition.target.getLatitude(), actualPosition.target.getLatitude(), 0.00001f);
+ assertEquals("Longitude should match",
+ expectedPosition.target.getLongitude(), actualPosition.target.getLongitude(), 0.00001f);
+ assertEquals("Zoom should match",
+ expectedPosition.zoom, actualPosition.zoom, 0.01f);
+ assertEquals("Tilt should match",
+ expectedPosition.tilt, actualPosition.tilt, 0.01f);
+ assertEquals("Bearing should match",
+ expectedPosition.bearing, actualPosition.bearing, 0.01f);
}
@Test
+ @UiThreadTest
public void testGetCameraForGeometryTilt() {
validateTestSetup();
- onMapView().perform(getMapboxMapAction((uiController, mapboxMap) -> {
- List<List<Point>> polygonDefinition = getPolygonDefinition();
- CameraPosition actualPosition = mapboxMap.getCameraForGeometry(Polygon.fromLngLats(polygonDefinition), 0, 45);
- CameraPosition expectedPosition = new CameraPosition.Builder()
- .target(new LatLng(-0.2645769752, 0)).zoom(4.13).tilt(45).bearing(0).build();
- assertEquals("Latitude should match",
- expectedPosition.target.getLatitude(), actualPosition.target.getLatitude(), 0.00001f);
- assertEquals("Longitude should match",
- expectedPosition.target.getLongitude(), actualPosition.target.getLongitude(), 0.00001f);
- assertEquals("Zoom should match",
- expectedPosition.zoom, actualPosition.zoom, 0.01f);
- assertEquals("Tilt should match",
- expectedPosition.tilt, actualPosition.tilt, 0.01f);
- assertEquals("Bearing should match",
- expectedPosition.bearing, actualPosition.bearing, 0.01f);
- }));
+ List<List<Point>> polygonDefinition = getPolygonDefinition();
+ CameraPosition actualPosition = mapboxMap.getCameraForGeometry(Polygon.fromLngLats(polygonDefinition), 0, 45);
+ CameraPosition expectedPosition = new CameraPosition.Builder()
+ .target(new LatLng(-0.2645769752, 0)).zoom(4.13).tilt(45).bearing(0).build();
+ assertEquals("Latitude should match",
+ expectedPosition.target.getLatitude(), actualPosition.target.getLatitude(), 0.00001f);
+ assertEquals("Longitude should match",
+ expectedPosition.target.getLongitude(), actualPosition.target.getLongitude(), 0.00001f);
+ assertEquals("Zoom should match",
+ expectedPosition.zoom, actualPosition.zoom, 0.01f);
+ assertEquals("Tilt should match",
+ expectedPosition.tilt, actualPosition.tilt, 0.01f);
+ assertEquals("Bearing should match",
+ expectedPosition.bearing, actualPosition.bearing, 0.01f);
}
@Test
+ @UiThreadTest
public void testGetCameraForGeometryAll() {
validateTestSetup();
- onMapView().perform(getMapboxMapAction((uiController, mapboxMap) -> {
- List<List<Point>> polygonDefinition = getPolygonDefinition();
- CameraPosition actualPosition = mapboxMap.getCameraForGeometry(Polygon.fromLngLats(polygonDefinition),
- new int[] {5, 5, 5, 5}, 45, 45);
- CameraPosition expectedPosition = new CameraPosition.Builder()
- .target(new LatLng(-0.373213463, -0.37131910534)).zoom(3.63).tilt(45).bearing(45).build();
- assertEquals("Latitude should match",
- expectedPosition.target.getLatitude(), actualPosition.target.getLatitude(), 0.00001f);
- assertEquals("Longitude should match",
- expectedPosition.target.getLongitude(), actualPosition.target.getLongitude(), 0.00001f);
- assertEquals("Zoom should match",
- expectedPosition.zoom, actualPosition.zoom, 0.01f);
- assertEquals("Tilt should match",
- expectedPosition.tilt, actualPosition.tilt, 0.01f);
- assertEquals("Bearing should match",
- expectedPosition.bearing, actualPosition.bearing, 0.01f);
- }));
+ List<List<Point>> polygonDefinition = getPolygonDefinition();
+ CameraPosition actualPosition = mapboxMap.getCameraForGeometry(Polygon.fromLngLats(polygonDefinition),
+ new int[] {5, 5, 5, 5}, 45, 45);
+ CameraPosition expectedPosition = new CameraPosition.Builder()
+ .target(new LatLng(-0.373213463, -0.37131910534)).zoom(3.63).tilt(45).bearing(45).build();
+ assertEquals("Latitude should match",
+ expectedPosition.target.getLatitude(), actualPosition.target.getLatitude(), 0.00001f);
+ assertEquals("Longitude should match",
+ expectedPosition.target.getLongitude(), actualPosition.target.getLongitude(), 0.00001f);
+ assertEquals("Zoom should match",
+ expectedPosition.zoom, actualPosition.zoom, 0.01f);
+ assertEquals("Tilt should match",
+ expectedPosition.tilt, actualPosition.tilt, 0.01f);
+ assertEquals("Bearing should match",
+ expectedPosition.bearing, actualPosition.bearing, 0.01f);
}
@Test
+ @UiThreadTest
public void testGetCameraForGeometryDeprecatedApi() {
validateTestSetup();
- onMapView().perform(getMapboxMapAction((uiController, mapboxMap) -> {
- List<List<Point>> polygonDefinition = getPolygonDefinition();
- CameraPosition actualPosition = mapboxMap.getCameraForGeometry(
- Polygon.fromLngLats(polygonDefinition),
- new int[] {5, 5, 5, 5},
- 45, 0);
- CameraPosition expectedPosition = new CameraPosition.Builder()
- .target(new LatLng()).zoom(3.63).tilt(0).bearing(45).build();
- assertEquals("Latitude should match",
- expectedPosition.target.getLatitude(), actualPosition.target.getLatitude(), 0.00001f);
- assertEquals("Longitude should match",
- expectedPosition.target.getLongitude(), actualPosition.target.getLongitude(), 0.00001f);
- assertEquals("Zoom should match",
- expectedPosition.zoom, actualPosition.zoom, 0.01f);
- assertEquals("Tilt should match",
- expectedPosition.tilt, actualPosition.tilt, 0.01f);
- assertEquals("Bearing should match",
- expectedPosition.bearing, actualPosition.bearing, 0.01f);
- }));
+ List<List<Point>> polygonDefinition = getPolygonDefinition();
+ CameraPosition actualPosition = mapboxMap.getCameraForGeometry(
+ Polygon.fromLngLats(polygonDefinition),
+ new int[] {5, 5, 5, 5},
+ 45, 0);
+ CameraPosition expectedPosition = new CameraPosition.Builder()
+ .target(new LatLng()).zoom(3.63).tilt(0).bearing(45).build();
+ assertEquals("Latitude should match",
+ expectedPosition.target.getLatitude(), actualPosition.target.getLatitude(), 0.00001f);
+ assertEquals("Longitude should match",
+ expectedPosition.target.getLongitude(), actualPosition.target.getLongitude(), 0.00001f);
+ assertEquals("Zoom should match",
+ expectedPosition.zoom, actualPosition.zoom, 0.01f);
+ assertEquals("Tilt should match",
+ expectedPosition.tilt, actualPosition.tilt, 0.01f);
+ assertEquals("Bearing should match",
+ expectedPosition.bearing, actualPosition.bearing, 0.01f);
}
@Override
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/fragment/MapDialogFragmentTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/fragment/MapDialogFragmentTest.kt
index 418191e91a..2731b20db7 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/fragment/MapDialogFragmentTest.kt
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/fragment/MapDialogFragmentTest.kt
@@ -10,6 +10,7 @@ import android.support.test.runner.AndroidJUnit4
import com.mapbox.mapboxsdk.testapp.R
import com.mapbox.mapboxsdk.testapp.action.WaitAction
import com.mapbox.mapboxsdk.testapp.activity.maplayout.MapInDialogActivity
+import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -25,9 +26,10 @@ class MapDialogFragmentTest {
var activityRule: ActivityTestRule<MapInDialogActivity> = ActivityTestRule(MapInDialogActivity::class.java)
@Test
+ @Ignore
fun openCloseDialog() {
onView(withId(R.id.button_open_dialog)).perform(click())
- onView(withId(R.id.mapView)).perform(WaitAction(2500))
+ Thread.sleep(2500)
Espresso.pressBack()
}
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/geometry/GeoJsonConversionTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/geometry/GeoJsonConversionTest.java
index c34e76a6e5..f30b3aa8cf 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/geometry/GeoJsonConversionTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/geometry/GeoJsonConversionTest.java
@@ -1,5 +1,6 @@
package com.mapbox.mapboxsdk.testapp.geometry;
+import android.support.test.annotation.UiThreadTest;
import com.google.gson.JsonArray;
import com.mapbox.geojson.Feature;
import com.mapbox.geojson.FeatureCollection;
@@ -13,11 +14,13 @@ import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
import com.mapbox.mapboxsdk.style.sources.CustomGeometrySource;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
import com.mapbox.mapboxsdk.style.sources.GeometryTileProvider;
+import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
import com.mapbox.mapboxsdk.testapp.activity.EspressoTest;
import com.mapbox.mapboxsdk.testapp.utils.TestingAsyncUtils;
-
import org.junit.Test;
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.matcher.ViewMatchers.isRoot;
import static com.mapbox.geojson.Feature.fromGeometry;
import static com.mapbox.geojson.FeatureCollection.fromFeatures;
import static com.mapbox.geojson.GeometryCollection.fromGeometries;
@@ -35,101 +38,94 @@ public class GeoJsonConversionTest extends EspressoTest {
// Regression test for #12343
@Test
+ @UiThreadTest
public void testEmptyFeatureCollection() {
validateTestSetup();
- onMapView().perform(getMapboxMapAction((uiController, mapboxMap) -> {
- mapboxMap.getStyle().addSource(
- new CustomGeometrySource("test-id",
- new CustomProvider(fromFeatures(singletonList(fromGeometry(fromGeometries(emptyList())))))
- )
- );
- mapboxMap.getStyle().addLayer(new SymbolLayer("test-id", "test-id"));
- }));
+ mapboxMap.getStyle().addSource(
+ new CustomGeometrySource("test-id",
+ new CustomProvider(fromFeatures(singletonList(fromGeometry(fromGeometries(emptyList())))))
+ )
+ );
+ mapboxMap.getStyle().addLayer(new SymbolLayer("test-id", "test-id"));
}
@Test
+ @UiThreadTest
public void testPointFeatureCollection() {
validateTestSetup();
- onMapView().perform(getMapboxMapAction((uiController, mapboxMap) -> {
- mapboxMap.getStyle().addSource(
- new CustomGeometrySource("test-id",
- new CustomProvider(fromFeatures(singletonList(fromGeometry(Point.fromLngLat(0.0, 0.0)))))
- )
- );
- mapboxMap.getStyle().addLayer(new SymbolLayer("test-id", "test-id"));
- }));
+ mapboxMap.getStyle().addSource(
+ new CustomGeometrySource("test-id",
+ new CustomProvider(fromFeatures(singletonList(fromGeometry(Point.fromLngLat(0.0, 0.0)))))
+ )
+ );
+ mapboxMap.getStyle().addLayer(new SymbolLayer("test-id", "test-id"));
}
@Test
+ @UiThreadTest
public void testMultiPointFeatureCollection() {
validateTestSetup();
- onMapView().perform(getMapboxMapAction((uiController, mapboxMap) -> {
- mapboxMap.getStyle().addSource(
- new CustomGeometrySource("test-id",
- new CustomProvider(fromFeatures(singletonList(fromGeometry(fromLngLats(emptyList())))))
- )
- );
- mapboxMap.getStyle().addLayer(new SymbolLayer("test-id", "test-id"));
- }));
+ mapboxMap.getStyle().addSource(
+ new CustomGeometrySource("test-id",
+ new CustomProvider(fromFeatures(singletonList(fromGeometry(fromLngLats(emptyList())))))
+ )
+ );
+ mapboxMap.getStyle().addLayer(new SymbolLayer("test-id", "test-id"));
}
-
@Test
+ @UiThreadTest
public void testPolygonFeatureCollection() {
validateTestSetup();
- onMapView().perform(getMapboxMapAction((uiController, mapboxMap) -> {
- mapboxMap.getStyle().addSource(
- new CustomGeometrySource("test-id",
- new CustomProvider(fromFeatures(singletonList(fromGeometry(Polygon.fromLngLats(emptyList())))))
- )
- );
- mapboxMap.getStyle().addLayer(new SymbolLayer("test-id", "test-id"));
- }));
+ mapboxMap.getStyle().addSource(
+ new CustomGeometrySource("test-id",
+ new CustomProvider(fromFeatures(singletonList(fromGeometry(Polygon.fromLngLats(emptyList())))))
+ )
+ );
+ mapboxMap.getStyle().addLayer(new SymbolLayer("test-id", "test-id"));
}
@Test
+ @UiThreadTest
public void testMultiPolygonFeatureCollection() {
validateTestSetup();
- onMapView().perform(getMapboxMapAction((uiController, mapboxMap) -> {
- mapboxMap.getStyle().addSource(
- new CustomGeometrySource("test-id",
- new CustomProvider(fromFeatures(singletonList(fromGeometry(fromPolygon(Polygon.fromLngLats(emptyList()))))))
- )
- );
- mapboxMap.getStyle().addLayer(new SymbolLayer("test-id", "test-id"));
- }));
+ mapboxMap.getStyle().addSource(
+ new CustomGeometrySource("test-id",
+ new CustomProvider(fromFeatures(singletonList(fromGeometry(fromPolygon(Polygon.fromLngLats(emptyList()))))))
+ )
+ );
+ mapboxMap.getStyle().addLayer(new SymbolLayer("test-id", "test-id"));
}
@Test
+ @UiThreadTest
public void testLineStringFeatureCollection() {
validateTestSetup();
- onMapView().perform(getMapboxMapAction((uiController, mapboxMap) -> {
- mapboxMap.getStyle().addSource(
- new CustomGeometrySource("test-id",
- new CustomProvider(fromFeatures(singletonList(fromGeometry(fromLngLats(emptyList())))))
- )
- );
- mapboxMap.getStyle().addLayer(new SymbolLayer("test-id", "test-id"));
- }));
+ mapboxMap.getStyle().addSource(
+ new CustomGeometrySource("test-id",
+ new CustomProvider(fromFeatures(singletonList(fromGeometry(fromLngLats(emptyList())))))
+ )
+ );
+ mapboxMap.getStyle().addLayer(new SymbolLayer("test-id", "test-id"));
}
@Test
+ @UiThreadTest
public void testMultiLineStringFeatureCollection() {
validateTestSetup();
- onMapView().perform(getMapboxMapAction((uiController, mapboxMap) -> {
- mapboxMap.getStyle().addSource(
- new CustomGeometrySource("test-id",
- new CustomProvider(fromFeatures(singletonList(fromGeometry(fromLineString(fromLngLats(emptyList()))))))
- )
- );
- mapboxMap.getStyle().addLayer(new SymbolLayer("test-id", "test-id"));
- }));
+ mapboxMap.getStyle().addSource(
+ new CustomGeometrySource("test-id",
+ new CustomProvider(fromFeatures(singletonList(fromGeometry(fromLineString(fromLngLats(emptyList()))))))
+ )
+ );
+ mapboxMap.getStyle().addLayer(new SymbolLayer("test-id", "test-id"));
}
+
@Test
public void testNegativeNumberPropertyConversion() {
validateTestSetup();
- onMapView().perform(getMapboxMapAction((uiController, mapboxMap) -> {
+ onView(isRoot()).perform(new MapboxMapAction((uiController, mapboxMap) -> {
LatLng latLng = new LatLng();
Feature feature = Feature.fromGeometry(Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude()));
@@ -148,10 +144,10 @@ public class GeoJsonConversionTest extends EspressoTest {
);
mapboxMap.getStyle().addLayer(layer);
- TestingAsyncUtils.INSTANCE.waitForLayer(uiController, idlingResource.getMapView());
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
assertFalse(mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng)).isEmpty());
- }));
+ }, mapboxMap));
}
class CustomProvider implements GeometryTileProvider {
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/StyleLoadTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/StyleLoadTest.kt
index 84af279bd0..ac73b028f3 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/StyleLoadTest.kt
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/StyleLoadTest.kt
@@ -18,14 +18,6 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class StyleLoadTest : EspressoTest() {
- private lateinit var mapView: MapView
-
- @Before
- override fun beforeTest() {
- super.beforeTest()
- mapView = (rule.activity as EspressoTestActivity).mapView
- }
-
@Test
fun updateSourceAfterStyleLoad() {
validateTestSetup()
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/AttributionTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/AttributionTest.java
index 0fadd33325..ca5c9adc1f 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/AttributionTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/AttributionTest.java
@@ -3,6 +3,7 @@ package com.mapbox.mapboxsdk.testapp.maps.widgets;
import android.app.Instrumentation;
import android.content.Intent;
import android.net.Uri;
+import android.os.Build;
import android.support.test.espresso.UiController;
import android.support.test.espresso.ViewAction;
import android.support.test.espresso.intent.Intents;
@@ -31,12 +32,14 @@ import static android.support.test.espresso.intent.Intents.intended;
import static android.support.test.espresso.intent.Intents.intending;
import static android.support.test.espresso.intent.matcher.IntentMatchers.hasAction;
import static android.support.test.espresso.intent.matcher.IntentMatchers.hasData;
+import static android.support.test.espresso.matcher.RootMatchers.isDialog;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.anything;
import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assume.assumeTrue;
public class AttributionTest extends EspressoTest {
@@ -126,15 +129,20 @@ public class AttributionTest extends EspressoTest {
@Test
public void testTelemetryDialog() {
+ assumeTrue(
+ "Can only run on API Level 23 or newer because of instability",
+ Build.VERSION.SDK_INT >= 23
+ );
+
validateTestSetup();
// click on View to open dialog
onView(withId(R.id.attributionView)).perform(click());
- onView(withText(R.string.mapbox_attributionsDialogTitle)).check(matches(isDisplayed()));
+ onView(withText(R.string.mapbox_attributionsDialogTitle)).inRoot(isDialog()).check(matches(isDisplayed()));
// click on item to open second dialog
- onView(withText(R.string.mapbox_telemetrySettings)).perform(click());
- onView(withText(R.string.mapbox_attributionTelemetryTitle)).check(matches(isDisplayed()));
+ onView(withText(R.string.mapbox_telemetrySettings)).inRoot(isDialog()).perform(click());
+ onView(withText(R.string.mapbox_attributionTelemetryTitle)).inRoot(isDialog()).check(matches(isDisplayed()));
}
@After
@@ -206,4 +214,4 @@ public class AttributionTest extends EspressoTest {
interface InvokeViewAction {
void onViewAction(UiController uiController, View view);
}
-}
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/CompassViewTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/CompassViewTest.java
index 1cdf1423a3..8b62ee7612 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/CompassViewTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/CompassViewTest.java
@@ -4,6 +4,7 @@ import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.action.WaitAction;
import com.mapbox.mapboxsdk.testapp.activity.EspressoTest;
import com.mapbox.mapboxsdk.testapp.utils.TestConstants;
import org.junit.Ignore;
@@ -55,7 +56,7 @@ public class CompassViewTest extends EspressoTest {
.build()
)));
onView(withId(R.id.compassView)).perform(click());
- waitAction();
+ WaitAction.invoke(500);
onView(withId(R.id.compassView)).check(matches(not(isDisplayed())));
invoke(mapboxMap, (uiController, mapboxMap) -> {
CameraPosition cameraPosition = mapboxMap.getCameraPosition();
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/offline/OfflineManagerTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/offline/OfflineManagerTest.kt
index 144d67feee..8e5f3f7c5f 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/offline/OfflineManagerTest.kt
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/offline/OfflineManagerTest.kt
@@ -1,59 +1,43 @@
package com.mapbox.mapboxsdk.testapp.offline
import android.content.Context
-import android.support.test.espresso.Espresso
-import android.support.test.espresso.IdlingRegistry
-import android.support.test.espresso.UiController
-import android.support.test.espresso.idling.CountingIdlingResource
+import android.support.test.rule.ActivityTestRule
import android.support.test.runner.AndroidJUnit4
-import com.mapbox.mapboxsdk.maps.MapboxMap
import com.mapbox.mapboxsdk.offline.OfflineManager
import com.mapbox.mapboxsdk.offline.OfflineRegion
import com.mapbox.mapboxsdk.storage.FileSource
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke
-import com.mapbox.mapboxsdk.testapp.activity.EspressoTest
+import com.mapbox.mapboxsdk.testapp.activity.FeatureOverviewActivity
import com.mapbox.mapboxsdk.testapp.utils.FileUtils
+import org.junit.FixMethodOrder
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
import java.io.IOException
+import java.util.concurrent.CountDownLatch
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@RunWith(AndroidJUnit4::class)
-class OfflineManagerTest : EspressoTest() {
+class OfflineManagerTest {
companion object {
private const val TEST_DB_FILE_NAME = "offline_test.db"
+ private lateinit var mergedRegion: OfflineRegion
}
- private val context: Context by lazy { rule.activity }
-
- private lateinit var offlineIdlingResource: CountingIdlingResource
-
- override fun beforeTest() {
- super.beforeTest()
- offlineIdlingResource = CountingIdlingResource("idling_resource")
- IdlingRegistry.getInstance().register(offlineIdlingResource)
- }
+ @Rule
+ @JvmField
+ var rule = ActivityTestRule(FeatureOverviewActivity::class.java)
- @Test
- fun offlineMergeListDeleteTest() {
- validateTestSetup()
+ private val context: Context by lazy { rule.activity }
- invoke(mapboxMap) { _: UiController, _: MapboxMap ->
- offlineIdlingResource.increment()
+ @Test(timeout = 30_000)
+ fun a_copyFileFromAssets() {
+ val latch = CountDownLatch(1)
+ rule.runOnUiThread {
FileUtils.CopyFileFromAssetsTask(rule.activity, object : FileUtils.OnFileCopiedFromAssetsListener {
override fun onFileCopiedFromAssets() {
- OfflineManager.getInstance(context).mergeOfflineRegions(
- FileSource.getResourcesCachePath(rule.activity) + "/" + TEST_DB_FILE_NAME,
- object : OfflineManager.MergeOfflineRegionsCallback {
- override fun onMerge(offlineRegions: Array<out OfflineRegion>?) {
- assert(offlineRegions?.size == 1)
- offlineIdlingResource.decrement()
- }
-
- override fun onError(error: String?) {
- throw RuntimeException("Unable to merge external offline database. $error")
- }
- })
+ latch.countDown()
}
override fun onError() {
@@ -61,43 +45,62 @@ class OfflineManagerTest : EspressoTest() {
}
}).execute(TEST_DB_FILE_NAME, FileSource.getResourcesCachePath(rule.activity))
}
+ latch.await()
+ }
+
+ @Test(timeout = 30_000)
+ fun b_mergeRegion() {
+ val latch = CountDownLatch(1)
+ rule.runOnUiThread {
+ OfflineManager.getInstance(context).mergeOfflineRegions(
+ FileSource.getResourcesCachePath(rule.activity) + "/" + TEST_DB_FILE_NAME,
+ object : OfflineManager.MergeOfflineRegionsCallback {
+ override fun onMerge(offlineRegions: Array<out OfflineRegion>?) {
+ assert(offlineRegions?.size == 1)
+ latch.countDown()
+ }
+
+ override fun onError(error: String?) {
+ throw RuntimeException("Unable to merge external offline database. $error")
+ }
+ })
+ }
+ latch.await()
+ }
- invoke(mapboxMap) { _: UiController, _: MapboxMap ->
- offlineIdlingResource.increment()
+ @Test(timeout = 30_000)
+ fun c_listRegion() {
+ val latch = CountDownLatch(1)
+ rule.runOnUiThread {
OfflineManager.getInstance(context).listOfflineRegions(object : OfflineManager.ListOfflineRegionsCallback {
override fun onList(offlineRegions: Array<out OfflineRegion>?) {
assert(offlineRegions?.size == 1)
- if (offlineRegions != null) {
- for (region in offlineRegions) {
- offlineIdlingResource.increment()
- region.delete(object : OfflineRegion.OfflineRegionDeleteCallback {
- override fun onDelete() {
- offlineIdlingResource.decrement()
- }
-
- override fun onError(error: String?) {
- throw RuntimeException("Unable to delete region with ID: ${region.id}. $error")
- }
- })
- }
- } else {
- throw RuntimeException("Unable to find merged region.")
- }
- offlineIdlingResource.decrement()
+ mergedRegion = offlineRegions!![0]
+ latch.countDown()
}
override fun onError(error: String?) {
- throw RuntimeException("Unable to obtain offline regions list. $error")
+ throw RuntimeException("Unable to merge external offline database. $error")
}
})
}
-
- // waiting for offline idling resource
- Espresso.onIdle()
+ latch.await()
}
- override fun afterTest() {
- super.afterTest()
- IdlingRegistry.getInstance().unregister(offlineIdlingResource)
+ @Test(timeout = 30_000)
+ fun d_deleteRegion() {
+ val latch = CountDownLatch(1)
+ rule.runOnUiThread {
+ mergedRegion.delete(object : OfflineRegion.OfflineRegionDeleteCallback {
+ override fun onDelete() {
+ latch.countDown()
+ }
+
+ override fun onError(error: String?) {
+ throw RuntimeException("Unable to delete region")
+ }
+ })
+ }
+ latch.await()
}
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CustomGeometrySourceTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CustomGeometrySourceTest.kt
index eb458ab8f5..a6238ebf14 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CustomGeometrySourceTest.kt
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CustomGeometrySourceTest.kt
@@ -6,8 +6,9 @@ import com.mapbox.mapboxsdk.style.sources.CustomGeometrySource
import com.mapbox.mapboxsdk.style.sources.CustomGeometrySource.THREAD_POOL_LIMIT
import com.mapbox.mapboxsdk.style.sources.CustomGeometrySource.THREAD_PREFIX
import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke
-import com.mapbox.mapboxsdk.testapp.action.OrientationChangeAction.orientationLandscape
-import com.mapbox.mapboxsdk.testapp.action.OrientationChangeAction.orientationPortrait
+import com.mapbox.mapboxsdk.testapp.action.OrientationAction.orientationLandscape
+import com.mapbox.mapboxsdk.testapp.action.OrientationAction.orientationPortrait
+import com.mapbox.mapboxsdk.testapp.action.WaitAction
import com.mapbox.mapboxsdk.testapp.activity.BaseTest
import com.mapbox.mapboxsdk.testapp.activity.style.GridSourceActivity
import com.mapbox.mapboxsdk.testapp.activity.style.GridSourceActivity.ID_GRID_LAYER
@@ -25,11 +26,11 @@ class CustomGeometrySourceTest : BaseTest() {
@Ignore
fun sourceNotLeakingThreadsTest() {
validateTestSetup()
- waitAction(4000)
+ WaitAction.invoke(4000)
onView(isRoot()).perform(orientationLandscape())
- waitAction(2000)
+ WaitAction.invoke(2000)
onView(isRoot()).perform(orientationPortrait())
- waitAction(2000)
+ WaitAction.invoke(2000)
Assert.assertFalse("Threads should be shutdown when the source is destroyed.",
Thread.getAllStackTraces().keys.filter {
it.name.startsWith(THREAD_PREFIX)
@@ -42,9 +43,9 @@ class CustomGeometrySourceTest : BaseTest() {
validateTestSetup()
invoke(mapboxMap) { uiController, mapboxMap ->
mapboxMap.style!!.removeLayer(ID_GRID_LAYER)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
mapboxMap.style!!.removeSource(ID_GRID_SOURCE)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
Assert.assertTrue("There should be no threads running when the source is removed.",
Thread.getAllStackTraces().keys.filter {
it.name.startsWith(CustomGeometrySource.THREAD_PREFIX)
@@ -58,12 +59,12 @@ class CustomGeometrySourceTest : BaseTest() {
validateTestSetup()
invoke(mapboxMap) { uiController, mapboxMap ->
mapboxMap.style!!.removeLayer((rule.activity as GridSourceActivity).layer)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
mapboxMap.style!!.removeSource(ID_GRID_SOURCE)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
mapboxMap.style!!.addSource((rule.activity as GridSourceActivity).source)
mapboxMap.style!!.addLayer((rule.activity as GridSourceActivity).layer)
- TestingAsyncUtils.waitForLayer(uiController, idlingResource.mapView)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
Assert.assertTrue("Threads should be restarted when the source is re-added to the map.",
Thread.getAllStackTraces().keys.filter {
it.name.startsWith(CustomGeometrySource.THREAD_PREFIX)
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ExpressionTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ExpressionTest.java
index 75dcbf1209..ff3b2a9d6d 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ExpressionTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ExpressionTest.java
@@ -252,7 +252,7 @@ public class ExpressionTest extends EspressoTest {
)
));
mapboxMap.getStyle().addLayer(layer);
- TestingAsyncUtils.INSTANCE.waitForLayer(uiController, idlingResource.getMapView());
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
assertFalse(mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng), "layer")
.isEmpty());
@@ -262,7 +262,7 @@ public class ExpressionTest extends EspressoTest {
literal(ColorUtils.colorToRgbaString(Color.RED))
)
));
- TestingAsyncUtils.INSTANCE.waitForLayer(uiController, idlingResource.getMapView());
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
assertFalse(mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng), "layer")
.isEmpty());
@@ -272,7 +272,7 @@ public class ExpressionTest extends EspressoTest {
literal(ColorUtils.colorToRgbaString(Color.RED))
)
));
- TestingAsyncUtils.INSTANCE.waitForLayer(uiController, idlingResource.getMapView());
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
assertFalse(mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng), "layer")
.isEmpty());
});
@@ -292,7 +292,7 @@ public class ExpressionTest extends EspressoTest {
formatEntry("test")
);
layer.setProperties(textField(expression));
- TestingAsyncUtils.INSTANCE.waitForLayer(uiController, idlingResource.getMapView());
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
assertFalse(mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng), "layer")
.isEmpty());
@@ -315,7 +315,7 @@ public class ExpressionTest extends EspressoTest {
formatEntry("test", formatFontScale(1.75))
);
layer.setProperties(textField(expression));
- TestingAsyncUtils.INSTANCE.waitForLayer(uiController, idlingResource.getMapView());
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
assertFalse(mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng), "layer")
.isEmpty());
@@ -341,7 +341,7 @@ public class ExpressionTest extends EspressoTest {
)
);
layer.setProperties(textField(expression));
- TestingAsyncUtils.INSTANCE.waitForLayer(uiController, idlingResource.getMapView());
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
assertFalse(
mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng), "layer").isEmpty()
@@ -371,7 +371,7 @@ public class ExpressionTest extends EspressoTest {
)
);
layer.setProperties(textField(expression));
- TestingAsyncUtils.INSTANCE.waitForLayer(uiController, idlingResource.getMapView());
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
assertFalse(
mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng), "layer").isEmpty()
@@ -402,7 +402,7 @@ public class ExpressionTest extends EspressoTest {
)
);
layer.setProperties(textField(expression));
- TestingAsyncUtils.INSTANCE.waitForLayer(uiController, idlingResource.getMapView());
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
assertFalse(
mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng), "layer").isEmpty()
@@ -436,7 +436,7 @@ public class ExpressionTest extends EspressoTest {
formatEntry("\ntest2", formatFontScale(2), formatTextColor(Color.BLUE))
);
layer.setProperties(textField(expression));
- TestingAsyncUtils.INSTANCE.waitForLayer(uiController, idlingResource.getMapView());
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
assertFalse(
mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng), "layer").isEmpty()
@@ -472,7 +472,7 @@ public class ExpressionTest extends EspressoTest {
)
);
layer.setProperties(textField(expression));
- TestingAsyncUtils.INSTANCE.waitForLayer(uiController, idlingResource.getMapView());
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
assertFalse(mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng), "layer")
.isEmpty());
@@ -504,7 +504,7 @@ public class ExpressionTest extends EspressoTest {
formatEntry("\ntest2", formatFontScale(2))
);
layer.setProperties(textField(expression), textColor("rgba(128, 0, 0, 1)"));
- TestingAsyncUtils.INSTANCE.waitForLayer(uiController, idlingResource.getMapView());
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
assertFalse(mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng), "layer")
.isEmpty());
@@ -524,7 +524,7 @@ public class ExpressionTest extends EspressoTest {
mapboxMap.getStyle().addLayer(layer);
layer.setProperties(textField("test"));
- TestingAsyncUtils.INSTANCE.waitForLayer(uiController, idlingResource.getMapView());
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
assertFalse(mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng), "layer")
.isEmpty());
@@ -550,7 +550,7 @@ public class ExpressionTest extends EspressoTest {
new FormattedSection("test", null, null, "rgba(0, 255, 0, 1)")
);
layer.setProperties(textField(formatted), textColor("rgba(128, 0, 0, 1)"));
- TestingAsyncUtils.INSTANCE.waitForLayer(uiController, idlingResource.getMapView());
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
assertFalse(mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng), "layer")
.isEmpty());
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/GeoJsonSourceTests.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/GeoJsonSourceTests.java
index 92d060fee4..99e0ae4016 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/GeoJsonSourceTests.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/GeoJsonSourceTests.java
@@ -94,7 +94,7 @@ public class GeoJsonSourceTests extends EspressoTest {
}
source.setGeoJson(Point.fromLngLat(20, 55));
- TestingAsyncUtils.INSTANCE.waitForLayer(uiController, idlingResource.getMapView());
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
assertEquals(1, mapboxMap.queryRenderedFeatures(
mapboxMap.getProjection().toScreenLocation(
new LatLng(55, 20)), "layer").size());
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ImageTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ImageTest.java
deleted file mode 100644
index 0e4c8f3f2e..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ImageTest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.mapbox.mapboxsdk.testapp.style;
-
-import android.graphics.Bitmap;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.support.test.runner.AndroidJUnit4;
-
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
-
-import com.mapbox.mapboxsdk.testapp.activity.EspressoTest;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-/**
- * CRUD tests around Image
- */
-@RunWith(AndroidJUnit4.class)
-public class ImageTest extends EspressoTest {
-
- private static final String IMAGE_ID = "test.image";
-
- @Test
- public void testAddGetImage() {
- validateTestSetup();
- MapboxMapAction.invoke(mapboxMap, (uiController, mapboxMap) -> {
- Drawable drawable = rule.getActivity().getResources().getDrawable(R.drawable.ic_launcher_round);
- assertTrue(drawable instanceof BitmapDrawable);
-
- Bitmap bitmapSet = ((BitmapDrawable) drawable).getBitmap();
- mapboxMap.getStyle().addImage(IMAGE_ID, bitmapSet);
-
- // adding an image requires converting the image with an asynctask
- uiController.loopMainThreadForAtLeast(200);
-
- Bitmap bitmapGet = mapboxMap.getStyle().getImage(IMAGE_ID);
- assertTrue(bitmapGet.sameAs(bitmapSet));
-
- mapboxMap.getStyle().removeImage(IMAGE_ID);
- assertNull(mapboxMap.getStyle().getImage(IMAGE_ID));
- });
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ImageTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ImageTest.kt
new file mode 100644
index 0000000000..9cef677e7c
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ImageTest.kt
@@ -0,0 +1,75 @@
+package com.mapbox.mapboxsdk.testapp.style
+
+import android.graphics.Bitmap
+import android.graphics.drawable.BitmapDrawable
+import android.support.test.runner.AndroidJUnit4
+import com.mapbox.mapboxsdk.testapp.R
+import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction
+import com.mapbox.mapboxsdk.testapp.activity.EspressoTest
+import org.junit.Assert.assertNull
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.util.*
+
+/**
+ * CRUD tests around Image
+ */
+@RunWith(AndroidJUnit4::class)
+class ImageTest : EspressoTest() {
+
+ companion object {
+ private const val IMAGE_ID = "test.image"
+ }
+
+ @Test
+ fun testAddGetImage() {
+ validateTestSetup()
+ MapboxMapAction.invoke(mapboxMap) { uiController, mapboxMap ->
+ val drawable = rule.activity.resources.getDrawable(R.drawable.ic_launcher_round)
+ assertTrue(drawable is BitmapDrawable)
+
+ val bitmapSet = (drawable as BitmapDrawable).bitmap
+ mapboxMap.style!!.addImage(IMAGE_ID, bitmapSet)
+
+ // adding an image requires converting the image with an asynctask
+ uiController.loopMainThreadForAtLeast(200)
+
+ val bitmapGet = mapboxMap.style!!.getImage(IMAGE_ID)
+ assertTrue(bitmapGet!!.similarTo(bitmapSet))
+
+ mapboxMap.style!!.removeImage(IMAGE_ID)
+ assertNull(mapboxMap.style!!.getImage(IMAGE_ID))
+ }
+ }
+}
+
+/**
+ * Alternative implementation of Bitmap.sameAs #14060
+ */
+fun Bitmap.similarTo(other: Bitmap): Boolean {
+ if (invalidConfig(other)) {
+ return false
+ }
+
+ // Allocate arrays
+ val argb = IntArray(width * height)
+ val argbOther = IntArray(other.width * other.height)
+ getPixels(argb, 0, width, 0, 0, width, height)
+ other.getPixels(argbOther, 0, width, 0, 0, width, height)
+
+ // Alpha channel special check
+ if (config == Bitmap.Config.ALPHA_8) {
+ // in this case we have to manually compare the alpha channel as the rest is garbage.
+ val length = width * height
+ for (i in 0 until length) {
+ if (argb[i] and -0x1000000 != argbOther[i] and -0x1000000) {
+ return false
+ }
+ }
+ return true
+ }
+ return Arrays.equals(argb, argbOther)
+}
+
+fun Bitmap.invalidConfig(other: Bitmap): Boolean = this.config != other.config || this.width != other.width || this.height != other.height \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTests.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTests.java
index ed39f36e32..a4a34e752e 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTests.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTests.java
@@ -2,12 +2,10 @@ package com.mapbox.mapboxsdk.testapp.style;
import android.graphics.Color;
import android.graphics.PointF;
-import android.support.test.espresso.Espresso;
import android.support.test.espresso.UiController;
import android.support.test.espresso.ViewAction;
import android.support.test.runner.AndroidJUnit4;
import android.view.View;
-
import com.mapbox.mapboxsdk.style.layers.CannotAddLayerException;
import com.mapbox.mapboxsdk.style.layers.CircleLayer;
import com.mapbox.mapboxsdk.style.layers.FillLayer;
@@ -22,20 +20,16 @@ import com.mapbox.mapboxsdk.style.sources.Source;
import com.mapbox.mapboxsdk.style.sources.VectorSource;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.activity.EspressoTest;
-
import junit.framework.Assert;
-
import org.hamcrest.Matcher;
-import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
+import timber.log.Timber;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
-import timber.log.Timber;
-
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
@@ -366,11 +360,6 @@ public class RuntimeStyleTests extends EspressoTest {
}
}
- @After
- public void unregisterIntentServiceIdlingResource() {
- Espresso.unregisterIdlingResources(idlingResource);
- }
-
public abstract class BaseViewAction implements ViewAction {
@Override
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java
index 149064d684..ae2c6d98f6 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java
@@ -559,7 +559,7 @@ public class SymbolLayerTest extends BaseLayerTest {
assertNull(layer.getTextJustify().getValue());
// Set and Get
- String propertyValue = TEXT_JUSTIFY_LEFT;
+ String propertyValue = TEXT_JUSTIFY_AUTO;
layer.setProperties(textJustify(propertyValue));
assertEquals(layer.getTextJustify().getValue(), propertyValue);
}
@@ -579,6 +579,32 @@ public class SymbolLayerTest extends BaseLayerTest {
@Test
@UiThreadTest
+ public void testTextRadialOffsetAsConstant() {
+ Timber.i("text-radial-offset");
+ assertNotNull(layer);
+ assertNull(layer.getTextRadialOffset().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(textRadialOffset(propertyValue));
+ assertEquals(layer.getTextRadialOffset().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextVariableAnchorAsConstant() {
+ Timber.i("text-variable-anchor");
+ assertNotNull(layer);
+ assertNull(layer.getTextVariableAnchor().getValue());
+
+ // Set and Get
+ String[] propertyValue = new String[0];
+ layer.setProperties(textVariableAnchor(propertyValue));
+ assertEquals(layer.getTextVariableAnchor().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
public void testTextAnchorAsConstant() {
Timber.i("text-anchor");
assertNotNull(layer);
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/FinishLoadingStyleIdlingResource.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/FinishLoadingStyleIdlingResource.java
deleted file mode 100644
index 323d2c0f15..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/FinishLoadingStyleIdlingResource.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.mapbox.mapboxsdk.testapp.utils;
-
-import android.app.Activity;
-import android.os.Handler;
-import android.os.Looper;
-import android.support.annotation.WorkerThread;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-public class FinishLoadingStyleIdlingResource extends MapboxIdlingResource {
-
- @WorkerThread
- public FinishLoadingStyleIdlingResource(final Activity activity) {
- new Handler(Looper.getMainLooper()).post(() -> inflateMap(activity));
- }
-
- @Override
- public void initMap(MapboxMap mapboxMap) {
- super.initMap(mapboxMap);
- mapboxMap.getStyle(style -> {
- assertNotNull(style);
- assertTrue(style.isFullyLoaded());
- if (resourceCallback != null) {
- resourceCallback.onTransitionToIdle();
- }
- });
- }
-
- @Override
- public boolean isIdleNow() {
- return getMapboxMap() != null && getMapboxMap().getStyle() != null;
- }
-} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/LoadStyleIdlingResource.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/LoadStyleIdlingResource.java
deleted file mode 100644
index 5dead21fbb..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/LoadStyleIdlingResource.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.mapbox.mapboxsdk.testapp.utils;
-
-import android.app.Activity;
-import android.os.Handler;
-import android.os.Looper;
-import android.support.annotation.UiThread;
-import android.support.annotation.WorkerThread;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.Style;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-public class LoadStyleIdlingResource extends MapboxIdlingResource {
-
- private Style style;
-
- @WorkerThread
- public LoadStyleIdlingResource(final Activity activity) {
- new Handler(Looper.getMainLooper()).post(() -> inflateMap(activity));
- }
-
- @UiThread
- public void initMap(MapboxMap mapboxMap) {
- super.initMap(mapboxMap);
- mapboxMap.setStyle("asset://streets.json", style -> {
- assertNotNull(style);
- assertTrue(style.isFullyLoaded());
- this.style = style;
- if (resourceCallback != null) {
- resourceCallback.onTransitionToIdle();
- }
- });
- }
-
- @Override
- public boolean isIdleNow() {
- return style != null;
- }
-} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/MapboxIdlingResource.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/MapboxIdlingResource.java
deleted file mode 100644
index a05221d618..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/MapboxIdlingResource.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.mapbox.mapboxsdk.testapp.utils;
-
-import android.app.Activity;
-import android.support.annotation.UiThread;
-import android.support.test.espresso.IdlingResource;
-import com.mapbox.mapboxsdk.maps.MapView;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.testapp.R;
-
-public abstract class MapboxIdlingResource implements IdlingResource {
-
- private MapView mapView;
- private MapboxMap mapboxMap;
- IdlingResource.ResourceCallback resourceCallback;
-
- @UiThread
- void inflateMap(Activity activity) {
- mapView = activity.findViewById(R.id.mapView);
- if (mapView != null) {
- mapView.getMapAsync(this::initMap);
- }
- }
-
- @UiThread
- protected void initMap(MapboxMap mapboxMap) {
- this.mapboxMap = mapboxMap;
- }
-
- @Override
- public String getName() {
- return getClass().getSimpleName();
- }
-
- @Override
- public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
- this.resourceCallback = resourceCallback;
- }
-
- public MapboxMap getMapboxMap() {
- return mapboxMap;
- }
-
- public MapView getMapView() {
- return mapView;
- }
-} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/OnMapReadyIdlingResource.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/OnMapReadyIdlingResource.java
deleted file mode 100644
index 7696447289..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/OnMapReadyIdlingResource.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.mapbox.mapboxsdk.testapp.utils;
-
-import android.app.Activity;
-import android.os.Handler;
-import android.os.Looper;
-import android.support.annotation.WorkerThread;
-import android.support.test.espresso.IdlingResource;
-
-import com.mapbox.mapboxsdk.maps.MapView;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.Style;
-import com.mapbox.mapboxsdk.testapp.R;
-
-public class OnMapReadyIdlingResource implements IdlingResource {
-
- private boolean styleLoaded;
- private MapboxMap mapboxMap;
- private IdlingResource.ResourceCallback resourceCallback;
-
- @WorkerThread
- public OnMapReadyIdlingResource(final Activity activity) {
- Handler handler = new Handler(Looper.getMainLooper());
- handler.post(() -> {
- MapView mapView = activity.findViewById(R.id.mapView);
- if (mapView != null) {
- mapView.addOnDidFinishLoadingStyleListener(() -> {
- styleLoaded = true;
- if (resourceCallback != null) {
- resourceCallback.onTransitionToIdle();
- }
- });
- mapView.getMapAsync(this::initMap);
- }
- });
- }
-
- private void initMap(MapboxMap mapboxMap) {
- this.mapboxMap = mapboxMap;
- mapboxMap.setStyle(new Style.Builder().fromUrl("asset://streets.json"));
- }
-
- @Override
- public String getName() {
- return getClass().getSimpleName();
- }
-
- @Override
- public boolean isIdleNow() {
- return styleLoaded;
- }
-
- @Override
- public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
- this.resourceCallback = resourceCallback;
- }
-
- public MapboxMap getMapboxMap() {
- return mapboxMap;
- }
-} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
index 2fa26f822a..017fe3ddca 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
@@ -173,10 +173,11 @@
<activity
android:name=".activity.fragment.FragmentBackStackActivity"
android:description="@string/description_map_fragment_backstack"
- android:label="@string/activity_map_fragment_backstack">
+ android:label="@string/activity_map_fragment_backstack"
+ android:launchMode="singleInstance">
<meta-data
android:name="@string/category"
- android:value="@string/category_fragment" />
+ android:value="@string/category_integration" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activity.FeatureOverviewActivity" />
@@ -399,7 +400,7 @@
android:label="@string/activity_viewpager">
<meta-data
android:name="@string/category"
- android:value="@string/category_fragment" />
+ android:value="@string/category_integration" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activity.FeatureOverviewActivity" />
@@ -407,7 +408,8 @@
<activity
android:name=".activity.maplayout.SimpleMapActivity"
android:description="@string/description_simple_map"
- android:label="@string/activity_simple_map">
+ android:label="@string/activity_simple_map"
+ android:launchMode="singleInstance">
<meta-data
android:name="@string/category"
android:value="@string/category_basic" />
@@ -720,7 +722,8 @@
<activity
android:name=".activity.textureview.TextureViewDebugModeActivity"
android:description="@string/description_textureview_debug"
- android:label="@string/activity_textureview_debug">
+ android:label="@string/activity_textureview_debug"
+ android:launchMode="singleInstance">
<meta-data
android:name="@string/category"
android:value="@string/category_basic" />
@@ -895,27 +898,49 @@
android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
- android:name=".activity.maplayout.RecyclerViewActivity"
- android:description="@string/description_recyclerview"
- android:label="@string/activity_recyclerview">
+ android:name=".activity.maplayout.TextureRecyclerViewActivity"
+ android:description="@string/description_recyclerview_textureview"
+ android:label="@string/activity_recyclerview_textureview">
<meta-data
android:name="@string/category"
- android:value="@string/category_maplayout" />
+ android:value="@string/category_integration" />
+ <meta-data
+ android:name="android.support.PARENT_ACTIVITY"
+ android:value=".activity.FeatureOverviewActivity" />
+ </activity>
+ <activity
+ android:name=".activity.maplayout.GLSurfaceRecyclerViewActivity"
+ android:description="@string/description_recyclerview_glsurfaceview"
+ android:label="@string/activity_recyclerview_glsurfaceview">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_integration" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.fragment.NestedViewPagerActivity"
- android:description="@string/description_recyclerview"
+ android:description="@string/description_nested_viewpager"
android:label="@string/activity_nested_viewpager">
<meta-data
android:name="@string/category"
- android:value="@string/category_fragment" />
+ android:value="@string/category_integration" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activity.FeatureOverviewActivity" />
</activity>
+ <activity
+ android:name=".activity.telemetry.PerformanceMeasurementActivity"
+ android:description="@string/description_performance_measurement"
+ android:label="@string/activity_performance_measurement">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_telemetry" />
+ <meta-data
+ android:name="android.support.PARENT_ACTIVITY"
+ android:value=".activity.FeatureOverviewActivity" />
+ </activity>
<!-- For Instrumentation tests -->
<activity
android:name=".activity.style.RuntimeStyleTimingTestActivity"
@@ -924,6 +949,9 @@
android:name=".activity.espresso.EspressoTestActivity"
android:screenOrientation="portrait" />
<activity
+ android:name=".activity.espresso.PixelTestActivity"
+ android:screenOrientation="portrait" />
+ <activity
android:name=".activity.espresso.DeviceIndependentTestActivity"
android:screenOrientation="portrait" />
<activity
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapboxApplication.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapboxApplication.java
index 9ade97f91e..d5cff301db 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapboxApplication.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapboxApplication.java
@@ -40,7 +40,7 @@ public class MapboxApplication extends Application {
initializeMapbox();
}
- private boolean initializeLeakCanary() {
+ protected boolean initializeLeakCanary() {
if (LeakCanary.isInAnalyzerProcess(this)) {
// This process is dedicated to LeakCanary for heap analysis.
// You should not init your app in this process.
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/GestureDetectorActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/GestureDetectorActivity.java
index f4639b0f1a..ed5364655e 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/GestureDetectorActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/GestureDetectorActivity.java
@@ -267,7 +267,18 @@ public class GestureDetectorActivity extends AppCompatActivity {
if (enabled) {
focalPointLatLng = new LatLng(51.50325, -0.12968);
marker = mapboxMap.addMarker(new MarkerOptions().position(focalPointLatLng));
- mapboxMap.easeCamera(CameraUpdateFactory.newLatLngZoom(focalPointLatLng, 16));
+ mapboxMap.easeCamera(CameraUpdateFactory.newLatLngZoom(focalPointLatLng, 16),
+ new MapboxMap.CancelableCallback() {
+ @Override
+ public void onCancel() {
+ recalculateFocalPoint();
+ }
+
+ @Override
+ public void onFinish() {
+ recalculateFocalPoint();
+ }
+ });
} else {
if (marker != null) {
mapboxMap.removeMarker(marker);
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/espresso/PixelTestActivity.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/espresso/PixelTestActivity.kt
new file mode 100644
index 0000000000..b69d1ee5ed
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/espresso/PixelTestActivity.kt
@@ -0,0 +1,66 @@
+package com.mapbox.mapboxsdk.testapp.activity.espresso
+
+import android.os.Bundle
+import android.support.v7.app.AppCompatActivity
+import com.mapbox.mapboxsdk.maps.MapView
+import com.mapbox.mapboxsdk.maps.MapboxMap
+import com.mapbox.mapboxsdk.maps.OnMapReadyCallback
+import com.mapbox.mapboxsdk.maps.Style
+import com.mapbox.mapboxsdk.testapp.R
+
+/**
+ * Test activity used for instrumentation tests that require a specific device size.
+ */
+class PixelTestActivity : AppCompatActivity(), OnMapReadyCallback {
+
+ lateinit var mapView: MapView
+ lateinit var mapboxMap: MapboxMap
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_pixel_test)
+ mapView = findViewById(R.id.mapView)
+ mapView.onCreate(savedInstanceState)
+ mapView.getMapAsync(this)
+ }
+
+ override fun onMapReady(map: MapboxMap) {
+ mapboxMap = map
+ mapboxMap.setStyle(Style.MAPBOX_STREETS)
+ }
+
+ public override fun onResume() {
+ super.onResume()
+ mapView.onResume()
+ }
+
+ override fun onStart() {
+ super.onStart()
+ mapView.onStart()
+ }
+
+ public override fun onPause() {
+ super.onPause()
+ mapView.onPause()
+ }
+
+ override fun onStop() {
+ super.onStop()
+ mapView.onStop()
+ }
+
+ override fun onSaveInstanceState(outState: Bundle) {
+ super.onSaveInstanceState(outState)
+ mapView.onSaveInstanceState(outState)
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ mapView.onDestroy()
+ }
+
+ override fun onLowMemory() {
+ super.onLowMemory()
+ mapView.onLowMemory()
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/MapFragmentActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/MapFragmentActivity.java
index 472b9b7d57..c7f530b123 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/MapFragmentActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/MapFragmentActivity.java
@@ -3,16 +3,15 @@ package com.mapbox.mapboxsdk.testapp.activity.fragment;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
-
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
-import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapFragment;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.MapboxMapOptions;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
+import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.testapp.R;
/**
@@ -24,6 +23,7 @@ import com.mapbox.mapboxsdk.testapp.R;
public class MapFragmentActivity extends AppCompatActivity implements MapFragment.OnMapViewReadyCallback,
OnMapReadyCallback, MapView.OnDidFinishRenderingFrameListener {
+ private static final String TAG = "com.mapbox.map";
private MapboxMap mapboxMap;
private MapView mapView;
private boolean initialCameraAnimation = true;
@@ -32,14 +32,18 @@ public class MapFragmentActivity extends AppCompatActivity implements MapFragmen
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map_fragment);
+
+ MapFragment mapFragment;
if (savedInstanceState == null) {
- MapFragment mapFragment = MapFragment.newInstance(createFragmentOptions());
+ mapFragment = MapFragment.newInstance(createFragmentOptions());
getFragmentManager()
.beginTransaction()
- .add(R.id.fragment_container, mapFragment, "com.mapbox.map")
+ .add(R.id.fragment_container, mapFragment, TAG)
.commit();
- mapFragment.getMapAsync(this);
+ } else {
+ mapFragment = (MapFragment) getFragmentManager().findFragmentByTag(TAG);
}
+ mapFragment.getMapAsync(this);
}
private MapboxMapOptions createFragmentOptions() {
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/SupportMapFragmentActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/SupportMapFragmentActivity.java
index 4baf40d51b..7fd84bcd25 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/SupportMapFragmentActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/SupportMapFragmentActivity.java
@@ -3,16 +3,15 @@ package com.mapbox.mapboxsdk.testapp.activity.fragment;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
-
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
-import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapFragment;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.MapboxMapOptions;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
+import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.maps.SupportMapFragment;
import com.mapbox.mapboxsdk.testapp.R;
@@ -25,6 +24,7 @@ import com.mapbox.mapboxsdk.testapp.R;
public class SupportMapFragmentActivity extends AppCompatActivity implements MapFragment.OnMapViewReadyCallback,
OnMapReadyCallback, MapView.OnDidFinishRenderingFrameListener {
+ private static final String TAG = "com.mapbox.map";
private MapboxMap mapboxMap;
private MapView mapView;
private boolean initialCameraAnimation = true;
@@ -33,14 +33,18 @@ public class SupportMapFragmentActivity extends AppCompatActivity implements Map
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map_fragment);
+ SupportMapFragment mapFragment;
if (savedInstanceState == null) {
- SupportMapFragment mapFragment = SupportMapFragment.newInstance(createFragmentOptions());
+ mapFragment = SupportMapFragment.newInstance(createFragmentOptions());
getSupportFragmentManager()
.beginTransaction()
- .add(R.id.fragment_container, mapFragment, "com.mapbox.map")
+ .add(R.id.fragment_container, mapFragment, TAG)
.commit();
- mapFragment.getMapAsync(this);
+ } else {
+ mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentByTag(TAG);
}
+ mapFragment.getMapAsync(this);
+
}
private MapboxMapOptions createFragmentOptions() {
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/ViewPagerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/ViewPagerActivity.java
deleted file mode 100644
index c494842b14..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/ViewPagerActivity.java
+++ /dev/null
@@ -1,117 +0,0 @@
-package com.mapbox.mapboxsdk.testapp.activity.fragment;
-
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentManager;
-import android.support.v4.app.FragmentStatePagerAdapter;
-import android.support.v4.view.ViewPager;
-import android.support.v7.app.AppCompatActivity;
-
-import com.mapbox.mapboxsdk.camera.CameraPosition;
-import com.mapbox.mapboxsdk.geometry.LatLng;
-import com.mapbox.mapboxsdk.maps.MapboxMapOptions;
-import com.mapbox.mapboxsdk.maps.Style;
-import com.mapbox.mapboxsdk.maps.SupportMapFragment;
-import com.mapbox.mapboxsdk.testapp.R;
-
-/**
- * Test activity showcasing using the Android SDK ViewPager API to show MapFragments.
- */
-public class ViewPagerActivity extends AppCompatActivity {
-
- private ViewPager viewPager;
- private MapFragmentAdapter adapter;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_viewpager);
-
- viewPager = (ViewPager) findViewById(R.id.viewpager);
- if (viewPager != null) {
- adapter = new MapFragmentAdapter(getSupportFragmentManager());
- viewPager.setAdapter(adapter);
- }
- }
-
- @Override
- protected void onRestoreInstanceState(Bundle savedInstanceState) {
- super.onRestoreInstanceState(savedInstanceState);
-
- int currentPosition = viewPager.getCurrentItem();
- SupportMapFragment mapFragment;
-
- if (Math.abs(0 - currentPosition) <= 1) {
- mapFragment = (SupportMapFragment) adapter.instantiateItem(viewPager, 0);
- mapFragment.getMapAsync(mapboxMap -> {
- mapboxMap.setStyle(Style.MAPBOX_STREETS);
- });
- }
-
- if (Math.abs(1 - currentPosition) <= 1) {
- mapFragment = (SupportMapFragment) adapter.instantiateItem(viewPager, 1);
- mapFragment.getMapAsync(mapboxMap -> {
- mapboxMap.setStyle(Style.DARK);
- });
- }
-
- if (Math.abs(2 - currentPosition) <= 1) {
- mapFragment = (SupportMapFragment) adapter.instantiateItem(viewPager, 2);
- mapFragment.getMapAsync(mapboxMap -> {
- mapboxMap.setStyle(Style.SATELLITE);
- });
- }
- }
-
- static class MapFragmentAdapter extends FragmentStatePagerAdapter {
-
- private static int NUM_ITEMS = 3;
-
- MapFragmentAdapter(FragmentManager fragmentManager) {
- super(fragmentManager);
- }
-
- @Override
- public int getCount() {
- return NUM_ITEMS;
- }
-
- @Override
- public Fragment getItem(int position) {
- SupportMapFragment fragment = null;
- MapboxMapOptions options = new MapboxMapOptions();
- options.textureMode(true);
-
- switch (position) {
- case 0:
- options.camera(new CameraPosition.Builder().target(new LatLng(34.920526, 102.634774)).zoom(3).build());
- fragment = SupportMapFragment.newInstance(options);
- fragment.getMapAsync(mapboxMap -> {
- mapboxMap.setStyle(Style.MAPBOX_STREETS);
- });
- break;
- case 1:
- options.camera(new CameraPosition.Builder().target(new LatLng(62.326440, 92.764913)).zoom(3).build());
- fragment = SupportMapFragment.newInstance(options);
- fragment.getMapAsync(mapboxMap -> {
- mapboxMap.setStyle(Style.DARK);
- });
- break;
- case 2:
- options.camera(new CameraPosition.Builder().target(new LatLng(-25.007786, 133.623852)).zoom(3).build());
- fragment = SupportMapFragment.newInstance(options);
- fragment.getMapAsync(mapboxMap -> {
- mapboxMap.setStyle(Style.SATELLITE);
- });
- break;
- }
- return fragment;
- }
-
- @Override
- public CharSequence getPageTitle(int position) {
- return "Page " + position;
- }
- }
-}
-
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/ViewPagerActivity.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/ViewPagerActivity.kt
new file mode 100644
index 0000000000..77e2e1370d
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/ViewPagerActivity.kt
@@ -0,0 +1,109 @@
+package com.mapbox.mapboxsdk.testapp.activity.fragment
+
+import android.os.Bundle
+import android.support.v4.app.Fragment
+import android.support.v4.app.FragmentManager
+import android.support.v4.app.FragmentStatePagerAdapter
+import android.support.v7.app.AppCompatActivity
+import com.mapbox.mapboxsdk.camera.CameraPosition
+import com.mapbox.mapboxsdk.geometry.LatLng
+import com.mapbox.mapboxsdk.maps.MapboxMapOptions
+import com.mapbox.mapboxsdk.maps.Style
+import com.mapbox.mapboxsdk.maps.SupportMapFragment
+import com.mapbox.mapboxsdk.testapp.R
+import kotlinx.android.synthetic.main.activity_viewpager.*
+
+/**
+ * Test activity showcasing using the Android SDK ViewPager API to show MapFragments.
+ */
+class ViewPagerActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_viewpager)
+ viewPager.adapter = MapFragmentAdapter(supportFragmentManager)
+ }
+
+ override fun onRestoreInstanceState(savedInstanceState: Bundle) {
+ super.onRestoreInstanceState(savedInstanceState)
+
+ val currentPosition = viewPager.currentItem
+ var mapFragment: SupportMapFragment
+
+ if (Math.abs(0 - currentPosition) <= 1) {
+ mapFragment = viewPager.adapter?.instantiateItem(viewPager, 0) as SupportMapFragment
+ mapFragment.getMapAsync { mapboxMap -> mapboxMap.setStyle(Style.MAPBOX_STREETS) }
+ }
+
+ if (Math.abs(1 - currentPosition) <= 1) {
+ mapFragment = viewPager.adapter?.instantiateItem(viewPager, 1) as SupportMapFragment
+ mapFragment.getMapAsync { mapboxMap -> mapboxMap.setStyle(Style.DARK) }
+ }
+
+ if (Math.abs(2 - currentPosition) <= 1) {
+ mapFragment = viewPager.adapter?.instantiateItem(viewPager, 2) as SupportMapFragment
+ mapFragment.getMapAsync { mapboxMap -> mapboxMap.setStyle(Style.SATELLITE) }
+ }
+
+ if (Math.abs(3 - currentPosition) <= 1) {
+ mapFragment = viewPager.adapter?.instantiateItem(viewPager, 3) as SupportMapFragment
+ mapFragment.getMapAsync { mapboxMap -> mapboxMap.setStyle(Style.SATELLITE) }
+ }
+
+ if (Math.abs(4 - currentPosition) <= 1) {
+ mapFragment = viewPager.adapter?.instantiateItem(viewPager, 4) as SupportMapFragment
+ mapFragment.getMapAsync { mapboxMap -> mapboxMap.setStyle(Style.SATELLITE) }
+ }
+ }
+
+ internal class MapFragmentAdapter(fragmentManager: FragmentManager) : FragmentStatePagerAdapter(fragmentManager) {
+
+ override fun getCount(): Int {
+ return NUM_ITEMS
+ }
+
+ override fun getItem(position: Int): Fragment? {
+ var fragment: SupportMapFragment? = null
+ val options = MapboxMapOptions()
+ options.textureMode(true)
+
+ when (position) {
+ 0 -> {
+ options.camera(CameraPosition.Builder().target(LatLng(34.920526, 102.634774)).zoom(3.0).build())
+ fragment = SupportMapFragment.newInstance(options)
+ fragment.getMapAsync { mapboxMap -> mapboxMap.setStyle(Style.MAPBOX_STREETS) }
+ }
+ 1 -> {
+ options.camera(CameraPosition.Builder().target(LatLng(62.326440, 92.764913)).zoom(3.0).build())
+ fragment = SupportMapFragment.newInstance(options)
+ fragment.getMapAsync { mapboxMap -> mapboxMap.setStyle(Style.DARK) }
+ }
+ 2 -> {
+ options.camera(CameraPosition.Builder().target(LatLng(-25.007786, 133.623852)).zoom(3.0).build())
+ fragment = SupportMapFragment.newInstance(options)
+ fragment.getMapAsync { mapboxMap -> mapboxMap.setStyle(Style.SATELLITE) }
+ }
+ 3 -> {
+ options.camera(CameraPosition.Builder().target(LatLng(62.326440, 92.764913)).zoom(3.0).build())
+ fragment = SupportMapFragment.newInstance(options)
+ fragment.getMapAsync { mapboxMap -> mapboxMap.setStyle(Style.LIGHT) }
+ }
+ 4 -> {
+ options.camera(CameraPosition.Builder().target(LatLng(34.920526, 102.634774)).zoom(3.0).build())
+ fragment = SupportMapFragment.newInstance(options)
+ fragment.getMapAsync { mapboxMap -> mapboxMap.setStyle(Style.TRAFFIC_NIGHT) }
+ }
+ }
+ return fragment
+ }
+
+ override fun getPageTitle(position: Int): CharSequence? {
+ return "Page $position"
+ }
+
+ companion object {
+
+ private val NUM_ITEMS = 5
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/SnapshotActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/SnapshotActivity.java
deleted file mode 100644
index c1697ab960..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/SnapshotActivity.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package com.mapbox.mapboxsdk.testapp.activity.imagegenerator;
-
-import android.graphics.Bitmap;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.design.widget.FloatingActionButton;
-import android.support.v4.content.ContextCompat;
-import android.support.v7.app.AppCompatActivity;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.Toast;
-
-import com.mapbox.mapboxsdk.maps.Style;
-import com.mapbox.mapboxsdk.maps.MapView;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
-import com.mapbox.mapboxsdk.testapp.R;
-
-import java.util.Locale;
-
-import timber.log.Timber;
-
-/**
- * Test activity showcasing the Snapshot API to create and display a bitmap of the current shown Map.
- */
-public class SnapshotActivity extends AppCompatActivity implements OnMapReadyCallback, View.OnClickListener {
-
- private MapView mapView;
- private MapboxMap mapboxMap;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_snapshot);
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(this);
- }
-
- @Override
- public void onMapReady(@NonNull MapboxMap map) {
- mapboxMap = map;
- mapboxMap.setStyle(new Style.Builder().fromUrl(Style.OUTDOORS));
- FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
- if (fab != null) {
- fab.setColorFilter(ContextCompat.getColor(SnapshotActivity.this, R.color.primary));
- fab.setOnClickListener(this);
- }
- }
-
- @Override
- public void onClick(View view) {
- final long startTime = System.nanoTime();
- mapboxMap.snapshot(snapshot -> {
- long endTime = System.nanoTime();
- long duration = (long) ((endTime - startTime) / 1e6);
- ImageView snapshotView = (ImageView) findViewById(R.id.imageView);
- snapshotView.setImageBitmap(snapshot);
- Toast.makeText(
- SnapshotActivity.this,
- String.format(Locale.getDefault(), "Snapshot taken in %d ms", duration),
- Toast.LENGTH_LONG).show();
- });
- }
-
- @Override
- protected void onStart() {
- super.onStart();
- mapView.onStart();
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- mapView.onResume();
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- mapboxMap.snapshot(new MapboxMap.SnapshotReadyCallback() {
- @Override
- public void onSnapshotReady(Bitmap snapshot) {
- Timber.e("Regression test for https://github.com/mapbox/mapbox-gl-native/pull/11358");
- }
- });
- mapView.onPause();
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- mapView.onStop();
- }
-
- @Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
-
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/SnapshotActivity.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/SnapshotActivity.kt
new file mode 100644
index 0000000000..51b1c08ba5
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/SnapshotActivity.kt
@@ -0,0 +1,80 @@
+package com.mapbox.mapboxsdk.testapp.activity.imagegenerator
+
+import android.os.Bundle
+import android.support.v7.app.AppCompatActivity
+import com.mapbox.mapboxsdk.maps.MapView
+import com.mapbox.mapboxsdk.maps.MapboxMap
+import com.mapbox.mapboxsdk.maps.OnMapReadyCallback
+import com.mapbox.mapboxsdk.maps.Style
+import com.mapbox.mapboxsdk.testapp.R
+import kotlinx.android.synthetic.main.activity_snapshot.*
+import timber.log.Timber
+
+/**
+ * Test activity showcasing the Snapshot API to create and display a bitmap of the current shown Map.
+ */
+class SnapshotActivity : AppCompatActivity(), OnMapReadyCallback {
+
+ private lateinit var mapboxMap: MapboxMap
+
+ private val idleListener = object : MapView.OnDidBecomeIdleListener {
+ override fun onDidBecomeIdle() {
+ mapView.removeOnDidBecomeIdleListener(this)
+ mapboxMap.snapshot { snapshot ->
+ imageView.setImageBitmap(snapshot)
+ mapView.addOnDidBecomeIdleListener(this)
+ }
+ }
+ }
+
+ public override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_snapshot)
+ mapView.onCreate(savedInstanceState)
+ mapView.getMapAsync(this)
+ }
+
+ override fun onMapReady(map: MapboxMap) {
+ mapboxMap = map
+ mapboxMap.setStyle(Style.Builder().fromUrl(Style.OUTDOORS)) { mapView.addOnDidBecomeIdleListener(idleListener) }
+ }
+
+ override fun onStart() {
+ super.onStart()
+ mapView.onStart()
+ }
+
+ override fun onResume() {
+ super.onResume()
+ mapView.onResume()
+ }
+
+ override fun onPause() {
+ super.onPause()
+ mapboxMap.snapshot {
+ Timber.e("Regression test for https://github.com/mapbox/mapbox-gl-native/pull/11358")
+ }
+ mapView.onPause()
+ }
+
+ override fun onStop() {
+ super.onStop()
+ mapView.onStop()
+ }
+
+ public override fun onSaveInstanceState(outState: Bundle) {
+ super.onSaveInstanceState(outState)
+ mapView.onSaveInstanceState(outState)
+ }
+
+ override fun onLowMemory() {
+ super.onLowMemory()
+ mapView.onLowMemory()
+ }
+
+ public override fun onDestroy() {
+ super.onDestroy()
+ mapView.removeOnDidBecomeIdleListener(idleListener)
+ mapView.onDestroy()
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/GLSurfaceRecyclerViewActivity.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/GLSurfaceRecyclerViewActivity.kt
new file mode 100644
index 0000000000..5acf356696
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/GLSurfaceRecyclerViewActivity.kt
@@ -0,0 +1,155 @@
+package com.mapbox.mapboxsdk.testapp.activity.maplayout
+
+import android.annotation.SuppressLint
+import android.os.Bundle
+import android.support.v7.app.AppCompatActivity
+import android.support.v7.widget.LinearLayoutManager
+import android.support.v7.widget.RecyclerView
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import android.widget.TextView
+import com.mapbox.mapboxsdk.maps.MapView
+import com.mapbox.mapboxsdk.maps.Style
+import com.mapbox.mapboxsdk.testapp.R
+import kotlinx.android.synthetic.main.activity_recyclerview.*
+
+/**
+ * TestActivity showcasing how to integrate a GLSurfaceView MapView in a RecyclerView.
+ * <p>
+ * It requires calling the correct lifecycle methods when detaching and attaching the View to
+ * the RecyclerView with onViewAttachedToWindow and onViewDetachedFromWindow.
+ * </p>
+ */
+@SuppressLint("ClickableViewAccessibility")
+open class GLSurfaceRecyclerViewActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_recyclerview)
+ recyclerView.layoutManager = LinearLayoutManager(this)
+ recyclerView.adapter = ItemAdapter(this, LayoutInflater.from(this), savedInstanceState)
+ }
+
+ override fun onSaveInstanceState(outState: Bundle?) {
+ super.onSaveInstanceState(outState)
+ // to save state, we need to call MapView#onSaveInstanceState
+ (recyclerView.adapter as ItemAdapter).onSaveInstanceState(outState)
+ }
+
+ override fun onLowMemory() {
+ super.onLowMemory()
+ // to release memory, we need to call MapView#onLowMemory
+ (recyclerView.adapter as ItemAdapter).onLowMemory()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ // to perform cleanup, we need to call MapView#onDestroy
+ (recyclerView.adapter as ItemAdapter).onDestroy()
+ }
+
+ open fun getMapItemLayoutId(): Int {
+ return R.layout.item_map_gl
+ }
+
+ class ItemAdapter(private val activity: GLSurfaceRecyclerViewActivity, private val inflater: LayoutInflater, val savedInstanceState: Bundle?) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
+
+ private val items = listOf(
+ "one", "two", "three", MapItem(), "four", "five", "six", "seven", "eight", "nine", "ten",
+ "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen",
+ "nineteen", "twenty", "twenty-one"
+ )
+
+ private var mapHolder: MapHolder? = null
+
+ companion object {
+ const val TYPE_MAP = 0
+ const val TYPE_TEXT = 1
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
+ return if (viewType == TYPE_MAP) {
+ val mapView = inflater.inflate(activity.getMapItemLayoutId(), parent, false) as MapView
+ mapView.getMapAsync { mapboxMap -> mapboxMap.setStyle(Style.MAPBOX_STREETS) }
+ mapHolder = MapHolder(mapView, savedInstanceState)
+ return mapHolder as MapHolder
+ } else {
+ TextHolder(inflater.inflate(android.R.layout.simple_list_item_1, parent, false) as TextView)
+ }
+ }
+
+ override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) {
+ super.onViewAttachedToWindow(holder)
+ if (holder is MapHolder) {
+ val mapView = holder.mapView
+ mapView.onStart()
+ mapView.onResume()
+ }
+ }
+
+ override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) {
+ super.onViewDetachedFromWindow(holder)
+ if (holder is MapHolder) {
+ val mapView = holder.mapView
+ mapView.onPause()
+ mapView.onStop()
+ }
+ }
+
+ override fun getItemCount(): Int {
+ return items.count()
+ }
+
+ override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
+ if (holder.itemViewType == TYPE_TEXT) {
+ val textHolder = holder as TextHolder
+ textHolder.bind(items[position] as String)
+ }
+ }
+
+ override fun getItemViewType(position: Int): Int {
+ return if (items[position] is MapItem) {
+ TYPE_MAP
+ } else {
+ TYPE_TEXT
+ }
+ }
+
+ fun onSaveInstanceState(savedInstanceState: Bundle?) {
+ savedInstanceState?.let {
+ mapHolder?.mapView?.onSaveInstanceState(it)
+ }
+ }
+
+ fun onLowMemory() {
+ mapHolder?.mapView?.onLowMemory()
+ }
+
+ fun onDestroy() {
+ mapHolder?.mapView?.let {
+ it.onPause()
+ it.onStop()
+ it.onDestroy()
+ }
+ }
+
+ class MapItem
+ class MapHolder(val mapView: MapView, bundle: Bundle?) : RecyclerView.ViewHolder(mapView) {
+ init {
+ mapView.onCreate(bundle)
+ mapView.setOnTouchListener { view, motionEvent ->
+ // Disallow the touch request for recyclerView scroll
+ view.parent.requestDisallowInterceptTouchEvent(true)
+ mapView.onTouchEvent(motionEvent)
+ true
+ }
+ }
+ }
+
+ class TextHolder(val textView: TextView) : RecyclerView.ViewHolder(textView) {
+ fun bind(item: String) {
+ textView.text = item
+ }
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapInDialogActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapInDialogActivity.java
index c9a9377885..18092ce372 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapInDialogActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapInDialogActivity.java
@@ -1,6 +1,5 @@
package com.mapbox.mapboxsdk.testapp.activity.maplayout;
-import android.app.Dialog;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@@ -17,9 +16,6 @@ import com.mapbox.mapboxsdk.testapp.R;
/**
* Test activity showcasing showing a Map inside of a DialogFragment.
- * <p>
- * Uses the deprecated TextureView API to workaround the issue of seeing a grey background before the gl surface.
- * </p>
*/
public class MapInDialogActivity extends AppCompatActivity {
@@ -64,23 +60,6 @@ public class MapInDialogActivity extends AppCompatActivity {
mapView.getMapAsync(mapboxMap -> mapboxMap.setStyle(Style.OUTDOORS));
}
- @NonNull
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- return new Dialog(getActivity(), getTheme()) {
- @Override
- public void dismiss() {
- if (mapView != null && !mapView.isDestroyed()) {
- mapView.onPause();
- mapView.onStop();
- mapView.onDestroy();
- mapView = null;
- }
- super.dismiss();
- }
- };
- }
-
@Override
public void onStart() {
super.onStart();
@@ -96,25 +75,20 @@ public class MapInDialogActivity extends AppCompatActivity {
@Override
public void onPause() {
super.onPause();
- if (mapView != null) {
- mapView.onPause();
- }
+ mapView.onPause();
}
@Override
public void onStop() {
super.onStop();
- if (mapView != null) {
- mapView.onStop();
- }
+ mapView.onStop();
}
@Override
public void onDestroyView() {
super.onDestroyView();
- if (mapView != null) {
- mapView.onDestroy();
- }
+ mapView.onDestroy();
+ mapView = null;
}
@Override
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/RecyclerViewActivity.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/RecyclerViewActivity.kt
deleted file mode 100644
index 9989d1b137..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/RecyclerViewActivity.kt
+++ /dev/null
@@ -1,151 +0,0 @@
-package com.mapbox.mapboxsdk.testapp.activity.maplayout
-
-import android.annotation.SuppressLint
-import android.os.Bundle
-import android.support.v7.app.AppCompatActivity
-import android.support.v7.widget.LinearLayoutManager
-import android.support.v7.widget.RecyclerView
-import android.view.LayoutInflater
-import android.view.ViewGroup
-import android.widget.TextView
-import com.mapbox.mapboxsdk.maps.MapView
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback
-import com.mapbox.mapboxsdk.maps.Style
-import com.mapbox.mapboxsdk.testapp.R
-import kotlinx.android.synthetic.main.activity_recyclerview.*
-
-/**
- * TestActivity showcasing how to integrate a MapView in a RecyclerView.
- * <p>
- * It requires calling the correct lifecycle methods when detaching and attaching the View to
- * the RecyclerView with onViewAttachedToWindow and onViewDetachedFromWindow.
- * </p>
- */
-@SuppressLint("ClickableViewAccessibility")
-class RecyclerViewActivity : AppCompatActivity() {
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_recyclerview)
- recyclerView.layoutManager = LinearLayoutManager(this)
- recyclerView.adapter = ItemAdapter(LayoutInflater.from(this), savedInstanceState)
- }
-
- override fun onSaveInstanceState(outState: Bundle?) {
- super.onSaveInstanceState(outState)
- // to save state, we need to call MapView#onSaveInstanceState
- (recyclerView.adapter as ItemAdapter).onSaveInstanceState(outState)
- }
-
- override fun onLowMemory() {
- super.onLowMemory()
- // to release memory, we need to call MapView#onLowMemory
- (recyclerView.adapter as ItemAdapter).onLowMemory()
- }
-
- override fun onDestroy() {
- super.onDestroy()
- // to perform cleanup, we need to call MapView#onDestroy
- (recyclerView.adapter as ItemAdapter).onDestroy()
- }
-
- class ItemAdapter(private val inflater: LayoutInflater, val savedInstanceState: Bundle?) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
-
- private val items = listOf(
- "one", "two", "three", MapItem(), "four", "five", "six", "seven", "eight", "nine", "ten",
- "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen",
- "nineteen", "twenty", "twenty-one"
- )
-
- private var mapHolder: MapHolder? = null
-
- companion object {
- const val TYPE_MAP = 0
- const val TYPE_TEXT = 1
- }
-
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
- return if (viewType == TYPE_MAP) {
- val mapView = inflater.inflate(R.layout.item_map, parent, false) as MapView
- mapView.getMapAsync { mapboxMap -> mapboxMap.setStyle(Style.MAPBOX_STREETS) }
- mapHolder = MapHolder(mapView, savedInstanceState)
- return mapHolder as MapHolder
- } else {
- TextHolder(inflater.inflate(android.R.layout.simple_list_item_1, parent, false) as TextView)
- }
- }
-
- override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) {
- super.onViewAttachedToWindow(holder)
- if (holder is MapHolder) {
- val mapView = holder.mapView
- mapView.onStart()
- mapView.onResume()
- }
- }
-
- override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) {
- super.onViewDetachedFromWindow(holder)
- if (holder is MapHolder) {
- val mapView = holder.mapView
- mapView.onPause()
- mapView.onStop()
- }
- }
-
- override fun getItemCount(): Int {
- return items.count()
- }
-
- override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
- if (holder.itemViewType == TYPE_TEXT) {
- val textHolder = holder as TextHolder
- textHolder.bind(items[position] as String)
- }
- }
-
- override fun getItemViewType(position: Int): Int {
- return if (items[position] is MapItem) {
- TYPE_MAP
- } else {
- TYPE_TEXT
- }
- }
-
- fun onSaveInstanceState(savedInstanceState: Bundle?){
- savedInstanceState?.let {
- mapHolder?.mapView?.onSaveInstanceState(it)
- }
- }
-
- fun onLowMemory() {
- mapHolder?.mapView?.onLowMemory()
- }
-
- fun onDestroy() {
- mapHolder?.mapView?.let {
- it.onPause()
- it.onStop()
- it.onDestroy()
- }
- }
-
- class MapItem
- class MapHolder(val mapView: MapView, bundle: Bundle?) : RecyclerView.ViewHolder(mapView) {
- init {
- mapView.onCreate(bundle)
- mapView.setOnTouchListener { view, motionEvent ->
- // Disallow the touch request for recyclerView scroll
- view.parent.requestDisallowInterceptTouchEvent(true)
- mapView.onTouchEvent(motionEvent)
- true
- }
- }
- }
- class TextHolder(val textView: TextView) : RecyclerView.ViewHolder(textView) {
- fun bind(item: String) {
- textView.text = item
- }
- }
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/TextureRecyclerViewActivity.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/TextureRecyclerViewActivity.kt
new file mode 100644
index 0000000000..895389bc1e
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/TextureRecyclerViewActivity.kt
@@ -0,0 +1,15 @@
+package com.mapbox.mapboxsdk.testapp.activity.maplayout
+
+import android.annotation.SuppressLint
+import com.mapbox.mapboxsdk.testapp.R
+
+/**
+ * TestActivity showcasing how to integrate a TexureView MapView in a RecyclerView.
+ */
+@SuppressLint("ClickableViewAccessibility")
+class TextureRecyclerViewActivity : GLSurfaceRecyclerViewActivity() {
+
+ override fun getMapItemLayoutId() : Int{
+ return R.layout.item_map_texture
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/telemetry/PerformanceMeasurementActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/telemetry/PerformanceMeasurementActivity.java
new file mode 100644
index 0000000000..285d7bc6c8
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/telemetry/PerformanceMeasurementActivity.java
@@ -0,0 +1,187 @@
+package com.mapbox.mapboxsdk.testapp.activity.telemetry;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.v7.app.AppCompatActivity;
+import android.util.DisplayMetrics;
+import android.view.Display;
+import android.view.WindowManager;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import com.mapbox.mapboxsdk.Mapbox;
+import com.mapbox.mapboxsdk.maps.MapView;
+import com.mapbox.mapboxsdk.maps.Style;
+import com.mapbox.mapboxsdk.module.http.HttpRequestUtil;
+import com.mapbox.mapboxsdk.testapp.R;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import okhttp3.Call;
+import okhttp3.EventListener;
+import okhttp3.OkHttpClient;
+import timber.log.Timber;
+
+/**
+ * Test activity showcasing gathering performance measurement data.
+ */
+public class PerformanceMeasurementActivity extends AppCompatActivity {
+
+ private MapView mapView;
+
+ private Map<String, Long> startTimes = new HashMap<>();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_map_simple);
+ mapView = findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+
+
+ OkHttpClient.Builder builder = new OkHttpClient.Builder();
+ builder.eventListener(new EventListener() {
+
+ @Override
+ public void callStart(Call call) {
+ String url = call.request().url().toString();
+ startTimes.put(url, System.nanoTime());
+ super.callStart(call);
+ Timber.e("callStart: %s", url);
+ }
+
+ @Override
+ public void callEnd(Call call) {
+ String url = call.request().url().toString();
+ Timber.e("callEnd: %s", url);
+ Long start = startTimes.get(url);
+ if (start != null) {
+ long elapsed = System.nanoTime() - start;
+ triggerPerformanceEvent(url.substring(0, url.indexOf('?')), elapsed);
+ startTimes.remove(start);
+ Timber.e("callEnd: %s took %d", url, elapsed);
+ }
+ super.callEnd(call);
+ }
+ });
+ HttpRequestUtil.setOkHttpClient(builder.build());
+
+ mapView.getMapAsync(mapboxMap -> mapboxMap.setStyle(
+ new Style.Builder().fromUrl(Style.MAPBOX_STREETS)));
+ }
+
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ protected void onDestroy() {
+
+ startTimes.clear();
+
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ private void triggerPerformanceEvent(String style, long elapsed) {
+
+ List<Attribute<String>> attributes = new ArrayList<>();
+ attributes.add(
+ new Attribute<>("style_id", style));
+ attributes.add(
+ new Attribute<>("test_perf_event", "true"));
+
+ List<Attribute<Long>> counters = new ArrayList();
+ counters.add(new Attribute<>("elapsed", elapsed));
+
+
+ JsonObject metaData = new JsonObject();
+ metaData.addProperty("os", "android");
+ metaData.addProperty("manufacturer", Build.MANUFACTURER);
+ metaData.addProperty("brand", Build.BRAND);
+ metaData.addProperty("device", Build.MODEL);
+ metaData.addProperty("version", Build.VERSION.RELEASE);
+ metaData.addProperty("abi", Build.CPU_ABI);
+ metaData.addProperty("country", Locale.getDefault().getISO3Country());
+ metaData.addProperty("ram", getRam());
+ metaData.addProperty("screenSize", getWindowSize());
+
+ Gson gson = new Gson();
+
+ Bundle bundle = new Bundle();
+ bundle.putString("attributes", gson.toJson(attributes));
+ bundle.putString("counters", gson.toJson(counters));
+ bundle.putString("metadata", metaData.toString());
+
+ Mapbox.getTelemetry().onPerformanceEvent(bundle);
+ }
+
+ private static String getRam() {
+ ActivityManager actManager =
+ (ActivityManager) Mapbox.getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
+ ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo();
+ actManager.getMemoryInfo(memInfo);
+ return String.valueOf(memInfo.totalMem);
+ }
+
+ private static String getWindowSize() {
+ WindowManager windowManager =
+ (WindowManager) Mapbox.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
+ Display display = windowManager.getDefaultDisplay();
+ DisplayMetrics metrics = new DisplayMetrics();
+ display.getMetrics(metrics);
+ int width = metrics.widthPixels;
+ int height = metrics.heightPixels;
+
+ return "{" + width + "," + height + "}";
+ }
+
+ private class Attribute<T> {
+ private String name;
+ private T value;
+
+ Attribute(String name, T value) {
+ this.name = name;
+ this.value = value;
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_backstack_fragment.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_backstack_fragment.xml
index b6b672cf73..10c11a9320 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_backstack_fragment.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_backstack_fragment.xml
@@ -10,6 +10,7 @@
<Button android:layout_width="match_parent"
android:layout_height="58dp"
android:id="@+id/button"
+ android:contentDescription="btn_change_fragment"
android:text="Replace with empty fragment"/>
</FrameLayout> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_pixel_test.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_pixel_test.xml
new file mode 100644
index 0000000000..4c88a87703
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_pixel_test.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <com.mapbox.mapboxsdk.maps.MapView
+ android:layout_gravity="center"
+ android:id="@id/mapView"
+ app:mapbox_cameraZoom="1"
+ android:layout_width="1080px"
+ android:layout_height="1920px"
+ app:mapbox_pixelRatio="1"/>
+
+</FrameLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_snapshot.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_snapshot.xml
index 53345571b4..f0787ecad9 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_snapshot.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_snapshot.xml
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
@@ -27,15 +26,4 @@
</LinearLayout>
- <android.support.design.widget.FloatingActionButton
- android:id="@id/fab"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_alignParentEnd="true"
- android:layout_alignParentRight="true"
- android:layout_margin="@dimen/fab_margin"
- android:src="@drawable/ic_add_a_photo_black"
- app:backgroundTint="@android:color/white"/>
-
</RelativeLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_viewpager.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_viewpager.xml
index 3edaff6985..516bf60b6b 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_viewpager.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_viewpager.xml
@@ -5,7 +5,7 @@
android:layout_height="match_parent">
<com.mapbox.mapboxsdk.testapp.view.MapViewPager
- android:id="@+id/viewpager"
+ android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent">
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/item_map_gl.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/item_map_gl.xml
new file mode 100644
index 0000000000..850399e355
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/item_map_gl.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<com.mapbox.mapboxsdk.maps.MapView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@id/mapView"
+ android:layout_width="match_parent"
+ android:layout_height="256dp"
+ app:mapbox_cameraTargetLat="45.38301927899065"
+ app:mapbox_cameraTargetLng="8.63525390625"
+ app:mapbox_cameraZoom="7"/>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/item_map.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/item_map_texture.xml
index 3224b73477..3224b73477 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/item_map.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/item_map_texture.xml
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/categories.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/categories.xml
index a4403a34f7..2c34a59327 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/categories.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/categories.xml
@@ -15,4 +15,6 @@
<string name="category_storage">Storage</string>
<string name="category_textureview">Texture View</string>
<string name="category_location">Location</string>
+ <string name="category_integration">_Integration</string>
+ <string name="category_telemetry">Telemetry</string>
</resources> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml
index 21ebeaabd5..778805b3b3 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml
@@ -78,6 +78,8 @@
<string name="description_location_fragment">Uses LocationComponent in a Fragment</string>
<string name="description_location_manual">Force location updates and don\'t rely on the engine</string>
<string name="description_location_activation_builder">Use LocationComponentActivationOptions to set options</string>
- <string name="description_recyclerview">Show a MapView as a recyclerView item</string>
+ <string name="description_recyclerview_textureview">Show a TextureView MapView as a recyclerView item</string>
+ <string name="description_recyclerview_glsurfaceview">Show a GLSurfaceView MapView as a recyclerView item</string>
<string name="description_nested_viewpager">Show a MapView inside a viewpager inside a recyclerView</string>
+ <string name="description_performance_measurement">Show the use PerformanceEvent for performance measurements</string>
</resources>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml
index 26f56f29b1..12c82bf21a 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml
@@ -78,6 +78,8 @@
<string name="activity_location_fragment">Location Fragment</string>
<string name="activity_location_manual">Manual Location updates</string>
<string name="activity_location_activation_builder">Build Location Activation</string>
- <string name="activity_recyclerview">RecyclerView</string>
+ <string name="activity_recyclerview_textureview">RecyclerView TextureView</string>
+ <string name="activity_recyclerview_glsurfaceview">RecyclerView GLSurfaceView</string>
<string name="activity_nested_viewpager">Nested ViewPager</string>
+ <string name="activity_performance_measurement">Performance Measurement</string>
</resources> \ No newline at end of file
diff --git a/platform/android/build.gradle b/platform/android/build.gradle
index 5334c93ce9..97f3037afb 100644
--- a/platform/android/build.gradle
+++ b/platform/android/build.gradle
@@ -12,6 +12,7 @@ buildscript {
classpath dependenciesList.bintrayPlugin
classpath dependenciesList.artifactoryPlugin
classpath dependenciesList.androidPublishPlugin
+ classpath dependenciesList.jacocoPlugin
}
}
diff --git a/platform/android/gradle/android-nitpick.gradle b/platform/android/gradle/android-nitpick.gradle
index f8e4a47b0b..32539270f5 100644
--- a/platform/android/gradle/android-nitpick.gradle
+++ b/platform/android/gradle/android-nitpick.gradle
@@ -17,6 +17,8 @@ task androidNitpick {
verifyVendorSubmodulePin(MAPBOX_JAVA_DIR, MAPBOX_JAVA_TAG_PREFIX, versions.mapboxServices)
verifyVendorSubmodulePin(MAPBOX_TELEMETRY_DIR, MAPBOX_TELEMETRY_TAG_PREFIX, versions.mapboxTelemetry)
verifyVendorSubmodulePin(MAPBOX_GESTURES_DIR, MAPBOX_GESTURES_TAG_PREFIX, versions.mapboxGestures)
+
+ verifyLicenseGeneration()
}
}
@@ -51,4 +53,12 @@ private def verifyVendorSubmodulePin(def dir, def prefix, def version) {
"If you've bumped the pin, make sure to verify the version tag prefix in the android-nitpick.gradle file.")
}
output.close()
+}
+
+private def verifyLicenseGeneration() {
+ println "Verify license generation with git diff..."
+ exec {
+ workingDir = "${rootDir}"
+ commandLine "python", "scripts/validate-license.py"
+ }
} \ No newline at end of file
diff --git a/platform/android/gradle/dependencies.gradle b/platform/android/gradle/dependencies.gradle
index 600901ca76..1d17e7f83d 100644
--- a/platform/android/gradle/dependencies.gradle
+++ b/platform/android/gradle/dependencies.gradle
@@ -8,7 +8,7 @@ ext {
versions = [
mapboxServices : '4.3.0',
- mapboxTelemetry : '4.2.0',
+ mapboxTelemetry : '4.3.0',
mapboxGestures : '0.4.0',
supportLib : '27.1.1',
constraintLayout: '1.1.2',
@@ -29,7 +29,8 @@ ext {
androidPublish : '3.6.2',
lint : '26.1.4',
gms : '16.0.0',
- reLinker : '1.3.1'
+ reLinker : '1.3.1',
+ jacoco : '0.8.3'
]
dependenciesList = [
@@ -72,6 +73,7 @@ ext {
bintrayPlugin : "com.jfrog.bintray.gradle:gradle-bintray-plugin:${versions.bintray}",
artifactoryPlugin : "org.jfrog.buildinfo:build-info-extractor-gradle:${versions.artifactory}",
androidPublishPlugin : "digital.wup:android-maven-publish:${versions.androidPublish}",
+ jacocoPlugin : "org.jacoco:org.jacoco.core:${versions.jacoco}",
lint : "com.android.tools.lint:lint:${versions.lint}",
lintApi : "com.android.tools.lint:lint-api:${versions.lint}",
diff --git a/platform/android/gradle/jacoco-report.gradle b/platform/android/gradle/jacoco-report.gradle
new file mode 100644
index 0000000000..e50facb683
--- /dev/null
+++ b/platform/android/gradle/jacoco-report.gradle
@@ -0,0 +1,33 @@
+apply plugin: 'jacoco'
+apply from: "${rootDir}/gradle/dependencies.gradle"
+
+jacoco {
+ toolVersion = versions.jacoco
+}
+
+task jacocoTestReport(type: JacocoReport, dependsOn: ['testDebugUnitTest']) {
+ group = "Reporting"
+ description = "Combine code coverage to unified report."
+
+ reports {
+ xml.enabled = true
+ html.enabled = true
+ }
+
+ def fileExcludes = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Test*.*', 'android/**/*.*']
+ def debugTree = fileTree(dir: "${project.buildDir}/intermediates/javac/debug/compileDebugJavaWithJavac/classes", excludes: fileExcludes)
+ def mainSrc = "${project.projectDir}/src/main/java"
+ println(mainSrc)
+ def ecSrc = fileTree(dir: "$project.buildDir", include: "**/*.ec")
+ def execSrc = fileTree(dir: "$project.buildDir", include: "**/*.exec")
+
+ doFirst {
+ def files = files([ecSrc, execSrc]).files
+ println "Creating Jacoco Report for ${files.size()} coverage files"
+ files.each { file -> println file }
+ }
+
+ sourceDirectories = files([mainSrc])
+ classDirectories = files([debugTree])
+ executionData = files([ecSrc, execSrc])
+} \ No newline at end of file
diff --git a/platform/android/scripts/exclude-activity-gen.json b/platform/android/scripts/exclude-activity-gen.json
index 9e0a1d154f..a6070edccf 100644
--- a/platform/android/scripts/exclude-activity-gen.json
+++ b/platform/android/scripts/exclude-activity-gen.json
@@ -48,5 +48,7 @@
"EspressoTestActivity",
"ChangeResourcesCachePathActivity",
"EspressoTestActivity",
- "FragmentBackStackActivity"
+ "FragmentBackStackActivity",
+ "ChildFragmentMapInDialogActivity",
+ "PerformanceMeasurementActivity"
]
diff --git a/platform/android/scripts/generate-style-code.js b/platform/android/scripts/generate-style-code.js
index 56e7511362..688a3aa527 100755
--- a/platform/android/scripts/generate-style-code.js
+++ b/platform/android/scripts/generate-style-code.js
@@ -197,7 +197,12 @@ global.defaultValueJava = function(property) {
case 'array':
switch (property.value) {
case 'string':
- return '[' + property['default'] + "]";
+ case 'enum':
+ if (property['default'] !== undefined) {
+ return '[' + property['default'] + ']';
+ } else {
+ return 'new String[0]';
+ }
case 'number':
var result ='new Float[] {';
for (var i = 0; i < property.length; i++) {
diff --git a/platform/android/scripts/parse-jacoco-report.py b/platform/android/scripts/parse-jacoco-report.py
new file mode 100755
index 0000000000..4d06fda6cc
--- /dev/null
+++ b/platform/android/scripts/parse-jacoco-report.py
@@ -0,0 +1,31 @@
+#!/usr/bin/python
+
+import os
+import re
+from io import open
+
+reportPath = os.getcwd() + "/platform/android/MapboxGLAndroidSDK/build/reports/jacoco/jacocoTestReport/jacocoTestReport.xml"
+with open(reportPath, 'r', encoding='utf-8') as jacocoReport:
+ line = jacocoReport.readline().strip()
+
+ # find the last INSTRUCTION coverage report which is a sum of all separate ones
+ instructionIndex = line.rfind('type="INSTRUCTION"')
+ startIndex = line.find('missed', instructionIndex)
+ endIndex = line.find('/>', startIndex)
+
+ # find the missed and covered lines counts
+ numbers = re.match(r'missed="(\d+)" covered="(\d+)"', line[startIndex:endIndex])
+ missed = int(numbers.group(1))
+ covered = int(numbers.group(2))
+
+ # calculate the code coverage percentage
+ percentage = round(covered * 100.0 / (missed + covered), 2)
+ print("Android tests code coverage: %s%%" % (str(percentage)))
+
+ # invoke the script that send the data to s3
+ testEnvironment = "LOCAL"
+ if os.environ.get('IS_LOCAL_DEVELOPMENT').lower()=='false':
+ testEnvironment = "CI"
+
+ cmd = os.getcwd() + ("/scripts/code-coverage.sh %.2f %s %s" % (percentage, "Android", testEnvironment))
+ os.system(cmd)
diff --git a/platform/android/scripts/validate-license.py b/platform/android/scripts/validate-license.py
new file mode 100644
index 0000000000..365d7ac265
--- /dev/null
+++ b/platform/android/scripts/validate-license.py
@@ -0,0 +1,17 @@
+#!/usr/bin/python
+
+from subprocess import call
+from subprocess import Popen, PIPE
+import sys
+
+## Run license generation
+call('cd ../../ && make android-license', shell=True)
+
+## Git diff changes
+p = Popen(['git', 'diff', '--name-only', 'LICENSE.md'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
+output, err = p.communicate(b"input data that is passed to subprocess' stdin")
+if "platform/android/LICENSE.md" in output:
+ raise ValueError("""An error ocurred while validating the license generation.
+ Changes were detected to the license generation output
+ but weren't commited. Run make android-license and
+ commit the changeset to make this validation pass.""") \ No newline at end of file
diff --git a/platform/android/src/conversion/constant.hpp b/platform/android/src/conversion/constant.hpp
index 4def670f3c..839e6e84dc 100644
--- a/platform/android/src/conversion/constant.hpp
+++ b/platform/android/src/conversion/constant.hpp
@@ -88,6 +88,17 @@ struct Converter<jni::Local<jni::Object<>>, T, typename std::enable_if_t<std::is
}
};
+template <class T>
+struct Converter<jni::Local<jni::Object<>>, std::vector<T>, typename std::enable_if_t<std::is_enum<T>::value>> {
+ Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const std::vector<T>& value) const {
+ auto result = jni::Array<jni::String>::New(env, value.size());
+ for (std::size_t i = 0; i < value.size(); ++i) {
+ result.Set(env, i, jni::Make<jni::String>(env, Enum<T>::toString(value.at(i))));
+ }
+ return result;
+ }
+};
+
} // namespace conversion
} // namespace android
} // namespace mbgl
diff --git a/platform/android/src/file_source.cpp b/platform/android/src/file_source.cpp
index 4cfb545b84..41081cd0fb 100644
--- a/platform/android/src/file_source.cpp
+++ b/platform/android/src/file_source.cpp
@@ -3,6 +3,7 @@
#include <mbgl/actor/actor.hpp>
#include <mbgl/actor/scheduler.hpp>
+#include <mbgl/storage/resource_options.hpp>
#include <mbgl/storage/resource_transform.hpp>
#include <mbgl/util/logging.hpp>
@@ -11,6 +12,14 @@
#include "asset_manager_file_source.hpp"
namespace mbgl {
+
+std::shared_ptr<FileSource> FileSource::createPlatformFileSource(const ResourceOptions& options) {
+ auto* assetFileSource = reinterpret_cast<AssetManagerFileSource*>(options.platformContext());
+ auto fileSource = std::make_shared<DefaultFileSource>(options.cachePath(), std::unique_ptr<AssetManagerFileSource>(assetFileSource));
+ fileSource->setAccessToken(options.accessToken());
+ return fileSource;
+}
+
namespace android {
// FileSource //
@@ -22,15 +31,13 @@ FileSource::FileSource(jni::JNIEnv& _env,
std::string path = jni::Make<std::string>(_env, _cachePath);
mapbox::sqlite::setTempPath(path);
- // Create a core default file source
- fileSource = std::make_unique<mbgl::DefaultFileSource>(
- path + DATABASE_FILE,
- std::make_unique<AssetManagerFileSource>(_env, assetManager));
+ resourceOptions
+ .withAccessToken(accessToken ? jni::Make<std::string>(_env, accessToken) : "")
+ .withCachePath(path + DATABASE_FILE)
+ .withPlatformContext(reinterpret_cast<void*>(new AssetManagerFileSource(_env, assetManager)));
- // Set access token
- if (accessToken) {
- fileSource->setAccessToken(jni::Make<std::string>(_env, accessToken));
- }
+ // Create a core default file source
+ fileSource = std::static_pointer_cast<mbgl::DefaultFileSource>(mbgl::FileSource::getSharedFileSource(resourceOptions));
}
FileSource::~FileSource() {
@@ -110,10 +117,10 @@ FileSource* FileSource::getNativePeer(jni::JNIEnv& env, const jni::Object<FileSo
return reinterpret_cast<FileSource *>(jFileSource.Get(env, field));
}
-mbgl::DefaultFileSource& FileSource::getDefaultFileSource(jni::JNIEnv& env, const jni::Object<FileSource>& jFileSource) {
+mbgl::ResourceOptions FileSource::getSharedResourceOptions(jni::JNIEnv& env, const jni::Object<FileSource>& jFileSource) {
FileSource* fileSource = FileSource::getNativePeer(env, jFileSource);
assert(fileSource != nullptr);
- return *fileSource->fileSource;
+ return fileSource->resourceOptions.clone();
}
void FileSource::registerNative(jni::JNIEnv& env) {
diff --git a/platform/android/src/file_source.hpp b/platform/android/src/file_source.hpp
index 575702120e..3001a5e0f0 100644
--- a/platform/android/src/file_source.hpp
+++ b/platform/android/src/file_source.hpp
@@ -1,6 +1,7 @@
#pragma once
#include <mbgl/storage/default_file_source.hpp>
+#include <mbgl/storage/resource_options.hpp>
#include "asset_manager.hpp"
@@ -49,15 +50,16 @@ public:
static FileSource* getNativePeer(jni::JNIEnv&, const jni::Object<FileSource>&);
- static mbgl::DefaultFileSource& getDefaultFileSource(jni::JNIEnv&, const jni::Object<FileSource>&);
+ static mbgl::ResourceOptions getSharedResourceOptions(jni::JNIEnv&, const jni::Object<FileSource>&);
static void registerNative(jni::JNIEnv&);
private:
const std::string DATABASE_FILE = "/mbgl-offline.db";
optional<int> activationCounter;
+ mbgl::ResourceOptions resourceOptions;
std::unique_ptr<Actor<ResourceTransform>> resourceTransform;
- std::unique_ptr<mbgl::DefaultFileSource> fileSource;
+ std::shared_ptr<mbgl::DefaultFileSource> fileSource;
};
diff --git a/platform/android/src/map_renderer.hpp b/platform/android/src/map_renderer.hpp
index 3e5b99605e..57265cebb1 100644
--- a/platform/android/src/map_renderer.hpp
+++ b/platform/android/src/map_renderer.hpp
@@ -1,13 +1,15 @@
#pragma once
+#include <mbgl/actor/actor_ref.hpp>
#include <mbgl/actor/scheduler.hpp>
#include <mbgl/util/image.hpp>
+#include <mbgl/util/optional.hpp>
#include <memory>
+#include <mutex>
#include <utility>
#include <jni/jni.hpp>
-#include <mbgl/storage/default_file_source.hpp>
namespace mbgl {
diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp
index 3a4e2014ba..e74e4c3bbc 100755
--- a/platform/android/src/native_map_view.cpp
+++ b/platform/android/src/native_map_view.cpp
@@ -13,6 +13,7 @@
#include <jni/jni.hpp>
+#include <mbgl/map/map.hpp>
#include <mbgl/map/map_options.hpp>
#include <mbgl/math/minmax.hpp>
#include <mbgl/util/constants.hpp>
@@ -74,24 +75,22 @@ NativeMapView::NativeMapView(jni::JNIEnv& _env,
return;
}
- // Get native peer for file source
- mbgl::FileSource& fileSource = mbgl::android::FileSource::getDefaultFileSource(_env, jFileSource);
-
// Create a renderer frontend
rendererFrontend = std::make_unique<AndroidRendererFrontend>(mapRenderer);
// Create Map options
MapOptions options;
options.withMapMode(MapMode::Continuous)
+ .withSize(mbgl::Size{ static_cast<uint32_t>(width), static_cast<uint32_t>(height) })
+ .withPixelRatio(pixelRatio)
.withConstrainMode(ConstrainMode::HeightOnly)
.withViewportMode(ViewportMode::Default)
.withCrossSourceCollisions(_crossSourceCollisions);
// Create the core map
- map = std::make_unique<mbgl::Map>(*rendererFrontend, *this,
- mbgl::Size{ static_cast<uint32_t>(width),
- static_cast<uint32_t>(height) }, pixelRatio,
- fileSource, *threadPool, options);
+ map = std::make_unique<mbgl::Map>(
+ *rendererFrontend, *this, *threadPool, options,
+ mbgl::android::FileSource::getSharedResourceOptions(_env, jFileSource));
}
/**
diff --git a/platform/android/src/native_map_view.hpp b/platform/android/src/native_map_view.hpp
index d695a91ce0..903543e5d1 100755
--- a/platform/android/src/native_map_view.hpp
+++ b/platform/android/src/native_map_view.hpp
@@ -6,7 +6,6 @@
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/default_thread_pool.hpp>
#include <mbgl/util/run_loop.hpp>
-#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/storage/network_status.hpp>
#include "annotation/marker.hpp"
diff --git a/platform/android/src/offline/offline_manager.cpp b/platform/android/src/offline/offline_manager.cpp
index 968c33b644..54b1142845 100644
--- a/platform/android/src/offline/offline_manager.cpp
+++ b/platform/android/src/offline/offline_manager.cpp
@@ -10,20 +10,19 @@ namespace android {
// OfflineManager //
OfflineManager::OfflineManager(jni::JNIEnv& env, const jni::Object<FileSource>& jFileSource)
- : fileSource(mbgl::android::FileSource::getDefaultFileSource(env, jFileSource)) {
-}
+ : fileSource(std::static_pointer_cast<DefaultFileSource>(mbgl::FileSource::getSharedFileSource(FileSource::getSharedResourceOptions(env, jFileSource)))) {}
OfflineManager::~OfflineManager() {}
void OfflineManager::setOfflineMapboxTileCountLimit(jni::JNIEnv&, jni::jlong limit) {
- fileSource.setOfflineMapboxTileCountLimit(limit);
+ fileSource->setOfflineMapboxTileCountLimit(limit);
}
void OfflineManager::listOfflineRegions(jni::JNIEnv& env_, const jni::Object<FileSource>& jFileSource_, const jni::Object<ListOfflineRegionsCallback>& callback_) {
auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_);
auto globalFilesource = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, jFileSource_);
- fileSource.listOfflineRegions([
+ fileSource->listOfflineRegions([
//Keep a shared ptr to a global reference of the callback and file source so they are not GC'd in the meanwhile
callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback)),
jFileSource = std::make_shared<decltype(globalFilesource)>(std::move(globalFilesource))
@@ -59,7 +58,7 @@ void OfflineManager::createOfflineRegion(jni::JNIEnv& env_,
auto globalFilesource = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, jFileSource_);
// Create region
- fileSource.createOfflineRegion(definition, metadata, [
+ fileSource->createOfflineRegion(definition, metadata, [
//Keep a shared ptr to a global reference of the callback and file source so they are not GC'd in the meanwhile
callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback)),
jFileSource = std::make_shared<decltype(globalFilesource)>(std::move(globalFilesource))
@@ -86,7 +85,7 @@ void OfflineManager::mergeOfflineRegions(jni::JNIEnv& env_, const jni::Object<Fi
auto globalFilesource = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, jFileSource_);
auto path = jni::Make<std::string>(env_, jString_);
- fileSource.mergeOfflineRegions(path, [
+ fileSource->mergeOfflineRegions(path, [
//Keep a shared ptr to a global reference of the callback and file source so they are not GC'd in the meanwhile
callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback)),
jFileSource = std::make_shared<decltype(globalFilesource)>(std::move(globalFilesource))
@@ -226,7 +225,7 @@ void OfflineManager::putResourceWithUrl(jni::JNIEnv& env,
response.expires = Timestamp(mbgl::Seconds(expires));
}
- fileSource.put(resource, response);
+ fileSource->put(resource, response);
}
} // namespace android
diff --git a/platform/android/src/offline/offline_manager.hpp b/platform/android/src/offline/offline_manager.hpp
index f8d57b88da..d0b637b900 100644
--- a/platform/android/src/offline/offline_manager.hpp
+++ b/platform/android/src/offline/offline_manager.hpp
@@ -1,7 +1,5 @@
#pragma once
-
-#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/storage/offline.hpp>
#include <jni/jni.hpp>
@@ -10,8 +8,12 @@
#include "offline_region_definition.hpp"
#include "../java_types.hpp"
+#include <memory>
namespace mbgl {
+
+class DefaultFileSource;
+
namespace android {
class OfflineManager {
@@ -85,7 +87,7 @@ public:
private:
- mbgl::DefaultFileSource& fileSource;
+ std::shared_ptr<mbgl::DefaultFileSource> fileSource;
};
} // namespace android
diff --git a/platform/android/src/offline/offline_region.cpp b/platform/android/src/offline/offline_region.cpp
index 1cd73a7c76..e0f28631b4 100644
--- a/platform/android/src/offline/offline_region.cpp
+++ b/platform/android/src/offline/offline_region.cpp
@@ -14,8 +14,8 @@ namespace android {
// OfflineRegion //
OfflineRegion::OfflineRegion(jni::JNIEnv& env, jni::jlong offlineRegionPtr, const jni::Object<FileSource>& jFileSource)
- : region(reinterpret_cast<mbgl::OfflineRegion *>(offlineRegionPtr)),
- fileSource(mbgl::android::FileSource::getDefaultFileSource(env, jFileSource)) {}
+ : region(reinterpret_cast<mbgl::OfflineRegion *>(offlineRegionPtr))
+ , fileSource(std::static_pointer_cast<DefaultFileSource>(mbgl::FileSource::getSharedFileSource(FileSource::getSharedResourceOptions(env, jFileSource)))) {}
OfflineRegion::~OfflineRegion() {}
@@ -62,7 +62,7 @@ void OfflineRegion::setOfflineRegionObserver(jni::JNIEnv& env_, const jni::Objec
};
// Set the observer
- fileSource.setOfflineRegionObserver(*region, std::make_unique<Observer>(jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback)));
+ fileSource->setOfflineRegionObserver(*region, std::make_unique<Observer>(jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback)));
}
void OfflineRegion::setOfflineRegionDownloadState(jni::JNIEnv&, jni::jint jState) {
@@ -80,13 +80,13 @@ void OfflineRegion::setOfflineRegionDownloadState(jni::JNIEnv&, jni::jint jState
return;
}
- fileSource.setOfflineRegionDownloadState(*region, state);
+ fileSource->setOfflineRegionDownloadState(*region, state);
}
void OfflineRegion::getOfflineRegionStatus(jni::JNIEnv& env_, const jni::Object<OfflineRegionStatusCallback>& callback_) {
auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_);
- fileSource.getOfflineRegionStatus(*region, [
+ fileSource->getOfflineRegionStatus(*region, [
//Ensure the object is not gc'd in the meanwhile
callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback))
](mbgl::expected<mbgl::OfflineRegionStatus, std::exception_ptr> status) mutable {
@@ -104,7 +104,7 @@ void OfflineRegion::getOfflineRegionStatus(jni::JNIEnv& env_, const jni::Object<
void OfflineRegion::deleteOfflineRegion(jni::JNIEnv& env_, const jni::Object<OfflineRegionDeleteCallback>& callback_) {
auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_);
- fileSource.deleteOfflineRegion(std::move(*region), [
+ fileSource->deleteOfflineRegion(std::move(*region), [
//Ensure the object is not gc'd in the meanwhile
callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback))
](std::exception_ptr error) mutable {
@@ -123,7 +123,7 @@ void OfflineRegion::updateOfflineRegionMetadata(jni::JNIEnv& env_, const jni::Ar
auto metadata = OfflineRegion::metadata(env_, jMetadata);
auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_);
- fileSource.updateOfflineMetadata(region->getID(), metadata, [
+ fileSource->updateOfflineMetadata(region->getID(), metadata, [
//Ensure the object is not gc'd in the meanwhile
callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback))
](mbgl::expected<mbgl::OfflineRegionMetadata, std::exception_ptr> data) mutable {
diff --git a/platform/android/src/offline/offline_region.hpp b/platform/android/src/offline/offline_region.hpp
index 49fa0c8ff8..4618e1abbd 100644
--- a/platform/android/src/offline/offline_region.hpp
+++ b/platform/android/src/offline/offline_region.hpp
@@ -74,7 +74,7 @@ public:
private:
std::unique_ptr<mbgl::OfflineRegion> region;
- mbgl::DefaultFileSource& fileSource;
+ std::shared_ptr<mbgl::DefaultFileSource> fileSource;
};
} // namespace android
diff --git a/platform/android/src/snapshotter/map_snapshotter.cpp b/platform/android/src/snapshotter/map_snapshotter.cpp
index 8eb1d02605..47a2781cb5 100644
--- a/platform/android/src/snapshotter/map_snapshotter.cpp
+++ b/platform/android/src/snapshotter/map_snapshotter.cpp
@@ -37,7 +37,6 @@ MapSnapshotter::MapSnapshotter(jni::JNIEnv& _env,
}
jFileSource = FileSource::getNativePeer(_env, _jFileSource);
- auto& fileSource = mbgl::android::FileSource::getDefaultFileSource(_env, _jFileSource);
auto size = mbgl::Size { static_cast<uint32_t>(width), static_cast<uint32_t>(height) };
optional<mbgl::CameraOptions> cameraOptions;
@@ -56,11 +55,10 @@ MapSnapshotter::MapSnapshotter(jni::JNIEnv& _env,
} else {
style = std::make_pair(false, jni::Make<std::string>(_env, styleURL));
}
-
+
showLogo = _showLogo;
// Create the core snapshotter
- snapshotter = std::make_unique<mbgl::MapSnapshotter>(&fileSource,
- threadPool,
+ snapshotter = std::make_unique<mbgl::MapSnapshotter>(threadPool,
style,
size,
pixelRatio,
@@ -69,8 +67,8 @@ MapSnapshotter::MapSnapshotter(jni::JNIEnv& _env,
jni::Make<std::string>(_env, _programCacheDir),
_localIdeographFontFamily ?
jni::Make<std::string>(_env, _localIdeographFontFamily) :
- optional<std::string>{});
-
+ optional<std::string>{},
+ mbgl::android::FileSource::getSharedResourceOptions(_env, _jFileSource));
}
MapSnapshotter::~MapSnapshotter() = default;
diff --git a/platform/android/src/style/layers/symbol_layer.cpp b/platform/android/src/style/layers/symbol_layer.cpp
index 61e4d59326..810848e9cb 100644
--- a/platform/android/src/style/layers/symbol_layer.cpp
+++ b/platform/android/src/style/layers/symbol_layer.cpp
@@ -176,6 +176,16 @@ namespace android {
return std::move(*convert<jni::Local<jni::Object<>>>(env, toSymbolLayer(layer).getTextJustify()));
}
+ jni::Local<jni::Object<>> SymbolLayer::getTextRadialOffset(jni::JNIEnv& env) {
+ using namespace mbgl::android::conversion;
+ return std::move(*convert<jni::Local<jni::Object<>>>(env, toSymbolLayer(layer).getTextRadialOffset()));
+ }
+
+ jni::Local<jni::Object<>> SymbolLayer::getTextVariableAnchor(jni::JNIEnv& env) {
+ using namespace mbgl::android::conversion;
+ return std::move(*convert<jni::Local<jni::Object<>>>(env, toSymbolLayer(layer).getTextVariableAnchor()));
+ }
+
jni::Local<jni::Object<>> SymbolLayer::getTextAnchor(jni::JNIEnv& env) {
using namespace mbgl::android::conversion;
return std::move(*convert<jni::Local<jni::Object<>>>(env, toSymbolLayer(layer).getTextAnchor()));
@@ -514,6 +524,8 @@ namespace android {
METHOD(&SymbolLayer::getTextLineHeight, "nativeGetTextLineHeight"),
METHOD(&SymbolLayer::getTextLetterSpacing, "nativeGetTextLetterSpacing"),
METHOD(&SymbolLayer::getTextJustify, "nativeGetTextJustify"),
+ METHOD(&SymbolLayer::getTextRadialOffset, "nativeGetTextRadialOffset"),
+ METHOD(&SymbolLayer::getTextVariableAnchor, "nativeGetTextVariableAnchor"),
METHOD(&SymbolLayer::getTextAnchor, "nativeGetTextAnchor"),
METHOD(&SymbolLayer::getTextMaxAngle, "nativeGetTextMaxAngle"),
METHOD(&SymbolLayer::getTextRotate, "nativeGetTextRotate"),
diff --git a/platform/android/src/style/layers/symbol_layer.hpp b/platform/android/src/style/layers/symbol_layer.hpp
index f52597ef6f..3b0f8ee5d1 100644
--- a/platform/android/src/style/layers/symbol_layer.hpp
+++ b/platform/android/src/style/layers/symbol_layer.hpp
@@ -80,6 +80,10 @@ public:
jni::Local<jni::Object<jni::ObjectTag>> getTextJustify(jni::JNIEnv&);
+ jni::Local<jni::Object<jni::ObjectTag>> getTextRadialOffset(jni::JNIEnv&);
+
+ jni::Local<jni::Object<jni::ObjectTag>> getTextVariableAnchor(jni::JNIEnv&);
+
jni::Local<jni::Object<jni::ObjectTag>> getTextAnchor(jni::JNIEnv&);
jni::Local<jni::Object<jni::ObjectTag>> getTextMaxAngle(jni::JNIEnv&);
diff --git a/platform/android/vendor/mapbox-events-android b/platform/android/vendor/mapbox-events-android
-Subproject 1636d1ae9d5b0f0dd2367c8f32f1af958640b14
+Subproject 5bdf0d90292fb46cd8b1f795763d281b5ac83e0
diff --git a/platform/darwin/docs/guides/For Style Authors.md.ejs b/platform/darwin/docs/guides/For Style Authors.md.ejs
index cf0f79f419..8df541d0f7 100644
--- a/platform/darwin/docs/guides/For Style Authors.md.ejs
+++ b/platform/darwin/docs/guides/For Style Authors.md.ejs
@@ -431,5 +431,16 @@ In style JSON | In the format string
`["any", f0, …, fn]` | `p0 OR … OR pn`
`["none", f0, …, fn]` | `NOT (p0 OR … OR pn)`
+## Specifying the text format
+
+The following format attributes are defined as `NSString` constans that you
+can use to update the formatting of `MGLSymbolStyleLayer.text` property.
+
+In style JSON | In Objective-C | In Swift
+--------------|-----------------------|---------
+`text-font` | `MGLFontNamesAttribute` | `.fontNamesAttribute`
+`font-scale` | `MGLFontScaleAttribute` | `.fontScaleAttribute`
+`text-color` | `MGLFontColorAttribute` | `.fontColorAttribute`
+
See the “[Predicates and Expressions](predicates-and-expressions.html)” guide for
a full description of the supported operators and operand types.
diff --git a/platform/darwin/docs/guides/Predicates and Expressions.md b/platform/darwin/docs/guides/Predicates and Expressions.md
index 5f5d9a22a8..b2e01b94db 100644
--- a/platform/darwin/docs/guides/Predicates and Expressions.md
+++ b/platform/darwin/docs/guides/Predicates and Expressions.md
@@ -546,6 +546,14 @@ operator in the Mapbox Style Specification.
Concatenates and returns the array of `MGLAttributedExpression` objects, for use
with the `MGLSymbolStyleLayer.text` property.
+`MGLAttributedExpression.attributes` valid attributes.
+
+ Key | Value Type
+ --- | ---
+ `MGLFontNamesAttribute` | An `NSExpression` evaluating to an `NSString` array.
+ `MGLFontScaleAttribute` | An `NSExpression` evaluating to an `NSNumber` value.
+ `MGLFontColorAttribute` | An `NSExpression` evaluating to an `UIColor` (iOS) or `NSColor` (macOS).
+
This function corresponds to the
[`format`](https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-types-format)
operator in the Mapbox Style Specification.
diff --git a/platform/darwin/filesource-files.json b/platform/darwin/filesource-files.json
index 3ee96f9b95..b2e6fbc9b4 100644
--- a/platform/darwin/filesource-files.json
+++ b/platform/darwin/filesource-files.json
@@ -4,6 +4,7 @@
"platform/darwin/src/MGLLoggingConfiguration.m",
"platform/darwin/src/MGLNetworkConfiguration.m",
"platform/darwin/src/http_file_source.mm",
+ "platform/default/src/mbgl/storage/file_source.cpp",
"platform/default/src/mbgl/storage/sqlite3.cpp"
],
"public_headers": {},
diff --git a/platform/darwin/scripts/generate-style-code.js b/platform/darwin/scripts/generate-style-code.js
index a8bdec7865..2eabd0a92b 100755
--- a/platform/darwin/scripts/generate-style-code.js
+++ b/platform/darwin/scripts/generate-style-code.js
@@ -137,6 +137,8 @@ global.objCTestValue = function (property, layerType, arraysAsStructs, indent) {
}
return '@"{1, 1}"';
}
+ case 'anchor':
+ return `@"{'top','bottom'}"`;
default:
throw new Error(`unknown array type for ${property.name}`);
}
@@ -185,6 +187,8 @@ global.mbglTestValue = function (property, layerType) {
case 'offset':
case 'translate':
return '{ 1, 1 }';
+ case 'anchor':
+ return '{ mbgl::style::SymbolAnchorType::Top, mbgl::style::SymbolAnchorType::Bottom }';
default:
throw new Error(`unknown array type for ${property.name}`);
}
@@ -200,6 +204,13 @@ global.mbglExpressionTestValue = function (property, layerType) {
return `"${_.last(_.keys(property.values))}"`;
case 'color':
return 'mbgl::Color(1, 0, 0, 1)';
+ case 'array':
+ switch (arrayType(property)) {
+ case 'anchor':
+ return `{"top", "bottom"}`;
+ default:
+ break;
+ }
default:
return global.mbglTestValue(property, layerType);
}
@@ -341,6 +352,9 @@ global.propertyDoc = function (propertyName, property, layerType, kind) {
if (property.type === 'enum') {
doc += '* Any of the following constant string values:\n';
doc += Object.keys(property.values).map(value => ' * `' + value + '`: ' + property.values[value].doc).join('\n') + '\n';
+ } else if (property.type === 'array' && property.value === 'enum') {
+ doc += '* Constant array, whose each element is any of the following constant string values:\n';
+ doc += Object.keys(property.values).map(value => ' * `' + value + '`: ' + property.values[value].doc).join('\n') + '\n';
}
doc += '* Predefined functions, including mathematical and string operators\n' +
'* Conditional expressions\n' +
@@ -415,6 +429,8 @@ global.describeType = function (property) {
return '`CGVector`';
case 'position':
return '`MGLSphericalPosition`';
+ case 'anchor':
+ return '`MGLTextAnchor` array';
default:
return 'array';
}
@@ -539,11 +555,12 @@ global.propertyType = function (property) {
case 'font':
return 'NSArray<NSString *> *';
case 'padding':
- return 'NSValue *';
case 'position':
case 'offset':
case 'translate':
return 'NSValue *';
+ case 'anchor':
+ return 'NSArray<NSValue *> *';
default:
throw new Error(`unknown array type for ${property.name}`);
}
@@ -588,6 +605,8 @@ global.valueTransformerArguments = function (property) {
case 'offset':
case 'translate':
return ['std::array<float, 2>', objCType];
+ case 'anchor':
+ return ['std::vector<mbgl::style::SymbolAnchorType>', objCType, 'mbgl::style::SymbolAnchorType', 'MGLTextAnchor'];
default:
throw new Error(`unknown array type for ${property.name}`);
}
@@ -637,6 +656,8 @@ global.mbglType = function(property) {
return 'std::array<float, 2>';
case 'position':
return 'mbgl::style::Position';
+ case 'anchor':
+ return 'std::vector<mbgl::style::SymbolAnchorType>';
default:
throw new Error(`unknown array type for ${property.name}`);
}
diff --git a/platform/darwin/src/MGLAttributedExpression.h b/platform/darwin/src/MGLAttributedExpression.h
index aa5d51c66e..ea298c7a44 100644
--- a/platform/darwin/src/MGLAttributedExpression.h
+++ b/platform/darwin/src/MGLAttributedExpression.h
@@ -2,14 +2,33 @@
NS_ASSUME_NONNULL_BEGIN
-typedef NSString * MGLAttributedExpressionKey NS_EXTENSIBLE_STRING_ENUM;
+/** Options for `MGLAttributedExpression.attributes`. */
+typedef NSString * MGLAttributedExpressionKey NS_TYPED_ENUM;
+/** The font name string array expression used to format the text. */
FOUNDATION_EXTERN MGL_EXPORT MGLAttributedExpressionKey const MGLFontNamesAttribute;
-FOUNDATION_EXTERN MGL_EXPORT MGLAttributedExpressionKey const MGLFontSizeAttribute;
+
+/** The font scale number expression relative to `MGLSymbolStyleLayer.textFontSize` used to format the text. */
+FOUNDATION_EXTERN MGL_EXPORT MGLAttributedExpressionKey const MGLFontScaleAttribute;
+
+/** The font color expression used to format the text. */
+FOUNDATION_EXTERN MGL_EXPORT MGLAttributedExpressionKey const MGLFontColorAttribute;
/**
An `MGLAttributedExpression` object associates text formatting attibutes (such as font size or
font names) to an `NSExpression`.
+
+ ### Example
+ ```swift
+ let redColor = UIColor.red
+ let expression = NSExpression(forConstantValue: "Foo")
+ let attributes: [MGLAttributedExpressionKey: NSExpression] = [.fontNamesAttribute : NSExpression(forConstantValue: ["DIN Offc Pro Italic",
+ "Arial Unicode MS Regular"]),
+ .fontScaleAttribute: NSExpression(forConstantValue: 1.2),
+ .fontColorAttribute: NSExpression(forConstantValue: redColor)]
+ let attributedExpression = MGLAttributedExpression(expression, attributes:attributes)
+ ```
+
*/
MGL_EXPORT
@interface MGLAttributedExpression : NSObject
@@ -19,10 +38,29 @@ MGL_EXPORT
*/
@property (strong, nonatomic) NSExpression *expression;
+#if TARGET_OS_IPHONE
+/**
+ The formatting attributes dictionary.
+ Key | Value Type
+ --- | ---
+ `MGLFontNamesAttribute` | An `NSExpression` evaluating to an `NSString` array.
+ `MGLFontScaleAttribute` | An `NSExpression` evaluating to an `NSNumber` value.
+ `MGLFontColorAttribute` | An `NSExpression` evaluating to an `UIColor`.
+
+ */
+@property (strong, nonatomic, readonly) NSDictionary<MGLAttributedExpressionKey, NSExpression *> *attributes;
+#else
/**
- The formatting attributes.
+ The formatting attributes dictionary.
+ Key | Value Type
+ --- | ---
+ `MGLFontNamesAttribute` | An `NSExpression` evaluating to an `NSString` array.
+ `MGLFontScaleAttribute` | An `NSExpression` evaluating to an `NSNumber` value.
+ `MGLFontColorAttribute` | An `NSExpression` evaluating to an `NSColor` on macos.
*/
-@property (strong, nonatomic, readonly) NSDictionary<MGLAttributedExpressionKey, id> *attributes;
+@property (strong, nonatomic, readonly) NSDictionary<MGLAttributedExpressionKey, NSExpression *> *attributes;
+#endif
+
/**
Returns an `MGLAttributedExpression` object initialized with an expression and no attribute information.
@@ -32,12 +70,17 @@ MGL_EXPORT
/**
Returns an `MGLAttributedExpression` object initialized with an expression and text format attributes.
*/
-- (instancetype)initWithExpression:(NSExpression *)expression attributes:(nullable NSDictionary <MGLAttributedExpressionKey, id> *)attrs;
+- (instancetype)initWithExpression:(NSExpression *)expression attributes:(nonnull NSDictionary <MGLAttributedExpressionKey, NSExpression *> *)attrs;
/**
Creates an `MGLAttributedExpression` object initialized with an expression and the format attributes for font names and font size.
*/
-+ (instancetype)attributedExpression:(NSExpression *)expression fontNames:(nullable NSArray<NSString*> *)fontNames fontSize:(nullable NSNumber *)fontSize;
++ (instancetype)attributedExpression:(NSExpression *)expression fontNames:(nullable NSArray<NSString*> *)fontNames fontScale:(nullable NSNumber *)fontScale;
+
+/**
+ Creates an `MGLAttributedExpression` object initialized with an expression and the format attributes dictionary.
+ */
++ (instancetype)attributedExpression:(NSExpression *)expression attributes:(nonnull NSDictionary <MGLAttributedExpressionKey, NSExpression *> *)attrs;
@end
diff --git a/platform/darwin/src/MGLAttributedExpression.m b/platform/darwin/src/MGLAttributedExpression.m
index 715f74e42f..a34480a957 100644
--- a/platform/darwin/src/MGLAttributedExpression.m
+++ b/platform/darwin/src/MGLAttributedExpression.m
@@ -2,33 +2,42 @@
#import "MGLLoggingConfiguration_Private.h"
const MGLAttributedExpressionKey MGLFontNamesAttribute = @"text-font";
-const MGLAttributedExpressionKey MGLFontSizeAttribute = @"font-scale";
+const MGLAttributedExpressionKey MGLFontScaleAttribute = @"font-scale";
+const MGLAttributedExpressionKey MGLFontColorAttribute = @"text-color";
@implementation MGLAttributedExpression
- (instancetype)initWithExpression:(NSExpression *)expression {
- self = [self initWithExpression:expression attributes:nil];
+ self = [self initWithExpression:expression attributes:@{}];
return self;
}
-+ (instancetype)attributedExpression:(NSExpression *)expression fontNames:(nullable NSArray<NSString *> *)fontNames fontSize:(nullable NSNumber *)fontSize {
++ (instancetype)attributedExpression:(NSExpression *)expression fontNames:(nullable NSArray<NSString *> *)fontNames fontScale:(nullable NSNumber *)fontScale {
MGLAttributedExpression *attributedExpression;
NSMutableDictionary *attrs = [NSMutableDictionary dictionary];
if (fontNames && fontNames.count > 0) {
- attrs[MGLFontNamesAttribute] = fontNames;
+ attrs[MGLFontNamesAttribute] = [NSExpression expressionForConstantValue:fontNames];
}
- if (fontSize) {
- attrs[MGLFontSizeAttribute] = fontSize;
+ if (fontScale) {
+ attrs[MGLFontScaleAttribute] = [NSExpression expressionForConstantValue:fontScale];
}
attributedExpression = [[self alloc] initWithExpression:expression attributes:attrs];
return attributedExpression;
}
-- (instancetype)initWithExpression:(NSExpression *)expression attributes:(NSDictionary<MGLAttributedExpressionKey,id> *)attrs {
++ (instancetype)attributedExpression:(NSExpression *)expression attributes:(nonnull NSDictionary<MGLAttributedExpressionKey, NSExpression *> *)attrs {
+ MGLAttributedExpression *attributedExpression;
+
+ attributedExpression = [[self alloc] initWithExpression:expression attributes:attrs];
+
+ return attributedExpression;
+}
+
+- (instancetype)initWithExpression:(NSExpression *)expression attributes:(nonnull NSDictionary<MGLAttributedExpressionKey, NSExpression *> *)attrs {
if (self = [super init])
{
MGLLogInfo(@"Starting %@ initialization.", NSStringFromClass([self class]));
diff --git a/platform/darwin/src/MGLLoggingConfiguration.h b/platform/darwin/src/MGLLoggingConfiguration.h
index 6782dc60a7..d79336df4c 100644
--- a/platform/darwin/src/MGLLoggingConfiguration.h
+++ b/platform/darwin/src/MGLLoggingConfiguration.h
@@ -4,7 +4,7 @@
#ifndef MGL_LOGGING_DISABLED
#ifndef MGL_LOGGING_ENABLE_DEBUG
- #ifdef DEBUG
+ #ifndef NDEBUG
#define MGL_LOGGING_ENABLE_DEBUG 1
#endif
#endif
diff --git a/platform/darwin/src/MGLMapSnapshotter.mm b/platform/darwin/src/MGLMapSnapshotter.mm
index 3918008b78..171f24e4d0 100644
--- a/platform/darwin/src/MGLMapSnapshotter.mm
+++ b/platform/darwin/src/MGLMapSnapshotter.mm
@@ -3,8 +3,10 @@
#import <mbgl/actor/actor.hpp>
#import <mbgl/actor/scheduler.hpp>
#import <mbgl/util/geo.hpp>
+#import <mbgl/map/map_options.hpp>
#import <mbgl/map/map_snapshotter.hpp>
#import <mbgl/map/camera.hpp>
+#import <mbgl/storage/resource_options.hpp>
#import <mbgl/storage/default_file_source.hpp>
#import <mbgl/util/default_thread_pool.hpp>
#import <mbgl/util/string.hpp>
@@ -587,7 +589,9 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
_cancelled = NO;
_options = options;
- mbgl::DefaultFileSource *mbglFileSource = [MGLOfflineStorage sharedOfflineStorage].mbglFileSource;
+
+ auto mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource];
+
_mbglThreadPool = mbgl::sharedThreadPool();
std::string styleURL = std::string([options.styleURL.absoluteString UTF8String]);
@@ -619,9 +623,14 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
// App-global configuration
MGLRendererConfiguration* config = [MGLRendererConfiguration currentConfiguration];
-
+
+ mbgl::ResourceOptions resourceOptions;
+ resourceOptions.withCachePath([[MGLOfflineStorage sharedOfflineStorage] mbglCachePath])
+ .withAssetPath([NSBundle mainBundle].resourceURL.path.UTF8String);
+
// Create the snapshotter
- _mbglMapSnapshotter = std::make_unique<mbgl::MapSnapshotter>(mbglFileSource, _mbglThreadPool, style, size, pixelRatio, cameraOptions, coordinateBounds, config.cacheDir, config.localFontFamilyName);
+ _mbglMapSnapshotter = std::make_unique<mbgl::MapSnapshotter>(
+ _mbglThreadPool, style, size, pixelRatio, cameraOptions, coordinateBounds, config.cacheDir, config.localFontFamilyName, resourceOptions);
}
@end
diff --git a/platform/darwin/src/MGLOfflinePack.mm b/platform/darwin/src/MGLOfflinePack.mm
index a8f807374c..0f2e8180fa 100644
--- a/platform/darwin/src/MGLOfflinePack.mm
+++ b/platform/darwin/src/MGLOfflinePack.mm
@@ -10,6 +10,7 @@
#import "NSValue+MGLAdditions.h"
+#include <mbgl/map/map_options.hpp>
#include <mbgl/storage/default_file_source.hpp>
const MGLExceptionName MGLInvalidOfflinePackException = @"MGLInvalidOfflinePackException";
@@ -58,6 +59,7 @@ private:
@implementation MGLOfflinePack {
BOOL _isSuspending;
+ std::shared_ptr<mbgl::DefaultFileSource> _mbglFileSource;
}
- (instancetype)init {
@@ -74,8 +76,8 @@ private:
_mbglOfflineRegion = region;
_state = MGLOfflinePackStateUnknown;
- mbgl::DefaultFileSource *mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource];
- mbglFileSource->setOfflineRegionObserver(*_mbglOfflineRegion, std::make_unique<MBGLOfflineRegionObserver>(self));
+ _mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource];
+ _mbglFileSource->setOfflineRegionObserver(*_mbglOfflineRegion, std::make_unique<MBGLOfflineRegionObserver>(self));
}
return self;
}
@@ -115,8 +117,7 @@ private:
self.state = MGLOfflinePackStateActive;
- mbgl::DefaultFileSource *mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource];
- mbglFileSource->setOfflineRegionDownloadState(*_mbglOfflineRegion, mbgl::OfflineRegionDownloadState::Active);
+ _mbglFileSource->setOfflineRegionDownloadState(*_mbglOfflineRegion, mbgl::OfflineRegionDownloadState::Active);
}
- (void)suspend {
@@ -128,8 +129,7 @@ private:
_isSuspending = YES;
}
- mbgl::DefaultFileSource *mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource];
- mbglFileSource->setOfflineRegionDownloadState(*_mbglOfflineRegion, mbgl::OfflineRegionDownloadState::Inactive);
+ _mbglFileSource->setOfflineRegionDownloadState(*_mbglOfflineRegion, mbgl::OfflineRegionDownloadState::Inactive);
}
- (void)invalidate {
@@ -137,8 +137,7 @@ private:
MGLAssert(_state != MGLOfflinePackStateInvalid, @"Cannot invalidate an already invalid offline pack.");
self.state = MGLOfflinePackStateInvalid;
- mbgl::DefaultFileSource *mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource];
- mbglFileSource->setOfflineRegionObserver(*self.mbglOfflineRegion, nullptr);
+ _mbglFileSource->setOfflineRegionObserver(*self.mbglOfflineRegion, nullptr);
self.mbglOfflineRegion = nil;
}
@@ -164,10 +163,8 @@ private:
MGLLogInfo(@"Requesting pack progress.");
MGLAssertOfflinePackIsValid();
- mbgl::DefaultFileSource *mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource];
-
__weak MGLOfflinePack *weakSelf = self;
- mbglFileSource->getOfflineRegionStatus(*_mbglOfflineRegion, [&, weakSelf](mbgl::expected<mbgl::OfflineRegionStatus, std::exception_ptr> status) {
+ _mbglFileSource->getOfflineRegionStatus(*_mbglOfflineRegion, [&, weakSelf](mbgl::expected<mbgl::OfflineRegionStatus, std::exception_ptr> status) {
if (status) {
mbgl::OfflineRegionStatus checkedStatus = *status;
dispatch_async(dispatch_get_main_queue(), ^{
diff --git a/platform/darwin/src/MGLOfflinePack_Private.h b/platform/darwin/src/MGLOfflinePack_Private.h
index 8a63152dca..ea3fb2da99 100644
--- a/platform/darwin/src/MGLOfflinePack_Private.h
+++ b/platform/darwin/src/MGLOfflinePack_Private.h
@@ -1,6 +1,6 @@
#import "MGLOfflinePack.h"
-#include <mbgl/storage/default_file_source.hpp>
+#include <mbgl/storage/offline.hpp>
NS_ASSUME_NONNULL_BEGIN
diff --git a/platform/darwin/src/MGLOfflineStorage.mm b/platform/darwin/src/MGLOfflineStorage.mm
index 4613b402fd..6effd8c3ce 100644
--- a/platform/darwin/src/MGLOfflineStorage.mm
+++ b/platform/darwin/src/MGLOfflineStorage.mm
@@ -10,7 +10,6 @@
#import "NSBundle+MGLAdditions.h"
#import "NSValue+MGLAdditions.h"
#import "NSDate+MGLAdditions.h"
-#import "NSData+MGLAdditions.h"
#import "MGLLoggingConfiguration_Private.h"
#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
@@ -20,6 +19,8 @@
#include <mbgl/actor/actor.hpp>
#include <mbgl/actor/scheduler.hpp>
+#include <mbgl/storage/default_file_source.hpp>
+#include <mbgl/storage/resource_options.hpp>
#include <mbgl/storage/resource_transform.hpp>
#include <mbgl/util/chrono.hpp>
#include <mbgl/util/run_loop.hpp>
@@ -44,7 +45,8 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio
@interface MGLOfflineStorage ()
@property (nonatomic, strong, readwrite) NSMutableArray<MGLOfflinePack *> *packs;
-@property (nonatomic) mbgl::DefaultFileSource *mbglFileSource;
+@property (nonatomic) std::shared_ptr<mbgl::DefaultFileSource> mbglFileSource;
+@property (nonatomic) std::string mbglCachePath;
@property (nonatomic, getter=isPaused) BOOL paused;
@end
@@ -223,7 +225,11 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio
[[NSFileManager defaultManager] moveItemAtPath:subdirectorylessCacheURL.path toPath:cachePath error:NULL];
}
- _mbglFileSource = new mbgl::DefaultFileSource(cachePath.UTF8String, [NSBundle mainBundle].resourceURL.path.UTF8String);
+ _mbglCachePath = cachePath.UTF8String;
+ mbgl::ResourceOptions options;
+ options.withCachePath(_mbglCachePath)
+ .withAssetPath([NSBundle mainBundle].resourceURL.path.UTF8String);
+ _mbglFileSource = std::static_pointer_cast<mbgl::DefaultFileSource>(mbgl::FileSource::getSharedFileSource(options));
// Observe for changes to the API base URL (and find out the current one).
[[MGLAccountManager sharedManager] addObserver:self
@@ -250,9 +256,6 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio
for (MGLOfflinePack *pack in self.packs) {
[pack invalidate];
}
-
- delete _mbglFileSource;
- _mbglFileSource = nullptr;
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *, id> *)change context:(void *)context {
@@ -260,14 +263,14 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio
if ([keyPath isEqualToString:@"accessToken"] && object == [MGLAccountManager sharedManager]) {
NSString *accessToken = change[NSKeyValueChangeNewKey];
if (![accessToken isKindOfClass:[NSNull class]]) {
- self.mbglFileSource->setAccessToken(accessToken.UTF8String);
+ _mbglFileSource->setAccessToken(accessToken.UTF8String);
}
} else if ([keyPath isEqualToString:@"apiBaseURL"] && object == [MGLAccountManager sharedManager]) {
NSURL *apiBaseURL = change[NSKeyValueChangeNewKey];
if ([apiBaseURL isKindOfClass:[NSNull class]]) {
- self.mbglFileSource->setAPIBaseURL(mbgl::util::API_BASE_URL);
+ _mbglFileSource->setAPIBaseURL(mbgl::util::API_BASE_URL);
} else {
- self.mbglFileSource->setAPIBaseURL(apiBaseURL.absoluteString.UTF8String);
+ _mbglFileSource->setAPIBaseURL(apiBaseURL.absoluteString.UTF8String);
}
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
@@ -333,7 +336,7 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio
}
- (void)_addContentsOfFile:(NSString *)filePath withCompletionHandler:(void (^)(NSArray<MGLOfflinePack *> * _Nullable packs, NSError * _Nullable error))completion {
- self.mbglFileSource->mergeOfflineRegions(std::string(static_cast<const char *>([filePath UTF8String])), [&, completion, filePath](mbgl::expected<mbgl::OfflineRegions, std::exception_ptr> result) {
+ _mbglFileSource->mergeOfflineRegions(std::string(static_cast<const char *>([filePath UTF8String])), [&, completion, filePath](mbgl::expected<mbgl::OfflineRegions, std::exception_ptr> result) {
NSError *error;
NSMutableArray *packs;
if (!result) {
@@ -394,7 +397,7 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio
const mbgl::OfflineRegionDefinition regionDefinition = [(id <MGLOfflineRegion_Private>)region offlineRegionDefinition];
mbgl::OfflineRegionMetadata metadata(context.length);
[context getBytes:&metadata[0] length:metadata.size()];
- self.mbglFileSource->createOfflineRegion(regionDefinition, metadata, [&, completion](mbgl::expected<mbgl::OfflineRegion, std::exception_ptr> mbglOfflineRegion) {
+ _mbglFileSource->createOfflineRegion(regionDefinition, metadata, [&, completion](mbgl::expected<mbgl::OfflineRegion, std::exception_ptr> mbglOfflineRegion) {
NSError *error;
if (!mbglOfflineRegion) {
NSString *errorDescription = @(mbgl::util::toString(mbglOfflineRegion.error()).c_str());
@@ -429,7 +432,7 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio
return;
}
- self.mbglFileSource->deleteOfflineRegion(std::move(*mbglOfflineRegion), [&, completion](std::exception_ptr exception) {
+ _mbglFileSource->deleteOfflineRegion(std::move(*mbglOfflineRegion), [&, completion](std::exception_ptr exception) {
NSError *error;
if (exception) {
error = [NSError errorWithDomain:MGLErrorDomain code:-1 userInfo:@{
@@ -455,7 +458,7 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio
}
- (void)getPacksWithCompletionHandler:(void (^)(NSArray<MGLOfflinePack *> *packs, NSError * _Nullable error))completion {
- self.mbglFileSource->listOfflineRegions([&, completion](mbgl::expected<mbgl::OfflineRegions, std::exception_ptr> result) {
+ _mbglFileSource->listOfflineRegions([&, completion](mbgl::expected<mbgl::OfflineRegions, std::exception_ptr> result) {
NSError *error;
NSMutableArray *packs;
if (!result) {
diff --git a/platform/darwin/src/MGLOfflineStorage_Private.h b/platform/darwin/src/MGLOfflineStorage_Private.h
index 7c7b80dc46..5ac64ea995 100644
--- a/platform/darwin/src/MGLOfflineStorage_Private.h
+++ b/platform/darwin/src/MGLOfflineStorage_Private.h
@@ -4,6 +4,8 @@
#include <mbgl/storage/default_file_source.hpp>
+#include <memory>
+
NS_ASSUME_NONNULL_BEGIN
@interface MGLOfflineStorage (Private)
@@ -11,7 +13,12 @@ NS_ASSUME_NONNULL_BEGIN
/**
The shared file source object owned by the shared offline storage object.
*/
-@property (nonatomic) mbgl::DefaultFileSource *mbglFileSource;
+@property (nonatomic) std::shared_ptr<mbgl::DefaultFileSource> mbglFileSource;
+
+/**
+ The shared offline cache path.
+ */
+@property (nonatomic) std::string mbglCachePath;
@end
diff --git a/platform/darwin/src/MGLRendererConfiguration.h b/platform/darwin/src/MGLRendererConfiguration.h
index a2ad4d6cdc..ef7122ec51 100644
--- a/platform/darwin/src/MGLRendererConfiguration.h
+++ b/platform/darwin/src/MGLRendererConfiguration.h
@@ -1,7 +1,8 @@
#import "MGLFoundation.h"
#import <Foundation/Foundation.h>
-#import <mbgl/storage/default_file_source.hpp>
-#import <mbgl/renderer/mode.hpp>
+
+#include <mbgl/renderer/mode.hpp>
+#include <mbgl/util/optional.hpp>
NS_ASSUME_NONNULL_BEGIN
@@ -15,9 +16,6 @@ MGL_EXPORT
/** Returns an instance of the current renderer configuration. */
@property (class, nonatomic, readonly) MGLRendererConfiguration *currentConfiguration;
-/** The file source to use. Defaults to `mbgl::DefaultFileSource` */
-@property (nonatomic, readonly) mbgl::DefaultFileSource *fileSource;
-
/** The GL context mode to use. Defaults to `mbgl::GLContextMode::Unique` */
@property (nonatomic, readonly) mbgl::GLContextMode contextMode;
diff --git a/platform/darwin/src/MGLRendererConfiguration.mm b/platform/darwin/src/MGLRendererConfiguration.mm
index 7a2f95cfda..78201987fe 100644
--- a/platform/darwin/src/MGLRendererConfiguration.mm
+++ b/platform/darwin/src/MGLRendererConfiguration.mm
@@ -57,10 +57,6 @@ static NSString * const MGLCollisionBehaviorPre4_0Key = @"MGLCollisionBehaviorPr
return self;
}
-- (mbgl::DefaultFileSource *)fileSource {
- return [MGLOfflineStorage sharedOfflineStorage].mbglFileSource;
-}
-
- (mbgl::GLContextMode)contextMode {
return mbgl::GLContextMode::Unique;
}
diff --git a/platform/darwin/src/MGLRendererFrontend.h b/platform/darwin/src/MGLRendererFrontend.h
index 2df67ca4e4..c0e03351c6 100644
--- a/platform/darwin/src/MGLRendererFrontend.h
+++ b/platform/darwin/src/MGLRendererFrontend.h
@@ -49,7 +49,12 @@ public:
mbgl::BackendScope guard { mbglBackend, mbgl::BackendScope::ScopeType::Implicit };
- renderer->render(*updateParameters);
+ // onStyleImageMissing might be called during a render. The user implemented method
+ // could trigger a call to MGLRenderFrontend#update which overwrites `updateParameters`.
+ // Copy the shared pointer here so that the parameters aren't destroyed while `render(...)` is
+ // still using them.
+ auto updateParameters_ = updateParameters;
+ renderer->render(*updateParameters_);
}
mbgl::Renderer* getRenderer() {
diff --git a/platform/darwin/src/MGLStyleValue_Private.h b/platform/darwin/src/MGLStyleValue_Private.h
index 84d7ccccec..fee34b4b71 100644
--- a/platform/darwin/src/MGLStyleValue_Private.h
+++ b/platform/darwin/src/MGLStyleValue_Private.h
@@ -307,10 +307,8 @@ private: // Private utilities for converting from mbgl to mgl values
// Enumerations
template <typename MBGLEnum = MBGLType, typename MGLEnum = ObjCEnum>
- static NSValue *toMGLRawStyleValue(const MBGLEnum &value) {
- auto str = mbgl::Enum<MBGLEnum>::toString(value);
- MGLEnum mglType = *mbgl::Enum<MGLEnum>::toEnum(str);
- return [NSValue value:&mglType withObjCType:@encode(MGLEnum)];
+ static NSString *toMGLRawStyleValue(const MBGLEnum &value) {
+ return @(mbgl::Enum<MBGLEnum>::toString(value));
}
/// Converts all types of mbgl property values into an equivalent NSExpression.
@@ -320,15 +318,6 @@ private: // Private utilities for converting from mbgl to mgl values
return nil;
}
- /**
- As hack to allow converting enum => string values, we accept a second, dummy parameter in
- the toRawStyleSpecValue() methods for converting 'atomic' (non-style-function) values.
- This allows us to use `std::enable_if` to test (at compile time) whether or not MBGLType is an Enum.
- */
- template <typename MBGLEnum = MBGLType,
- class = typename std::enable_if<!std::is_enum<MBGLEnum>::value>::type,
- typename MGLEnum = ObjCEnum,
- class = typename std::enable_if<!std::is_enum<MGLEnum>::value>::type>
NSExpression *operator()(const MBGLType &value) const {
id constantValue = toMGLRawStyleValue(value);
if ([constantValue isKindOfClass:[NSArray class]]) {
@@ -337,15 +326,6 @@ private: // Private utilities for converting from mbgl to mgl values
return [NSExpression expressionForConstantValue:constantValue];
}
- template <typename MBGLEnum = MBGLType,
- class = typename std::enable_if<std::is_enum<MBGLEnum>::value>::type,
- typename MGLEnum = ObjCEnum,
- class = typename std::enable_if<std::is_enum<MGLEnum>::value>::type>
- NSExpression *operator()(const MBGLEnum &value) const {
- NSString *constantValue = @(mbgl::Enum<MBGLEnum>::toString(value));
- return [NSExpression expressionForConstantValue:constantValue];
- }
-
NSExpression *operator()(const mbgl::style::PropertyExpression<MBGLType> &mbglValue) const {
return [NSExpression expressionWithMGLJSONObject:MGLJSONObjectFromMBGLExpression(mbglValue.getExpression())];
}
diff --git a/platform/darwin/src/MGLSymbolStyleLayer.h b/platform/darwin/src/MGLSymbolStyleLayer.h
index ee8afb1fb2..cf2c1466e7 100644
--- a/platform/darwin/src/MGLSymbolStyleLayer.h
+++ b/platform/darwin/src/MGLSymbolStyleLayer.h
@@ -223,6 +223,10 @@ typedef NS_ENUM(NSUInteger, MGLTextAnchor) {
*/
typedef NS_ENUM(NSUInteger, MGLTextJustification) {
/**
+ The text is aligned towards the anchor position.
+ */
+ MGLTextJustificationAuto,
+ /**
The text is aligned to the left.
*/
MGLTextJustificationLeft,
@@ -1279,6 +1283,7 @@ MGL_EXPORT
* Constant `MGLTextJustification` values
* Any of the following constant string values:
+ * `auto`: The text is aligned towards the anchor position.
* `left`: The text is aligned to the left.
* `center`: The text is centered.
* `right`: The text is aligned to the right.
@@ -1349,8 +1354,8 @@ MGL_EXPORT
`NSValue` object containing a `CGVector` struct set to 0 ems rightward and 0
ems downward. Set this property to `nil` to reset it to the default value.
- This property is only applied to the style if `text` is non-`nil`. Otherwise,
- it is ignored.
+ This property is only applied to the style if `text` is non-`nil`, and
+ `textRadialOffset` is set to `nil`. Otherwise, it is ignored.
You can set this property to an expression containing any of the following:
@@ -1372,8 +1377,8 @@ MGL_EXPORT
`NSValue` object containing a `CGVector` struct set to 0 ems rightward and 0
ems upward. Set this property to `nil` to reset it to the default value.
- This property is only applied to the style if `text` is non-`nil`. Otherwise,
- it is ignored.
+ This property is only applied to the style if `text` is non-`nil`, and
+ `textRadialOffset` is set to `nil`. Otherwise, it is ignored.
You can set this property to an expression containing any of the following:
@@ -1464,6 +1469,27 @@ MGL_EXPORT
@property (nonatomic, null_resettable) NSExpression *textPitchAlignment;
/**
+ Radial offset of text, in the direction of the symbol's anchor. Useful in
+ combination with `textVariableAnchor`, which doesn't support the
+ two-dimensional `textOffset`.
+
+ This property is measured in ems.
+
+ This property is only applied to the style if `textOffset` is set to `nil`.
+ Otherwise, it is ignored.
+
+ You can set this property to an expression containing any of the following:
+
+ * Constant numeric values
+ * Predefined functions, including mathematical and string operators
+ * Conditional expressions
+ * Variable assignments and references to assigned variables
+ * Interpolation and step functions applied to the `$zoomLevel` variable and/or
+ feature attributes
+ */
+@property (nonatomic, null_resettable) NSExpression *textRadialOffset;
+
+/**
Rotates the text clockwise.
This property is measured in degrees.
@@ -1549,6 +1575,47 @@ MGL_EXPORT
*/
@property (nonatomic, null_resettable) NSExpression *textTransform;
+/**
+ To increase the chance of placing high-priority labels on the map, you can
+ provide an array of `textAnchor` locations: the render will attempt to place
+ the label at each location, in order, before moving onto the next label. Use
+ `textJustify: auto` to choose justification based on anchor position. To apply
+ an offset, use the `textRadialOffset` instead of the two-dimensional
+ `textOffset`.
+
+ This property is only applied to the style if `textAnchor` is set to `nil`, and
+ `textOffset` is set to `nil`, and `symbolPlacement` is set to an expression
+ that evaluates to or `MGLSymbolPlacementPoint`. Otherwise, it is ignored.
+
+ You can set this property to an expression containing any of the following:
+
+ * Constant `MGLTextAnchor` array values
+ * Constant array, whose each element is any of the following constant string
+ values:
+ * `center`: The center of the text is placed closest to the anchor.
+ * `left`: The left side of the text is placed closest to the anchor.
+ * `right`: The right side of the text is placed closest to the anchor.
+ * `top`: The top of the text is placed closest to the anchor.
+ * `bottom`: The bottom of the text is placed closest to the anchor.
+ * `top-left`: The top left corner of the text is placed closest to the
+ anchor.
+ * `top-right`: The top right corner of the text is placed closest to the
+ anchor.
+ * `bottom-left`: The bottom left corner of the text is placed closest to the
+ anchor.
+ * `bottom-right`: The bottom right corner of the text is placed closest to
+ the anchor.
+ * Predefined functions, including mathematical and string operators
+ * Conditional expressions
+ * Variable assignments and references to assigned variables
+ * Step functions applied to the `$zoomLevel` variable
+
+ This property does not support applying interpolation functions to the
+ `$zoomLevel` variable or applying interpolation or step functions to feature
+ attributes.
+ */
+@property (nonatomic, null_resettable) NSExpression *textVariableAnchor;
+
#pragma mark - Accessing the Paint Attributes
#if TARGET_OS_IPHONE
diff --git a/platform/darwin/src/MGLSymbolStyleLayer.mm b/platform/darwin/src/MGLSymbolStyleLayer.mm
index 60fc4d6881..6d91bbe87f 100644
--- a/platform/darwin/src/MGLSymbolStyleLayer.mm
+++ b/platform/darwin/src/MGLSymbolStyleLayer.mm
@@ -71,6 +71,7 @@ namespace mbgl {
});
MBGL_DEFINE_ENUM(MGLTextJustification, {
+ { MGLTextJustificationAuto, "auto" },
{ MGLTextJustificationLeft, "left" },
{ MGLTextJustificationCenter, "center" },
{ MGLTextJustificationRight, "right" },
@@ -906,6 +907,24 @@ namespace mbgl {
return MGLStyleValueTransformer<mbgl::style::AlignmentType, NSValue *, mbgl::style::AlignmentType, MGLTextPitchAlignment>().toExpression(propertyValue);
}
+- (void)setTextRadialOffset:(NSExpression *)textRadialOffset {
+ MGLAssertStyleLayerIsValid();
+ MGLLogDebug(@"Setting textRadialOffset: %@", textRadialOffset);
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue<mbgl::style::PropertyValue<float>>(textRadialOffset, true);
+ self.rawLayer->setTextRadialOffset(mbglValue);
+}
+
+- (NSExpression *)textRadialOffset {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = self.rawLayer->getTextRadialOffset();
+ if (propertyValue.isUndefined()) {
+ propertyValue = self.rawLayer->getDefaultTextRadialOffset();
+ }
+ return MGLStyleValueTransformer<float, NSNumber *>().toExpression(propertyValue);
+}
+
- (void)setTextRotation:(NSExpression *)textRotation {
MGLAssertStyleLayerIsValid();
MGLLogDebug(@"Setting textRotation: %@", textRotation);
@@ -967,6 +986,24 @@ namespace mbgl {
return MGLStyleValueTransformer<mbgl::style::TextTransformType, NSValue *, mbgl::style::TextTransformType, MGLTextTransform>().toExpression(propertyValue);
}
+- (void)setTextVariableAnchor:(NSExpression *)textVariableAnchor {
+ MGLAssertStyleLayerIsValid();
+ MGLLogDebug(@"Setting textVariableAnchor: %@", textVariableAnchor);
+
+ auto mbglValue = MGLStyleValueTransformer<std::vector<mbgl::style::SymbolAnchorType>, NSArray<NSValue *> *, mbgl::style::SymbolAnchorType, MGLTextAnchor>().toPropertyValue<mbgl::style::PropertyValue<std::vector<mbgl::style::SymbolAnchorType>>>(textVariableAnchor, false);
+ self.rawLayer->setTextVariableAnchor(mbglValue);
+}
+
+- (NSExpression *)textVariableAnchor {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = self.rawLayer->getTextVariableAnchor();
+ if (propertyValue.isUndefined()) {
+ propertyValue = self.rawLayer->getDefaultTextVariableAnchor();
+ }
+ return MGLStyleValueTransformer<std::vector<mbgl::style::SymbolAnchorType>, NSArray<NSValue *> *, mbgl::style::SymbolAnchorType, MGLTextAnchor>().toExpression(propertyValue);
+}
+
#pragma mark - Accessing the Paint Attributes
- (void)setIconColor:(NSExpression *)iconColor {
diff --git a/platform/darwin/src/NSBundle+MGLAdditions.m b/platform/darwin/src/NSBundle+MGLAdditions.m
index d472e40b1f..da70a95373 100644
--- a/platform/darwin/src/NSBundle+MGLAdditions.m
+++ b/platform/darwin/src/NSBundle+MGLAdditions.m
@@ -35,10 +35,15 @@ const MGLExceptionName MGLBundleNotFoundException = @"MGLBundleNotFoundException
+ (nullable NSString *)mgl_applicationBundleIdentifier {
NSString *bundleIdentifier = [NSBundle mainBundle].bundleIdentifier;
+
+#if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && (__IPHONE_OS_VERSION_MAX_ALLOWED < 120200)) || \
+ (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && (__MAC_OS_X_VERSION_MAX_ALLOWED < 101404))
+ // Before SDK 12.2 (bundled with Xcode 10.2): There’s no main bundle identifier when running in a unit test bundle.
+ // 12.2 and after: the above bundle identifier is: com.apple.dt.xctest.tool
if (!bundleIdentifier) {
- // There’s no main bundle identifier when running in a unit test bundle.
bundleIdentifier = [NSBundle bundleForClass:[MGLAccountManager class]].bundleIdentifier;
}
+#endif
return bundleIdentifier;
}
diff --git a/platform/darwin/src/NSData+MGLAdditions.h b/platform/darwin/src/NSData+MGLAdditions.h
deleted file mode 100644
index 38af7961b6..0000000000
--- a/platform/darwin/src/NSData+MGLAdditions.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#import <Foundation/Foundation.h>
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface NSData (MGLAdditions)
-
-- (NSData *)mgl_compressedData;
-
-- (NSData *)mgl_decompressedData;
-
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/NSData+MGLAdditions.mm b/platform/darwin/src/NSData+MGLAdditions.mm
deleted file mode 100644
index 97c3bb4a26..0000000000
--- a/platform/darwin/src/NSData+MGLAdditions.mm
+++ /dev/null
@@ -1,23 +0,0 @@
-#import "NSData+MGLAdditions.h"
-
-#include <mbgl/util/compression.hpp>
-
-@implementation NSData (MGLAdditions)
-
-- (NSData *)mgl_compressedData
-{
- std::string string(static_cast<const char*>(self.bytes), self.length);
- std::string compressed_string = mbgl::util::compress(string);
-
- return [NSData dataWithBytes:&compressed_string[0] length:compressed_string.length()];
-}
-
-- (NSData *)mgl_decompressedData
-{
- std::string string(static_cast<const char*>(self.bytes), self.length);
- std::string decompressed_string = mbgl::util::decompress(string);
-
- return [NSData dataWithBytes:&decompressed_string[0] length:decompressed_string.length()];
-}
-
-@end
diff --git a/platform/darwin/src/NSExpression+MGLAdditions.mm b/platform/darwin/src/NSExpression+MGLAdditions.mm
index c4e2908888..4b1fdb818e 100644
--- a/platform/darwin/src/NSExpression+MGLAdditions.mm
+++ b/platform/darwin/src/NSExpression+MGLAdditions.mm
@@ -1,3 +1,4 @@
+#import "MGLFoundation_Private.h"
#import "NSExpression+MGLPrivateAdditions.h"
#import "MGLTypes.h"
@@ -878,9 +879,12 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
NSExpression *expression = [NSExpression expressionWithMGLJSONObject:argumentObjects[index]];
NSMutableDictionary *attrs = [NSMutableDictionary dictionary];
if ((index + 1) < argumentObjects.count) {
- attrs = argumentObjects[index + 1];
+ attrs = [NSMutableDictionary dictionaryWithDictionary:argumentObjects[index + 1]];
}
+ for (NSString *key in attrs.allKeys) {
+ attrs[key] = [NSExpression expressionWithMGLJSONObject:attrs[key]];
+ }
MGLAttributedExpression *attributedExpression = [[MGLAttributedExpression alloc] initWithExpression:expression attributes:attrs];
[attributedExpressions addObject:[NSExpression expressionForConstantValue:attributedExpression]];
@@ -1001,19 +1005,17 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
if ([constantValue isKindOfClass:[MGLAttributedExpression class]]) {
MGLAttributedExpression *attributedExpression = (MGLAttributedExpression *)constantValue;
id jsonObject = attributedExpression.expression.mgl_jsonExpressionObject;
- NSMutableArray *attributes = [NSMutableArray array];
- if ([jsonObject isKindOfClass:[NSArray class]]) {
- [attributes addObjectsFromArray:jsonObject];
- } else {
- [attributes addObject:jsonObject];
- }
+ NSMutableDictionary<MGLAttributedExpressionKey, NSExpression *> *attributedDictionary = [NSMutableDictionary dictionary];
+
if (attributedExpression.attributes) {
- [attributes addObject:attributedExpression.attributes];
- } else {
- [attributes addObject:@{}];
- }
-
- return attributes;
+ attributedDictionary = [NSMutableDictionary dictionaryWithDictionary:attributedExpression.attributes];
+
+ for (NSString *key in attributedExpression.attributes.allKeys) {
+ attributedDictionary[key] = attributedExpression.attributes[key].mgl_jsonExpressionObject;
+ }
+
+ }
+ return @[jsonObject, attributedDictionary];
}
return self.constantValue;
}
@@ -1215,27 +1217,10 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
}
case NSConditionalExpressionType: {
- NSMutableArray *arguments = [NSMutableArray arrayWithObjects:self.predicate.mgl_jsonExpressionObject, nil];
-
- if (self.trueExpression.expressionType == NSConditionalExpressionType) {
- // Fold nested conditionals into a single case expression.
- NSArray *trueArguments = self.trueExpression.mgl_jsonExpressionObject;
- trueArguments = [trueArguments subarrayWithRange:NSMakeRange(1, trueArguments.count - 1)];
- [arguments addObjectsFromArray:trueArguments];
- } else {
- [arguments addObject:self.trueExpression.mgl_jsonExpressionObject];
- }
-
- if (self.falseExpression.expressionType == NSConditionalExpressionType) {
- // Fold nested conditionals into a single case expression.
- NSArray *falseArguments = self.falseExpression.mgl_jsonExpressionObject;
- falseArguments = [falseArguments subarrayWithRange:NSMakeRange(1, falseArguments.count - 1)];
- [arguments addObjectsFromArray:falseArguments];
- } else {
- [arguments addObject:self.falseExpression.mgl_jsonExpressionObject];
- }
+ NSMutableArray *arguments = [NSMutableArray arrayWithObjects:@"case", self.predicate.mgl_jsonExpressionObject, nil];
+ [arguments addObject:self.trueExpression.mgl_jsonExpressionObject];
+ [arguments addObject:self.falseExpression.mgl_jsonExpressionObject];
- [arguments insertObject:@"case" atIndex:0];
return arguments;
}
diff --git a/platform/darwin/test/MGLAttributionInfoTests.m b/platform/darwin/test/MGLAttributionInfoTests.m
index 48779f3407..b6f053a8af 100644
--- a/platform/darwin/test/MGLAttributionInfoTests.m
+++ b/platform/darwin/test/MGLAttributionInfoTests.m
@@ -55,10 +55,21 @@
XCTAssertEqualObjects(infos[3].URL, [NSURL URLWithString:@"https://apps.mapbox.com/feedback/"]);
XCTAssertTrue(infos[3].feedbackLink);
NSURL *styleURL = [MGLStyle satelliteStreetsStyleURLWithVersion:99];
+
+#if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 120200) || \
+ (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 101404)
+ NSString *bundleId = @"com.apple.dt.xctest.tool";
+#else
+ NSString *bundleId = @"com.mapbox.Mapbox";
+#endif
+
+ NSString *urlString = [NSString stringWithFormat:@"https://apps.mapbox.com/feedback/?referrer=%@#/77.63680/12.98108/14.00/0.0/0", bundleId];
XCTAssertEqualObjects([infos[3] feedbackURLAtCenterCoordinate:mapbox zoomLevel:14],
- [NSURL URLWithString:@"https://apps.mapbox.com/feedback/?referrer=com.mapbox.Mapbox#/77.63680/12.98108/14.00/0.0/0"]);
+ [NSURL URLWithString:urlString]);
+
+ urlString = [NSString stringWithFormat:@"https://apps.mapbox.com/feedback/?referrer=%@&owner=mapbox&id=satellite-streets-v99&access_token=pk.feedcafedeadbeefbadebede&map_sdk_version=1.0.0#/77.63680/12.98108/3.14/90.9/13", bundleId];
XCTAssertEqualObjects([infos[3] feedbackURLForStyleURL:styleURL atCenterCoordinate:mapbox zoomLevel:3.14159 direction:90.9 pitch:12.5],
- [NSURL URLWithString:@"https://apps.mapbox.com/feedback/?referrer=com.mapbox.Mapbox&owner=mapbox&id=satellite-streets-v99&access_token=pk.feedcafedeadbeefbadebede&map_sdk_version=1.0.0#/77.63680/12.98108/3.14/90.9/13"]);
+ [NSURL URLWithString:urlString]);
}
- (void)testStyle {
diff --git a/platform/darwin/test/MGLDocumentationExampleTests.swift b/platform/darwin/test/MGLDocumentationExampleTests.swift
index 91fb02dfd2..2a64fbc601 100644
--- a/platform/darwin/test/MGLDocumentationExampleTests.swift
+++ b/platform/darwin/test/MGLDocumentationExampleTests.swift
@@ -542,6 +542,24 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
}
}
+ func testMGLAttributedExpression() {
+ //#-example-code
+ #if os(macOS)
+ let redColor = NSColor.red
+ #else
+ let redColor = UIColor.red
+ #endif
+ let expression = NSExpression(forConstantValue: "Foo")
+ let attributes: [MGLAttributedExpressionKey: NSExpression] = [.fontNamesAttribute : NSExpression(forConstantValue: ["DIN Offc Pro Italic",
+ "Arial Unicode MS Regular"]),
+ .fontScaleAttribute: NSExpression(forConstantValue: 1.2),
+ .fontColorAttribute: NSExpression(forConstantValue: redColor)]
+ let attributedExpression = MGLAttributedExpression(expression, attributes:attributes)
+ //#-end-example-code
+
+ XCTAssertNotNil(attributedExpression)
+ }
+
// For testMGLMapView().
func myCustomFunction() {}
}
diff --git a/platform/darwin/test/MGLExpressionTests.mm b/platform/darwin/test/MGLExpressionTests.mm
index 8b8a79f184..68806e38f6 100644
--- a/platform/darwin/test/MGLExpressionTests.mm
+++ b/platform/darwin/test/MGLExpressionTests.mm
@@ -846,12 +846,9 @@ using namespace std::string_literals;
}
{
NSExpression *expression = [NSExpression expressionWithFormat:@"TERNARY(0 = 1, TRUE, TERNARY(1 = 2, TRUE, FALSE))"];
- NSArray *jsonExpression = @[@"case", @[@"==", @0, @1], @YES, @[@"==", @1, @2], @YES, @NO];
+ NSArray *jsonExpression = @[@"case", @[@"==", @0, @1], @YES, @[@"case", @[@"==", @1, @2], @YES, @NO]];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @NO);
- expression = [NSExpression expressionWithFormat:@"MGL_IF(%@, TRUE, %@, TRUE, FALSE)",
- MGLConstantExpression([NSPredicate predicateWithFormat:@"0 = 1"]),
- MGLConstantExpression([NSPredicate predicateWithFormat:@"1 = 2"])];
XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
}
{
@@ -995,16 +992,16 @@ using namespace std::string_literals;
{
MGLAttributedExpression *attribute1 = [MGLAttributedExpression attributedExpression:[NSExpression expressionForConstantValue:@"foo"]
fontNames:nil
- fontSize:@(1.2)];
+ fontScale:@(1.2)];
MGLAttributedExpression *attribute2 = [MGLAttributedExpression attributedExpression:[NSExpression expressionForConstantValue:@"biz"]
fontNames:nil
- fontSize:@(1.0)];
+ fontScale:@(1.0)];
MGLAttributedExpression *attribute3 = [MGLAttributedExpression attributedExpression:[NSExpression expressionForConstantValue:@"bar"]
fontNames:nil
- fontSize:@(0.8)];
+ fontScale:@(0.8)];
MGLAttributedExpression *attribute4 = [MGLAttributedExpression attributedExpression:[NSExpression expressionForConstantValue:@"\r"]
fontNames:@[]
- fontSize:nil];
+ fontScale:nil];
NSExpression *expression = [NSExpression expressionWithFormat:@"mgl_attributed:(%@, %@, %@, %@)",
MGLConstantExpression(attribute1),
MGLConstantExpression(attribute4),
@@ -1017,16 +1014,16 @@ using namespace std::string_literals;
{
MGLAttributedExpression *attribute1 = [MGLAttributedExpression attributedExpression:[NSExpression expressionForConstantValue:@"foo"]
fontNames:nil
- fontSize:@(1.2)];
+ fontScale:@(1.2)];
MGLAttributedExpression *attribute2 = [MGLAttributedExpression attributedExpression:[NSExpression expressionForConstantValue:@"biz"]
fontNames:nil
- fontSize:@(1.0)];
+ fontScale:@(1.0)];
MGLAttributedExpression *attribute3 = [MGLAttributedExpression attributedExpression:[NSExpression expressionForConstantValue:@"bar"]
fontNames:nil
- fontSize:@(0.8)];
+ fontScale:@(0.8)];
MGLAttributedExpression *attribute4 = [MGLAttributedExpression attributedExpression:[NSExpression expressionForConstantValue:@"\n"]
fontNames:@[]
- fontSize:nil];
+ fontScale:nil];
NSExpression *expression = [NSExpression expressionWithFormat:@"mgl_attributed:(%@, %@, %@, %@)",
MGLConstantExpression(attribute1),
MGLConstantExpression(attribute4),
@@ -1039,7 +1036,7 @@ using namespace std::string_literals;
{
MGLAttributedExpression *attribute1 = [MGLAttributedExpression attributedExpression:[NSExpression expressionForConstantValue:@"foo"]
fontNames:nil
- fontSize:@(1.2)];
+ fontScale:@(1.2)];
NSExpression *expression = [NSExpression expressionWithFormat:@"mgl_attributed:(%@)", MGLConstantExpression(attribute1)];
NSExpression *compatibilityExpression = [NSExpression expressionForFunction:@"mgl_attributed:" arguments:@[MGLConstantExpression(attribute1)]];
@@ -1050,18 +1047,79 @@ using namespace std::string_literals;
XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
}
{
+ MGLAttributedExpression *attribute1 = [[MGLAttributedExpression alloc] initWithExpression:[NSExpression expressionForConstantValue:@"foo"]
+ attributes:@{ MGLFontScaleAttribute: MGLConstantExpression(@(1.2)),
+ MGLFontColorAttribute: MGLConstantExpression(@"yellow") }] ;
+ NSExpression *expression = [NSExpression expressionWithFormat:@"mgl_attributed:(%@)", MGLConstantExpression(attribute1)];
+
+ NSExpression *compatibilityExpression = [NSExpression expressionForFunction:@"mgl_attributed:" arguments:@[MGLConstantExpression(attribute1)]];
+ NSArray *jsonExpression = @[ @"format", @"foo", @{ @"font-scale": @1.2, @"text-color": @"yellow" } ];
+ XCTAssertEqualObjects(compatibilityExpression.mgl_jsonExpressionObject, expression.mgl_jsonExpressionObject);
+ XCTAssertEqualObjects(compatibilityExpression, expression);
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ MGLAttributedExpression *attribute1 = [[MGLAttributedExpression alloc] initWithExpression:[NSExpression expressionForConstantValue:@"foo"]] ;
+ NSExpression *expression = [NSExpression expressionWithFormat:@"mgl_attributed:(%@)", MGLConstantExpression(attribute1)];
+
+ NSArray *jsonExpression = @[ @"format", @"foo", @{ } ];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *fontNames = [NSExpression expressionForAggregate:@[ MGLConstantExpression(@"DIN Offc Pro Bold"), MGLConstantExpression(@"Arial Unicode MS Bold") ]];
+ MGLAttributedExpression *attribute1 = [[MGLAttributedExpression alloc] initWithExpression:[NSExpression expressionForConstantValue:@"foo"]
+ attributes:@{ MGLFontScaleAttribute: MGLConstantExpression(@(1.2)),
+ MGLFontColorAttribute: MGLConstantExpression(@"yellow"),
+ MGLFontNamesAttribute: fontNames
+ }] ;
+ NSExpression *expression = [NSExpression expressionWithFormat:@"mgl_attributed:(%@)", MGLConstantExpression(attribute1)];
+
+ NSArray *jsonExpression = @[ @"format", @"foo", @{ @"font-scale": @1.2, @"text-color": @"yellow" , @"text-font" : @[ @"literal", @[ @"DIN Offc Pro Bold", @"Arial Unicode MS Bold" ]]} ];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ NSExpression *exp = [NSExpression expressionWithMGLJSONObject:jsonExpression];
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *fontNames = [NSExpression expressionForAggregate:@[ MGLConstantExpression(@"DIN Offc Pro Bold"), MGLConstantExpression(@"Arial Unicode MS Bold") ]];
+ MGLAttributedExpression *attribute1 = [[MGLAttributedExpression alloc] initWithExpression:[NSExpression expressionForConstantValue:@"foo"]
+ attributes:@{ MGLFontScaleAttribute: MGLConstantExpression(@(1.2)),
+ MGLFontColorAttribute: MGLConstantExpression([MGLColor redColor]),
+ MGLFontNamesAttribute: fontNames
+ }] ;
+ NSExpression *expression = [NSExpression expressionWithFormat:@"mgl_attributed:(%@)", MGLConstantExpression(attribute1)];
+
+ NSArray *jsonExpression = @[ @"format", @"foo", @{ @"font-scale": @1.2, @"text-color": @[@"rgb", @255, @0, @0] , @"text-font" : @[ @"literal", @[ @"DIN Offc Pro Bold", @"Arial Unicode MS Bold" ]]} ];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *fontNames = [NSExpression expressionForAggregate:@[ MGLConstantExpression(@"DIN Offc Pro Bold"), MGLConstantExpression(@"Arial Unicode MS Bold") ]];
+ MGLAttributedExpression *attribute1 = [[MGLAttributedExpression alloc] initWithExpression:[NSExpression expressionWithFormat:@"CAST(x, 'NSString')"]
+ attributes:@{ MGLFontScaleAttribute: MGLConstantExpression(@(1.2)),
+ MGLFontColorAttribute: MGLConstantExpression([MGLColor redColor]),
+ MGLFontNamesAttribute: fontNames
+ }] ;
+ NSExpression *expression = [NSExpression expressionWithFormat:@"mgl_attributed:(%@)", MGLConstantExpression(attribute1)];
+
+ NSArray *jsonExpression = @[ @"format", @[@"to-string", @[@"get", @"x"]], @{ @"font-scale": @1.2, @"text-color": @[@"rgb", @255, @0, @0] , @"text-font" : @[ @"literal", @[ @"DIN Offc Pro Bold", @"Arial Unicode MS Bold" ]]} ];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
MGLAttributedExpression *attribute1 = [MGLAttributedExpression attributedExpression:[NSExpression expressionForConstantValue:@"foo"]
fontNames:nil
- fontSize:@(1.2)];
+ fontScale:@(1.2)];
MGLAttributedExpression *attribute2 = [MGLAttributedExpression attributedExpression:[NSExpression expressionForConstantValue:@"biz"]
fontNames:nil
- fontSize:@(1.0)];
+ fontScale:@(1.0)];
MGLAttributedExpression *attribute3 = [MGLAttributedExpression attributedExpression:[NSExpression expressionForConstantValue:@"bar"]
fontNames:nil
- fontSize:@(0.8)];
+ fontScale:@(0.8)];
MGLAttributedExpression *attribute4 = [MGLAttributedExpression attributedExpression:[NSExpression expressionForConstantValue:@"\n"]
fontNames:@[]
- fontSize:nil];
+ fontScale:nil];
NSExpression *expression = [NSExpression mgl_expressionForAttributedExpressions:@[MGLConstantExpression(attribute1),
MGLConstantExpression(attribute4),
MGLConstantExpression(attribute2),
diff --git a/platform/darwin/test/MGLOfflineStorageTests.mm b/platform/darwin/test/MGLOfflineStorageTests.mm
index 7f0ead7cab..86dc28eb04 100644
--- a/platform/darwin/test/MGLOfflineStorageTests.mm
+++ b/platform/darwin/test/MGLOfflineStorageTests.mm
@@ -1,6 +1,7 @@
#import <Mapbox/Mapbox.h>
#import "MGLOfflineStorage_Private.h"
+#import "NSBundle+MGLAdditions.h"
#import "NSDate+MGLAdditions.h"
#import <XCTest/XCTest.h>
@@ -10,7 +11,6 @@
#pragma clang diagnostic ignored "-Wshadow"
@interface MGLOfflineStorageTests : XCTestCase <MGLOfflineStorageDelegate>
-
@end
@implementation MGLOfflineStorageTests
@@ -21,8 +21,7 @@
appropriateForURL:nil
create:NO
error:nil];
- // Unit tests don't use the main bundle; use com.mapbox.ios.sdk instead.
- NSString *bundleIdentifier = [NSBundle bundleForClass:[MGLMapView class]].bundleIdentifier;
+ NSString *bundleIdentifier = [NSBundle mgl_applicationBundleIdentifier];
cacheDirectoryURL = [cacheDirectoryURL URLByAppendingPathComponent:bundleIdentifier];
cacheDirectoryURL = [cacheDirectoryURL URLByAppendingPathComponent:@".mapbox"];
XCTAssertTrue([[NSFileManager defaultManager] fileExistsAtPath:cacheDirectoryURL.path], @"Cache subdirectory should exist.");
@@ -208,8 +207,8 @@
appropriateForURL:nil
create:NO
error:nil];
- // Unit tests don't use the main bundle; use com.mapbox.ios.sdk instead.
- NSString *bundleIdentifier = [NSBundle bundleForClass:[MGLMapView class]].bundleIdentifier;
+ // As of iOS SDK 12.2 unit tests now have a bundle id: com.apple.dt.xctest.tool
+ NSString *bundleIdentifier = [NSBundle mgl_applicationBundleIdentifier];
cacheDirectoryURL = [cacheDirectoryURL URLByAppendingPathComponent:bundleIdentifier];
cacheDirectoryURL = [cacheDirectoryURL URLByAppendingPathComponent:@".mapbox"];
XCTAssertTrue([[NSFileManager defaultManager] fileExistsAtPath:cacheDirectoryURL.path], @"Cache subdirectory should exist.");
diff --git a/platform/darwin/test/MGLSymbolStyleLayerTests.mm b/platform/darwin/test/MGLSymbolStyleLayerTests.mm
index 2f4206a96b..083b12bcc3 100644
--- a/platform/darwin/test/MGLSymbolStyleLayerTests.mm
+++ b/platform/darwin/test/MGLSymbolStyleLayerTests.mm
@@ -1741,6 +1741,75 @@
XCTAssertThrowsSpecificNamed(layer.textPitchAlignment = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
+ // text-radial-offset
+ {
+ XCTAssertTrue(rawLayer->getTextRadialOffset().isUndefined(),
+ @"text-radial-offset should be unset initially.");
+ NSExpression *defaultExpression = layer.textRadialOffset;
+
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"1"];
+ layer.textRadialOffset = constantExpression;
+ mbgl::style::PropertyValue<float> propertyValue = { 1.0 };
+ XCTAssertEqual(rawLayer->getTextRadialOffset(), propertyValue,
+ @"Setting textRadialOffset to a constant value expression should update text-radial-offset.");
+ XCTAssertEqualObjects(layer.textRadialOffset, constantExpression,
+ @"textRadialOffset should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"1"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.textRadialOffset = functionExpression;
+
+ {
+ using namespace mbgl::style::expression::dsl;
+ propertyValue = mbgl::style::PropertyExpression<float>(
+ step(zoom(), literal(1.0), 18.0, literal(1.0))
+ );
+ }
+
+ XCTAssertEqual(rawLayer->getTextRadialOffset(), propertyValue,
+ @"Setting textRadialOffset to a camera expression should update text-radial-offset.");
+ XCTAssertEqualObjects(layer.textRadialOffset, functionExpression,
+ @"textRadialOffset should round-trip camera expressions.");
+
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.textRadialOffset = functionExpression;
+
+ {
+ using namespace mbgl::style::expression::dsl;
+ propertyValue = mbgl::style::PropertyExpression<float>(
+ interpolate(linear(), number(get("keyName")), 18.0, literal(1.0))
+ );
+ }
+
+ XCTAssertEqual(rawLayer->getTextRadialOffset(), propertyValue,
+ @"Setting textRadialOffset to a data expression should update text-radial-offset.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.textRadialOffset, pedanticFunctionExpression,
+ @"textRadialOffset should round-trip data expressions.");
+
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.textRadialOffset = functionExpression;
+
+ {
+ using namespace mbgl::style::expression::dsl;
+ propertyValue = mbgl::style::PropertyExpression<float>(
+ interpolate(linear(), zoom(), 10.0, interpolate(linear(), number(get("keyName")), 18.0, literal(1.0)))
+ );
+ }
+
+ XCTAssertEqual(rawLayer->getTextRadialOffset(), propertyValue,
+ @"Setting textRadialOffset to a camera-data expression should update text-radial-offset.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.textRadialOffset, pedanticFunctionExpression,
+ @"textRadialOffset should round-trip camera-data expressions.");
+
+ layer.textRadialOffset = nil;
+ XCTAssertTrue(rawLayer->getTextRadialOffset().isUndefined(),
+ @"Unsetting textRadialOffset should return text-radial-offset to the default value.");
+ XCTAssertEqualObjects(layer.textRadialOffset, defaultExpression,
+ @"textRadialOffset should return the default value after being unset.");
+ }
+
// text-rotate
{
XCTAssertTrue(rawLayer->getTextRotate().isUndefined(),
@@ -1892,6 +1961,50 @@
@"textTransform should return the default value after being unset.");
}
+ // text-variable-anchor
+ {
+ XCTAssertTrue(rawLayer->getTextVariableAnchor().isUndefined(),
+ @"text-variable-anchor should be unset initially.");
+ NSExpression *defaultExpression = layer.textVariableAnchor;
+
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"{'top','bottom'}"];
+ layer.textVariableAnchor = constantExpression;
+ mbgl::style::PropertyValue<std::vector<mbgl::style::SymbolAnchorType>> propertyValue = { { mbgl::style::SymbolAnchorType::Top, mbgl::style::SymbolAnchorType::Bottom } };
+ XCTAssertEqual(rawLayer->getTextVariableAnchor(), propertyValue,
+ @"Setting textVariableAnchor to a constant value expression should update text-variable-anchor.");
+ XCTAssertEqualObjects(layer.textVariableAnchor, constantExpression,
+ @"textVariableAnchor should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"{'top','bottom'}"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.textVariableAnchor = functionExpression;
+
+ {
+ using namespace mbgl::style::expression::dsl;
+ propertyValue = mbgl::style::PropertyExpression<std::vector<mbgl::style::SymbolAnchorType>>(
+ step(zoom(), literal({"top", "bottom"}), 18.0, literal({"top", "bottom"}))
+ );
+ }
+
+ XCTAssertEqual(rawLayer->getTextVariableAnchor(), propertyValue,
+ @"Setting textVariableAnchor to a camera expression should update text-variable-anchor.");
+ XCTAssertEqualObjects(layer.textVariableAnchor, functionExpression,
+ @"textVariableAnchor should round-trip camera expressions.");
+
+
+ layer.textVariableAnchor = nil;
+ XCTAssertTrue(rawLayer->getTextVariableAnchor().isUndefined(),
+ @"Unsetting textVariableAnchor should return text-variable-anchor to the default value.");
+ XCTAssertEqualObjects(layer.textVariableAnchor, defaultExpression,
+ @"textVariableAnchor should return the default value after being unset.");
+
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.textVariableAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.textVariableAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ }
+
// icon-color
{
XCTAssertTrue(rawLayer->getIconColor().isUndefined(),
@@ -2896,9 +3009,11 @@
[self testPropertyName:@"is-text-optional" isBoolean:YES];
[self testPropertyName:@"text-padding" isBoolean:NO];
[self testPropertyName:@"text-pitch-alignment" isBoolean:NO];
+ [self testPropertyName:@"text-radial-offset" isBoolean:NO];
[self testPropertyName:@"text-rotation" isBoolean:NO];
[self testPropertyName:@"text-rotation-alignment" isBoolean:NO];
[self testPropertyName:@"text-transform" isBoolean:NO];
+ [self testPropertyName:@"text-variable-anchor" isBoolean:NO];
[self testPropertyName:@"icon-color" isBoolean:NO];
[self testPropertyName:@"icon-halo-blur" isBoolean:NO];
[self testPropertyName:@"icon-halo-color" isBoolean:NO];
@@ -2949,6 +3064,7 @@
XCTAssertEqual([NSValue valueWithMGLTextAnchor:MGLTextAnchorTopRight].MGLTextAnchorValue, MGLTextAnchorTopRight);
XCTAssertEqual([NSValue valueWithMGLTextAnchor:MGLTextAnchorBottomLeft].MGLTextAnchorValue, MGLTextAnchorBottomLeft);
XCTAssertEqual([NSValue valueWithMGLTextAnchor:MGLTextAnchorBottomRight].MGLTextAnchorValue, MGLTextAnchorBottomRight);
+ XCTAssertEqual([NSValue valueWithMGLTextJustification:MGLTextJustificationAuto].MGLTextJustificationValue, MGLTextJustificationAuto);
XCTAssertEqual([NSValue valueWithMGLTextJustification:MGLTextJustificationLeft].MGLTextJustificationValue, MGLTextJustificationLeft);
XCTAssertEqual([NSValue valueWithMGLTextJustification:MGLTextJustificationCenter].MGLTextJustificationValue, MGLTextJustificationCenter);
XCTAssertEqual([NSValue valueWithMGLTextJustification:MGLTextJustificationRight].MGLTextJustificationValue, MGLTextJustificationRight);
diff --git a/platform/default/include/mbgl/map/map_snapshotter.hpp b/platform/default/include/mbgl/map/map_snapshotter.hpp
index 2deb2b3cda..ccc3ee17f7 100644
--- a/platform/default/include/mbgl/map/map_snapshotter.hpp
+++ b/platform/default/include/mbgl/map/map_snapshotter.hpp
@@ -18,6 +18,7 @@ struct CameraOptions;
class FileSource;
class Size;
class LatLngBounds;
+class ResourceOptions;
namespace style {
class Style;
@@ -25,15 +26,15 @@ class Style;
class MapSnapshotter {
public:
- MapSnapshotter(FileSource* fileSource,
- std::shared_ptr<Scheduler> scheduler,
+ MapSnapshotter(std::shared_ptr<Scheduler> scheduler,
const std::pair<bool, std::string> style,
const Size&,
const float pixelRatio,
const optional<CameraOptions> cameraOptions,
const optional<LatLngBounds> region,
- const optional<std::string> cacheDir = {},
- const optional<std::string> localFontFamily = {});
+ const optional<std::string> cacheDir,
+ const optional<std::string> localFontFamily,
+ const ResourceOptions&);
~MapSnapshotter();
diff --git a/platform/default/src/mbgl/gl/headless_frontend.cpp b/platform/default/src/mbgl/gl/headless_frontend.cpp
index f3dae2dbc9..c311e2df41 100644
--- a/platform/default/src/mbgl/gl/headless_frontend.cpp
+++ b/platform/default/src/mbgl/gl/headless_frontend.cpp
@@ -20,7 +20,13 @@ HeadlessFrontend::HeadlessFrontend(Size size_, float pixelRatio_, Scheduler& sch
asyncInvalidate([this] {
if (renderer && updateParameters) {
mbgl::BackendScope guard { backend };
- renderer->render(*updateParameters);
+
+ // onStyleImageMissing might be called during a render. The user implemented method
+ // could trigger a call to MGLRenderFrontend#update which overwrites `updateParameters`.
+ // Copy the shared pointer here so that the parameters aren't destroyed while `render(...)` is
+ // still using them.
+ auto updateParameters_ = updateParameters;
+ renderer->render(*updateParameters_);
}
}),
renderer(std::make_unique<Renderer>(backend, pixelRatio, scheduler, mode, programCacheDir, localFontFamily)) {
diff --git a/platform/default/src/mbgl/map/map_snapshotter.cpp b/platform/default/src/mbgl/map/map_snapshotter.cpp
index 415ef7befd..227a61d272 100644
--- a/platform/default/src/mbgl/map/map_snapshotter.cpp
+++ b/platform/default/src/mbgl/map/map_snapshotter.cpp
@@ -5,7 +5,7 @@
#include <mbgl/map/map.hpp>
#include <mbgl/map/map_options.hpp>
#include <mbgl/map/transform_state.hpp>
-#include <mbgl/storage/file_source.hpp>
+#include <mbgl/storage/resource_options.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/util/event.hpp>
#include <mbgl/map/transform.hpp>
@@ -14,15 +14,15 @@ namespace mbgl {
class MapSnapshotter::Impl {
public:
- Impl(FileSource*,
- std::shared_ptr<Scheduler>,
+ Impl(std::shared_ptr<Scheduler>,
const std::pair<bool, std::string> style,
const Size&,
const float pixelRatio,
const optional<CameraOptions> cameraOptions,
const optional<LatLngBounds> region,
const optional<std::string> programCacheDir,
- const optional<std::string> localFontFamily = {});
+ const optional<std::string> localFontFamily,
+ const ResourceOptions& resourceOptions);
void setStyleURL(std::string styleURL);
std::string getStyleURL() const;
@@ -47,19 +47,20 @@ private:
Map map;
};
-MapSnapshotter::Impl::Impl(FileSource* fileSource,
- std::shared_ptr<Scheduler> scheduler_,
- const std::pair<bool, std::string> style,
- const Size& size,
- const float pixelRatio,
- const optional<CameraOptions> cameraOptions,
- const optional<LatLngBounds> region,
- const optional<std::string> programCacheDir,
- const optional<std::string> localFontFamily)
- : scheduler(std::move(scheduler_))
- , frontend(size, pixelRatio, *scheduler, programCacheDir, GLContextMode::Unique, localFontFamily)
- , map(frontend, MapObserver::nullObserver(), size, pixelRatio, *fileSource, *scheduler, MapOptions().withMapMode(MapMode::Static)) {
-
+MapSnapshotter::Impl::Impl(std::shared_ptr<Scheduler> scheduler_,
+ const std::pair<bool, std::string> style,
+ const Size& size,
+ const float pixelRatio,
+ const optional<CameraOptions> cameraOptions,
+ const optional<LatLngBounds> region,
+ const optional<std::string> programCacheDir,
+ const optional<std::string> localFontFamily,
+ const ResourceOptions& resourceOptions)
+ : scheduler(std::move(scheduler_))
+ , frontend(size, pixelRatio, *scheduler, programCacheDir, GLContextMode::Unique, localFontFamily)
+ , map(frontend, MapObserver::nullObserver(), *scheduler,
+ MapOptions().withMapMode(MapMode::Static).withSize(size).withPixelRatio(pixelRatio),
+ resourceOptions) {
if (style.first) {
map.getStyle().loadJSON(style.second);
} else{
@@ -142,7 +143,7 @@ void MapSnapshotter::Impl::setSize(Size size) {
}
Size MapSnapshotter::Impl::getSize() const {
- return map.getSize();
+ return map.getMapOptions().size();
}
void MapSnapshotter::Impl::setCameraOptions(CameraOptions cameraOptions) {
@@ -164,17 +165,18 @@ LatLngBounds MapSnapshotter::Impl::getRegion() const {
return map.latLngBoundsForCamera(getCameraOptions());
}
-MapSnapshotter::MapSnapshotter(FileSource* fileSource,
- std::shared_ptr<Scheduler> scheduler,
+MapSnapshotter::MapSnapshotter(std::shared_ptr<Scheduler> scheduler,
const std::pair<bool, std::string> style,
const Size& size,
const float pixelRatio,
const optional<CameraOptions> cameraOptions,
const optional<LatLngBounds> region,
const optional<std::string> programCacheDir,
- const optional<std::string> localFontFamily)
- : impl(std::make_unique<util::Thread<MapSnapshotter::Impl>>("Map Snapshotter", fileSource, std::move(scheduler), style, size, pixelRatio, cameraOptions, region, programCacheDir, localFontFamily)) {
-}
+ const optional<std::string> localFontFamily,
+ const ResourceOptions& resourceOptions)
+ : impl(std::make_unique<util::Thread<MapSnapshotter::Impl>>(
+ "Map Snapshotter", std::move(scheduler), style, size, pixelRatio, cameraOptions,
+ region, programCacheDir, localFontFamily, resourceOptions.clone())) {}
MapSnapshotter::~MapSnapshotter() = default;
diff --git a/platform/default/src/mbgl/storage/default_file_source.cpp b/platform/default/src/mbgl/storage/default_file_source.cpp
index 32eb8b3d58..4d812044cf 100644
--- a/platform/default/src/mbgl/storage/default_file_source.cpp
+++ b/platform/default/src/mbgl/storage/default_file_source.cpp
@@ -201,9 +201,9 @@ private:
};
DefaultFileSource::DefaultFileSource(const std::string& cachePath,
- const std::string& assetRoot,
+ const std::string& assetPath,
uint64_t maximumCacheSize)
- : DefaultFileSource(cachePath, std::make_unique<AssetFileSource>(assetRoot), maximumCacheSize) {
+ : DefaultFileSource(cachePath, std::make_unique<AssetFileSource>(assetPath), maximumCacheSize) {
}
DefaultFileSource::DefaultFileSource(const std::string& cachePath,
diff --git a/platform/default/src/mbgl/storage/file_source.cpp b/platform/default/src/mbgl/storage/file_source.cpp
new file mode 100644
index 0000000000..a7bbe82f5a
--- /dev/null
+++ b/platform/default/src/mbgl/storage/file_source.cpp
@@ -0,0 +1,15 @@
+#include <mbgl/storage/resource_options.hpp>
+#include <mbgl/storage/default_file_source.hpp>
+
+#include <memory>
+
+namespace mbgl {
+
+std::shared_ptr<FileSource> FileSource::createPlatformFileSource(const ResourceOptions& options) {
+ auto fileSource = std::make_shared<DefaultFileSource>(options.cachePath(), options.assetPath());
+ fileSource->setAccessToken(options.accessToken());
+ fileSource->setAPIBaseURL(options.baseURL());
+ return fileSource;
+}
+
+} // namespace mbgl
diff --git a/platform/glfw/glfw_renderer_frontend.cpp b/platform/glfw/glfw_renderer_frontend.cpp
index 73205f1c56..9c5320cc78 100644
--- a/platform/glfw/glfw_renderer_frontend.cpp
+++ b/platform/glfw/glfw_renderer_frontend.cpp
@@ -32,7 +32,12 @@ void GLFWRendererFrontend::render() {
mbgl::BackendScope guard { glfwView, mbgl::BackendScope::ScopeType::Implicit };
- renderer->render(*updateParameters);
+ // onStyleImageMissing might be called during a render. The user implemented method
+ // could trigger a call to MGLRenderFrontend#update which overwrites `updateParameters`.
+ // Copy the shared pointer here so that the parameters aren't destroyed while `render(...)` is
+ // still using them.
+ auto updateParameters_ = updateParameters;
+ renderer->render(*updateParameters_);
}
mbgl::Renderer* GLFWRendererFrontend::getRenderer() {
diff --git a/platform/glfw/glfw_view.cpp b/platform/glfw/glfw_view.cpp
index e768851a53..601642cfa6 100644
--- a/platform/glfw/glfw_view.cpp
+++ b/platform/glfw/glfw_view.cpp
@@ -385,7 +385,7 @@ GLFWView::makeImage(const std::string& id, int width, int height, float pixelRat
void GLFWView::nextOrientation() {
using NO = mbgl::NorthOrientation;
- switch (map->getNorthOrientation()) {
+ switch (map->getMapOptions().northOrientation()) {
case NO::Upwards: map->setNorthOrientation(NO::Rightwards); break;
case NO::Rightwards: map->setNorthOrientation(NO::Downwards); break;
case NO::Downwards: map->setNorthOrientation(NO::Leftwards); break;
diff --git a/platform/glfw/main.cpp b/platform/glfw/main.cpp
index 38a41cbf18..fb7c2b4ffb 100644
--- a/platform/glfw/main.cpp
+++ b/platform/glfw/main.cpp
@@ -10,7 +10,7 @@
#include <mbgl/style/style.hpp>
#include <mbgl/renderer/renderer.hpp>
-#include <args/args.hxx>
+#include <args.hxx>
#include <csignal>
#include <fstream>
@@ -93,23 +93,26 @@ int main(int argc, char *argv[]) {
GLFWView backend(fullscreen, benchmark);
view = &backend;
- mbgl::DefaultFileSource fileSource(cacheDB, ".");
- if (!settings.online) {
- fileSource.setOnlineStatus(false);
- mbgl::Log::Warning(mbgl::Event::Setup, "Application is offline. Press `O` to toggle online status.");
- }
-
// Set access token if present
- const char *token = getenv("MAPBOX_ACCESS_TOKEN");
- if (token == nullptr) {
+ std::string token(getenv("MAPBOX_ACCESS_TOKEN") ?: "");
+ if (token.empty()) {
mbgl::Log::Warning(mbgl::Event::Setup, "no access token set. mapbox.com tiles won't work.");
- } else {
- fileSource.setAccessToken(std::string(token));
+ }
+
+ mbgl::ResourceOptions resourceOptions;
+ resourceOptions.withCachePath(cacheDB).withAccessToken(token);
+
+ auto fileSource = std::static_pointer_cast<mbgl::DefaultFileSource>(mbgl::FileSource::getSharedFileSource(resourceOptions));
+ if (!settings.online) {
+ fileSource->setOnlineStatus(false);
+ mbgl::Log::Warning(mbgl::Event::Setup, "Application is offline. Press `O` to toggle online status.");
}
mbgl::ThreadPool threadPool(4);
GLFWRendererFrontend rendererFrontend { std::make_unique<mbgl::Renderer>(backend, view->getPixelRatio(), threadPool), backend };
- mbgl::Map map(rendererFrontend, backend, view->getSize(), view->getPixelRatio(), fileSource, threadPool, mbgl::MapOptions());
+
+ mbgl::Map map(rendererFrontend, backend, threadPool,
+ mbgl::MapOptions().withSize(view->getSize()).withPixelRatio(view->getPixelRatio()), resourceOptions);
backend.setMap(&map);
@@ -124,9 +127,9 @@ int main(int argc, char *argv[]) {
.withPitch(settings.pitch));
map.setDebug(mbgl::MapDebugOptions(settings.debug));
- view->setOnlineStatusCallback([&settings, &fileSource]() {
+ view->setOnlineStatusCallback([&settings, fileSource]() {
settings.online = !settings.online;
- fileSource.setOnlineStatus(settings.online);
+ fileSource->setOnlineStatus(settings.online);
mbgl::Log::Info(mbgl::Event::Setup, "Application is %s. Press `O` to toggle online status.", settings.online ? "online" : "offline");
});
@@ -144,13 +147,13 @@ int main(int argc, char *argv[]) {
mbgl::Log::Info(mbgl::Event::Setup, "Changed style to: %s", newStyle.name);
});
- view->setPauseResumeCallback([&fileSource] () {
+ view->setPauseResumeCallback([fileSource] () {
static bool isPaused = false;
if (isPaused) {
- fileSource.resume();
+ fileSource->resume();
} else {
- fileSource.pause();
+ fileSource->pause();
}
isPaused = !isPaused;
diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md
index a1ab7c949a..d7a68c40b4 100644
--- a/platform/ios/CHANGELOG.md
+++ b/platform/ios/CHANGELOG.md
@@ -4,15 +4,29 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
## 4.10.0
+### Styles and rendering
+
* Client-side text rendering of CJK ideographs is now enabled by default. ([#13988](https://github.com/mapbox/mapbox-gl-native/pull/13988))
-* Added an MGLMapView.prefetchesTiles property that you can disable if you don’t want to prefetch simplified tiles as a performance optimization. ([#14031](https://github.com/mapbox/mapbox-gl-native/pull/14031))
* Fixed an issue that caused `MGL_FUNCTION` to ignore multiple formatting parameters when passed a `format` function as parameter. ([#14064](https://github.com/mapbox/mapbox-gl-native/pull/14064))
+* Added `mgl_attributed:` expression operator, which concatenates `MGLAttributedExpression` objects for specifying rich text in the `MGLSymbolStyleLayer.text` property. ([#14094](https://github.com/mapbox/mapbox-gl-native/pull/14094))
+* Fixed an issue that caused conditional expressions to crash when passed nested conditional expressions as parameters. ([#14181](https://github.com/mapbox/mapbox-gl-native/pull/14181))
+* Added `-[MGLMapViewDelegate mapView:didFailToLoadImage:]` to load missing symbol icons in the style if they are not found. ([#14302](https://github.com/mapbox/mapbox-gl-native/pull/14302))
+
+### Packaging
+
* Added a Galician localization. ([#14095](https://github.com/mapbox/mapbox-gl-native/pull/14095))
-* Added `mgl_attributed:` expression operator, which concatenate `MGLAttributedExpression` objects for specifying rich text in the `MGLSymbolStyleLayer.text` property. ([#14094](https://github.com/mapbox/mapbox-gl-native/pull/14094))
+* Added support for building with Xcode 10.2 / iOS SDK 12.2. ([#14241](https://github.com/mapbox/mapbox-gl-native/pull/14241))
-### User interaction
+### Offline maps
+
+* Fixed a bug that caused offline packs created prior to v4.0.0 to be marked as `MGLOfflinePackStateInactive`. ([#14188](https://github.com/mapbox/mapbox-gl-native/pull/14188))
+
+### Other changes
+
+* Added `MGLOrnamentPosition` enum and margin properties to customize scale bar, compass, logo, and attribution position within the map view. ([#13911](https://github.com/mapbox/mapbox-gl-native/pull/13911))
+* Added an `MGLMapView.prefetchesTiles` property to configure lower-resolution tile prefetching behavior. ([#14031](https://github.com/mapbox/mapbox-gl-native/pull/14031))
+* Speculatively fixed a performance issue seen on iOS 12.2, when an `MGLMapView` is repeatedly removed and re-added in a view hierarchy. ([#14264](https://github.com/mapbox/mapbox-gl-native/pull/14264))
-* Added `MGLOrnamentPosition` enum and margins methods to customize MGLMapView's scale bar, compass, logo and attribution position. ([#13911](https://github.com/mapbox/mapbox-gl-native/pull/13911))
## 4.9.0 - February 27, 2019
diff --git a/platform/ios/Integration Tests/Annotation Tests/MGLAnnotationViewIntegrationTests.m b/platform/ios/Integration Tests/Annotation Tests/MGLAnnotationViewIntegrationTests.m
index 7ec45de072..0b32df55b4 100644
--- a/platform/ios/Integration Tests/Annotation Tests/MGLAnnotationViewIntegrationTests.m
+++ b/platform/ios/Integration Tests/Annotation Tests/MGLAnnotationViewIntegrationTests.m
@@ -405,7 +405,6 @@ static const CGFloat kAnnotationScale = 0.125f;
NSString * const MGLTestAnnotationReuseIdentifer = @"MGLTestAnnotationReuseIdentifer";
- CGFloat epsilon = 0.0000001;
CGSize size = self.mapView.bounds.size;
CGSize annotationSize = CGSizeMake(40.0, 40.0);
diff --git a/platform/ios/Integration Tests/MGLCameraTransitionTests.mm b/platform/ios/Integration Tests/MGLCameraTransitionTests.mm
index e422c46cf4..60d5fc6c9a 100644
--- a/platform/ios/Integration Tests/MGLCameraTransitionTests.mm
+++ b/platform/ios/Integration Tests/MGLCameraTransitionTests.mm
@@ -277,7 +277,7 @@
// Now set another coordinate.
MGLMapCamera *camera = [MGLMapCamera cameraLookingAtCenterCoordinate:target2
- fromDistance:altitude
+ altitude:altitude
pitch:0.0
heading:0.0];
diff --git a/platform/ios/Mapbox-iOS-SDK-snapshot-dynamic.podspec b/platform/ios/Mapbox-iOS-SDK-snapshot-dynamic.podspec
index bff5531290..4030511c1b 100644
--- a/platform/ios/Mapbox-iOS-SDK-snapshot-dynamic.podspec
+++ b/platform/ios/Mapbox-iOS-SDK-snapshot-dynamic.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |m|
- version = '4.10.0-alpha.2'
+ version = '4.10.0-beta.2'
m.name = 'Mapbox-iOS-SDK-snapshot-dynamic'
m.version = "#{version}-snapshot"
diff --git a/platform/ios/Mapbox-iOS-SDK-stripped.podspec b/platform/ios/Mapbox-iOS-SDK-stripped.podspec
index 9a32524ef0..d3a6d698a7 100644
--- a/platform/ios/Mapbox-iOS-SDK-stripped.podspec
+++ b/platform/ios/Mapbox-iOS-SDK-stripped.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |m|
- version = '4.10.0-alpha.2'
+ version = '4.10.0-beta.2'
m.name = 'Mapbox-iOS-SDK-stripped'
m.version = "#{version}-stripped"
diff --git a/platform/ios/Mapbox-iOS-SDK.podspec b/platform/ios/Mapbox-iOS-SDK.podspec
index 1cbd82c5e4..f8dc21a155 100644
--- a/platform/ios/Mapbox-iOS-SDK.podspec
+++ b/platform/ios/Mapbox-iOS-SDK.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |m|
- version = '4.10.0-alpha.2'
+ version = '4.10.0-beta.2'
m.name = 'Mapbox-iOS-SDK'
m.version = version
diff --git a/platform/ios/app/MBXViewController.m b/platform/ios/app/MBXViewController.m
index 9c506cadfa..8d936d6a25 100644
--- a/platform/ios/app/MBXViewController.m
+++ b/platform/ios/app/MBXViewController.m
@@ -103,6 +103,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
MBXSettingsMiscellaneousToggleTwoMaps,
MBXSettingsMiscellaneousLocalizeLabels,
MBXSettingsMiscellaneousShowSnapshots,
+ MBXSettingsMiscellaneousMissingIcon,
MBXSettingsMiscellaneousShouldLimitCameraChanges,
MBXSettingsMiscellaneousShowCustomLocationManager,
MBXSettingsMiscellaneousOrnamentsPlacement,
@@ -499,6 +500,7 @@ CLLocationCoordinate2D randomWorldCoordinate() {
[NSString stringWithFormat:@"%@ Second Map", ([self.view viewWithTag:2] == nil ? @"Show" : @"Hide")],
[NSString stringWithFormat:@"Show Labels in %@", (_localizingLabels ? @"Default Language" : [[NSLocale currentLocale] displayNameForKey:NSLocaleIdentifier value:[self bestLanguageForUser]])],
@"Show Snapshots",
+ @"Missing Icon",
[NSString stringWithFormat:@"%@ Camera Changes", (_shouldLimitCameraChanges ? @"Unlimit" : @"Limit")],
@"View Route Simulation",
@"Ornaments Placement",
@@ -746,6 +748,11 @@ CLLocationCoordinate2D randomWorldCoordinate() {
[self performSegueWithIdentifier:@"ShowSnapshots" sender:nil];
break;
}
+ case MBXSettingsMiscellaneousMissingIcon:
+ {
+ [self loadMissingIcon];
+ break;
+ }
case MBXSettingsMiscellaneousShowCustomLocationManager:
{
[self performSegueWithIdentifier:@"ShowCustomLocationManger" sender:nil];
@@ -1718,6 +1725,19 @@ CLLocationCoordinate2D randomWorldCoordinate() {
[self.mapView addAnnotation:line];
}
+- (void)loadMissingIcon
+{
+ self.mapView.centerCoordinate = CLLocationCoordinate2DMake(0, 0);
+ self.mapView.zoomLevel = 1;
+ NSURL *customStyleJSON = [[NSBundle mainBundle] URLForResource:@"missing_icon" withExtension:@"json"];
+ [self.mapView setStyleURL:customStyleJSON];
+}
+
+- (UIImage *)mapView:(MGLMapView *)mapView didFailToLoadImage:(NSString *)imageName {
+ UIImage *backupImage = [UIImage imageNamed:@"AppIcon"];
+ return backupImage;
+}
+
- (void)printTelemetryLogFile
{
NSString *fileContents = [NSString stringWithContentsOfFile:[self telemetryDebugLogFilePath] encoding:NSUTF8StringEncoding error:nil];
diff --git a/platform/ios/app/missing_icon.json b/platform/ios/app/missing_icon.json
new file mode 100644
index 0000000000..5da4125990
--- /dev/null
+++ b/platform/ios/app/missing_icon.json
@@ -0,0 +1,40 @@
+{
+ "version": 8,
+ "name": "Mapbox Streets",
+ "sprite": "mapbox://sprites/mapbox/streets-v8",
+ "glyphs": "mapbox://fonts/mapbox/{fontstack}/{range}.pbf",
+ "sources": {
+ "point": {
+ "type": "geojson",
+ "data": {
+ "type": "Feature",
+ "properties": {},
+ "geometry": {
+ "type": "Point",
+ "coordinates": [0, 0]
+ }
+ }
+ }
+ },
+ "layers": [{
+ "id": "bg",
+ "type": "background",
+ "paint": {
+ "background-color": "#f00"
+ }
+ }, {
+ "id": "point",
+ "type": "circle",
+ "source": "point",
+ "paint": {
+ "circle-radius": 100
+ }
+ }, {
+ "id": "icon",
+ "type": "symbol",
+ "source": "point",
+ "layout": {
+ "icon-image": "missing-icon"
+ }
+ }]
+}
diff --git a/platform/ios/docs/guides/For Style Authors.md b/platform/ios/docs/guides/For Style Authors.md
index 73394ff6ed..1acf587cda 100644
--- a/platform/ios/docs/guides/For Style Authors.md
+++ b/platform/ios/docs/guides/For Style Authors.md
@@ -418,5 +418,16 @@ In style JSON | In the format string
`["any", f0, …, fn]` | `p0 OR … OR pn`
`["none", f0, …, fn]` | `NOT (p0 OR … OR pn)`
+## Specifying the text format
+
+The following format attributes are defined as `NSString` constans that you
+can use to update the formatting of `MGLSymbolStyleLayer.text` property.
+
+In style JSON | In Objective-C | In Swift
+--------------|-----------------------|---------
+`text-font` | `MGLFontNamesAttribute` | `.fontNamesAttribute`
+`font-scale` | `MGLFontScaleAttribute` | `.fontScaleAttribute`
+`text-color` | `MGLFontColorAttribute` | `.fontColorAttribute`
+
See the “[Predicates and Expressions](predicates-and-expressions.html)” guide for
a full description of the supported operators and operand types.
diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj
index b24bcbe110..1fe22d2c7d 100644
--- a/platform/ios/ios.xcodeproj/project.pbxproj
+++ b/platform/ios/ios.xcodeproj/project.pbxproj
@@ -98,9 +98,6 @@
35136D4D1D4277FC00C20EFD /* MGLSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 35136D4A1D4277FC00C20EFD /* MGLSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
35136D4E1D4277FC00C20EFD /* MGLSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35136D4B1D4277FC00C20EFD /* MGLSource.mm */; };
35136D4F1D4277FC00C20EFD /* MGLSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35136D4B1D4277FC00C20EFD /* MGLSource.mm */; };
- 35305D481D22AA680007D005 /* NSData+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35305D471D22AA450007D005 /* NSData+MGLAdditions.mm */; };
- 35305D491D22AA680007D005 /* NSData+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35305D471D22AA450007D005 /* NSData+MGLAdditions.mm */; };
- 35305D4A1D22AA6A0007D005 /* NSData+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 35305D461D22AA450007D005 /* NSData+MGLAdditions.h */; };
3538AA1D1D542239008EC33D /* MGLForegroundStyleLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 3538AA1B1D542239008EC33D /* MGLForegroundStyleLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
3538AA1E1D542239008EC33D /* MGLForegroundStyleLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 3538AA1B1D542239008EC33D /* MGLForegroundStyleLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
3538AA1F1D542239008EC33D /* MGLForegroundStyleLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3538AA1C1D542239008EC33D /* MGLForegroundStyleLayer.mm */; };
@@ -179,7 +176,6 @@
35E0CFE71D3E501500188327 /* MGLStyle_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 35E0CFE51D3E501500188327 /* MGLStyle_Private.h */; };
35E1A4D81D74336F007AA97F /* MGLValueEvaluator.h in Headers */ = {isa = PBXBuildFile; fileRef = 35E1A4D71D74336F007AA97F /* MGLValueEvaluator.h */; };
35E1A4D91D74336F007AA97F /* MGLValueEvaluator.h in Headers */ = {isa = PBXBuildFile; fileRef = 35E1A4D71D74336F007AA97F /* MGLValueEvaluator.h */; };
- 35E208A71D24210F00EC9A46 /* MGLNSDataAdditionsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 35E208A61D24210F00EC9A46 /* MGLNSDataAdditionsTests.m */; };
35E79F201D41266300957B9E /* MGLStyleLayer_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 35E79F1F1D41266300957B9E /* MGLStyleLayer_Private.h */; };
35E79F211D41266300957B9E /* MGLStyleLayer_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 35E79F1F1D41266300957B9E /* MGLStyleLayer_Private.h */; };
3E6465D62065767A00685536 /* LimeGreenStyleLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E6465D42065767A00685536 /* LimeGreenStyleLayer.m */; };
@@ -223,7 +219,6 @@
40834BEE1FE05E1800C1BD0D /* MMEEventsConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BB21FE05D6D00C1BD0D /* MMEEventsConfiguration.m */; };
40834BEF1FE05E1800C1BD0D /* MMEEventsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BA41FE05D6B00C1BD0D /* MMEEventsManager.m */; };
40834BF01FE05E1800C1BD0D /* MMELocationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BB81FE05D6D00C1BD0D /* MMELocationManager.m */; };
- 40834BF11FE05E1800C1BD0D /* MMENSDateWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BBC1FE05D6E00C1BD0D /* MMENSDateWrapper.m */; };
40834BF21FE05E1800C1BD0D /* MMENSURLSessionWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BC61FE05D7000C1BD0D /* MMENSURLSessionWrapper.m */; };
40834BF31FE05E1800C1BD0D /* MMETimerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BB91FE05D6E00C1BD0D /* MMETimerManager.m */; };
40834BF51FE05E1800C1BD0D /* MMETypes.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BBD1FE05D6E00C1BD0D /* MMETypes.m */; };
@@ -242,7 +237,7 @@
40834C021FE05E1800C1BD0D /* MMEEventsConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BB21FE05D6D00C1BD0D /* MMEEventsConfiguration.m */; };
40834C031FE05E1800C1BD0D /* MMEEventsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BA41FE05D6B00C1BD0D /* MMEEventsManager.m */; };
40834C041FE05E1800C1BD0D /* MMELocationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BB81FE05D6D00C1BD0D /* MMELocationManager.m */; };
- 40834C051FE05E1800C1BD0D /* MMENSDateWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BBC1FE05D6E00C1BD0D /* MMENSDateWrapper.m */; };
+ 40834C051FE05E1800C1BD0D /* MMEDate.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BBC1FE05D6E00C1BD0D /* MMEDate.m */; };
40834C061FE05E1800C1BD0D /* MMENSURLSessionWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BC61FE05D7000C1BD0D /* MMENSURLSessionWrapper.m */; };
40834C071FE05E1800C1BD0D /* MMETimerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BB91FE05D6E00C1BD0D /* MMETimerManager.m */; };
40834C091FE05E1800C1BD0D /* MMETypes.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BBD1FE05D6E00C1BD0D /* MMETypes.m */; };
@@ -340,7 +335,6 @@
55E5666221C2A2080008B8B5 /* MMELocationManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 40834BB31FE05D6D00C1BD0D /* MMELocationManager.h */; };
55E5666321C2A2080008B8B5 /* MMEMetrics.h in Headers */ = {isa = PBXBuildFile; fileRef = ACD024552187EAAF00D8C8A7 /* MMEMetrics.h */; };
55E5666421C2A2080008B8B5 /* MMEMetricsManager.h in Headers */ = {isa = PBXBuildFile; fileRef = ACD024562187EAAF00D8C8A7 /* MMEMetricsManager.h */; };
- 55E5666521C2A2080008B8B5 /* MMENSDateWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 40834BC51FE05D6F00C1BD0D /* MMENSDateWrapper.h */; };
55E5666621C2A2080008B8B5 /* MMENSURLSessionWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 40834BAA1FE05D6C00C1BD0D /* MMENSURLSessionWrapper.h */; };
55E5666721C2A2080008B8B5 /* MMETimerManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 40834BC91FE05D7000C1BD0D /* MMETimerManager.h */; };
55E5666821C2A2080008B8B5 /* MMETypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 40834BB61FE05D6D00C1BD0D /* MMETypes.h */; };
@@ -451,7 +445,6 @@
96E516F12000596800A02306 /* NSString+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848171CBAFA6200AB86E3 /* NSString+MGLAdditions.h */; };
96E516F22000596D00A02306 /* NSException+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848141CBAFA6200AB86E3 /* NSException+MGLAdditions.h */; };
96E516F32000597100A02306 /* NSDictionary+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 408AA8551DAEDA0800022900 /* NSDictionary+MGLAdditions.h */; };
- 96E516F42000597D00A02306 /* NSData+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 35305D461D22AA450007D005 /* NSData+MGLAdditions.h */; };
96E516F5200059B100A02306 /* MGLNetworkConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = DD0902A41DB18F1B00C5BDCE /* MGLNetworkConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; };
96E516F6200059EC00A02306 /* MGLRendererFrontend.h in Headers */ = {isa = PBXBuildFile; fileRef = 92F2C3EC1F0E3C3A00268EC0 /* MGLRendererFrontend.h */; };
96E516F720005A2700A02306 /* MGLAnnotationContainerView.h in Headers */ = {isa = PBXBuildFile; fileRef = 40EDA1BD1CFE0D4A00D9EA68 /* MGLAnnotationContainerView.h */; };
@@ -464,6 +457,9 @@
96E5170420005A6B00A02306 /* SMCalloutView.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848891CBB037E00AB86E3 /* SMCalloutView.h */; };
96ED34DE22374C0900E9FCA9 /* MGLMapViewDirectionTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 96ED34DD22374C0900E9FCA9 /* MGLMapViewDirectionTests.mm */; };
96F3F73C1F57124B003E2D2C /* MGLUserLocationHeadingIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 96F3F73B1F5711F1003E2D2C /* MGLUserLocationHeadingIndicator.h */; };
+ 9C188C4F2242C95A0022FA55 /* MMEDate.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BBC1FE05D6E00C1BD0D /* MMEDate.m */; };
+ 9C188C502242C96F0022FA55 /* MMEDate.h in Headers */ = {isa = PBXBuildFile; fileRef = 40834BC51FE05D6F00C1BD0D /* MMEDate.h */; };
+ A4F3FB1D2254865900A30170 /* missing_icon.json in Resources */ = {isa = PBXBuildFile; fileRef = A4F3FB1C2254865900A30170 /* missing_icon.json */; };
AC1B0916221CA14D00DB56C8 /* CLLocationManager+MMEMobileEvents.h in Headers */ = {isa = PBXBuildFile; fileRef = AC1B0914221CA14500DB56C8 /* CLLocationManager+MMEMobileEvents.h */; };
AC1B0917221CA14D00DB56C8 /* CLLocationManager+MMEMobileEvents.h in Headers */ = {isa = PBXBuildFile; fileRef = AC1B0914221CA14500DB56C8 /* CLLocationManager+MMEMobileEvents.h */; };
AC1B0918221CA14D00DB56C8 /* CLLocationManager+MMEMobileEvents.m in Sources */ = {isa = PBXBuildFile; fileRef = AC1B0915221CA14C00DB56C8 /* CLLocationManager+MMEMobileEvents.m */; };
@@ -914,8 +910,6 @@
35136D441D42275100C20EFD /* MGLSymbolStyleLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLSymbolStyleLayer.mm; sourceTree = "<group>"; };
35136D4A1D4277FC00C20EFD /* MGLSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLSource.h; sourceTree = "<group>"; };
35136D4B1D4277FC00C20EFD /* MGLSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLSource.mm; sourceTree = "<group>"; };
- 35305D461D22AA450007D005 /* NSData+MGLAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSData+MGLAdditions.h"; sourceTree = "<group>"; };
- 35305D471D22AA450007D005 /* NSData+MGLAdditions.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSData+MGLAdditions.mm"; sourceTree = "<group>"; };
3538AA1B1D542239008EC33D /* MGLForegroundStyleLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLForegroundStyleLayer.h; sourceTree = "<group>"; };
3538AA1C1D542239008EC33D /* MGLForegroundStyleLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLForegroundStyleLayer.mm; sourceTree = "<group>"; };
353933F11D3FB753003F57D7 /* MGLCircleStyleLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLCircleStyleLayer.h; sourceTree = "<group>"; };
@@ -964,7 +958,6 @@
35DE35531EB7CBA8004917C5 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = sv; path = sv.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
35E0CFE51D3E501500188327 /* MGLStyle_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLStyle_Private.h; sourceTree = "<group>"; };
35E1A4D71D74336F007AA97F /* MGLValueEvaluator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLValueEvaluator.h; sourceTree = "<group>"; };
- 35E208A61D24210F00EC9A46 /* MGLNSDataAdditionsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLNSDataAdditionsTests.m; sourceTree = "<group>"; };
35E79F1F1D41266300957B9E /* MGLStyleLayer_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLStyleLayer_Private.h; sourceTree = "<group>"; };
36F1153C1D46080700878E1A /* libmbgl-platform-ios.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libmbgl-platform-ios.a"; path = "build/Debug-iphoneos/libmbgl-platform-ios.a"; sourceTree = "<group>"; };
3E6465D42065767A00685536 /* LimeGreenStyleLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LimeGreenStyleLayer.m; path = ../../darwin/app/LimeGreenStyleLayer.m; sourceTree = "<group>"; };
@@ -1012,7 +1005,7 @@
40834BB91FE05D6E00C1BD0D /* MMETimerManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMETimerManager.m; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMETimerManager.m"; sourceTree = SOURCE_ROOT; };
40834BBA1FE05D6E00C1BD0D /* MMEEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMEEvent.h; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMEEvent.h"; sourceTree = SOURCE_ROOT; };
40834BBB1FE05D6E00C1BD0D /* MMEEventsConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMEEventsConfiguration.h; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMEEventsConfiguration.h"; sourceTree = SOURCE_ROOT; };
- 40834BBC1FE05D6E00C1BD0D /* MMENSDateWrapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMENSDateWrapper.m; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMENSDateWrapper.m"; sourceTree = SOURCE_ROOT; };
+ 40834BBC1FE05D6E00C1BD0D /* MMEDate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMEDate.m; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMEDate.m"; sourceTree = SOURCE_ROOT; };
40834BBD1FE05D6E00C1BD0D /* MMETypes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMETypes.m; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMETypes.m"; sourceTree = SOURCE_ROOT; };
40834BBE1FE05D6E00C1BD0D /* MMEUIApplicationWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMEUIApplicationWrapper.h; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMEUIApplicationWrapper.h"; sourceTree = SOURCE_ROOT; };
40834BBF1FE05D6E00C1BD0D /* MMEUniqueIdentifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMEUniqueIdentifier.h; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMEUniqueIdentifier.h"; sourceTree = SOURCE_ROOT; };
@@ -1020,7 +1013,7 @@
40834BC21FE05D6F00C1BD0D /* CLLocation+MMEMobileEvents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "CLLocation+MMEMobileEvents.h"; path = "vendor/mapbox-events-ios/MapboxMobileEvents/CLLocation+MMEMobileEvents.h"; sourceTree = SOURCE_ROOT; };
40834BC31FE05D6F00C1BD0D /* CLLocation+MMEMobileEvents.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "CLLocation+MMEMobileEvents.m"; path = "vendor/mapbox-events-ios/MapboxMobileEvents/CLLocation+MMEMobileEvents.m"; sourceTree = SOURCE_ROOT; };
40834BC41FE05D6F00C1BD0D /* MMECategoryLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMECategoryLoader.m; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMECategoryLoader.m"; sourceTree = SOURCE_ROOT; };
- 40834BC51FE05D6F00C1BD0D /* MMENSDateWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMENSDateWrapper.h; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMENSDateWrapper.h"; sourceTree = SOURCE_ROOT; };
+ 40834BC51FE05D6F00C1BD0D /* MMEDate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMEDate.h; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMEDate.h"; sourceTree = SOURCE_ROOT; };
40834BC61FE05D7000C1BD0D /* MMENSURLSessionWrapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMENSURLSessionWrapper.m; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMENSURLSessionWrapper.m"; sourceTree = SOURCE_ROOT; };
40834BC71FE05D7000C1BD0D /* MMEEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMEEvent.m; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMEEvent.m"; sourceTree = SOURCE_ROOT; };
40834BC81FE05D7000C1BD0D /* MMENamespacedDependencies.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMENamespacedDependencies.h; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMENamespacedDependencies.h"; sourceTree = SOURCE_ROOT; };
@@ -1151,6 +1144,7 @@
96ED34DD22374C0900E9FCA9 /* MGLMapViewDirectionTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLMapViewDirectionTests.mm; sourceTree = "<group>"; };
96F017292118FBAE00892778 /* MGLMapView_Experimental.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLMapView_Experimental.h; sourceTree = "<group>"; };
96F3F73B1F5711F1003E2D2C /* MGLUserLocationHeadingIndicator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLUserLocationHeadingIndicator.h; sourceTree = "<group>"; };
+ A4F3FB1C2254865900A30170 /* missing_icon.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = missing_icon.json; sourceTree = "<group>"; };
AC1B0914221CA14500DB56C8 /* CLLocationManager+MMEMobileEvents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "CLLocationManager+MMEMobileEvents.h"; path = "../vendor/mapbox-events-ios/MapboxMobileEvents/CLLocationManager+MMEMobileEvents.h"; sourceTree = "<group>"; };
AC1B0915221CA14C00DB56C8 /* CLLocationManager+MMEMobileEvents.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "CLLocationManager+MMEMobileEvents.m"; path = "../vendor/mapbox-events-ios/MapboxMobileEvents/CLLocationManager+MMEMobileEvents.m"; sourceTree = "<group>"; };
AC518DFD201BB55A00EBC820 /* MGLTelemetryConfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLTelemetryConfig.h; sourceTree = "<group>"; };
@@ -1774,8 +1768,8 @@
ACD024572187EAAF00D8C8A7 /* MMEMetrics.m */,
ACD024562187EAAF00D8C8A7 /* MMEMetricsManager.h */,
ACD024542187EAAF00D8C8A7 /* MMEMetricsManager.m */,
- 40834BC51FE05D6F00C1BD0D /* MMENSDateWrapper.h */,
- 40834BBC1FE05D6E00C1BD0D /* MMENSDateWrapper.m */,
+ 40834BC51FE05D6F00C1BD0D /* MMEDate.h */,
+ 40834BBC1FE05D6E00C1BD0D /* MMEDate.m */,
40834BAA1FE05D6C00C1BD0D /* MMENSURLSessionWrapper.h */,
40834BC61FE05D7000C1BD0D /* MMENSURLSessionWrapper.m */,
40834BC91FE05D7000C1BD0D /* MMETimerManager.h */,
@@ -1891,6 +1885,7 @@
children = (
353BAEF51D646370009A8DA9 /* amsterdam.geojson */,
DA1DC96C1CB6C6CE006E619F /* points.geojson */,
+ A4F3FB1C2254865900A30170 /* missing_icon.json */,
DA1DC96D1CB6C6CE006E619F /* polyline.geojson */,
1F26B6C220E1A351007BCC21 /* simple_route.json */,
DA1DC96F1CB6C6CE006E619F /* threestates.geojson */,
@@ -2041,7 +2036,6 @@
96ED34DD22374C0900E9FCA9 /* MGLMapViewDirectionTests.mm */,
16376B481FFEED010000563E /* MGLMapViewLayoutTests.m */,
9658C154204761FC00D8A674 /* MGLMapViewScaleBarTests.m */,
- 35E208A61D24210F00EC9A46 /* MGLNSDataAdditionsTests.m */,
1F95931C1E6DE2E900D5B294 /* MGLNSDateAdditionsTests.mm */,
96036A0520059BBA00510F3D /* MGLNSOrthographyAdditionsTests.m */,
DAE7DEC11E245455007505A6 /* MGLNSStringAdditionsTests.m */,
@@ -2318,8 +2312,6 @@
3510FFE91D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.mm */,
3510FFF71D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.h */,
3510FFF81D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.mm */,
- 35305D461D22AA450007D005 /* NSData+MGLAdditions.h */,
- 35305D471D22AA450007D005 /* NSData+MGLAdditions.mm */,
353AFA121D65AB17005A69F4 /* NSDate+MGLAdditions.h */,
353AFA131D65AB17005A69F4 /* NSDate+MGLAdditions.mm */,
408AA8551DAEDA0800022900 /* NSDictionary+MGLAdditions.h */,
@@ -2461,6 +2453,7 @@
DD0902AB1DB192A800C5BDCE /* MGLNetworkConfiguration.h in Headers */,
35D3A1E61E9BE7EB002B38EE /* MGLScaleBar.h in Headers */,
0778DD431F67556700A73B34 /* MGLComputedShapeSource.h in Headers */,
+ 9C188C502242C96F0022FA55 /* MMEDate.h in Headers */,
1F6A82A221360F9D00BA5B41 /* MGLLoggingConfiguration.h in Headers */,
AC1B0916221CA14D00DB56C8 /* CLLocationManager+MMEMobileEvents.h in Headers */,
DA8848311CBAFA6200AB86E3 /* NSString+MGLAdditions.h in Headers */,
@@ -2530,7 +2523,6 @@
DA72620B1DEEE3480043BB89 /* MGLOpenGLStyleLayer.h in Headers */,
404C26E71D89C55D000AA13D /* MGLTileSource_Private.h in Headers */,
DA88485C1CBAFB9800AB86E3 /* MGLFaux3DUserLocationAnnotationView.h in Headers */,
- 35305D4A1D22AA6A0007D005 /* NSData+MGLAdditions.h in Headers */,
359F57461D2FDDA6005217F1 /* MGLUserLocationAnnotationView_Private.h in Headers */,
404C26E21D89B877000AA13D /* MGLTileSource.h in Headers */,
DA8847FD1CBAFA5100AB86E3 /* MGLTilePyramidOfflineRegion.h in Headers */,
@@ -2580,7 +2572,6 @@
55E5666221C2A2080008B8B5 /* MMELocationManager.h in Headers */,
55E5666321C2A2080008B8B5 /* MMEMetrics.h in Headers */,
55E5666421C2A2080008B8B5 /* MMEMetricsManager.h in Headers */,
- 55E5666521C2A2080008B8B5 /* MMENSDateWrapper.h in Headers */,
55E5666621C2A2080008B8B5 /* MMENSURLSessionWrapper.h in Headers */,
55E5666721C2A2080008B8B5 /* MMETimerManager.h in Headers */,
55E5666821C2A2080008B8B5 /* MMETypes.h in Headers */,
@@ -2724,7 +2715,6 @@
74CB5EB2219B252C00102936 /* MGLStyleLayerManager.h in Headers */,
9221BAB020699F8A0054BDF4 /* MGLTilePyramidOfflineRegion_Private.h in Headers */,
96E516F5200059B100A02306 /* MGLNetworkConfiguration.h in Headers */,
- 96E516F42000597D00A02306 /* NSData+MGLAdditions.h in Headers */,
96E516DD200054F200A02306 /* MGLPolygon_Private.h in Headers */,
353933F91D3FB79F003F57D7 /* MGLLineStyleLayer.h in Headers */,
96E516EB2000560B00A02306 /* MGLUserLocation_Private.h in Headers */,
@@ -2945,6 +2935,7 @@
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
+ English,
en,
Base,
"zh-Hans",
@@ -3014,6 +3005,7 @@
buildActionMask = 2147483647;
files = (
DD4823771D94AE6C00EB71B7 /* numeric_filter_style.json in Resources */,
+ A4F3FB1D2254865900A30170 /* missing_icon.json in Resources */,
DA1DC9701CB6C6CE006E619F /* points.geojson in Resources */,
353BAEF61D646370009A8DA9 /* amsterdam.geojson in Resources */,
DA1DC9711CB6C6CE006E619F /* polyline.geojson in Resources */,
@@ -3177,7 +3169,6 @@
357579831D502AE6000B822E /* MGLRasterStyleLayerTests.mm in Sources */,
DAF25720201902BC00367EF5 /* MGLHillshadeStyleLayerTests.mm in Sources */,
353D23961D0B0DFE002BE09D /* MGLAnnotationViewTests.m in Sources */,
- 35E208A71D24210F00EC9A46 /* MGLNSDataAdditionsTests.m in Sources */,
DA0CD5901CF56F6A00A5F5A5 /* MGLFeatureTests.mm in Sources */,
556660D81E1D085500E2C41B /* MGLVersionNumber.m in Sources */,
4031ACFF1E9FD29F00A3EA26 /* MGLSDKTestHelpers.swift in Sources */,
@@ -3189,6 +3180,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ 9C188C4F2242C95A0022FA55 /* MMEDate.m in Sources */,
35136D391D42271A00C20EFD /* MGLBackgroundStyleLayer.mm in Sources */,
3510FFEC1D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.mm in Sources */,
40834C431FE05F7500C1BD0D /* TSKSPKIHashCache.m in Sources */,
@@ -3224,7 +3216,6 @@
40834BF31FE05E1800C1BD0D /* MMETimerManager.m in Sources */,
35136D421D42274500C20EFD /* MGLRasterStyleLayer.mm in Sources */,
3538AA1F1D542239008EC33D /* MGLForegroundStyleLayer.mm in Sources */,
- 40834BF11FE05E1800C1BD0D /* MMENSDateWrapper.m in Sources */,
AC1B0918221CA14D00DB56C8 /* CLLocationManager+MMEMobileEvents.m in Sources */,
40834C461FE05F7500C1BD0D /* TSKPinFailureReport.m in Sources */,
406E99B91FFEFF1B00D9FFCC /* MMEEventLogReportViewController.m in Sources */,
@@ -3272,7 +3263,6 @@
DA35A2A11CC9E95F00E826B2 /* MGLCoordinateFormatter.m in Sources */,
92FC0AEE207CEE16007B6B54 /* MGLShapeOfflineRegion.mm in Sources */,
ACD0245E2187EACB00D8C8A7 /* MMEMetrics.m in Sources */,
- 35305D481D22AA680007D005 /* NSData+MGLAdditions.mm in Sources */,
40834BF61FE05E1800C1BD0D /* MMEUIApplicationWrapper.m in Sources */,
DA8848291CBAFA6200AB86E3 /* MGLStyle.mm in Sources */,
357FE2DF1E02D2B20068B753 /* NSCoder+MGLAdditions.mm in Sources */,
@@ -3361,7 +3351,7 @@
ACA65F5A2140697200537748 /* MMEDispatchManager.m in Sources */,
3538AA201D542239008EC33D /* MGLForegroundStyleLayer.mm in Sources */,
DA00FC911D5EEB0D009AABC8 /* MGLAttributionInfo.mm in Sources */,
- 40834C051FE05E1800C1BD0D /* MMENSDateWrapper.m in Sources */,
+ 40834C051FE05E1800C1BD0D /* MMEDate.m in Sources */,
40834C531FE05F7600C1BD0D /* TSKPinFailureReport.m in Sources */,
AC1B0919221CA14D00DB56C8 /* CLLocationManager+MMEMobileEvents.m in Sources */,
40834BFA1FE05E1800C1BD0D /* CLLocation+MMEMobileEvents.m in Sources */,
@@ -3405,7 +3395,6 @@
DAA4E4281CBB730400178DFB /* MGLTypes.m in Sources */,
DA35A2A21CC9E95F00E826B2 /* MGLCoordinateFormatter.m in Sources */,
40834C511FE05F7600C1BD0D /* reporting_utils.m in Sources */,
- 35305D491D22AA680007D005 /* NSData+MGLAdditions.mm in Sources */,
357FE2E01E02D2B20068B753 /* NSCoder+MGLAdditions.mm in Sources */,
92FC0AEF207CEE16007B6B54 /* MGLShapeOfflineRegion.mm in Sources */,
DAA4E42D1CBB730400178DFB /* MGLAnnotationImage.m in Sources */,
@@ -3693,7 +3682,7 @@
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Integration Tests/integration-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Integration Test Harness.app/Integration Test Harness";
};
@@ -3723,7 +3712,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.mapbox.integration-tests";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Integration Tests/integration-Bridging-Header.h";
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Integration Test Harness.app/Integration Test Harness";
};
@@ -3878,6 +3867,7 @@
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
GCC_PREFIX_HEADER = "$SRCROOT/src/Mapbox-Prefix.pch";
+ GCC_PREPROCESSOR_DEFINITIONS = "NDEBUG=1";
HEADER_SEARCH_PATHS = (
"$(mbgl_core_INCLUDE_DIRECTORIES)",
"$(mbgl_filesource_INCLUDE_DIRECTORIES)",
@@ -4007,7 +3997,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.mapbox.integration-tests";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Integration Tests/integration-Bridging-Header.h";
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Integration Test Harness.app/Integration Test Harness";
};
@@ -4312,6 +4302,7 @@
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
GCC_PREFIX_HEADER = "$SRCROOT/src/Mapbox-Prefix.pch";
+ GCC_PREPROCESSOR_DEFINITIONS = "NDEBUG=1";
HEADER_SEARCH_PATHS = (
"$(mbgl_core_INCLUDE_DIRECTORIES)",
"$(mbgl_filesource_INCLUDE_DIRECTORIES)",
diff --git a/platform/ios/scripts/package.sh b/platform/ios/scripts/package.sh
index 45aab45f3f..a37b3c7fda 100755
--- a/platform/ios/scripts/package.sh
+++ b/platform/ios/scripts/package.sh
@@ -11,6 +11,7 @@ PRODUCTS=${DERIVED_DATA}
LOG_PATH=build/xcodebuild-$(date +"%Y-%m-%d_%H%M%S").log
BUILD_FOR_DEVICE=${BUILD_DEVICE:-true}
+BUILD_DOCS=${BUILD_DOCS:-true}
SYMBOLS=${SYMBOLS:-YES}
BUILDTYPE=${BUILDTYPE:-Debug}
@@ -270,5 +271,7 @@ sed -i '' \
"${README}"
cp ${README} "${OUTPUT}"
-step "Generating API documentation…"
-make idocument OUTPUT="${OUTPUT}/documentation"
+if [ ${BUILD_DOCS} == true ]; then
+ step "Generating API documentation for ${BUILDTYPE} Build…"
+ make idocument OUTPUT="${OUTPUT}/documentation"
+fi
diff --git a/platform/ios/sdk-files.json b/platform/ios/sdk-files.json
index 7dbfee1a2d..94f928b77e 100644
--- a/platform/ios/sdk-files.json
+++ b/platform/ios/sdk-files.json
@@ -1,6 +1,7 @@
{
"//": "This file is generated. Do not edit. Regenerate it with scripts/generate-file-lists.js",
"sources": [
+ "platform/ios/vendor/mapbox-events-ios/MapboxMobileEvents/MMEDate.m",
"platform/darwin/src/MGLBackgroundStyleLayer.mm",
"platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm",
"platform/ios/vendor/mapbox-events-ios/vendor/TrustKit/Pinning/TSKSPKIHashCache.m",
@@ -36,7 +37,6 @@
"platform/ios/vendor/mapbox-events-ios/MapboxMobileEvents/MMETimerManager.m",
"platform/darwin/src/MGLRasterStyleLayer.mm",
"platform/darwin/src/MGLForegroundStyleLayer.mm",
- "platform/ios/vendor/mapbox-events-ios/MapboxMobileEvents/MMENSDateWrapper.m",
"platform/ios/vendor/mapbox-events-ios/MapboxMobileEvents/CLLocationManager+MMEMobileEvents.m",
"platform/ios/vendor/mapbox-events-ios/vendor/TrustKit/Reporting/TSKPinFailureReport.m",
"platform/ios/vendor/mapbox-events-ios/MapboxMobileEvents/MMEEventLogReportViewController.m",
@@ -84,7 +84,6 @@
"platform/darwin/src/MGLCoordinateFormatter.m",
"platform/darwin/src/MGLShapeOfflineRegion.mm",
"platform/ios/vendor/mapbox-events-ios/MapboxMobileEvents/MMEMetrics.m",
- "platform/darwin/src/NSData+MGLAdditions.mm",
"platform/ios/vendor/mapbox-events-ios/MapboxMobileEvents/MMEUIApplicationWrapper.m",
"platform/darwin/src/MGLStyle.mm",
"platform/darwin/src/NSCoder+MGLAdditions.mm",
@@ -243,6 +242,7 @@
"NSComparisonPredicate+MGLAdditions.h": "platform/darwin/src/NSComparisonPredicate+MGLAdditions.h",
"MGLMapAccessibilityElement.h": "platform/ios/src/MGLMapAccessibilityElement.h",
"MGLScaleBar.h": "platform/ios/src/MGLScaleBar.h",
+ "MMEDate.h": "platform/ios/vendor/mapbox-events-ios/MapboxMobileEvents/MMEDate.h",
"CLLocationManager+MMEMobileEvents.h": "platform/ios/vendor/mapbox-events-ios/MapboxMobileEvents/CLLocationManager+MMEMobileEvents.h",
"NSString+MGLAdditions.h": "platform/darwin/src/NSString+MGLAdditions.h",
"UIDevice+MGLAdditions.h": "platform/ios/src/UIDevice+MGLAdditions.h",
@@ -279,7 +279,6 @@
"MGLOpenGLStyleLayer_Private.h": "platform/darwin/src/MGLOpenGLStyleLayer_Private.h",
"MGLTileSource_Private.h": "platform/darwin/src/MGLTileSource_Private.h",
"MGLFaux3DUserLocationAnnotationView.h": "platform/ios/src/MGLFaux3DUserLocationAnnotationView.h",
- "NSData+MGLAdditions.h": "platform/darwin/src/NSData+MGLAdditions.h",
"MGLUserLocationAnnotationView_Private.h": "platform/ios/src/MGLUserLocationAnnotationView_Private.h",
"NSProcessInfo+MGLAdditions.h": "platform/darwin/src/NSProcessInfo+MGLAdditions.h",
"MGLRasterTileSource_Private.h": "platform/darwin/src/MGLRasterTileSource_Private.h",
@@ -323,7 +322,6 @@
"MMELocationManager.h": "platform/ios/vendor/mapbox-events-ios/MapboxMobileEvents/MMELocationManager.h",
"MMEMetrics.h": "platform/ios/vendor/mapbox-events-ios/MapboxMobileEvents/MMEMetrics.h",
"MMEMetricsManager.h": "platform/ios/vendor/mapbox-events-ios/MapboxMobileEvents/MMEMetricsManager.h",
- "MMENSDateWrapper.h": "platform/ios/vendor/mapbox-events-ios/MapboxMobileEvents/MMENSDateWrapper.h",
"MMENSURLSessionWrapper.h": "platform/ios/vendor/mapbox-events-ios/MapboxMobileEvents/MMENSURLSessionWrapper.h",
"MMETimerManager.h": "platform/ios/vendor/mapbox-events-ios/MapboxMobileEvents/MMETimerManager.h",
"MMETypes.h": "platform/ios/vendor/mapbox-events-ios/MapboxMobileEvents/MMETypes.h",
diff --git a/platform/ios/src/MGLMapView.h b/platform/ios/src/MGLMapView.h
index 1ef64a587b..589b7b547b 100644
--- a/platform/ios/src/MGLMapView.h
+++ b/platform/ios/src/MGLMapView.h
@@ -414,12 +414,12 @@ MGL_EXPORT IB_DESIGNABLE
/**
A Boolean value indicating whether the map should prefetch tiles.
- When this property is set to YES, the map view prefetches loads tiles designed for a
- low zoom level and displays them until receiving more detailed tiles for the current
- zoom level. The prefetched tiles typically contain simplified versions of each shape,
- improving the map view’s perceived performance.
+ When this property is set to `YES`, the map view prefetches tiles designed for
+ a low zoom level and displays them until receiving more detailed tiles for the
+ current zoom level. The prefetched tiles typically contain simplified versions
+ of each shape, improving the map view’s perceived performance.
- The default value of this property is YES.
+ The default value of this property is `YES`.
*/
@property (nonatomic, assign) BOOL prefetchesTiles;
@@ -434,17 +434,18 @@ MGL_EXPORT IB_DESIGNABLE
#pragma mark Displaying the User’s Location
/**
- The object that this map view uses to start and stop the delivery of location-related
- updates.
+ The object that this map view uses to start and stop the delivery of
+ location-related updates.
- To receive the current user location, implement the `-[MGLMapViewDelegate mapView:didUpdateUserLocation:]`
- and `-[MGLMapViewDelegate mapView:didFailToLocateUserWithError:]` methods.
+ To receive the current user location, implement the
+ `-[MGLMapViewDelegate mapView:didUpdateUserLocation:]` and
+ `-[MGLMapViewDelegate mapView:didFailToLocateUserWithError:]` methods.
- If setting this property to `nil` or if no custom manager is provided this property
- is set to the default location manager.
+ If setting this property to `nil` or if no custom manager is provided this
+ property is set to the default location manager.
- `MGLMapView` uses a default location manager. If you want to substitute your own
- location manager, you should do so by setting this property before setting
+ `MGLMapView` uses a default location manager. If you want to substitute your
+ own location manager, you should do so by setting this property before setting
`showsUserLocation` to `YES`. To restore the default location manager,
set this property to `nil`.
*/
diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm
index bda212de84..24e195c70a 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -11,7 +11,7 @@
#include <mbgl/util/platform.hpp>
#include <mbgl/storage/reachability.h>
#include <mbgl/util/default_thread_pool.hpp>
-#include <mbgl/storage/default_file_source.hpp>
+#include <mbgl/storage/resource_options.hpp>
#include <mbgl/storage/network_status.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/image.hpp>
@@ -156,6 +156,10 @@ const CGFloat MGLAnnotationImagePaddingForCallout = 1;
const CGSize MGLAnnotationAccessibilityElementMinimumSize = CGSizeMake(10, 10);
+/// The number of view annotations (excluding the user location view) that must
+/// be descendents of `MGLMapView` before presentsWithTransaction is enabled.
+static const NSUInteger MGLPresentsWithTransactionAnnotationCount = 0;
+
/// An indication that the requested annotation was not found or is nonexistent.
enum { MGLAnnotationTagNotFound = UINT32_MAX };
@@ -252,6 +256,7 @@ public:
@property (nonatomic) MGLAnnotationContainerView *annotationContainerView;
@property (nonatomic) MGLUserLocation *userLocation;
@property (nonatomic) NSMutableDictionary<NSString *, NSMutableArray<MGLAnnotationView *> *> *annotationViewReuseQueueByIdentifier;
+@property (nonatomic) BOOL enablePresentsWithTransaction;
/// Experimental rendering performance measurement.
@property (nonatomic) BOOL experimental_enableFrameRateMeasurement;
@@ -328,6 +333,9 @@ public:
CFTimeInterval _frameCounterStartTime;
NSInteger _frameCount;
CFTimeInterval _frameDurations;
+
+ BOOL _atLeastiOS_12_2_0;
+
}
#pragma mark - Setup & Teardown -
@@ -441,6 +449,7 @@ public:
{
_isTargetingInterfaceBuilder = NSProcessInfo.processInfo.mgl_isInterfaceBuilderDesignablesAgent;
_opaque = NO;
+ _atLeastiOS_12_2_0 = [NSProcessInfo.processInfo isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){12,2,0}];
BOOL background = [UIApplication sharedApplication].applicationState == UIApplicationStateBackground;
if (!background)
@@ -479,12 +488,18 @@ public:
mbgl::MapOptions mapOptions;
mapOptions.withMapMode(mbgl::MapMode::Continuous)
+ .withSize(self.size)
+ .withPixelRatio(config.scaleFactor)
.withConstrainMode(mbgl::ConstrainMode::None)
.withViewportMode(mbgl::ViewportMode::Default)
.withCrossSourceCollisions(enableCrossSourceCollisions);
+ mbgl::ResourceOptions resourceOptions;
+ resourceOptions.withCachePath([[MGLOfflineStorage sharedOfflineStorage] mbglCachePath])
+ .withAssetPath([NSBundle mainBundle].resourceURL.path.UTF8String);
+
NSAssert(!_mbglMap, @"_mbglMap should be NULL");
- _mbglMap = new mbgl::Map(*_rendererFrontend, *_mbglView, self.size, config.scaleFactor, *[config fileSource], *_mbglThreadPool, mapOptions);
+ _mbglMap = new mbgl::Map(*_rendererFrontend, *_mbglView, *_mbglThreadPool, mapOptions, resourceOptions);
// start paused if in IB
if (_isTargetingInterfaceBuilder || background) {
@@ -675,6 +690,20 @@ public:
static_cast<uint32_t>(self.glView.drawableHeight) };
}
++ (GLKView *)GLKViewWithFrame:(CGRect)frame context:(EAGLContext *)context opaque:(BOOL)opaque
+{
+ GLKView *glView = [[GLKView alloc] initWithFrame:frame context:context];
+ glView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+ glView.enableSetNeedsDisplay = NO;
+ glView.drawableStencilFormat = GLKViewDrawableStencilFormat8;
+ glView.drawableDepthFormat = GLKViewDrawableDepthFormat16;
+ glView.contentScaleFactor = [UIScreen instancesRespondToSelector:@selector(nativeScale)] ? [[UIScreen mainScreen] nativeScale] : [[UIScreen mainScreen] scale];
+ glView.layer.opaque = opaque;
+ glView.contentMode = UIViewContentModeCenter;
+
+ return glView;
+}
+
- (void)createGLView
{
if (_context) return;
@@ -686,21 +715,14 @@ public:
// create GL view
//
- _glView = [[GLKView alloc] initWithFrame:self.bounds context:_context];
- _glView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
- _glView.enableSetNeedsDisplay = NO;
- _glView.drawableStencilFormat = GLKViewDrawableStencilFormat8;
- _glView.drawableDepthFormat = GLKViewDrawableDepthFormat16;
- _glView.contentScaleFactor = [UIScreen instancesRespondToSelector:@selector(nativeScale)] ? [[UIScreen mainScreen] nativeScale] : [[UIScreen mainScreen] scale];
- _glView.layer.opaque = _opaque;
+ _glView = [MGLMapView GLKViewWithFrame:self.bounds context:_context opaque:_opaque];
_glView.delegate = self;
CAEAGLLayer *eaglLayer = MGL_OBJC_DYNAMIC_CAST(_glView.layer, CAEAGLLayer);
- eaglLayer.presentsWithTransaction = YES;
+ eaglLayer.presentsWithTransaction = NO;
[_glView bindDrawable];
[self insertSubview:_glView atIndex:0];
- _glView.contentMode = UIViewContentModeCenter;
}
- (UIImage *)compassImage
@@ -1095,6 +1117,13 @@ public:
{
MGLAssertIsMainThread();
+ // Not "visible" - this isn't a full definition of visibility, but if
+ // the map view doesn't have a window then it *cannot* be visible.
+ if (!self.window) {
+ return;
+ }
+
+ // Mismatched display link
if (displayLink && displayLink != _displayLink) {
return;
}
@@ -1107,8 +1136,28 @@ public:
[self updateUserLocationAnnotationView];
[self updateAnnotationViews];
[self updateCalloutView];
-
- [self.glView display];
+
+#ifdef MGL_RECREATE_GL_IN_AN_EMERGENCY
+ // See https://github.com/mapbox/mapbox-gl-native/issues/14232
+ // glClear can be blocked for 1 second. This code is an "escape hatch",
+ // an attempt to detect this situation and rebuild the GL views.
+ if (self.enablePresentsWithTransaction && _atLeastiOS_12_2_0)
+ {
+ CFTimeInterval before = CACurrentMediaTime();
+ [self.glView display];
+ CFTimeInterval after = CACurrentMediaTime();
+
+ if (after-before >= 1.0) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [self emergencyRecreateGL];
+ });
+ }
+ }
+ else
+#endif
+ {
+ [self.glView display];
+ }
}
if (self.experimental_enableFrameRateMeasurement)
@@ -1159,7 +1208,7 @@ public:
BOOL isVisible = self.superview && self.window;
if (isVisible && ! _displayLink)
{
- if (_mbglMap && self.mbglMap.getConstrainMode() == mbgl::ConstrainMode::None)
+ if (_mbglMap && self.mbglMap.getMapOptions().constrainMode() == mbgl::ConstrainMode::None)
{
self.mbglMap.setConstrainMode(mbgl::ConstrainMode::HeightOnly);
}
@@ -1225,15 +1274,96 @@ public:
[self updateDisplayLinkPreferredFramesPerSecond];
}
+- (void)setEnablePresentsWithTransaction:(BOOL)enablePresentsWithTransaction
+{
+ if (_enablePresentsWithTransaction == enablePresentsWithTransaction)
+ {
+ return;
+ }
+
+ _enablePresentsWithTransaction = enablePresentsWithTransaction;
+
+ // If the map is visible, change the layer property too
+ if (self.window) {
+ CAEAGLLayer *eaglLayer = MGL_OBJC_DYNAMIC_CAST(_glView.layer, CAEAGLLayer);
+ eaglLayer.presentsWithTransaction = enablePresentsWithTransaction;
+ }
+}
+
+#ifdef MGL_RECREATE_GL_IN_AN_EMERGENCY
+// See https://github.com/mapbox/mapbox-gl-native/issues/14232
+- (void)emergencyRecreateGL {
+ MGLLogError(@"Rendering took too long - creating GL views");
+
+ CAEAGLLayer *eaglLayer = MGL_OBJC_DYNAMIC_CAST(_glView.layer, CAEAGLLayer);
+ eaglLayer.presentsWithTransaction = NO;
+
+ [self sleepGL:nil];
+
+ // Just performing a sleepGL/wakeGL pair isn't sufficient - in this case
+ // we can still get errors when calling bindDrawable. Here we completely
+ // recreate the GLKView
+
+ [self.userLocationAnnotationView removeFromSuperview];
+ [_glView removeFromSuperview];
+
+ _glView = [MGLMapView GLKViewWithFrame:self.bounds context:_context opaque:_opaque];
+ _glView.delegate = self;
+
+ [self insertSubview:_glView atIndex:0];
+
+ if (self.annotationContainerView)
+ {
+ [_glView insertSubview:self.annotationContainerView atIndex:0];
+ }
+
+ [self updateUserLocationAnnotationView];
+
+ // Do not bind...yet
+
+ if (self.window) {
+ [self wakeGL:nil];
+ CAEAGLLayer *eaglLayer = MGL_OBJC_DYNAMIC_CAST(_glView.layer, CAEAGLLayer);
+ eaglLayer.presentsWithTransaction = self.enablePresentsWithTransaction;
+ }
+ else {
+ MGLLogDebug(@"No window - skipping wakeGL");
+ }
+}
+#endif
+
- (void)willMoveToWindow:(UIWindow *)newWindow {
[super willMoveToWindow:newWindow];
[self refreshSupportedInterfaceOrientationsWithWindow:newWindow];
+
+ if (!newWindow)
+ {
+ // See https://github.com/mapbox/mapbox-gl-native/issues/14232
+ // In iOS 12.2, CAEAGLLayer.presentsWithTransaction can cause dramatic
+ // slow down. The exact cause of this is unknown, but this work around
+ // appears to lessen the effects.
+ //
+ // Also, consider calling the new mbgl::Renderer::flush()
+ CAEAGLLayer *eaglLayer = MGL_OBJC_DYNAMIC_CAST(_glView.layer, CAEAGLLayer);
+ eaglLayer.presentsWithTransaction = NO;
+
+ // Moved from didMoveToWindow
+ [self validateDisplayLink];
+ }
}
- (void)didMoveToWindow
{
- [self validateDisplayLink];
[super didMoveToWindow];
+
+ if (self.window)
+ {
+ // See above comment
+ CAEAGLLayer *eaglLayer = MGL_OBJC_DYNAMIC_CAST(_glView.layer, CAEAGLLayer);
+ eaglLayer.presentsWithTransaction = self.enablePresentsWithTransaction;
+
+ [self validateDisplayLink];
+ }
}
- (void)didMoveToSuperview
@@ -2508,10 +2638,15 @@ public:
{
MGLLogInfo(@"Resetting the map to the current style’s default viewport.");
auto camera = self.mbglMap.getStyle().getDefaultCamera();
- CGFloat pitch = *camera.pitch;
- CLLocationDirection heading = mbgl::util::wrap(*camera.bearing, 0., 360.);
- CLLocationDistance altitude = MGLAltitudeForZoomLevel(*camera.zoom, pitch, 0, self.frame.size);
- self.camera = [MGLMapCamera cameraLookingAtCenterCoordinate:MGLLocationCoordinate2DFromLatLng(*camera.center)
+
+ double pitch = camera.pitch ? *camera.pitch : 0.0;
+ double bearing = camera.bearing ? *camera.bearing : 0.0;
+ double zoom = camera.zoom ? *camera.zoom : 0.0;
+ mbgl::LatLng center = camera.center ? *camera.center : mbgl::LatLng();
+
+ CLLocationDirection heading = mbgl::util::wrap(bearing, 0., 360.);
+ CLLocationDistance altitude = MGLAltitudeForZoomLevel(zoom, pitch, 0, self.frame.size);
+ self.camera = [MGLMapCamera cameraLookingAtCenterCoordinate:MGLLocationCoordinate2DFromLatLng(center)
altitude:altitude
pitch:pitch
heading:heading];
@@ -2560,11 +2695,13 @@ public:
}
}
-- (void)setPrefetchesTiles:(BOOL)prefetchesTiles{
+- (void)setPrefetchesTiles:(BOOL)prefetchesTiles
+{
_mbglMap->setPrefetchZoomDelta(prefetchesTiles ? mbgl::util::DEFAULT_PREFETCH_ZOOM_DELTA : 0);
}
-- (BOOL)prefetchesTiles{
+- (BOOL)prefetchesTiles
+{
return _mbglMap->getPrefetchZoomDelta() > 0 ? YES : NO;
}
@@ -4138,6 +4275,8 @@ public:
[newAnnotationContainerView addSubviews:annotationViews];
[_glView insertSubview:newAnnotationContainerView atIndex:0];
self.annotationContainerView = newAnnotationContainerView;
+
+ self.enablePresentsWithTransaction = (self.annotationContainerView.annotationViews.count > MGLPresentsWithTransactionAnnotationCount);
}
/// Initialize and return a default annotation image that depicts a round pin
@@ -4311,6 +4450,8 @@ public:
annotationView.annotation = nil;
[annotationView removeFromSuperview];
[self.annotationContainerView.annotationViews removeObject:annotationView];
+
+ self.enablePresentsWithTransaction = (self.annotationContainerView.annotationViews.count > MGLPresentsWithTransactionAnnotationCount);
if (annotationTag == _selectedAnnotationTag)
{
@@ -6686,6 +6827,20 @@ public:
void onDidFinishLoadingStyle() override {
[nativeView didFinishLoadingStyle];
}
+
+ void onStyleImageMissing(const std::string& imageIdentifier) override {
+ NSString *imageName = [NSString stringWithUTF8String:imageIdentifier.c_str()];
+
+ if ([nativeView.delegate respondsToSelector:@selector(mapView:didFailToLoadImage:)]) {
+ UIImage *imageToLoad = [nativeView.delegate mapView:nativeView didFailToLoadImage:imageName];
+
+ if (imageToLoad) {
+ auto image = [imageToLoad mgl_styleImageWithIdentifier:imageName];
+ nativeView.mbglMap.getStyle().addImage(std::move(image));
+ }
+
+ }
+ }
mbgl::gl::ProcAddress getExtensionFunctionPointer(const char* name) override {
static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengles"));
diff --git a/platform/ios/src/MGLMapViewDelegate.h b/platform/ios/src/MGLMapViewDelegate.h
index 7e098f340d..055d4c9517 100644
--- a/platform/ios/src/MGLMapViewDelegate.h
+++ b/platform/ios/src/MGLMapViewDelegate.h
@@ -275,6 +275,8 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style;
+- (nullable UIImage *)mapView:(MGLMapView *)mapView didFailToLoadImage:(NSString *)imageName;
+
#pragma mark Tracking User Location
/**
diff --git a/platform/ios/src/UIColor+MGLAdditions.h b/platform/ios/src/UIColor+MGLAdditions.h
index 60cfe1c58b..19702fa105 100644
--- a/platform/ios/src/UIColor+MGLAdditions.h
+++ b/platform/ios/src/UIColor+MGLAdditions.h
@@ -17,5 +17,6 @@
+ (NSExpression *)mgl_expressionForRGBComponents:(NSArray<NSExpression *> *)components;
+ (NSExpression *)mgl_expressionForRGBAComponents:(NSArray<NSExpression *> *)components;
++ (UIColor *)mgl_colorWithRGBComponents:(NSArray<NSExpression *> *)components;
@end
diff --git a/platform/ios/test/MGLMapViewDelegateIntegrationTests.swift b/platform/ios/test/MGLMapViewDelegateIntegrationTests.swift
index 2bf3dc06bd..1330281faa 100644
--- a/platform/ios/test/MGLMapViewDelegateIntegrationTests.swift
+++ b/platform/ios/test/MGLMapViewDelegateIntegrationTests.swift
@@ -96,4 +96,6 @@ extension MGLMapViewDelegateIntegrationTests: MGLMapViewDelegate {
func mapView(_ mapView: MGLMapView, shouldChangeFrom oldCamera: MGLMapCamera, to newCamera: MGLMapCamera, reason: MGLCameraChangeReason) -> Bool { return false }
func mapViewUserLocationAnchorPoint(_ mapView: MGLMapView) -> CGPoint { return CGPoint(x: 100, y: 100) }
+
+ func mapView(_ mapView: MGLMapView, didFailToLoadImage imageName: String) -> UIImage? { return nil }
}
diff --git a/platform/ios/test/MGLNSDataAdditionsTests.m b/platform/ios/test/MGLNSDataAdditionsTests.m
deleted file mode 100644
index 8d145be4a0..0000000000
--- a/platform/ios/test/MGLNSDataAdditionsTests.m
+++ /dev/null
@@ -1,48 +0,0 @@
-#import <XCTest/XCTest.h>
-
-#import "../../darwin/src/NSData+MGLAdditions.h"
-
-@interface MGLNSDataAdditionsTests : XCTestCase
-@end
-
-@implementation MGLNSDataAdditionsTests
-
-- (void)testCompressDecompress
-{
- NSArray *originalArray = [self mockDataWithCount:180];
-
- NSData *originalData = [NSJSONSerialization dataWithJSONObject:originalArray options:0 error:nil];
-
- NSData *compressedData = [originalData mgl_compressedData];
- NSData *decompressedData = [compressedData mgl_decompressedData];
-
- NSArray *decompressedArray = [NSJSONSerialization JSONObjectWithData:decompressedData options:0 error:nil];
-
- XCTAssertTrue([originalArray isEqualToArray:decompressedArray], @"originalArray and decompressedArray should be equal");
-}
-
-- (NSArray *)mockDataWithCount:(NSUInteger)count
-{
- NSMutableArray *array = [NSMutableArray array];
-
- for (NSUInteger i=0;i<count;i++)
- {
- [array addObject:@{@"lat": @([self safeValueBetween:-90 and:90]),
- @"lng": @([self safeValueBetween:-180 and:180]),
- @"timestamp": @((floor([NSDate date].timeIntervalSince1970) * 100) / 100)}];
- }
-
- return array;
-}
-
-- (double)safeValueBetween:(double)lowerBound and:(double)upperBound
-{
- return floor([self randomBetween:lowerBound and:upperBound] * 100 ) / 100;
-}
-
-- (double)randomBetween:(double)lowerBound and:(double)upperBound
-{
- return lowerBound * drand48() + upperBound * drand48();
-}
-
-@end
diff --git a/platform/ios/vendor/mapbox-events-ios b/platform/ios/vendor/mapbox-events-ios
-Subproject d79e62581df5f51a0064dd2f78972c489c71d41
+Subproject 67d59dbe10f232dfeb3a1604c6696c6619abe88
diff --git a/platform/linux/config.cmake b/platform/linux/config.cmake
index 6d4715e451..4405e0583f 100644
--- a/platform/linux/config.cmake
+++ b/platform/linux/config.cmake
@@ -104,13 +104,8 @@ endmacro()
macro(mbgl_filesource)
- target_sources(mbgl-filesource
- # File source
- PRIVATE platform/default/src/mbgl/storage/http_file_source.cpp
-
- # Database
- PRIVATE platform/default/src/mbgl/storage/sqlite3.cpp
- )
+ # Modify platform/linux/filesource-files.json to change the source files for this target.
+ target_sources_from_file(mbgl-filesource PRIVATE platform/linux/filesource-files.json)
# We're not referencing any cURL symbols since we're dynamically loading it. However, we want to
# link the library anyway since we're definitely going to load it on startup anyway.
diff --git a/platform/linux/filesource-files.json b/platform/linux/filesource-files.json
new file mode 100644
index 0000000000..448f5f8613
--- /dev/null
+++ b/platform/linux/filesource-files.json
@@ -0,0 +1,10 @@
+{
+ "//": "This file can be edited manually and is the canonical source.",
+ "sources": [
+ "platform/default/src/mbgl/storage/file_source.cpp",
+ "platform/default/src/mbgl/storage/http_file_source.cpp",
+ "platform/default/src/mbgl/storage/sqlite3.cpp"
+ ],
+ "public_headers": {},
+ "private_headers": {}
+}
diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md
index 2542f57d95..ebfb3f335a 100644
--- a/platform/macos/CHANGELOG.md
+++ b/platform/macos/CHANGELOG.md
@@ -10,6 +10,12 @@
* Added `MGLNetworkConfiguration` class to customize the SDK's `NSURLSessionConfiguration` object. ([#11447](https://github.com/mapbox/mapbox-gl-native/pull/13886))
* Fixed an issue that caused `MGL_FUNCTION` to ignore multiple formatting parameters when passed a `format` function as parameter. ([#14064](https://github.com/mapbox/mapbox-gl-native/pull/14064))
* Added `mgl_attributed:` expression operator, which concatenate `MGLAttributedExpression` objects for specifying rich text in the `MGLSymbolStyleLayer.text` property. ([#14094](https://github.com/mapbox/mapbox-gl-native/pull/14094))
+* Fixed an issue that caused conditional expressions to crash when passed nested conditional expressions as parameters. ([#14181](https://github.com/mapbox/mapbox-gl-native/pull/14181))
+* Added `-[MGLMapViewDelegate mapView:didFailToLoadImage:]` to load missing symbol icons in the style if they are not found. ([#14302](https://github.com/mapbox/mapbox-gl-native/pull/14302))
+
+### Offline
+
+* Fixed a bug that caused offline packs created prior to v0.7.0 (introduced in [#11055](https://github.com/mapbox/mapbox-gl-native/pull/11055)) to be marked as `MGLOfflinePackStateInactive`. ([#14188](https://github.com/mapbox/mapbox-gl-native/pull/14188))
### Annotations
@@ -19,6 +25,7 @@
### Packaging
* Added Czech and Galician localizations. ([#13782](https://github.com/mapbox/mapbox-gl-native/pull/13782), [#14095](https://github.com/mapbox/mapbox-gl-native/pull/14095))
+* Added support for building with Xcode 10.2 / iOS SDK 12.2. ([#14241](https://github.com/mapbox/mapbox-gl-native/pull/14241))
## 0.13.0 - December 20, 2018
diff --git a/platform/macos/docs/guides/For Style Authors.md b/platform/macos/docs/guides/For Style Authors.md
index 038ddf1f93..5a81eb3593 100644
--- a/platform/macos/docs/guides/For Style Authors.md
+++ b/platform/macos/docs/guides/For Style Authors.md
@@ -411,5 +411,16 @@ In style JSON | In the format string
`["any", f0, …, fn]` | `p0 OR … OR pn`
`["none", f0, …, fn]` | `NOT (p0 OR … OR pn)`
+## Specifying the text format
+
+The following format attributes are defined as `NSString` constans that you
+can use to update the formatting of `MGLSymbolStyleLayer.text` property.
+
+In style JSON | In Objective-C | In Swift
+--------------|-----------------------|---------
+`text-font` | `MGLFontNamesAttribute` | `.fontNamesAttribute`
+`font-scale` | `MGLFontScaleAttribute` | `.fontScaleAttribute`
+`text-color` | `MGLFontColorAttribute` | `.fontColorAttribute`
+
See the “[Predicates and Expressions](predicates-and-expressions.html)” guide for
a full description of the supported operators and operand types.
diff --git a/platform/macos/macos.xcodeproj/project.pbxproj b/platform/macos/macos.xcodeproj/project.pbxproj
index 5d5a94c78a..57c4f198f0 100644
--- a/platform/macos/macos.xcodeproj/project.pbxproj
+++ b/platform/macos/macos.xcodeproj/project.pbxproj
@@ -2008,6 +2008,7 @@
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_CPP_RTTI = NO;
GCC_NO_COMMON_BLOCKS = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = "NDEBUG=1";
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm
index 911d254889..0fdecd6cc8 100644
--- a/platform/macos/src/MGLMapView.mm
+++ b/platform/macos/src/MGLMapView.mm
@@ -36,8 +36,8 @@
#import <mbgl/renderer/renderer.hpp>
#import <mbgl/renderer/renderer_backend.hpp>
#import <mbgl/renderer/backend_scope.hpp>
-#import <mbgl/storage/default_file_source.hpp>
#import <mbgl/storage/network_status.hpp>
+#import <mbgl/storage/resource_options.hpp>
#import <mbgl/math/wrap.hpp>
#import <mbgl/util/constants.hpp>
#import <mbgl/util/chrono.hpp>
@@ -292,10 +292,17 @@ public:
mbgl::MapOptions mapOptions;
mapOptions.withMapMode(mbgl::MapMode::Continuous)
+ .withSize(self.size)
+ .withPixelRatio(config.scaleFactor)
.withConstrainMode(mbgl::ConstrainMode::None)
.withViewportMode(mbgl::ViewportMode::Default)
.withCrossSourceCollisions(enableCrossSourceCollisions);
- _mbglMap = new mbgl::Map(*_rendererFrontend, *_mbglView, self.size, config.scaleFactor, *config.fileSource, *_mbglThreadPool, mapOptions);
+
+ mbgl::ResourceOptions resourceOptions;
+ resourceOptions.withCachePath([[MGLOfflineStorage sharedOfflineStorage] mbglCachePath])
+ .withAssetPath([NSBundle mainBundle].resourceURL.path.UTF8String);
+
+ _mbglMap = new mbgl::Map(*_rendererFrontend, *_mbglView, *_mbglThreadPool, mapOptions, resourceOptions);
// Install the OpenGL layer. Interface Builder’s synchronous drawing means
// we can’t display a map, so don’t even bother to have a map layer.
@@ -690,7 +697,7 @@ public:
self.dormant = NO;
}
- if (window && _mbglMap->getConstrainMode() == mbgl::ConstrainMode::None) {
+ if (window && _mbglMap->getMapOptions().constrainMode() == mbgl::ConstrainMode::None) {
_mbglMap->setConstrainMode(mbgl::ConstrainMode::HeightOnly);
}
diff --git a/platform/macos/src/NSColor+MGLAdditions.h b/platform/macos/src/NSColor+MGLAdditions.h
index 21c939fec6..a3c5aba63f 100644
--- a/platform/macos/src/NSColor+MGLAdditions.h
+++ b/platform/macos/src/NSColor+MGLAdditions.h
@@ -23,5 +23,6 @@
+ (NSExpression *)mgl_expressionForRGBComponents:(NSArray<NSExpression *> *)components;
+ (NSExpression *)mgl_expressionForRGBAComponents:(NSArray<NSExpression *> *)components;
++ (NSColor *)mgl_colorWithRGBComponents:(NSArray<NSExpression *> *)componentExpressions;
@end
diff --git a/platform/macos/src/NSColor+MGLAdditions.mm b/platform/macos/src/NSColor+MGLAdditions.mm
index c73c1a41b7..ea7d99f66d 100644
--- a/platform/macos/src/NSColor+MGLAdditions.mm
+++ b/platform/macos/src/NSColor+MGLAdditions.mm
@@ -37,7 +37,7 @@
@implementation NSExpression (MGLColorAdditions)
+ (NSExpression *)mgl_expressionForRGBComponents:(NSArray<NSExpression *> *)components {
- if (NSColor *color = [self mgl_colorWithComponentExpressions:components]) {
+ if (NSColor *color = [self mgl_colorWithRGBComponents:components]) {
return [NSExpression expressionForConstantValue:color];
}
@@ -49,7 +49,7 @@
}
+ (NSExpression *)mgl_expressionForRGBAComponents:(NSArray<NSExpression *> *)components {
- if (NSColor *color = [self mgl_colorWithComponentExpressions:components]) {
+ if (NSColor *color = [self mgl_colorWithRGBComponents:components]) {
return [NSExpression expressionForConstantValue:color];
}
@@ -62,7 +62,7 @@
/**
Returns a color object corresponding to the given component expressions.
*/
-+ (NSColor *)mgl_colorWithComponentExpressions:(NSArray<NSExpression *> *)componentExpressions {
++ (NSColor *)mgl_colorWithRGBComponents:(NSArray<NSExpression *> *)componentExpressions {
// Map the component expressions to constant components. If any component is
// a non-constant expression, the components cannot be converted into a
// constant color value.
diff --git a/platform/node/src/node_map.cpp b/platform/node/src/node_map.cpp
index 0d69e606c1..291dea6bb7 100644
--- a/platform/node/src/node_map.cpp
+++ b/platform/node/src/node_map.cpp
@@ -20,15 +20,25 @@
#include <mbgl/style/layers/raster_layer.hpp>
#include <mbgl/style/layers/symbol_layer.hpp>
+#include <mbgl/storage/resource_options.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/image.hpp>
#include <mbgl/style/light.hpp>
+#include <mbgl/map/map.hpp>
#include <mbgl/map/map_observer.hpp>
#include <mbgl/util/exception.hpp>
#include <mbgl/util/premultiply.hpp>
#include <unistd.h>
+namespace mbgl {
+
+std::shared_ptr<FileSource> FileSource::createPlatformFileSource(const ResourceOptions& options) {
+ return std::make_shared<node_mbgl::NodeFileSource>(reinterpret_cast<node_mbgl::NodeMap*>(options.platformContext()));
+}
+
+} // namespace mbgl
+
namespace node_mbgl {
struct NodeMap::RenderOptions {
@@ -621,13 +631,12 @@ void NodeMap::cancel() {
});
frontend = std::make_unique<mbgl::HeadlessFrontend>(mbgl::Size{ 256, 256 }, pixelRatio, threadpool);
- mbgl::MapOptions options;
- options.withMapMode(mode)
- .withConstrainMode(mbgl::ConstrainMode::HeightOnly)
- .withViewportMode(mbgl::ViewportMode::Default)
- .withCrossSourceCollisions(crossSourceCollisions);
- map = std::make_unique<mbgl::Map>(*frontend, mapObserver, frontend->getSize(), pixelRatio,
- fileSource, threadpool, options);
+ map = std::make_unique<mbgl::Map>(*frontend, mapObserver, threadpool,
+ mbgl::MapOptions().withSize(frontend->getSize())
+ .withPixelRatio(pixelRatio)
+ .withMapMode(mode)
+ .withCrossSourceCollisions(crossSourceCollisions),
+ mbgl::ResourceOptions().withPlatformContext(reinterpret_cast<void*>(this)));
// FIXME: Reload the style after recreating the map. We need to find
// a better way of canceling an ongoing rendering on the core level
@@ -1205,20 +1214,14 @@ NodeMap::NodeMap(v8::Local<v8::Object> options)
: true;
}())
, mapObserver(NodeMapObserver())
- , fileSource(this)
, frontend(std::make_unique<mbgl::HeadlessFrontend>(mbgl::Size { 256, 256 }, pixelRatio, threadpool))
- , map(std::make_unique<mbgl::Map>(*frontend,
- mapObserver,
- frontend->getSize(),
- pixelRatio,
- fileSource,
- threadpool,
- mbgl::MapOptions().withMapMode(mode)
- .withConstrainMode(mbgl::ConstrainMode::HeightOnly)
- .withViewportMode(mbgl::ViewportMode::Default)
- .withCrossSourceCollisions(crossSourceCollisions))),
- async(new uv_async_t) {
-
+ , map(std::make_unique<mbgl::Map>(*frontend, mapObserver, threadpool,
+ mbgl::MapOptions().withSize(frontend->getSize())
+ .withPixelRatio(pixelRatio)
+ .withMapMode(mode)
+ .withCrossSourceCollisions(crossSourceCollisions),
+ mbgl::ResourceOptions().withPlatformContext(reinterpret_cast<void*>(this))))
+ , async(new uv_async_t) {
async->data = this;
uv_async_init(uv_default_loop(), async, [](uv_async_t* h) {
reinterpret_cast<NodeMap *>(h->data)->renderFinished();
@@ -1232,8 +1235,6 @@ NodeMap::~NodeMap() {
if (map) release();
}
-NodeFileSource::NodeFileSource(NodeMap* nodeMap_) : nodeMap(nodeMap_) {}
-
std::unique_ptr<mbgl::AsyncRequest> NodeFileSource::request(const mbgl::Resource& resource, mbgl::FileSource::Callback callback_) {
assert(nodeMap);
@@ -1248,15 +1249,15 @@ std::unique_ptr<mbgl::AsyncRequest> NodeFileSource::request(const mbgl::Resource
Nan::New<v8::External>(&callback_)
};
- auto instance = Nan::NewInstance(Nan::New(NodeRequest::constructor), 2, argv).ToLocalChecked();
+ auto instance = Nan::NewInstance(Nan::New(node_mbgl::NodeRequest::constructor), 2, argv).ToLocalChecked();
Nan::Set(instance, Nan::New("url").ToLocalChecked(), Nan::New(resource.url).ToLocalChecked());
Nan::Set(instance, Nan::New("kind").ToLocalChecked(), Nan::New<v8::Integer>(resource.kind));
- auto request = Nan::ObjectWrap::Unwrap<NodeRequest>(instance);
+ auto request = Nan::ObjectWrap::Unwrap<node_mbgl::NodeRequest>(instance);
request->Execute();
- return std::make_unique<NodeRequest::NodeAsyncRequest>(request);
+ return std::make_unique<node_mbgl::NodeRequest::NodeAsyncRequest>(request);
}
} // namespace node_mbgl
diff --git a/platform/node/src/node_map.hpp b/platform/node/src/node_map.hpp
index 9e3eb1ad12..65664b34bb 100644
--- a/platform/node/src/node_map.hpp
+++ b/platform/node/src/node_map.hpp
@@ -15,26 +15,13 @@
#pragma GCC diagnostic pop
namespace mbgl {
-class Map;
class HeadlessFrontend;
} // namespace mbgl
namespace node_mbgl {
-class NodeMapObserver : public mbgl::MapObserver {
- void onDidFailLoadingMap(mbgl::MapLoadError, const std::string&) override;
-};
-
-class NodeMap;
-
-class NodeFileSource : public mbgl::FileSource {
-public:
- NodeFileSource(NodeMap*);
-
- std::unique_ptr<mbgl::AsyncRequest> request(const mbgl::Resource&, mbgl::FileSource::Callback) final;
-
-private:
- NodeMap* nodeMap;
+struct NodeMapObserver : public mbgl::MapObserver {
+ void onDidFailLoadingMap(mbgl::MapLoadError, const std::string&) final;
};
class RenderRequest;
@@ -94,7 +81,6 @@ public:
bool crossSourceCollisions;
NodeThreadPool threadpool;
NodeMapObserver mapObserver;
- NodeFileSource fileSource;
std::unique_ptr<mbgl::HeadlessFrontend> frontend;
std::unique_ptr<mbgl::Map> map;
@@ -108,4 +94,10 @@ public:
bool loaded = false;
};
+struct NodeFileSource : public mbgl::FileSource {
+ NodeFileSource(NodeMap* nodeMap_) : nodeMap(nodeMap_) {}
+ std::unique_ptr<mbgl::AsyncRequest> request(const mbgl::Resource&, mbgl::FileSource::Callback) final;
+ NodeMap* nodeMap;
+};
+
} // namespace node_mbgl
diff --git a/platform/node/test/ignores.json b/platform/node/test/ignores.json
index d0becfc58a..060f4935a6 100644
--- a/platform/node/test/ignores.json
+++ b/platform/node/test/ignores.json
@@ -149,24 +149,9 @@
"render-tests/symbol-sort-key/text-expression": "https://github.com/mapbox/mapbox-gl-native/issues/14028",
"render-tests/symbol-sort-key/text-placement": "https://github.com/mapbox/mapbox-gl-native/issues/14028",
"render-tests/fill-opacity/opaque-fill-over-symbol-layer": "skip - port https://github.com/mapbox/mapbox-gl-js/pull/7612",
- "render-tests/text-radial-offset/basic": "skip - port of https://github.com/mapbox/mapbox-gl-js/pull/7596",
- "render-tests/text-variable-anchor/all-anchors-offset": "skip - port of https://github.com/mapbox/mapbox-gl-js/pull/7596",
- "render-tests/text-variable-anchor/all-anchors": "skip - port of https://github.com/mapbox/mapbox-gl-js/pull/7596",
- "render-tests/text-variable-anchor/icon-image-all-anchors": "skip - port of https://github.com/mapbox/mapbox-gl-js/pull/7596",
- "render-tests/text-variable-anchor/icon-image": "skip - port of https://github.com/mapbox/mapbox-gl-js/pull/7596",
- "render-tests/text-variable-anchor/no-animate-zoom": "skip - port of https://github.com/mapbox/mapbox-gl-js/pull/7596",
- "render-tests/text-variable-anchor/pitched-offset": "skip - port of https://github.com/mapbox/mapbox-gl-js/pull/7596",
- "render-tests/text-variable-anchor/pitched-rotated-debug": "skip - port of https://github.com/mapbox/mapbox-gl-js/pull/7596",
- "render-tests/text-variable-anchor/pitched-with-map": "skip - port of https://github.com/mapbox/mapbox-gl-js/pull/7596",
- "render-tests/text-variable-anchor/pitched": "skip - port of https://github.com/mapbox/mapbox-gl-js/pull/7596",
- "render-tests/text-variable-anchor/remember-last-placement": "skip - port of https://github.com/mapbox/mapbox-gl-js/pull/7596",
- "render-tests/text-variable-anchor/rotated-offset": "skip - port of https://github.com/mapbox/mapbox-gl-js/pull/7596",
- "render-tests/text-variable-anchor/rotated-with-map": "skip - port of https://github.com/mapbox/mapbox-gl-js/pull/7596",
- "render-tests/text-variable-anchor/rotated": "skip - port of https://github.com/mapbox/mapbox-gl-js/pull/7596",
- "render-tests/text-variable-anchor/single-justification": "skip - port of https://github.com/mapbox/mapbox-gl-js/pull/7596",
- "render-tests/text-variable-anchor/single-line": "skip - port of https://github.com/mapbox/mapbox-gl-js/pull/7596",
- "render-tests/text-variable-anchor/top-bottom-left-right": "skip - port of https://github.com/mapbox/mapbox-gl-js/pull/7596",
- "render-tests/text-justify/auto": "skip - port of https://github.com/mapbox/mapbox-gl-js/pull/7596",
+ "render-tests/text-variable-anchor/pitched-rotated-debug": "https://github.com/mapbox/mapbox-gl-native/issues/14211",
+ "render-tests/text-variable-anchor/rotated-offset": "https://github.com/mapbox/mapbox-gl-native/issues/14211",
+ "render-tests/text-variable-anchor/remember-last-placement": "skip - fails on gl-native, as symbol index is not functional at static map mode - needs issue",
"render-tests/geojson/clustered-properties": "https://github.com/mapbox/mapbox-gl-native/issues/14043",
"render-tests/remove-feature-state/composite-expression": "https://github.com/mapbox/mapbox-gl-native/issues/12413",
"render-tests/remove-feature-state/data-expression": "https://github.com/mapbox/mapbox-gl-native/issues/12413",
diff --git a/platform/qt/qt.cmake b/platform/qt/qt.cmake
index 14f09007ac..911af25bc4 100644
--- a/platform/qt/qt.cmake
+++ b/platform/qt/qt.cmake
@@ -50,6 +50,7 @@ set(MBGL_QT_CORE_FILES
set(MBGL_QT_FILESOURCE_FILES
# File source
+ PRIVATE platform/default/src/mbgl/storage/file_source.cpp
PRIVATE platform/qt/src/http_file_source.cpp
PRIVATE platform/qt/src/http_file_source.hpp
PRIVATE platform/qt/src/http_request.cpp
diff --git a/platform/qt/src/qmapboxgl.cpp b/platform/qt/src/qmapboxgl.cpp
index b05c82a783..4f79525257 100644
--- a/platform/qt/src/qmapboxgl.cpp
+++ b/platform/qt/src/qmapboxgl.cpp
@@ -10,6 +10,7 @@
#include <mbgl/annotation/annotation.hpp>
#include <mbgl/map/camera.hpp>
#include <mbgl/map/map.hpp>
+#include <mbgl/map/map_options.hpp>
#include <mbgl/math/log2.hpp>
#include <mbgl/math/minmax.hpp>
#include <mbgl/style/style.hpp>
@@ -33,7 +34,9 @@
#include <mbgl/style/image.hpp>
#include <mbgl/renderer/renderer.hpp>
#include <mbgl/renderer/backend_scope.hpp>
+#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/storage/network_status.hpp>
+#include <mbgl/storage/resource_options.hpp>
#include <mbgl/util/color.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/geo.hpp>
@@ -91,49 +94,6 @@ namespace {
QThreadStorage<std::shared_ptr<mbgl::util::RunLoop>> loop;
-std::shared_ptr<mbgl::DefaultFileSource> sharedDefaultFileSource(const QMapboxGLSettings &settings) {
- static std::mutex mutex;
- static std::unordered_map<std::string, std::weak_ptr<mbgl::DefaultFileSource>> fileSources;
-
- const std::string cachePath = settings.cacheDatabasePath().toStdString();
- const std::string accessToken = settings.accessToken().toStdString();
- const std::string apiBaseUrl = settings.apiBaseUrl().toStdString();
-
- std::lock_guard<std::mutex> lock(mutex);
-
- // Purge entries no longer in use.
- for (auto it = fileSources.begin(); it != fileSources.end();) {
- if (it->second.expired()) {
- it = fileSources.erase(it);
- } else {
- ++it;
- }
- }
-
- const auto key = cachePath + "|" + accessToken + "|" + apiBaseUrl;
-
- // Return an existing FileSource if available.
- auto sharedFileSource = fileSources.find(key);
- if (sharedFileSource != fileSources.end()) {
- auto lockedSharedFileSource = sharedFileSource->second.lock();
- if (lockedSharedFileSource) {
- return lockedSharedFileSource;
- }
- }
-
- // New path, create a new FileSource.
- auto newFileSource = std::make_shared<mbgl::DefaultFileSource>(
- cachePath, settings.assetPath().toStdString(), settings.cacheDatabaseMaximumSize());
-
- // Setup the FileSource
- newFileSource->setAccessToken(accessToken);
- newFileSource->setAPIBaseURL(apiBaseUrl);
-
- fileSources[key] = newFileSource;
-
- return newFileSource;
-}
-
// Conversion helper functions.
mbgl::Size sanitizedSize(const QSize& size) {
@@ -907,7 +867,7 @@ void QMapboxGL::pitchBy(double pitch_)
*/
QMapboxGL::NorthOrientation QMapboxGL::northOrientation() const
{
- return static_cast<QMapboxGL::NorthOrientation>(d_ptr->mapObj->getNorthOrientation());
+ return static_cast<QMapboxGL::NorthOrientation>(d_ptr->mapObj->getMapOptions().northOrientation());
}
/*!
@@ -1167,7 +1127,7 @@ void QMapboxGL::resize(const QSize& size_)
{
auto size = sanitizedSize(size_);
- if (d_ptr->mapObj->getSize() == size)
+ if (d_ptr->mapObj->getMapOptions().size() == size)
return;
d_ptr->mapObj->setSize(size);
@@ -1745,22 +1705,31 @@ void QMapboxGL::connectionEstablished()
\a copyrightsHtml is a string with a HTML snippet.
*/
+mbgl::MapOptions mapOptionsFromQMapboxGLSettings(const QMapboxGLSettings &settings, const QSize &size, qreal pixelRatio) {
+ return std::move(mbgl::MapOptions()
+ .withSize(sanitizedSize(size))
+ .withPixelRatio(pixelRatio)
+ .withMapMode(static_cast<mbgl::MapMode>(settings.mapMode()))
+ .withConstrainMode(static_cast<mbgl::ConstrainMode>(settings.constrainMode()))
+ .withViewportMode(static_cast<mbgl::ViewportMode>(settings.viewportMode())));
+}
+
+mbgl::ResourceOptions resourceOptionsFromQMapboxGLSettings(const QMapboxGLSettings &settings) {
+ return std::move(mbgl::ResourceOptions()
+ .withAccessToken(settings.accessToken().toStdString())
+ .withAssetPath(settings.assetPath().toStdString())
+ .withBaseURL(settings.apiBaseUrl().toStdString())
+ .withCachePath(settings.cacheDatabasePath().toStdString())
+ .withMaximumCacheSize(settings.cacheDatabaseMaximumSize()));
+}
+
QMapboxGLPrivate::QMapboxGLPrivate(QMapboxGL *q, const QMapboxGLSettings &settings, const QSize &size, qreal pixelRatio_)
: QObject(q)
- , m_fileSourceObj(sharedDefaultFileSource(settings))
, m_threadPool(mbgl::sharedThreadPool())
, m_mode(settings.contextMode())
, m_pixelRatio(pixelRatio_)
, m_localFontFamily(settings.localFontFamily())
{
- if (settings.resourceTransform()) {
- m_resourceTransform = std::make_unique<mbgl::Actor<mbgl::ResourceTransform>>(*mbgl::Scheduler::GetCurrent(),
- [callback = settings.resourceTransform()] (mbgl::Resource::Kind, const std::string &&url_) -> std::string {
- return callback(std::move(url_));
- });
- m_fileSourceObj->setResourceTransform(m_resourceTransform->self());
- }
-
// Setup MapObserver
m_mapObserver = std::make_unique<QMapboxGLMapObserver>(this);
@@ -1770,18 +1739,21 @@ QMapboxGLPrivate::QMapboxGLPrivate(QMapboxGL *q, const QMapboxGLSettings &settin
connect(m_mapObserver.get(), SIGNAL(mapLoadingFailed(QMapboxGL::MapLoadingFailure,QString)), q, SIGNAL(mapLoadingFailed(QMapboxGL::MapLoadingFailure,QString)));
connect(m_mapObserver.get(), SIGNAL(copyrightsChanged(QString)), q, SIGNAL(copyrightsChanged(QString)));
- mbgl::MapOptions options;
- options.withMapMode(static_cast<mbgl::MapMode>(settings.mapMode()))
- .withConstrainMode(static_cast<mbgl::ConstrainMode>(settings.constrainMode()))
- .withViewportMode(static_cast<mbgl::ViewportMode>(settings.viewportMode()));
-
- // Setup the Map object
- mapObj = std::make_unique<mbgl::Map>(
- *this, // RendererFrontend
- *m_mapObserver,
- sanitizedSize(size),
- m_pixelRatio, *m_fileSourceObj, *m_threadPool,
- options);
+ auto resourceOptions = resourceOptionsFromQMapboxGLSettings(settings);
+
+ // Setup the Map object.
+ mapObj = std::make_unique<mbgl::Map>(*this, *m_mapObserver, *m_threadPool,
+ mapOptionsFromQMapboxGLSettings(settings, size, m_pixelRatio),
+ resourceOptions);
+
+ if (settings.resourceTransform()) {
+ m_resourceTransform = std::make_unique<mbgl::Actor<mbgl::ResourceTransform>>(*mbgl::Scheduler::GetCurrent(),
+ [callback = settings.resourceTransform()] (mbgl::Resource::Kind, const std::string &&url_) -> std::string {
+ return callback(std::move(url_));
+ });
+ auto fs = mbgl::FileSource::getSharedFileSource(resourceOptions);
+ std::static_pointer_cast<mbgl::DefaultFileSource>(fs)->setResourceTransform(m_resourceTransform->self());
+ }
// Needs to be Queued to give time to discard redundant draw calls via the `renderQueued` flag.
connect(this, SIGNAL(needsRendering()), q, SIGNAL(needsRendering()), Qt::QueuedConnection);
diff --git a/platform/qt/src/qmapboxgl_p.hpp b/platform/qt/src/qmapboxgl_p.hpp
index 7157df0aba..6a5b5ce04f 100644
--- a/platform/qt/src/qmapboxgl_p.hpp
+++ b/platform/qt/src/qmapboxgl_p.hpp
@@ -7,7 +7,6 @@
#include <mbgl/actor/actor.hpp>
#include <mbgl/map/map.hpp>
#include <mbgl/renderer/renderer_frontend.hpp>
-#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/storage/resource_transform.hpp>
#include <mbgl/util/default_thread_pool.hpp>
#include <mbgl/util/geo.hpp>
@@ -57,7 +56,6 @@ private:
std::shared_ptr<mbgl::UpdateParameters> m_updateParameters;
std::unique_ptr<QMapboxGLMapObserver> m_mapObserver;
- std::shared_ptr<mbgl::DefaultFileSource> m_fileSourceObj;
std::shared_ptr<mbgl::ThreadPool> m_threadPool;
std::unique_ptr<QMapboxGLMapRenderer> m_mapRenderer;
std::unique_ptr<mbgl::Actor<mbgl::ResourceTransform>> m_resourceTransform;
diff --git a/scripts/clang-tools.sh b/scripts/clang-tools.sh
index bdda4544b9..1e73951176 100755
--- a/scripts/clang-tools.sh
+++ b/scripts/clang-tools.sh
@@ -33,7 +33,7 @@ function run_clang_tidy() {
}
function run_clang_tidy_diff() {
- OUTPUT=$(git diff origin/master --src-prefix=${CDUP} --dst-prefix=${CDUP} | \
+ OUTPUT=$(git diff origin/$2 --src-prefix=${CDUP} --dst-prefix=${CDUP} | \
${CLANG_TIDY_PREFIX}/share/clang-tidy-diff.py \
-clang-tidy-binary ${CLANG_TIDY} \
2>/dev/null)
@@ -45,7 +45,7 @@ function run_clang_tidy_diff() {
function run_clang_format() {
echo "Running clang-format on $0..."
- DIFF_FILES=$(git diff origin/master --name-only *cpp)
+ DIFF_FILES=$(git diff origin/$2 --name-only *cpp)
echo "${DIFF_FILES}" | xargs -I{} -P ${JOBS} bash -c 'run_clang_format' {}
${CLANG_FORMAT} -i ${CDUP}/$0 || exit 1
}
@@ -54,7 +54,7 @@ export -f run_clang_tidy run_clang_tidy_diff run_clang_format
echo "Running Clang checks... (this might take a while)"
-if [[ -n $2 ]] && [[ $2 == "--diff" ]]; then
+if [[ -n $3 ]] && [[ $3 == "--diff" ]]; then
run_clang_tidy_diff $@
# XXX disabled until we run clang-format over the entire codebase.
#run_clang_format $@
diff --git a/scripts/code-coverage.sh b/scripts/code-coverage.sh
index d6866f61b8..cb99bd9646 100755
--- a/scripts/code-coverage.sh
+++ b/scripts/code-coverage.sh
@@ -4,7 +4,7 @@ set -e
set -o pipefail
#
-# This script takes three values: $1 should be a decimal value reflecting the
+# This script takes three values: $1 should be a decimal value reflecting the
# percentage of lines covered, with a maximum value of 100.0, $2 is
# the platform the percentage pertains to (iOS or Android), and $3 is the
# test scheme being run (on iOS, this is currently CI).
@@ -17,19 +17,22 @@ if [[ ! $2 = "iOS" && ! $2 = "Android" ]]; then
exit 1
fi
-# Create a formatted JSON file that contains the current coverage.
+circle_sha=""
+if [[ $CIRCLE_SHA1 ]]; then
+ circle_sha="$CIRCLE_SHA1"
+fi
+# Create a formatted JSON file that contains the current coverage.
-current_date=$(TZ=UTC date +"%Y-%m-%d")
+current_date=$(TZ=UTC date +"%FT%T%z")
file_name=$2_coverage.json
cat <<EOF > $file_name
- {"code_coverage":$1,"platform":"$2","sdk":"Maps","scheme":"$3","created_at":"$current_date"}
+{"code_coverage":$1,"platform":"$2","sdk":"Maps","scheme":"$3","created_at":"$current_date","sha":"$circle_sha"}
EOF
gzip -f $file_name
-if [ -z `which aws` ]; then
- brew install awscli
+if [ -z `which aws` ]; then
+ brew install awscli
fi
aws s3 cp $file_name.gz s3://mapbox-loading-dock/raw/mobile.codecoverage/$current_date/
echo $
-
diff --git a/scripts/generate-file-lists.js b/scripts/generate-file-lists.js
index 37e4dbc20b..760a01d87c 100755
--- a/scripts/generate-file-lists.js
+++ b/scripts/generate-file-lists.js
@@ -124,6 +124,7 @@ generateXcodeSourceList('platform/macos/macos.xcodeproj', 'dynamic', 'sdk');
generateXcodeSourceList('platform/ios/ios.xcodeproj', 'dynamic', 'sdk');
const vendorRegex = /^(?:(?:src|include)\/)?(?:(.+)\/)?[^\/]+$/
+generateFileList('vendor/args-files.json', 'vendor/args', vendorRegex, [ "args.hxx" ]);
generateFileList('vendor/boost-files.json', 'vendor/boost', vendorRegex, [ "include/**/*.hpp", "include/**/*.h" ]);
generateFileList('vendor/cheap-ruler-cpp-files.json', 'vendor/cheap-ruler-cpp', vendorRegex, [ "include/**/*.hpp" ]);
generateFileList('vendor/earcut.hpp-files.json', 'vendor/earcut.hpp', vendorRegex, [ "include/**/*.hpp" ]);
diff --git a/scripts/generate-shaders.js b/scripts/generate-shaders.js
index 59544d0b34..fc9088fd21 100755
--- a/scripts/generate-shaders.js
+++ b/scripts/generate-shaders.js
@@ -5,6 +5,7 @@ require('flow-remove-types/register');
const path = require('path');
const outputPath = 'src/mbgl/programs/gl';
const zlib = require('zlib');
+const crypto = require('crypto');
var shaders = require('../mapbox-gl-js/src/shaders');
@@ -23,18 +24,28 @@ function basicMinify(src) {
}
for (const key in shaders) {
+ // Rename a_*_t uniforms to u_*_t. This is a workaround until we can use
+ // https://github.com/mapbox/mapbox-gl-js/pull/8055, which is blocked by
+ // https://github.com/mapbox/mapbox-gl-native/issues/13984
+ shaders[key].vertexSource = shaders[key].vertexSource.replace(/\ba_(\w+)_t\b/mg, 'u_$1_t');
+
+ const hash = crypto.createHash('sha1');
+
const vertex = concatenated.length;
- concatenated += basicMinify(shaders[key].vertexSource);
- concatenated += '\n\0';
+ const vertexSource = basicMinify(shaders[key].vertexSource) + '\n\0';
+ hash.update(vertexSource);
+ concatenated += vertexSource;
const fragment = concatenated.length;
- concatenated += basicMinify(shaders[key].fragmentSource);
- concatenated += '\n\0';
+ const fragmentSource = basicMinify(shaders[key].fragmentSource) + '\n\0';
+ hash.update(fragmentSource);
+ concatenated += fragmentSource;
offsets[key] = {
vertex,
fragment,
originalKey: key,
+ hash: hash.digest('hex').substring(0, 16).match(/.{1,2}/g).map(n => `0x${n}`).join(', '),
shaderName: key.replace(/[A-Z]+/g, (match) => `_${match.toLowerCase()}`),
ShaderName: key.replace(/^[a-z]/g, (match) => match.toUpperCase())
};
@@ -44,6 +55,7 @@ for (const key in shaders) {
offsets.symbolSDFIcon = {
vertex: offsets.symbolSDF.vertex,
fragment: offsets.symbolSDF.fragment,
+ hash: offsets.symbolSDF.hash,
originalKey: 'symbolSDF',
shaderName: 'symbol_sdf_icon',
ShaderName: 'SymbolSDFIcon',
@@ -52,6 +64,7 @@ offsets.symbolSDFIcon = {
offsets.symbolSDFText = {
vertex: offsets.symbolSDF.vertex,
fragment: offsets.symbolSDF.fragment,
+ hash: offsets.symbolSDF.hash,
originalKey: 'symbolSDF',
shaderName: 'symbol_sdf_text',
ShaderName: 'SymbolSDFText',
@@ -66,10 +79,6 @@ const compressed = zlib.deflateSync(concatenated, {level: zlib.Z_BEST_COMPRESSIO
.join(',\n ')
.trim();
-function sourceOffset(key, type) {
- return `programs::gl::shaderSource() + ${offsets[key][type]}`
-}
-
writeIfModified(path.join(outputPath, 'shader_source.hpp'), `// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
#pragma once
@@ -80,6 +89,9 @@ namespace gl {
const char* shaderSource();
+template <typename>
+struct ShaderSource;
+
} // namespace gl
} // namespace programs
} // namespace mbgl
@@ -114,29 +126,15 @@ writeIfModified(path.join(outputPath, 'preludes.hpp'), `// NOTE: DO NOT CHANGE T
#pragma once
-namespace mbgl {
-namespace programs {
-namespace gl {
-
-extern const char* vertexShaderPrelude;
-extern const char* fragmentShaderPrelude;
-
-} // namespace gl
-} // namespace programs
-} // namespace mbgl
-`);
-
-writeIfModified(path.join(outputPath, 'preludes.cpp'), `// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
-
-#include <mbgl/programs/gl/preludes.hpp>
-#include <mbgl/programs/gl/shader_source.hpp>
+#include <cstdint>
namespace mbgl {
namespace programs {
namespace gl {
-const char* vertexShaderPrelude = ${sourceOffset('prelude', 'vertex')};
-const char* fragmentShaderPrelude = ${sourceOffset('prelude', 'fragment')};
+constexpr const uint8_t preludeHash[8] = { ${offsets['prelude'].hash} };
+constexpr const auto vertexPreludeOffset = ${offsets['prelude'].vertex};
+constexpr const auto fragmentPreludeOffset = ${offsets['prelude'].fragment};
} // namespace gl
} // namespace programs
@@ -152,18 +150,37 @@ for (const key in offsets) {
writeIfModified(path.join(outputPath, `${shaderName}.cpp`), `// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
#include <mbgl/programs/${shaderName}_program.hpp>
+#include <mbgl/programs/gl/preludes.hpp>
#include <mbgl/programs/gl/shader_source.hpp>
#include <mbgl/gl/program.hpp>
namespace mbgl {
+namespace programs {
+namespace gl {
+
+template <typename>
+struct ShaderSource;
+
+template <>
+struct ShaderSource<${ShaderName}Program> {
+ static constexpr const char* name = "${shaderName}";
+ static constexpr const uint8_t hash[8] = { ${offsets[key].hash} };
+ static constexpr const auto vertexOffset = ${offsets[key].vertex};
+ static constexpr const auto fragmentOffset = ${offsets[key].fragment};
+};
+
+constexpr const char* ShaderSource<${ShaderName}Program>::name;
+constexpr const uint8_t ShaderSource<${ShaderName}Program>::hash[8];
+
+} // namespace gl
+} // namespace programs
+
namespace gfx {
template <>
std::unique_ptr<Program<${ShaderName}Program>>
Context::createProgram<gl::Context>(const ProgramParameters& programParameters) {
- return gl::Program<${ShaderName}Program>::createProgram(
- reinterpret_cast<gl::Context&>(*this), programParameters, "${shaderName}",
- ${sourceOffset(key, 'vertex')}, ${sourceOffset(key, 'fragment')});
+ return std::make_unique<gl::Program<${ShaderName}Program>>(programParameters);
}
} // namespace gfx
diff --git a/scripts/generate-style-code.js b/scripts/generate-style-code.js
index ae25a856a8..5145755cec 100755
--- a/scripts/generate-style-code.js
+++ b/scripts/generate-style-code.js
@@ -72,7 +72,7 @@ global.evaluatedType = function (property) {
if (property.length) {
return `std::array<${evaluatedType({type: property.value})}, ${property.length}>`;
} else {
- return `std::vector<${evaluatedType({type: property.value})}>`;
+ return `std::vector<${evaluatedType({type: property.value, name: property.name})}>`;
}
default: throw new Error(`unknown type for ${property.name}`)
}
@@ -99,7 +99,7 @@ function attributeUniformType(property, type) {
[ property.name.replace(type + '-', '').replace(/-/g, '_') ];
return names.map(name => {
- return `attributes::a_${name}, uniforms::u_${name}`
+ return `attributes::${name}, uniforms::${name}`
}).join(', ');
}
@@ -153,7 +153,11 @@ global.defaultValue = function (property) {
switch (property.type) {
case 'number':
+ if (property.default === undefined) {
+ return 0;
+ } else {
return property.default;
+ }
case 'formatted':
case 'string':
return JSON.stringify(property.default || "");
diff --git a/scripts/publish_core_codecoverage.js b/scripts/publish_core_codecoverage.js
new file mode 100755
index 0000000000..43de662a13
--- /dev/null
+++ b/scripts/publish_core_codecoverage.js
@@ -0,0 +1,170 @@
+#!/usr/bin/env node
+
+// Script to retrieve total code coverage ratio from codecov.io
+// for a given commit hash, and upload it to the S3 bucket.
+
+const https = require('https');
+const zlib = require('zlib');
+const AWS = require('aws-sdk');
+const {execSync} = require('child_process');
+
+const args = process.argv.slice(2);
+const options = {
+ help: false
+};
+
+const usage = 'usage: publish_code_coverage.js [options]\n' +
+'options: \n' +
+' -h, --help \n' +
+' -p, --platform <Platform Name>\n' +
+' -s, --sdk <Sdk Name> \n' +
+' -c, --commit <Commit Hash> \n';
+
+for (var i = 0; i < args.length; i++) {
+ var arg = args[i];
+
+ switch(arg) {
+ case '-h':
+ case '--help':
+ options.help = true;
+ break;
+ case '-s':
+ case '--sdk':
+ options.sdkName = args[i + 1];
+ break;
+ case '-p':
+ case '--platform':
+ options.platformName = args[i + 1];
+ break;
+ case '-c':
+ case '--commit':
+ options.commitId = args[i + 1];
+ break;
+ }
+}
+
+if (options.help == true) {
+ console.log(usage);
+ process.exit(0);
+}
+
+// Commit hash
+const commitHash = options.commitId ? options.commitId : process.env['CIRCLE_SHA1'];
+if (!options.sdkName || !options.platformName || !commitHash) {
+ console.log(usage);
+ process.exit(0);
+}
+
+// Commit Message
+const commitMessage = execSync(`git show --pretty=format:%s -s ${commitHash}`).toString().trim();
+if (!commitMessage) {
+ throw new Error ('Commit message is missing');
+}
+
+const date = new Date().toISOString().substring(0, 19);
+
+process.on('uncaughtException', (err) => {
+ console.error(err);
+ process.exit(1);
+});
+
+// Parse the response received from codecov.io and build the
+// data point that is going to be uploaded to S3 bucket.
+function parseResponse(data) {
+ if (data && data.commit) {
+ if (!data.commit.totals || !data.commit.totals.c) {
+ return;
+ }
+
+ const source = {
+ code_coverage: Number(data.commit.totals.c),
+ platform: options.platformName,
+ sdk: options.sdkName,
+ commit: commitHash,
+ commit_message: commitMessage,
+ created_at: date
+ };
+
+ return source;
+ }
+}
+
+// Upload to data source used by Mapbox internal metrics dashboards
+function uploadData(data) {
+ return new AWS.S3({region: 'us-east-1'}).putObject({
+ Body: zlib.gzipSync(JSON.stringify(data)),
+ Bucket: 'mapbox-loading-dock',
+ Key: `raw/mobile_staging.codecoverage/${date.substring(0,10)}/${options.sdkName}-coverage-${commitHash}.json.gz`,
+ CacheControl: 'max-age=300',
+ ContentEncoding: 'gzip',
+ ContentType: 'application/json'
+ }).promise();
+}
+
+// Attempt to retrieve code coverage report from codecov.io
+// for a given commit hash.
+function httpRequest() {
+ const options = {
+ hostname: 'codecov.io',
+ port: 443,
+ path: '/api/gh/mapbox/mapbox-gl-native/commit/' + commitHash,
+ method: 'GET'
+ };
+
+ return new Promise((resolve, reject) => {
+ setTimeout(function() {
+ const req = https.request(options, (res) => {
+ var body = [];
+ res.on('data', (chunk) => {
+ body.push(chunk);
+ }).on('error', (error) => {
+ reject(error);
+ }).on('end', () => {
+ if (res.statusCode < 200 || res.statusCode >= 300) {
+ return reject(new Error('Failed to fetch coverage report from codecov.io. StatusCode=' + res.statusCode));
+ }
+
+ try {
+ body = JSON.parse(Buffer.concat(body).toString());
+ resolve(body);
+ } catch(e) {
+ reject(e);
+ }
+ });
+ });
+
+ // Reject on error
+ req.on('error', (err) => {
+ reject(err);
+ });
+
+ req.end();
+ }, 30000);
+ });
+}
+
+var errResponse = false;
+const publishWithRetry = (maxRetries) => {
+ httpRequest().then((body) => {
+ const dataSource = parseResponse(body);
+ if (dataSource) {
+ return uploadData(dataSource);
+ } else {
+ errResponse = true;
+ throw new Error('Failed to parse coverage report received from codecov.io.');
+ }
+ }).then(data => {
+ console.log('Successfully uploaded code coverage metrics to S3');
+ }).catch(err => {
+ if (maxRetries > 1 && errResponse) {
+ console.log('Invalid coverage report received. Trying to retrieve again.');
+ errResponse = false;
+ return publishWithRetry(maxRetries - 1);
+ }
+
+ console.error('Failed to upload code coverage metrics to S3: ' + err.message);
+ });
+};
+
+// Fetch and publish code coverage report
+publishWithRetry(5);
diff --git a/scripts/publish_github_stats.js b/scripts/publish_github_stats.js
new file mode 100755
index 0000000000..f79a5082d0
--- /dev/null
+++ b/scripts/publish_github_stats.js
@@ -0,0 +1,147 @@
+#!/usr/bin/env node
+
+const assert = require('assert');
+const jwt = require('jsonwebtoken');
+const github = require('@octokit/rest')();
+const zlib = require('zlib');
+const AWS = require('aws-sdk');
+
+const SIZE_CHECK_APP_ID = 14028;
+const SIZE_CHECK_APP_INSTALLATION_ID = 229425;
+
+// Error handling
+
+process.on('unhandledRejection', error => {
+ console.log(error);
+ process.exit(1)
+});
+
+// Github authorization
+
+const pk = process.env['SIZE_CHECK_APP_PRIVATE_KEY'];
+if (!pk) {
+ console.log('Fork PR; not publishing size.');
+ process.exit(0);
+}
+
+const key = Buffer.from(pk, 'base64').toString('binary');
+const payload = {
+ exp: Math.floor(Date.now() / 1000) + 60,
+ iat: Math.floor(Date.now() / 1000),
+ iss: SIZE_CHECK_APP_ID
+};
+
+const token = jwt.sign(payload, key, {algorithm: 'RS256'});
+github.authenticate({type: 'app', token});
+
+// Metrics: Github statistics
+let openIssuesTotal = 0;
+let openIssuesTotalFromNonMembers = 0;
+let openIssuesTotalCore = 0;
+let openIssuesTotalAndroid = 0;
+let openIssuesTotalIOS = 0;
+let openIssuesTotalGLJSParity = 0;
+let openPullRequestsTotal = 0;
+let openPullRequestsTotalFromNonMembers = 0;
+let openPullRequestsSinceLastMonth = 0;
+let openPullRequestsSinceLastMonthFromNonMembers = 0;
+
+function collectMetricsFromIssues(issues) {
+ const oneMonthAgo = function() { let date = new Date(); date.setMonth(date.getMonth() - 1); return date; }();
+
+ // Metrics
+ issues.data.forEach(function (issue) {
+ const issueCreatedAt = new Date(issue.created_at);
+ const isMapboxAuthor = issue.author_association === "MEMBER";
+
+ if (issue.pull_request) {
+ openPullRequestsTotal++;
+ if (!isMapboxAuthor) {
+ openPullRequestsTotalFromNonMembers++;
+ }
+ if (issueCreatedAt >= oneMonthAgo) {
+ openPullRequestsSinceLastMonth++;
+ if (!isMapboxAuthor) {
+ openPullRequestsSinceLastMonthFromNonMembers++;
+ }
+ }
+ } else {
+ openIssuesTotal++;
+ if (!isMapboxAuthor) {
+ openIssuesTotalFromNonMembers++;
+ }
+ issue.labels.forEach(function (label) {
+ switch (label.name) {
+ case "Core":
+ openIssuesTotalCore++;
+ break;
+ case "Android":
+ openIssuesTotalAndroid++;
+ break;
+ case "iOS":
+ openIssuesTotalIOS++;
+ break;
+ case "GL JS parity":
+ openIssuesTotalGLJSParity++;
+ break;
+ default:
+ break;
+ }
+ });
+ }
+ });
+}
+
+function publishMetrics() {
+ let metrics = {
+ 'created_at': new Date().toISOString().substring(0, 10),
+ 'open_issues_total': openIssuesTotal,
+ 'open_issues_total_from_non_members': openIssuesTotalFromNonMembers,
+ 'open_issues_total_core': openIssuesTotalCore,
+ 'open_issues_total_android': openIssuesTotalAndroid,
+ 'open_issues_total_ios': openIssuesTotalIOS,
+ 'open_issues_total_gl_js_parity': openIssuesTotalGLJSParity,
+ 'open_pull_requests_total': openPullRequestsTotal,
+ 'open_pull_requests_total_from_non_members': openPullRequestsTotalFromNonMembers,
+ 'open_pull_requests_since_last_month': openPullRequestsSinceLastMonth,
+ 'open_pull_requests_since_last_month_from_non_members': openPullRequestsSinceLastMonthFromNonMembers
+ };
+
+ var promise = new AWS.S3({region: 'us-east-1'}).putObject({
+ Body: zlib.gzipSync(JSON.stringify(metrics)),
+ Bucket: 'mapbox-loading-dock',
+ Key: `raw/mobile_staging.github_stats/${metrics['created_at']}/METRIC.json.gz`,
+ CacheControl: 'max-age=300',
+ ContentEncoding: 'gzip',
+ ContentType: 'application/json'
+ }).promise();
+
+ return Promise.all([promise]).then(data => {
+ return console.log("Successfully uploaded Github Stats metrics to S3");
+ }).catch(err => {
+ console.log("Error uploading Github Stats metrics to S3 " + err.message);
+ return err;
+ });
+}
+
+function recursiveListForRepo(query) {
+ assert(query);
+ query.then(result => {
+ collectMetricsFromIssues(result);
+ if (github.hasNextPage(result)) {
+ recursiveListForRepo(github.getNextPage(result));
+ } else {
+ publishMetrics();
+ }
+ }).catch(error => {
+ console.log("Error fetching the repository issues list: " + err.message);
+ });
+}
+
+github.apps.createInstallationToken({ installation_id: SIZE_CHECK_APP_INSTALLATION_ID })
+ .then(({data}) => {
+ github.authenticate({ type: 'token', token: data.token });
+ })
+ .then(() => {
+ recursiveListForRepo(github.issues.listForRepo({ owner: 'mapbox', repo: 'mapbox-gl-native', state: 'open', per_page: 100 }));
+ });
diff --git a/scripts/style-spec.js b/scripts/style-spec.js
index 4bbd453a86..b2686a6a77 100644
--- a/scripts/style-spec.js
+++ b/scripts/style-spec.js
@@ -3,9 +3,4 @@ var spec = module.exports = require('../mapbox-gl-js/src/style-spec/reference/v8
// Make temporary modifications here when Native doesn't have all features that JS has.
delete spec.layout_symbol['symbol-sort-key'];
delete spec.layout_symbol['symbol-z-order'].values['auto'];
-spec.layout_symbol['symbol-z-order'].default = 'viewport-y';
-
-delete spec.layout_symbol['text-variable-anchor'];
-delete spec.layout_symbol['text-radial-offset'];
-delete spec.layout_symbol['text-justify'].values['auto'];
-spec.layout_symbol['text-offset'].requires.splice(1, 1); // { "!": "text-radial-offset" } \ No newline at end of file
+spec.layout_symbol['symbol-z-order'].default = 'viewport-y'; \ No newline at end of file
diff --git a/src/core-files.json b/src/core-files.json
index 272faaf9b6..b257666e3e 100644
--- a/src/core-files.json
+++ b/src/core-files.json
@@ -82,7 +82,6 @@
"src/mbgl/programs/gl/line_gradient.cpp",
"src/mbgl/programs/gl/line_pattern.cpp",
"src/mbgl/programs/gl/line_sdf.cpp",
- "src/mbgl/programs/gl/preludes.cpp",
"src/mbgl/programs/gl/raster.cpp",
"src/mbgl/programs/gl/shader_source.cpp",
"src/mbgl/programs/gl/shaders.cpp",
@@ -144,8 +143,10 @@
"src/mbgl/sprite/sprite_loader.cpp",
"src/mbgl/sprite/sprite_loader_worker.cpp",
"src/mbgl/sprite/sprite_parser.cpp",
+ "src/mbgl/storage/file_source.cpp",
"src/mbgl/storage/network_status.cpp",
"src/mbgl/storage/resource.cpp",
+ "src/mbgl/storage/resource_options.cpp",
"src/mbgl/storage/resource_transform.cpp",
"src/mbgl/storage/response.cpp",
"src/mbgl/style/conversion/color_ramp_property_value.cpp",
@@ -359,6 +360,7 @@
"mbgl/storage/offline.hpp": "include/mbgl/storage/offline.hpp",
"mbgl/storage/online_file_source.hpp": "include/mbgl/storage/online_file_source.hpp",
"mbgl/storage/resource.hpp": "include/mbgl/storage/resource.hpp",
+ "mbgl/storage/resource_options.hpp": "include/mbgl/storage/resource_options.hpp",
"mbgl/storage/resource_transform.hpp": "include/mbgl/storage/resource_transform.hpp",
"mbgl/storage/response.hpp": "include/mbgl/storage/response.hpp",
"mbgl/style/color_ramp_property_value.hpp": "include/mbgl/style/color_ramp_property_value.hpp",
@@ -613,6 +615,7 @@
"mbgl/renderer/group_by_layout.hpp": "src/mbgl/renderer/group_by_layout.hpp",
"mbgl/renderer/image_atlas.hpp": "src/mbgl/renderer/image_atlas.hpp",
"mbgl/renderer/image_manager.hpp": "src/mbgl/renderer/image_manager.hpp",
+ "mbgl/renderer/image_manager_observer.hpp": "src/mbgl/renderer/image_manager_observer.hpp",
"mbgl/renderer/layers/render_background_layer.hpp": "src/mbgl/renderer/layers/render_background_layer.hpp",
"mbgl/renderer/layers/render_circle_layer.hpp": "src/mbgl/renderer/layers/render_circle_layer.hpp",
"mbgl/renderer/layers/render_custom_layer.hpp": "src/mbgl/renderer/layers/render_custom_layer.hpp",
@@ -744,6 +747,7 @@
"mbgl/util/i18n.hpp": "src/mbgl/util/i18n.hpp",
"mbgl/util/intersection_tests.hpp": "src/mbgl/util/intersection_tests.hpp",
"mbgl/util/io.hpp": "src/mbgl/util/io.hpp",
+ "mbgl/util/literal.hpp": "src/mbgl/util/literal.hpp",
"mbgl/util/longest_common_subsequence.hpp": "src/mbgl/util/longest_common_subsequence.hpp",
"mbgl/util/mapbox.hpp": "src/mbgl/util/mapbox.hpp",
"mbgl/util/mat2.hpp": "src/mbgl/util/mat2.hpp",
diff --git a/src/mbgl/annotation/annotation_manager.cpp b/src/mbgl/annotation/annotation_manager.cpp
index ab22404c15..345171b96e 100644
--- a/src/mbgl/annotation/annotation_manager.cpp
+++ b/src/mbgl/annotation/annotation_manager.cpp
@@ -10,7 +10,6 @@
#include <mbgl/style/layers/symbol_layer.hpp>
#include <mbgl/style/layers/symbol_layer_impl.hpp>
#include <mbgl/style/expression/dsl.hpp>
-#include <mbgl/storage/file_source.hpp>
#include <boost/function_output_iterator.hpp>
diff --git a/src/mbgl/gfx/attribute.hpp b/src/mbgl/gfx/attribute.hpp
index 4f44d68d7b..f5188ccfdb 100644
--- a/src/mbgl/gfx/attribute.hpp
+++ b/src/mbgl/gfx/attribute.hpp
@@ -14,7 +14,7 @@
#define MBGL_DEFINE_ATTRIBUTE(type_, n_, name_) \
struct name_ { \
using Type = ::mbgl::gfx::AttributeType<type_, n_>; \
- static auto name() { \
+ static constexpr auto name() { \
return #name_; \
} \
}
diff --git a/src/mbgl/gfx/context.hpp b/src/mbgl/gfx/context.hpp
index 90b62c94a4..e898006ff5 100644
--- a/src/mbgl/gfx/context.hpp
+++ b/src/mbgl/gfx/context.hpp
@@ -17,10 +17,14 @@ namespace gfx {
class Context {
protected:
- Context(ContextType type_) : backend(type_) {
+ Context(ContextType type_, uint32_t maximumVertexBindingCount_)
+ : backend(type_), maximumVertexBindingCount(maximumVertexBindingCount_) {
}
+public:
const ContextType backend;
+ static constexpr const uint32_t minimumRequiredVertexBindingCount = 8;
+ const uint32_t maximumVertexBindingCount;
public:
Context(Context&&) = delete;
@@ -30,6 +34,10 @@ public:
virtual ~Context() = default;
public:
+ // Called at the end of a frame.
+ virtual void performCleanup() = 0;
+
+public:
template <class Vertex>
VertexBuffer<Vertex>
createVertexBuffer(VertexVector<Vertex>&& v,
@@ -92,11 +100,25 @@ public:
texture.size = image.size;
}
+ template <typename Image>
+ void updateTextureSub(Texture& texture,
+ const Image& image,
+ const uint16_t offsetX,
+ const uint16_t offsetY,
+ TextureChannelDataType type = TextureChannelDataType::UnsignedByte) {
+ assert(image.size.width + offsetX <= texture.size.width);
+ assert(image.size.height + offsetY <= texture.size.height);
+ auto format = image.channels == 4 ? TexturePixelType::RGBA : TexturePixelType::Alpha;
+ updateTextureResourceSub(*texture.resource, offsetX, offsetY, image.size, image.data.get(), format, type);
+ }
+
protected:
virtual std::unique_ptr<TextureResource> createTextureResource(
Size, const void* data, TexturePixelType, TextureChannelDataType) = 0;
virtual void updateTextureResource(const TextureResource&, Size, const void* data,
TexturePixelType, TextureChannelDataType) = 0;
+ virtual void updateTextureResourceSub(const TextureResource&, uint16_t xOffset, uint16_t yOffset, Size, const void* data,
+ TexturePixelType, TextureChannelDataType) = 0;
public:
DrawScope createDrawScope() {
diff --git a/src/mbgl/gl/attribute.hpp b/src/mbgl/gl/attribute.hpp
index c4fe8b993f..c7f9ba3fd4 100644
--- a/src/mbgl/gl/attribute.hpp
+++ b/src/mbgl/gl/attribute.hpp
@@ -3,6 +3,7 @@
#include <mbgl/gfx/attribute.hpp>
#include <mbgl/gl/types.hpp>
#include <mbgl/util/ignore.hpp>
+#include <mbgl/util/literal.hpp>
#include <mbgl/util/indexed_tuple.hpp>
#include <mbgl/util/optional.hpp>
@@ -50,13 +51,15 @@ public:
}
};
- return Locations{ maybeBindLocation(As::name())... };
+ return Locations{ maybeBindLocation(
+ concat_literals<&string_literal<'a', '_'>::value, &As::name>::value())... };
}()) {
}
template <class BinaryProgram>
AttributeLocations(const BinaryProgram& program)
- : locations{ program.attributeLocation(As::name())... } {
+ : locations{ program.attributeLocation(
+ concat_literals<&string_literal<'a', '_'>::value, &As::name>::value())... } {
}
NamedAttributeLocations getNamedLocations() const {
@@ -68,7 +71,9 @@ public:
}
};
- util::ignore({ (maybeAddLocation(As::name(), locations.template get<As>()), 0)... });
+ util::ignore({ (maybeAddLocation(concat_literals<&string_literal<'a', '_'>::value, &As::name>::value(),
+ locations.template get<As>()),
+ 0)... });
return result;
}
@@ -90,5 +95,36 @@ public:
}
};
+template <class>
+class AttributeKey;
+
+constexpr auto attributeDefinePrefix() {
+ return "#define HAS_UNIFORM_u_";
+}
+
+template <class... As>
+class AttributeKey<TypeList<As...>> final {
+public:
+ static_assert(sizeof...(As) <= 32, "attribute count exceeds 32");
+
+ static uint32_t compute(const gfx::AttributeBindings<TypeList<As...>>& bindings) {
+ uint32_t value = 0;
+ util::ignore(
+ { (bindings.template get<As>() ? (void)(value |= 1 << TypeIndex<As, As...>::value)
+ : (void)0,
+ 0)... });
+ return value;
+ }
+
+ static std::string defines(const gfx::AttributeBindings<TypeList<As...>>& bindings) {
+ std::string result;
+ util::ignore({ (!bindings.template get<As>()
+ ? (void)(result += concat_literals<&attributeDefinePrefix, &As::name, &string_literal<'\n'>::value>::value())
+ : (void)0,
+ 0)... });
+ return result;
+ }
+};
+
} // namespace gl
} // namespace mbgl
diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp
index 5193381251..6cee364379 100644
--- a/src/mbgl/gl/context.cpp
+++ b/src/mbgl/gl/context.cpp
@@ -5,6 +5,7 @@
#include <mbgl/gl/texture_resource.hpp>
#include <mbgl/gl/draw_scope_resource.hpp>
#include <mbgl/gl/texture.hpp>
+#include <mbgl/gl/debugging.hpp>
#include <mbgl/gl/debugging_extension.hpp>
#include <mbgl/gl/vertex_array_extension.hpp>
#include <mbgl/gl/program_binary_extension.hpp>
@@ -67,7 +68,7 @@ static_assert(underlying_type(UniformDataType::SamplerCube) == GL_SAMPLER_CUBE,
static_assert(std::is_same<BinaryProgramFormat, GLenum>::value, "OpenGL type mismatch");
Context::Context()
- : gfx::Context(gfx::ContextType::OpenGL), maximumVertexBindingCount([] {
+ : gfx::Context(gfx::ContextType::OpenGL, [] {
GLint value;
MBGL_CHECK_ERROR(glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &value));
return value;
@@ -160,12 +161,10 @@ void Context::enableDebugging() {
MBGL_CHECK_ERROR(debugging->debugMessageCallback(extension::Debugging::DebugCallback, nullptr));
}
-UniqueShader Context::createShader(ShaderType type, const std::string& source) {
+UniqueShader Context::createShader(ShaderType type, const std::initializer_list<const char*>& sources) {
UniqueShader result { MBGL_CHECK_ERROR(glCreateShader(static_cast<GLenum>(type))), { this } };
- const GLchar* sources = source.data();
- const auto lengths = static_cast<GLsizei>(source.length());
- MBGL_CHECK_ERROR(glShaderSource(result, 1, &sources, &lengths));
+ MBGL_CHECK_ERROR(glShaderSource(result, static_cast<GLsizei>(sources.size()), sources.begin(), nullptr));
MBGL_CHECK_ERROR(glCompileShader(result));
GLint status = 0;
@@ -547,6 +546,24 @@ void Context::updateTextureResource(const gfx::TextureResource& resource,
Enum<gfx::TextureChannelDataType>::to(type), data));
}
+void Context::updateTextureResourceSub(const gfx::TextureResource& resource,
+ const uint16_t xOffset,
+ const uint16_t yOffset,
+ const Size size,
+ const void* data,
+ gfx::TexturePixelType format,
+ gfx::TextureChannelDataType type) {
+ // Always use texture unit 0 for manipulating it.
+ activeTextureUnit = 0;
+ texture[0] = static_cast<const gl::TextureResource&>(resource).texture;
+ MBGL_CHECK_ERROR(glTexSubImage2D(GL_TEXTURE_2D, 0,
+ xOffset, yOffset,
+ size.width, size.height,
+ Enum<gfx::TexturePixelType>::to(format),
+ Enum<gfx::TextureChannelDataType>::to(type), data));
+}
+
+
std::unique_ptr<gfx::DrawScopeResource> Context::createDrawScopeResource() {
return std::make_unique<gl::DrawScopeResource>(createVertexArray());
}
@@ -708,6 +725,19 @@ void Context::draw(const gfx::DrawMode& drawMode,
}
void Context::performCleanup() {
+ // TODO: Find a better way to unbind VAOs after we're done with them without introducing
+ // unnecessary bind(0)/bind(N) sequences.
+ {
+ MBGL_DEBUG_GROUP(*this, "cleanup");
+
+ activeTextureUnit = 1;
+ texture[1] = 0;
+ activeTextureUnit = 0;
+ texture[0] = 0;
+
+ bindVertexArray = 0;
+ }
+
for (auto id : abandonedPrograms) {
if (program == id) {
program.setDirty();
@@ -775,5 +805,9 @@ void Context::performCleanup() {
}
}
+void Context::flush() {
+ MBGL_CHECK_ERROR(glFinish());
+}
+
} // namespace gl
} // namespace mbgl
diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp
index fe09390cc6..d46727cb7a 100644
--- a/src/mbgl/gl/context.hpp
+++ b/src/mbgl/gl/context.hpp
@@ -46,7 +46,7 @@ public:
void enableDebugging();
- UniqueShader createShader(ShaderType type, const std::string& source);
+ UniqueShader createShader(ShaderType type, const std::initializer_list<const char*>& sources);
UniqueProgram createProgram(ShaderID vertexShader, ShaderID fragmentShader);
UniqueProgram createProgram(BinaryProgramFormat binaryFormat, const std::string& binaryProgram);
void verifyProgramLinkage(ProgramID);
@@ -56,7 +56,7 @@ public:
#if MBGL_HAS_BINARY_PROGRAMS
bool supportsProgramBinaries() const;
#else
- constexpr bool supportsProgramBinaries() const { return false; }
+ constexpr static bool supportsProgramBinaries() { return false; }
#endif
optional<std::pair<BinaryProgramFormat, std::string>> getBinaryProgram(ProgramID) const;
@@ -110,12 +110,17 @@ public:
// Actually remove the objects we marked as abandoned with the above methods.
// Only call this while the OpenGL context is exclusive to this thread.
- void performCleanup();
+ void performCleanup() override;
// Drain pools and remove abandoned objects, in preparation for destroying the store.
// Only call this while the OpenGL context is exclusive to this thread.
void reset();
+ // Flush pending graphics commands. Will block until the pipeline
+ // is empty. Should be used only with a very good reason because
+ // it will have a performance impact.
+ void flush();
+
bool empty() const {
return pooledTextures.empty()
&& abandonedPrograms.empty()
@@ -172,9 +177,7 @@ public:
#endif // MBGL_USE_GLES2
bool supportsHalfFloatTextures = false;
- const uint32_t maximumVertexBindingCount;
- static constexpr const uint32_t minimumRequiredVertexBindingCount = 8;
-
+
private:
State<value::StencilFunc> stencilFunc;
State<value::StencilMask> stencilMask;
@@ -208,6 +211,7 @@ private:
std::unique_ptr<gfx::TextureResource> createTextureResource(Size, const void* data, gfx::TexturePixelType, gfx::TextureChannelDataType) override;
void updateTextureResource(const gfx::TextureResource&, Size, const void* data, gfx::TexturePixelType, gfx::TextureChannelDataType) override;
+ void updateTextureResourceSub(const gfx::TextureResource&, const uint16_t xOffset, const uint16_t yOffset, Size, const void* data, gfx::TexturePixelType, gfx::TextureChannelDataType) override;
std::unique_ptr<gfx::DrawScopeResource> createDrawScopeResource() override;
diff --git a/src/mbgl/gl/debugging.cpp b/src/mbgl/gl/debugging.cpp
index 7b8121f003..54cee5fc09 100644
--- a/src/mbgl/gl/debugging.cpp
+++ b/src/mbgl/gl/debugging.cpp
@@ -9,8 +9,8 @@ using namespace platform;
#ifndef NDEBUG
-DebugGroup::DebugGroup(const Context& context_, const std::string& name) : context(context_) {
- if (auto debugging = context.getDebuggingExtension()) {
+DebugGroup::DebugGroup(const gfx::Context& context_, const std::string& name) : context(context_) {
+ if (auto debugging = reinterpret_cast<const gl::Context&>(context).getDebuggingExtension()) {
if (debugging->pushDebugGroup) {
MBGL_CHECK_ERROR(debugging->pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, GLsizei(name.size()), name.c_str()));
} else if (debugging->pushGroupMarkerEXT) {
@@ -20,7 +20,7 @@ DebugGroup::DebugGroup(const Context& context_, const std::string& name) : conte
}
DebugGroup::~DebugGroup() {
- if (auto debugging = context.getDebuggingExtension()) {
+ if (auto debugging = reinterpret_cast<const gl::Context&>(context).getDebuggingExtension()) {
if (debugging->popDebugGroup) {
MBGL_CHECK_ERROR(debugging->popDebugGroup());
} else if (debugging->popGroupMarkerEXT) {
diff --git a/src/mbgl/gl/debugging.hpp b/src/mbgl/gl/debugging.hpp
index d24b727295..d85eb631be 100644
--- a/src/mbgl/gl/debugging.hpp
+++ b/src/mbgl/gl/debugging.hpp
@@ -5,19 +5,22 @@
#include <string>
namespace mbgl {
-namespace gl {
+namespace gfx {
class Context;
+} // namespace gfx
+
+namespace gl {
#ifndef NDEBUG
class DebugGroup : private util::noncopyable {
public:
- DebugGroup(const Context&, const std::string&);
+ DebugGroup(const gfx::Context&, const std::string&);
~DebugGroup();
private:
- const Context& context;
+ const gfx::Context& context;
};
#define __MBGL_DEBUG_GROUP_NAME2(counter) __MBGL_DEBUG_GROUP_##counter
diff --git a/src/mbgl/gl/features.hpp b/src/mbgl/gl/features.hpp
index 1757093967..1da1371e45 100644
--- a/src/mbgl/gl/features.hpp
+++ b/src/mbgl/gl/features.hpp
@@ -3,5 +3,6 @@
#if __APPLE__
#define MBGL_HAS_BINARY_PROGRAMS 0
#else
- #define MBGL_HAS_BINARY_PROGRAMS 1
+ // https://github.com/mapbox/mapbox-gl-native/issues/14294
+ #define MBGL_HAS_BINARY_PROGRAMS 0
#endif
diff --git a/src/mbgl/gl/program.hpp b/src/mbgl/gl/program.hpp
index 9028ffdf53..1cec7671a1 100644
--- a/src/mbgl/gl/program.hpp
+++ b/src/mbgl/gl/program.hpp
@@ -18,6 +18,7 @@
#include <mbgl/util/logging.hpp>
#include <mbgl/programs/program_parameters.hpp>
+#include <mbgl/programs/gl/shader_source.hpp>
#include <mbgl/programs/gl/shaders.hpp>
#include <string>
@@ -31,93 +32,128 @@ public:
using AttributeList = typename Name::AttributeList;
using UniformList = typename Name::UniformList;
using TextureList = typename Name::TextureList;
-
- Program(Context& context, const std::string& vertexSource, const std::string& fragmentSource)
- : program(
- context.createProgram(context.createShader(ShaderType::Vertex, vertexSource),
- context.createShader(ShaderType::Fragment, fragmentSource))),
- attributeLocations(context, program) {
- // Re-link program after manually binding only active attributes in Attributes::queryLocations
- context.linkProgram(program);
-
- // We have to re-initialize the uniforms state from the bindings as the uniform locations
- // get shifted on some implementations
- uniformStates.queryLocations(program);
-
- // Texture units are specified via uniforms as well, so we need query their locations
- textureStates.queryLocations(program);
- }
- template <class BinaryProgram>
- Program(Context& context, const BinaryProgram& binaryProgram)
- : program(context.createProgram(binaryProgram.format(), binaryProgram.code())),
- attributeLocations(binaryProgram) {
- uniformStates.loadNamedLocations(binaryProgram);
- textureStates.loadNamedLocations(binaryProgram);
+ Program(ProgramParameters programParameters_)
+ : programParameters(std::move(programParameters_)) {
}
- static std::unique_ptr<Program> createProgram(gl::Context& context,
- const ProgramParameters& programParameters,
- const char* name,
- const char* vertexSource_,
- const char* fragmentSource_) {
- const std::string vertexSource = programs::gl::vertexSource(programParameters, vertexSource_);
- const std::string fragmentSource = programs::gl::fragmentSource(programParameters, fragmentSource_);
+ const ProgramParameters programParameters;
+
+ static constexpr const auto vertexOffset = programs::gl::ShaderSource<Name>::vertexOffset;
+ static constexpr const auto fragmentOffset = programs::gl::ShaderSource<Name>::fragmentOffset;
+
+ class Instance {
+ public:
+ Instance(Context& context,
+ const std::initializer_list<const char*>& vertexSource,
+ const std::initializer_list<const char*>& fragmentSource)
+ : program(context.createProgram(
+ context.createShader(ShaderType::Vertex, vertexSource),
+ context.createShader(ShaderType::Fragment, fragmentSource))),
+ attributeLocations(context, program) {
+ // Re-link program after manually binding only active attributes in Attributes::queryLocations
+ context.linkProgram(program);
+
+ // We have to re-initialize the uniforms state from the bindings as the uniform locations
+ // get shifted on some implementations
+ uniformStates.queryLocations(program);
+
+ // Texture units are specified via uniforms as well, so we need query their locations
+ textureStates.queryLocations(program);
+ }
+
+ template <class BinaryProgram>
+ Instance(Context& context, const BinaryProgram& binaryProgram)
+ : program(context.createProgram(binaryProgram.format(), binaryProgram.code())),
+ attributeLocations(binaryProgram) {
+ uniformStates.loadNamedLocations(binaryProgram);
+ textureStates.loadNamedLocations(binaryProgram);
+ }
+
+ static std::unique_ptr<Instance>
+ createInstance(gl::Context& context,
+ const ProgramParameters& programParameters,
+ const std::string& additionalDefines) {
+
+
#if MBGL_HAS_BINARY_PROGRAMS
- optional<std::string> cachePath = programParameters.cachePath(name);
- if (cachePath && context.supportsProgramBinaries()) {
- const std::string identifier = programs::gl::programIdentifier(vertexSource, fragmentSource);
-
- try {
- if (auto cachedBinaryProgram = util::readFile(*cachePath)) {
- const BinaryProgram binaryProgram(std::move(*cachedBinaryProgram));
- if (binaryProgram.identifier() == identifier) {
- return std::make_unique<Program>(context, binaryProgram);
- } else {
- Log::Warning(Event::OpenGL,
- "Cached program %s changed. Recompilation required.",
- name);
+ optional<std::string> cachePath =
+ programParameters.cachePath(programs::gl::ShaderSource<Name>::name);
+ std::string programIdentifier;
+ if (cachePath && context.supportsProgramBinaries()) {
+ programIdentifier = programs::gl::programIdentifier(
+ programParameters.getDefines(), additionalDefines, programs::gl::preludeHash,
+ programs::gl::ShaderSource<Name>::hash);
+
+ try {
+ if (auto cachedBinaryProgram = util::readFile(*cachePath)) {
+ const BinaryProgram binaryProgram(std::move(*cachedBinaryProgram));
+ if (binaryProgram.identifier() == programIdentifier) {
+ return std::make_unique<Instance>(context, binaryProgram);
+ } else {
+ Log::Warning(Event::OpenGL,
+ "Cached program %s changed. Recompilation required.",
+ programs::gl::ShaderSource<Name>::name);
+ }
}
+ } catch (std::runtime_error& error) {
+ Log::Warning(Event::OpenGL, "Could not load cached program: %s",
+ error.what());
}
- } catch (std::runtime_error& error) {
- Log::Warning(Event::OpenGL, "Could not load cached program: %s",
- error.what());
}
+#endif
// Compile the shader
- auto result = std::make_unique<Program>(context, vertexSource, fragmentSource);
+ const std::initializer_list<const char*> vertexSource = {
+ programParameters.getDefines().c_str(),
+ additionalDefines.c_str(),
+ (programs::gl::shaderSource() + programs::gl::vertexPreludeOffset),
+ (programs::gl::shaderSource() + vertexOffset)
+ };
+ const std::initializer_list<const char*> fragmentSource = {
+ programParameters.getDefines().c_str(),
+ additionalDefines.c_str(),
+ (programs::gl::shaderSource() + programs::gl::fragmentPreludeOffset),
+ (programs::gl::shaderSource() + fragmentOffset)
+ };
+ auto result = std::make_unique<Instance>(context, vertexSource, fragmentSource);
- try {
- if (const auto binaryProgram =
- result->template get<BinaryProgram>(context, identifier)) {
- util::write_file(*cachePath, binaryProgram->serialize());
- Log::Warning(Event::OpenGL, "Caching program in: %s", (*cachePath).c_str());
+#if MBGL_HAS_BINARY_PROGRAMS
+ if (cachePath && context.supportsProgramBinaries()) {
+ try {
+ if (const auto binaryProgram =
+ result->template get<BinaryProgram>(context, programIdentifier)) {
+ util::write_file(*cachePath, binaryProgram->serialize());
+ Log::Warning(Event::OpenGL, "Caching program in: %s", (*cachePath).c_str());
+ }
+ } catch (std::runtime_error& error) {
+ Log::Warning(Event::OpenGL, "Failed to cache program: %s", error.what());
}
- } catch (std::runtime_error& error) {
- Log::Warning(Event::OpenGL, "Failed to cache program: %s", error.what());
}
-
+#endif
+
return std::move(result);
}
-#endif
- (void)name;
- return std::make_unique<Program>(context, vertexSource, fragmentSource);
- }
-
- template <class BinaryProgram>
- optional<BinaryProgram> get(Context& context, const std::string& identifier) const {
- if (auto binaryProgram = context.getBinaryProgram(program)) {
- return BinaryProgram{ binaryProgram->first,
- std::move(binaryProgram->second),
- identifier,
- attributeLocations.getNamedLocations(),
- uniformStates.getNamedLocations(),
- textureStates.getNamedLocations() };
+ template <class BinaryProgram>
+ optional<BinaryProgram> get(Context& context, const std::string& identifier) const {
+ if (auto binaryProgram = context.getBinaryProgram(program)) {
+ return BinaryProgram{ binaryProgram->first,
+ std::move(binaryProgram->second),
+ identifier,
+ attributeLocations.getNamedLocations(),
+ uniformStates.getNamedLocations(),
+ textureStates.getNamedLocations() };
+ }
+ return {};
}
- return {};
- }
+
+ UniqueProgram program;
+ gl::AttributeLocations<AttributeList> attributeLocations;
+ gl::UniformStates<UniformList> uniformStates;
+ gl::TextureStates<TextureList> textureStates;
+ };
void draw(gfx::Context& genericContext,
const gfx::DrawMode& drawMode,
@@ -139,16 +175,29 @@ public:
context.setColorMode(colorMode);
context.setCullFaceMode(cullFaceMode);
- context.program = program;
+ const uint32_t key = gl::AttributeKey<AttributeList>::compute(attributeBindings);
+ auto it = instances.find(key);
+ if (it == instances.end()) {
+ it = instances
+ .emplace(key,
+ Instance::createInstance(
+ context,
+ programParameters,
+ gl::AttributeKey<AttributeList>::defines(attributeBindings)))
+ .first;
+ }
- uniformStates.bind(uniformValues);
+ auto& instance = *it->second;
+ context.program = instance.program;
- textureStates.bind(context, textureBindings);
+ instance.uniformStates.bind(uniformValues);
+
+ instance.textureStates.bind(context, textureBindings);
auto& vertexArray = reinterpret_cast<gl::DrawScopeResource&>(*drawScope.resource).vertexArray;
vertexArray.bind(context,
indexBuffer,
- attributeLocations.toBindingArray(attributeBindings));
+ instance.attributeLocations.toBindingArray(attributeBindings));
context.draw(drawMode,
indexOffset,
@@ -156,11 +205,7 @@ public:
}
private:
- UniqueProgram program;
-
- gl::AttributeLocations<AttributeList> attributeLocations;
- gl::UniformStates<UniformList> uniformStates;
- gl::TextureStates<TextureList> textureStates;
+ std::map<uint32_t, std::unique_ptr<Instance>> instances;
};
} // namespace gl
diff --git a/src/mbgl/gl/texture.hpp b/src/mbgl/gl/texture.hpp
index 0569adc3b0..44b81f9a45 100644
--- a/src/mbgl/gl/texture.hpp
+++ b/src/mbgl/gl/texture.hpp
@@ -2,6 +2,7 @@
#include <mbgl/gfx/texture.hpp>
#include <mbgl/gl/uniform.hpp>
+#include <mbgl/util/literal.hpp>
#include <mbgl/util/ignore.hpp>
#include <vector>
@@ -27,16 +28,19 @@ private:
public:
void queryLocations(const ProgramID& id) {
- state = State{ gl::uniformLocation(id, Ts::name())... };
+ state = State{ gl::uniformLocation(id,
+ concat_literals<&string_literal<'u', '_'>::value, &Ts::name>::value())... };
}
template <class BinaryProgram>
void loadNamedLocations(const BinaryProgram& program) {
- state = State{ program.textureLocation(Ts::name())... };
+ state = State{ program.textureLocation(
+ concat_literals<&string_literal<'u', '_'>::value, &Ts::name>::value())... };
}
NamedUniformLocations getNamedLocations() const {
- return NamedUniformLocations{ { Ts::name(), state.template get<Ts>().location }... };
+ return NamedUniformLocations{ { concat_literals<&string_literal<'u', '_'>::value, &Ts::name>::value(),
+ state.template get<Ts>().location }... };
}
void bind(gl::Context& context, const gfx::TextureBindings<TypeList<Ts...>>& bindings) {
diff --git a/src/mbgl/gl/uniform.hpp b/src/mbgl/gl/uniform.hpp
index 770f3e2294..89ef675a6b 100644
--- a/src/mbgl/gl/uniform.hpp
+++ b/src/mbgl/gl/uniform.hpp
@@ -3,6 +3,7 @@
#include <mbgl/gfx/uniform.hpp>
#include <mbgl/gl/types.hpp>
#include <mbgl/util/optional.hpp>
+#include <mbgl/util/literal.hpp>
#include <mbgl/util/ignore.hpp>
#include <mbgl/util/indexed_tuple.hpp>
@@ -73,21 +74,21 @@ public:
util::ignore(
{ // Some shader programs have uniforms declared, but not used, so they're not active.
// Therefore, we'll only verify them when they are indeed active.
- (active.find(Us::name()) != active.end()
- ? verifyUniform<typename Us::Value>(active.at(Us::name()))
+ (active.find(concat_literals<&string_literal<'u', '_'>::value, &Us::name>::value()) != active.end()
+ ? verifyUniform<typename Us::Value>(active.at(concat_literals<&string_literal<'u', '_'>::value, &Us::name>::value()))
: false)... });
#endif
- state = State{ gl::uniformLocation(id, Us::name())... };
+ state = State{ gl::uniformLocation(id, concat_literals<&string_literal<'u', '_'>::value, &Us::name>::value())... };
}
template <class BinaryProgram>
void loadNamedLocations(const BinaryProgram& program) {
- state = State{ UniformState<typename Us::Value>(program.uniformLocation(Us::name()))... };
+ state = State{ UniformState<typename Us::Value>(program.uniformLocation(concat_literals<&string_literal<'u', '_'>::value, &Us::name>::value()))... };
}
NamedUniformLocations getNamedLocations() const {
- return NamedUniformLocations{ { Us::name(), state.template get<Us>().location }... };
+ return NamedUniformLocations{ { concat_literals<&string_literal<'u', '_'>::value, &Us::name>::value(), state.template get<Us>().location }... };
}
void bind(const gfx::UniformValues<TypeList<Us...>>& values) {
diff --git a/src/mbgl/layout/symbol_instance.cpp b/src/mbgl/layout/symbol_instance.cpp
index 139a42113c..0197df1066 100644
--- a/src/mbgl/layout/symbol_instance.cpp
+++ b/src/mbgl/layout/symbol_instance.cpp
@@ -5,13 +5,25 @@ namespace mbgl {
using namespace style;
+namespace {
+
+const Shaping& getAnyShaping(const ShapedTextOrientations& shapedTextOrientations) {
+ if (shapedTextOrientations.right) return shapedTextOrientations.right;
+ if (shapedTextOrientations.center) return shapedTextOrientations.center;
+ if (shapedTextOrientations.left) return shapedTextOrientations.left;
+ if (shapedTextOrientations.vertical) return shapedTextOrientations.vertical;
+ return shapedTextOrientations.horizontal;
+}
+
+} // namespace
+
SymbolInstance::SymbolInstance(Anchor& anchor_,
GeometryCoordinates line_,
- const std::pair<Shaping, Shaping>& shapedTextOrientations,
+ const ShapedTextOrientations& shapedTextOrientations,
optional<PositionedIcon> shapedIcon,
const SymbolLayoutProperties::Evaluated& layout,
const float layoutTextSize,
- const float textBoxScale,
+ const float textBoxScale_,
const float textPadding,
const SymbolPlacementType textPlacement,
const std::array<float, 2> textOffset_,
@@ -24,43 +36,70 @@ SymbolInstance::SymbolInstance(Anchor& anchor_,
const std::size_t dataFeatureIndex_,
const std::u16string& key_,
const float overscaling,
- const float rotate) :
+ const float rotate,
+ float radialTextOffset_) :
anchor(anchor_),
line(line_),
hasText(false),
hasIcon(shapedIcon),
// Create the collision features that will be used to check whether this symbol instance can be placed
- textCollisionFeature(line_, anchor, shapedTextOrientations.first, textBoxScale, textPadding, textPlacement, indexedFeature, overscaling, rotate),
+ // As a collision approximation, we can use either the vertical or any of the horizontal versions of the feature
+ textCollisionFeature(line_, anchor, getAnyShaping(shapedTextOrientations), textBoxScale_, textPadding, textPlacement, indexedFeature, overscaling, rotate),
iconCollisionFeature(line_, anchor, shapedIcon, iconBoxScale, iconPadding, indexedFeature, rotate),
+ writingModes(WritingModeType::None),
layoutFeatureIndex(layoutFeatureIndex_),
dataFeatureIndex(dataFeatureIndex_),
textOffset(textOffset_),
iconOffset(iconOffset_),
- key(key_) {
+ key(key_),
+ textBoxScale(textBoxScale_),
+ radialTextOffset(radialTextOffset_),
+ singleLine(shapedTextOrientations.singleLine) {
// Create the quads used for rendering the icon and glyphs.
if (shapedIcon) {
- iconQuad = getIconQuad(*shapedIcon, layout, layoutTextSize, shapedTextOrientations.first);
+ iconQuad = getIconQuad(*shapedIcon, layout, layoutTextSize, shapedTextOrientations.horizontal);
}
- if (shapedTextOrientations.first) {
- horizontalGlyphQuads = getGlyphQuads(shapedTextOrientations.first, layout, textPlacement, positions);
+
+ bool singleLineInitialized = false;
+ const auto initHorizontalGlyphQuads = [&] (SymbolQuads& quads, const Shaping& shaping) {
+ writingModes |= WritingModeType::Horizontal;
+ if (!singleLine) {
+ quads = getGlyphQuads(shaping, textOffset, layout, textPlacement, positions);
+ return;
+ }
+ if (!singleLineInitialized) {
+ rightJustifiedGlyphQuads = getGlyphQuads(shaping, textOffset, layout, textPlacement, positions);
+ singleLineInitialized = true;
+ }
+ };
+
+ if (shapedTextOrientations.right) {
+ initHorizontalGlyphQuads(rightJustifiedGlyphQuads, shapedTextOrientations.right);
}
- if (shapedTextOrientations.second) {
- verticalGlyphQuads = getGlyphQuads(shapedTextOrientations.second, layout, textPlacement, positions);
+
+ if (shapedTextOrientations.center) {
+ initHorizontalGlyphQuads(centerJustifiedGlyphQuads, shapedTextOrientations.center);
}
- // 'hasText' depends on finding at least one glyph in the shaping that's also in the GlyphPositionMap
- hasText = horizontalGlyphQuads.size() > 0 || verticalGlyphQuads.size() > 0;
- if (shapedTextOrientations.first && shapedTextOrientations.second) {
- writingModes = WritingModeType::Horizontal | WritingModeType::Vertical;
- } else if (shapedTextOrientations.first) {
- writingModes = WritingModeType::Horizontal;
- } else if (shapedTextOrientations.second) {
- writingModes = WritingModeType::Vertical;
- } else {
- writingModes = WritingModeType::None;
+ if (shapedTextOrientations.left) {
+ initHorizontalGlyphQuads(leftJustifiedGlyphQuads, shapedTextOrientations.left);
}
+
+ if (shapedTextOrientations.vertical) {
+ writingModes |= WritingModeType::Vertical;
+ verticalGlyphQuads = getGlyphQuads(shapedTextOrientations.vertical, textOffset, layout, textPlacement, positions);
+ }
+
+ // 'hasText' depends on finding at least one glyph in the shaping that's also in the GlyphPositionMap
+ hasText = !rightJustifiedGlyphQuads.empty() || !centerJustifiedGlyphQuads.empty() || !leftJustifiedGlyphQuads.empty() || !verticalGlyphQuads.empty();
}
+optional<size_t> SymbolInstance::getDefaultHorizontalPlacedTextIndex() const {
+ if (placedRightTextIndex) return placedRightTextIndex;
+ if (placedCenterTextIndex) return placedCenterTextIndex;
+ if (placedLeftTextIndex) return placedLeftTextIndex;
+ return nullopt;
+}
} // namespace mbgl
diff --git a/src/mbgl/layout/symbol_instance.hpp b/src/mbgl/layout/symbol_instance.hpp
index 6148d7fe88..5169b16adb 100644
--- a/src/mbgl/layout/symbol_instance.hpp
+++ b/src/mbgl/layout/symbol_instance.hpp
@@ -11,11 +11,21 @@ namespace mbgl {
class Anchor;
class IndexedSubfeature;
+struct ShapedTextOrientations {
+ Shaping horizontal;
+ Shaping vertical;
+ // The following are used with variable text placement on.
+ Shaping& right = horizontal;
+ Shaping center;
+ Shaping left;
+ bool singleLine = false;
+};
+
class SymbolInstance {
public:
SymbolInstance(Anchor& anchor,
GeometryCoordinates line,
- const std::pair<Shaping, Shaping>& shapedTextOrientations,
+ const ShapedTextOrientations& shapedTextOrientations,
optional<PositionedIcon> shapedIcon,
const style::SymbolLayoutProperties::Evaluated&,
const float layoutTextSize,
@@ -32,14 +42,21 @@ public:
const std::size_t dataFeatureIndex,
const std::u16string& key,
const float overscaling,
- const float rotate);
+ const float rotate,
+ float radialTextOffset);
+ optional<size_t> getDefaultHorizontalPlacedTextIndex() const;
Anchor anchor;
GeometryCoordinates line;
bool hasText;
bool hasIcon;
- SymbolQuads horizontalGlyphQuads;
+ // Note: When singleLine == true, only `rightJustifiedGlyphQuads` is populated.
+ SymbolQuads rightJustifiedGlyphQuads;
+ SymbolQuads centerJustifiedGlyphQuads;
+ SymbolQuads leftJustifiedGlyphQuads;
+
SymbolQuads verticalGlyphQuads;
+
optional<SymbolQuad> iconQuad;
CollisionFeature textCollisionFeature;
CollisionFeature iconCollisionFeature;
@@ -50,9 +67,14 @@ public:
std::array<float, 2> iconOffset;
std::u16string key;
bool isDuplicate;
- optional<size_t> placedTextIndex;
+ optional<size_t> placedRightTextIndex;
+ optional<size_t> placedCenterTextIndex;
+ optional<size_t> placedLeftTextIndex;
optional<size_t> placedVerticalTextIndex;
optional<size_t> placedIconIndex;
+ float textBoxScale;
+ float radialTextOffset;
+ bool singleLine;
uint32_t crossTileID = 0;
};
diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp
index c40a705d7f..d1c50d7773 100644
--- a/src/mbgl/layout/symbol_layout.cpp
+++ b/src/mbgl/layout/symbol_layout.cpp
@@ -174,44 +174,173 @@ bool SymbolLayout::hasSymbolInstances() const {
return !symbolInstances.empty();
}
+namespace {
+
+// The radial offset is to the edge of the text box
+// In the horizontal direction, the edge of the text box is where glyphs start
+// But in the vertical direction, the glyphs appear to "start" at the baseline
+// We don't actually load baseline data, but we assume an offset of ONE_EM - 17
+// (see "yOffset" in shaping.js)
+const float baselineOffset = 7.0f;
+
+// We don't care which shaping we get because this is used for collision purposes
+// and all the justifications have the same collision box.
+const Shaping& getDefaultHorizontalShaping(const ShapedTextOrientations& shapedTextOrientations) {
+ if (shapedTextOrientations.right) return shapedTextOrientations.right;
+ if (shapedTextOrientations.center) return shapedTextOrientations.center;
+ if (shapedTextOrientations.left) return shapedTextOrientations.left;
+ return shapedTextOrientations.horizontal;
+}
+
+Shaping& shapingForTextJustifyType(ShapedTextOrientations& shapedTextOrientations, style::TextJustifyType type) {
+ switch(type) {
+ case style::TextJustifyType::Right: return shapedTextOrientations.right;
+ case style::TextJustifyType::Left: return shapedTextOrientations.left;
+ case style::TextJustifyType::Center: return shapedTextOrientations.center;
+ default:
+ assert(false);
+ return shapedTextOrientations.horizontal;
+ }
+}
+
+} // namespace
+
+// static
+Point<float> SymbolLayout::evaluateRadialOffset(SymbolAnchorType anchor, float radialOffset) {
+ Point<float> result{};
+ // solve for r where r^2 + r^2 = radialOffset^2
+ const float sqrt2 = 1.41421356237f;
+ const float hypotenuse = radialOffset / sqrt2;
+
+ switch (anchor) {
+ case SymbolAnchorType::TopRight:
+ case SymbolAnchorType::TopLeft:
+ result.y = hypotenuse - baselineOffset;
+ break;
+ case SymbolAnchorType::BottomRight:
+ case SymbolAnchorType::BottomLeft:
+ result.y = -hypotenuse + baselineOffset;
+ break;
+ case SymbolAnchorType::Bottom:
+ result.y = -radialOffset + baselineOffset;
+ break;
+ case SymbolAnchorType::Top:
+ result.y = radialOffset - baselineOffset;
+ break;
+ default:
+ break;
+ }
+
+ switch (anchor) {
+ case SymbolAnchorType::TopRight:
+ case SymbolAnchorType::BottomRight:
+ result.x = -hypotenuse;
+ break;
+ case SymbolAnchorType::TopLeft:
+ case SymbolAnchorType::BottomLeft:
+ result.x = hypotenuse;
+ break;
+ case SymbolAnchorType::Left:
+ result.x = radialOffset;
+ break;
+ case SymbolAnchorType::Right:
+ result.x = -radialOffset;
+ break;
+ default:
+ break;
+ }
+
+ return result;
+}
+
void SymbolLayout::prepareSymbols(const GlyphMap& glyphMap, const GlyphPositions& glyphPositions,
const ImageMap& imageMap, const ImagePositions& imagePositions) {
- const bool textAlongLine = layout.get<TextRotationAlignment>() == AlignmentType::Map &&
- layout.get<SymbolPlacement>() != SymbolPlacementType::Point;
+ const bool isPointPlacement = layout.get<SymbolPlacement>() == SymbolPlacementType::Point;
+ const bool textAlongLine = layout.get<TextRotationAlignment>() == AlignmentType::Map && !isPointPlacement;
for (auto it = features.begin(); it != features.end(); ++it) {
auto& feature = *it;
if (feature.geometry.empty()) continue;
- std::pair<Shaping, Shaping> shapedTextOrientations;
+ ShapedTextOrientations shapedTextOrientations;
optional<PositionedIcon> shapedIcon;
+ Point<float> textOffset;
// if feature has text, shape the text
if (feature.formattedText) {
- auto applyShaping = [&] (const TaggedString& formattedText, WritingModeType writingMode) {
- const float oneEm = 24.0f;
+ const float lineHeight = layout.get<TextLineHeight>() * util::ONE_EM;
+ const float spacing = util::i18n::allowsLetterSpacing(feature.formattedText->rawText()) ? layout.evaluate<TextLetterSpacing>(zoom, feature) * util::ONE_EM : 0.0f;
+
+ auto applyShaping = [&] (const TaggedString& formattedText, WritingModeType writingMode, SymbolAnchorType textAnchor, TextJustifyType textJustify) {
const Shaping result = getShaping(
/* string */ formattedText,
- /* maxWidth: ems */ layout.get<SymbolPlacement>() == SymbolPlacementType::Point ?
- layout.evaluate<TextMaxWidth>(zoom, feature) * oneEm : 0,
- /* lineHeight: ems */ layout.get<TextLineHeight>() * oneEm,
- /* anchor */ layout.evaluate<TextAnchor>(zoom, feature),
- /* justify */ layout.evaluate<TextJustify>(zoom, feature),
- /* spacing: ems */ util::i18n::allowsLetterSpacing(feature.formattedText->rawText()) ? layout.evaluate<TextLetterSpacing>(zoom, feature) * oneEm : 0.0f,
- /* translate */ Point<float>(layout.evaluate<TextOffset>(zoom, feature)[0] * oneEm, layout.evaluate<TextOffset>(zoom, feature)[1] * oneEm),
- /* verticalHeight */ oneEm,
+ /* maxWidth: ems */ isPointPlacement ? layout.evaluate<TextMaxWidth>(zoom, feature) * util::ONE_EM : 0.0f,
+ /* ems */ lineHeight,
+ textAnchor,
+ textJustify,
+ /* ems */ spacing,
+ /* translate */ textOffset,
/* writingMode */ writingMode,
/* bidirectional algorithm object */ bidi,
/* glyphs */ glyphMap);
return result;
};
+ const std::vector<style::TextVariableAnchorType> variableTextAnchor = layout.evaluate<TextVariableAnchor>(zoom, feature);
+ const float radialOffset = layout.evaluate<TextRadialOffset>(zoom, feature);
+ const SymbolAnchorType textAnchor = layout.evaluate<TextAnchor>(zoom, feature);
+ if (variableTextAnchor.empty()) {
+ // Layers with variable anchors use the `text-radial-offset` property and the [x, y] offset vector
+ // is calculated at placement time instead of layout time
+ if (radialOffset > 0.0f) {
+ // The style spec says don't use `text-offset` and `text-radial-offset` together
+ // but doesn't actually specify what happens if you use both. We go with the radial offset.
+ textOffset = evaluateRadialOffset(textAnchor, radialOffset * util::ONE_EM);
+ } else {
+ textOffset = { layout.evaluate<TextOffset>(zoom, feature)[0] * util::ONE_EM,
+ layout.evaluate<TextOffset>(zoom, feature)[1] * util::ONE_EM};
+ }
+ }
+ TextJustifyType textJustify = textAlongLine ? TextJustifyType::Center : layout.evaluate<TextJustify>(zoom, feature);
+ // If this layer uses text-variable-anchor, generate shapings for all justification possibilities.
+ if (!textAlongLine && !variableTextAnchor.empty()) {
+ std::vector<TextJustifyType> justifications;
+ if (textJustify != TextJustifyType::Auto) {
+ justifications.push_back(textJustify);
+ } else {
+ for (auto anchor : variableTextAnchor) {
+ justifications.push_back(getAnchorJustification(anchor));
+ }
+ }
+ for (TextJustifyType justification: justifications) {
+ Shaping& shapingForJustification = shapingForTextJustifyType(shapedTextOrientations, justification);
+ if (shapingForJustification) {
+ continue;
+ }
+ // If using text-variable-anchor for the layer, we use a center anchor for all shapings and apply
+ // the offsets for the anchor in the placement step.
+ Shaping shaping = applyShaping(*feature.formattedText, WritingModeType::Horizontal, SymbolAnchorType::Center, justification);
+ if (shaping) {
+ shapingForJustification = std::move(shaping);
+ if (shaping.lineCount == 1u) {
+ shapedTextOrientations.singleLine = true;
+ break;
+ }
+ }
+ }
+ } else {
+ if (textJustify == TextJustifyType::Auto) {
+ textJustify = getAnchorJustification(textAnchor);
+ }
+ Shaping shaping = applyShaping(*feature.formattedText, WritingModeType::Horizontal, textAnchor, textJustify);
+ if (shaping) {
+ shapedTextOrientations.horizontal = std::move(shaping);
+ }
- shapedTextOrientations.first = applyShaping(*feature.formattedText, WritingModeType::Horizontal);
-
- if (util::i18n::allowsVerticalWritingMode(feature.formattedText->rawText()) && textAlongLine) {
- feature.formattedText->verticalizePunctuation();
- shapedTextOrientations.second = applyShaping(*feature.formattedText, WritingModeType::Vertical);
+ if (util::i18n::allowsVerticalWritingMode(feature.formattedText->rawText()) && textAlongLine) {
+ feature.formattedText->verticalizePunctuation();
+ shapedTextOrientations.vertical = applyShaping(*feature.formattedText, WritingModeType::Vertical, textAnchor, textJustify);
+ }
}
}
@@ -236,8 +365,8 @@ void SymbolLayout::prepareSymbols(const GlyphMap& glyphMap, const GlyphPositions
}
// if either shapedText or icon position is present, add the feature
- if (shapedTextOrientations.first || shapedIcon) {
- addFeature(std::distance(features.begin(), it), feature, shapedTextOrientations, shapedIcon, glyphPositions);
+ if (getDefaultHorizontalShaping(shapedTextOrientations) || shapedIcon) {
+ addFeature(std::distance(features.begin(), it), feature, shapedTextOrientations, shapedIcon, glyphPositions, textOffset);
}
feature.geometry.clear();
@@ -248,15 +377,17 @@ void SymbolLayout::prepareSymbols(const GlyphMap& glyphMap, const GlyphPositions
void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex,
const SymbolFeature& feature,
- const std::pair<Shaping, Shaping>& shapedTextOrientations,
+ const ShapedTextOrientations& shapedTextOrientations,
optional<PositionedIcon> shapedIcon,
- const GlyphPositions& glyphPositions) {
+ const GlyphPositions& glyphPositions,
+ Point<float> offset) {
const float minScale = 0.5f;
const float glyphSize = 24.0f;
const float layoutTextSize = layout.evaluate<TextSize>(zoom + 1, feature);
const float layoutIconSize = layout.evaluate<IconSize>(zoom + 1, feature);
- const std::array<float, 2> textOffset = layout.evaluate<TextOffset>(zoom, feature);
+ const std::array<float, 2> textOffset = {{ offset.x, offset.y }};
+
const std::array<float, 2> iconOffset = layout.evaluate<IconOffset>(zoom, feature);
// To reduce the number of labels that jump around when zooming we need
@@ -274,6 +405,7 @@ void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex,
const float iconPadding = layout.get<IconPadding>() * tilePixelRatio;
const float textMaxAngle = layout.get<TextMaxAngle>() * util::DEG2RAD;
const float rotation = layout.evaluate<IconRotate>(zoom, feature);
+ const float radialTextOffset = layout.evaluate<TextRadialOffset>(zoom, feature) * util::ONE_EM;
const SymbolPlacementType textPlacement = layout.get<TextRotationAlignment>() != AlignmentType::Map
? SymbolPlacementType::Point
: layout.get<SymbolPlacement>();
@@ -296,7 +428,7 @@ void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex,
textBoxScale, textPadding, textPlacement, textOffset,
iconBoxScale, iconPadding, iconOffset,
glyphPositions, indexedFeature, layoutFeatureIndex, feature.index,
- feature.formattedText ? feature.formattedText->rawText() : std::u16string(), overscaling, rotation);
+ feature.formattedText ? feature.formattedText->rawText() : std::u16string(), overscaling, rotation, radialTextOffset);
}
};
@@ -308,8 +440,8 @@ void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex,
Anchors anchors = getAnchors(line,
symbolSpacing,
textMaxAngle,
- (shapedTextOrientations.second ?: shapedTextOrientations.first).left,
- (shapedTextOrientations.second ?: shapedTextOrientations.first).right,
+ (shapedTextOrientations.vertical ?: getDefaultHorizontalShaping(shapedTextOrientations)).left,
+ (shapedTextOrientations.vertical ?: getDefaultHorizontalShaping(shapedTextOrientations)).right,
(shapedIcon ? shapedIcon->left() : 0),
(shapedIcon ? shapedIcon->right() : 0),
glyphSize,
@@ -329,8 +461,8 @@ void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex,
if (line.size() > 1) {
optional<Anchor> anchor = getCenterAnchor(line,
textMaxAngle,
- (shapedTextOrientations.second ?: shapedTextOrientations.first).left,
- (shapedTextOrientations.second ?: shapedTextOrientations.first).right,
+ (shapedTextOrientations.vertical ?: getDefaultHorizontalShaping(shapedTextOrientations)).left,
+ (shapedTextOrientations.vertical ?: getDefaultHorizontalShaping(shapedTextOrientations)).right,
(shapedIcon ? shapedIcon->left() : 0),
(shapedIcon ? shapedIcon->right() : 0),
glyphSize,
@@ -414,25 +546,41 @@ void SymbolLayout::createBucket(const ImagePositions&, std::unique_ptr<FeatureIn
const bool sortFeaturesByY = zOrderByViewport && (layout.get<TextAllowOverlap>() || layout.get<IconAllowOverlap>() ||
layout.get<TextIgnorePlacement>() || layout.get<IconIgnorePlacement>());
- auto bucket = std::make_shared<SymbolBucket>(layout, layerPaintProperties, textSize, iconSize, zoom, sdfIcons, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(symbolInstances));
+ auto bucket = std::make_shared<SymbolBucket>(layout, layerPaintProperties, textSize, iconSize, zoom, sdfIcons, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(symbolInstances), tilePixelRatio);
for (SymbolInstance &symbolInstance : bucket->symbolInstances) {
-
const bool hasText = symbolInstance.hasText;
const bool hasIcon = symbolInstance.hasIcon;
+ const bool singleLine = symbolInstance.singleLine;
const auto& feature = features.at(symbolInstance.layoutFeatureIndex);
// Insert final placement into collision tree and add glyphs/icons to buffers
if (hasText && feature.formattedText) {
- std::size_t index = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, symbolInstance.placedTextIndex, symbolInstance.horizontalGlyphQuads);
-
+ optional<std::size_t> lastAddedSection;
+ if (singleLine) {
+ optional<std::size_t> placedTextIndex;
+ lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, placedTextIndex, symbolInstance.rightJustifiedGlyphQuads, lastAddedSection);
+ symbolInstance.placedRightTextIndex = placedTextIndex;
+ symbolInstance.placedCenterTextIndex = placedTextIndex;
+ symbolInstance.placedLeftTextIndex = placedTextIndex;
+ } else {
+ if (!symbolInstance.rightJustifiedGlyphQuads.empty()) {
+ lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, symbolInstance.placedRightTextIndex, symbolInstance.rightJustifiedGlyphQuads, lastAddedSection);
+ }
+ if (!symbolInstance.centerJustifiedGlyphQuads.empty()) {
+ lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, symbolInstance.placedCenterTextIndex, symbolInstance.centerJustifiedGlyphQuads, lastAddedSection);
+ }
+ if (!symbolInstance.leftJustifiedGlyphQuads.empty()) {
+ lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, symbolInstance.placedLeftTextIndex, symbolInstance.leftJustifiedGlyphQuads, lastAddedSection);
+ }
+ }
if (symbolInstance.writingModes & WritingModeType::Vertical) {
- index = addSymbolGlyphQuads(*bucket, symbolInstance, feature, WritingModeType::Vertical, symbolInstance.placedVerticalTextIndex, symbolInstance.verticalGlyphQuads, index);
+ lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, WritingModeType::Vertical, symbolInstance.placedVerticalTextIndex, symbolInstance.verticalGlyphQuads, lastAddedSection);
}
-
- updatePaintPropertiesForSection(*bucket, feature, index);
+ assert(lastAddedSection); // True, as hasText == true;
+ updatePaintPropertiesForSection(*bucket, feature, *lastAddedSection);
}
if (hasIcon) {
@@ -600,7 +748,7 @@ void SymbolLayout::addToDebugBuffers(SymbolBucket& bucket) {
// Dynamic vertices are initialized so that the vertex count always agrees with
// the layout vertex buffer, but they will always be updated before rendering happens
- auto dynamicVertex = CollisionBoxProgram::dynamicVertex(false, false);
+ auto dynamicVertex = CollisionBoxProgram::dynamicVertex(false, false, {});
collisionBuffer.dynamicVertices.emplace_back(dynamicVertex);
collisionBuffer.dynamicVertices.emplace_back(dynamicVertex);
collisionBuffer.dynamicVertices.emplace_back(dynamicVertex);
diff --git a/src/mbgl/layout/symbol_layout.hpp b/src/mbgl/layout/symbol_layout.hpp
index 53c66d31fe..d88c79c552 100644
--- a/src/mbgl/layout/symbol_layout.hpp
+++ b/src/mbgl/layout/symbol_layout.hpp
@@ -46,12 +46,15 @@ public:
const std::string bucketLeaderID;
std::vector<SymbolInstance> symbolInstances;
+ static Point<float> evaluateRadialOffset(style::SymbolAnchorType anchor, float radialOffset);
+
private:
void addFeature(const size_t,
const SymbolFeature&,
- const std::pair<Shaping, Shaping>& shapedTextOrientations,
+ const ShapedTextOrientations& shapedTextOrientations,
optional<PositionedIcon> shapedIcon,
- const GlyphPositions&);
+ const GlyphPositions&,
+ Point<float> textOffset);
bool anchorIsTooClose(const std::u16string& text, const float repeatDistance, const Anchor&);
std::map<std::u16string, std::vector<Anchor>> compareText;
diff --git a/src/mbgl/layout/symbol_projection.cpp b/src/mbgl/layout/symbol_projection.cpp
index dff2a569ac..b7858f8deb 100644
--- a/src/mbgl/layout/symbol_projection.cpp
+++ b/src/mbgl/layout/symbol_projection.cpp
@@ -291,9 +291,9 @@ namespace mbgl {
gfx::VertexVector<gfx::Vertex<SymbolDynamicLayoutAttributes>>& dynamicVertexArray,
const Point<float>& projectedAnchorPoint,
const float aspectRatio) {
- const float fontScale = fontSize / 24.0;
- const float lineOffsetX = symbol.lineOffset[0] * fontSize;
- const float lineOffsetY = symbol.lineOffset[1] * fontSize;
+ const float fontScale = fontSize / util::ONE_EM;
+ const float lineOffsetX = symbol.lineOffset[0] * fontScale;
+ const float lineOffsetY = symbol.lineOffset[1] * fontScale;
std::vector<PlacedGlyph> placedGlyphs;
if (symbol.glyphOffsets.size() > 1) {
diff --git a/src/mbgl/layout/symbol_projection.hpp b/src/mbgl/layout/symbol_projection.hpp
index 03e660b474..3699eee290 100644
--- a/src/mbgl/layout/symbol_projection.hpp
+++ b/src/mbgl/layout/symbol_projection.hpp
@@ -60,4 +60,9 @@ namespace mbgl {
const mat4& labelPlaneMatrix,
const bool returnTileDistance);
+ void hideGlyphs(std::size_t numGlyphs, gfx::VertexVector<gfx::Vertex<SymbolDynamicLayoutAttributes>>& dynamicVertices);
+ void addDynamicAttributes(const Point<float>& anchorPoint,
+ const float angle,
+ gfx::VertexVector<gfx::Vertex<SymbolDynamicLayoutAttributes>>& dynamicVertices);
+
} // end namespace mbgl
diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp
index f545fc8095..b22a9ee2f2 100644
--- a/src/mbgl/map/map.cpp
+++ b/src/mbgl/map/map.cpp
@@ -27,24 +27,16 @@ namespace mbgl {
using namespace style;
-Map::Map(RendererFrontend& rendererFrontend,
- MapObserver& mapObserver,
- const Size size,
- const float pixelRatio,
- FileSource& fileSource,
+Map::Map(RendererFrontend& frontend,
+ MapObserver& observer,
Scheduler& scheduler,
- const MapOptions& options)
- : impl(std::make_unique<Impl>(*this,
- rendererFrontend,
- mapObserver,
- fileSource,
- scheduler,
- size,
- pixelRatio,
- options.mapMode(),
- options.constrainMode(),
- options.viewportMode(),
- options.crossSourceCollisions())) {}
+ const MapOptions& mapOptions,
+ const ResourceOptions& resourceOptions)
+ : impl(std::make_unique<Impl>(frontend, observer, scheduler,
+ FileSource::getSharedFileSource(resourceOptions),
+ mapOptions)) {}
+
+Map::Map(std::unique_ptr<Impl> impl_) : impl(std::move(impl_)) {}
Map::~Map() = default;
@@ -139,9 +131,7 @@ CameraOptions Map::getCameraOptions(const EdgeInsets& padding) const {
}
void Map::jumpTo(const CameraOptions& camera) {
- impl->cameraMutated = true;
- impl->transform.jumpTo(camera);
- impl->onUpdate();
+ impl->jumpTo(camera);
}
void Map::easeTo(const CameraOptions& camera, const AnimationOptions& animation) {
@@ -214,8 +204,13 @@ CameraOptions cameraForLatLngs(const std::vector<LatLng>& latLngs, const Transfo
scaleY -= (padding.top() + padding.bottom()) / height;
minScale = util::min(scaleX, scaleY);
}
- double zoom = transform.getZoom() + util::log2(minScale);
- zoom = util::clamp(zoom, transform.getState().getMinZoom(), transform.getState().getMaxZoom());
+
+ double zoom = transform.getZoom();
+ if (minScale > 0) {
+ zoom = util::clamp(zoom + util::log2(minScale), transform.getState().getMinZoom(), transform.getState().getMaxZoom());
+ } else {
+ Log::Error(Event::General, "Unable to calculate appropriate zoom level for bounds. Vertical or horizontal padding is greater than map's height or width.");
+ }
// Calculate the center point of a virtual bounds that is extended in all directions by padding.
ScreenCoordinate centerPixel = nePixel + swPixel;
@@ -312,48 +307,37 @@ BoundOptions Map::getBounds() const {
.withMaxZoom(impl->transform.getState().getMaxZoom());
}
-#pragma mark - Size
+#pragma mark - Map options
void Map::setSize(const Size size) {
impl->transform.resize(size);
impl->onUpdate();
}
-Size Map::getSize() const {
- return impl->transform.getState().getSize();
-}
-
-#pragma mark - North Orientation
-
void Map::setNorthOrientation(NorthOrientation orientation) {
impl->transform.setNorthOrientation(orientation);
impl->onUpdate();
}
-NorthOrientation Map::getNorthOrientation() const {
- return impl->transform.getNorthOrientation();
-}
-
-#pragma mark - Constrain mode
-
void Map::setConstrainMode(mbgl::ConstrainMode mode) {
impl->transform.setConstrainMode(mode);
impl->onUpdate();
}
-ConstrainMode Map::getConstrainMode() const {
- return impl->transform.getConstrainMode();
-}
-
-#pragma mark - Viewport mode
-
void Map::setViewportMode(mbgl::ViewportMode mode) {
impl->transform.setViewportMode(mode);
impl->onUpdate();
}
-ViewportMode Map::getViewportMode() const {
- return impl->transform.getViewportMode();
+MapOptions Map::getMapOptions() const {
+ return std::move(MapOptions()
+ .withMapMode(impl->mode)
+ .withConstrainMode(impl->transform.getConstrainMode())
+ .withViewportMode(impl->transform.getViewportMode())
+ .withCrossSourceCollisions(impl->crossSourceCollisions)
+ .withNorthOrientation(impl->transform.getNorthOrientation())
+ .withSize(impl->transform.getState().getSize())
+ .withPixelRatio(impl->pixelRatio));
}
#pragma mark - Projection mode
diff --git a/src/mbgl/map/map_impl.cpp b/src/mbgl/map/map_impl.cpp
index 84cf324722..1ec7255822 100644
--- a/src/mbgl/map/map_impl.cpp
+++ b/src/mbgl/map/map_impl.cpp
@@ -1,39 +1,31 @@
#include <mbgl/layermanager/layer_manager.hpp>
#include <mbgl/map/map_impl.hpp>
#include <mbgl/renderer/update_parameters.hpp>
+#include <mbgl/storage/file_source.hpp>
#include <mbgl/style/style_impl.hpp>
#include <mbgl/util/exception.hpp>
namespace mbgl {
-Map::Impl::Impl(Map& map_,
- RendererFrontend& frontend,
- MapObserver& mapObserver,
- FileSource& fileSource_,
+Map::Impl::Impl(RendererFrontend& frontend_,
+ MapObserver& observer_,
Scheduler& scheduler_,
- Size size_,
- float pixelRatio_,
- MapMode mode_,
- ConstrainMode constrainMode_,
- ViewportMode viewportMode_,
- bool crossSourceCollisions_)
- : map(map_),
- observer(mapObserver),
- rendererFrontend(frontend),
- fileSource(fileSource_),
- scheduler(scheduler_),
- transform(observer,
- constrainMode_,
- viewportMode_),
- mode(mode_),
- pixelRatio(pixelRatio_),
- crossSourceCollisions(crossSourceCollisions_),
- style(std::make_unique<style::Style>(scheduler, fileSource, pixelRatio)),
- annotationManager(*style) {
-
+ std::shared_ptr<FileSource> fileSource_,
+ const MapOptions& mapOptions)
+ : observer(observer_),
+ rendererFrontend(frontend_),
+ scheduler(scheduler_),
+ transform(observer, mapOptions.constrainMode(), mapOptions.viewportMode()),
+ mode(mapOptions.mapMode()),
+ pixelRatio(mapOptions.pixelRatio()),
+ crossSourceCollisions(mapOptions.crossSourceCollisions()),
+ fileSource(std::move(fileSource_)),
+ style(std::make_unique<style::Style>(scheduler, *fileSource, pixelRatio)),
+ annotationManager(*style) {
+ transform.setNorthOrientation(mapOptions.northOrientation());
style->impl->setObserver(this);
rendererFrontend.setObserver(*this);
- transform.resize(size_);
+ transform.resize(mapOptions.size());
}
Map::Impl::~Impl() {
@@ -73,7 +65,7 @@ void Map::Impl::onUpdate() {
style->impl->getSourceImpls(),
style->impl->getLayerImpls(),
annotationManager,
- fileSource,
+ *fileSource,
prefetchZoomDelta,
bool(stillImageRequest),
crossSourceCollisions
@@ -90,7 +82,7 @@ void Map::Impl::onStyleLoading() {
void Map::Impl::onStyleLoaded() {
if (!cameraMutated) {
- map.jumpTo(style->getDefaultCamera());
+ jumpTo(style->getDefaultCamera());
}
if (LayerManager::annotationsEnabled) {
annotationManager.onStyleLoaded();
@@ -173,4 +165,20 @@ void Map::Impl::onDidFinishRenderingMap() {
}
};
+void Map::Impl::jumpTo(const CameraOptions& camera) {
+ cameraMutated = true;
+ transform.jumpTo(camera);
+ onUpdate();
+}
+
+void Map::Impl::onStyleImageMissing(const std::string& id, std::function<void()> done) {
+
+ if (style->getImage(id) == nullptr) {
+ observer.onStyleImageMissing(id);
+ }
+
+ done();
+ onUpdate();
+}
+
} // namespace mbgl
diff --git a/src/mbgl/map/map_impl.hpp b/src/mbgl/map/map_impl.hpp
index 32dc728b70..f233f78275 100644
--- a/src/mbgl/map/map_impl.hpp
+++ b/src/mbgl/map/map_impl.hpp
@@ -1,14 +1,15 @@
#pragma once
+#include <mbgl/actor/actor.hpp>
#include <mbgl/actor/scheduler.hpp>
#include <mbgl/annotation/annotation_manager.hpp>
#include <mbgl/map/map.hpp>
#include <mbgl/map/map_observer.hpp>
+#include <mbgl/map/map_options.hpp>
#include <mbgl/map/mode.hpp>
#include <mbgl/map/transform.hpp>
#include <mbgl/renderer/renderer_frontend.hpp>
#include <mbgl/renderer/renderer_observer.hpp>
-#include <mbgl/storage/file_source.hpp>
#include <mbgl/style/observer.hpp>
#include <mbgl/style/source.hpp>
#include <mbgl/style/style.hpp>
@@ -16,6 +17,9 @@
namespace mbgl {
+class FileSource;
+class ResourceTransform;
+
struct StillImageRequest {
StillImageRequest(Map::StillImageCallback&& callback_)
: callback(std::move(callback_)) {
@@ -26,20 +30,7 @@ struct StillImageRequest {
class Map::Impl : public style::Observer, public RendererObserver {
public:
- Impl(Map&,
- RendererFrontend&,
- MapObserver&,
- FileSource&,
- Scheduler&,
-
- Size size,
- float pixelRatio,
-
- MapMode,
- ConstrainMode,
- ViewportMode,
- bool crossSourceCollisions);
-
+ Impl(RendererFrontend&, MapObserver&, Scheduler&, std::shared_ptr<FileSource>, const MapOptions&);
~Impl() final;
// StyleObserver
@@ -56,11 +47,13 @@ public:
void onDidFinishRenderingFrame(RenderMode, bool) final;
void onWillStartRenderingMap() final;
void onDidFinishRenderingMap() final;
+ void onStyleImageMissing(const std::string&, std::function<void()>) final;
+
+ // Map
+ void jumpTo(const CameraOptions&);
- Map& map;
MapObserver& observer;
RendererFrontend& rendererFrontend;
- FileSource& fileSource;
Scheduler& scheduler;
Transform transform;
@@ -71,6 +64,8 @@ public:
MapDebugOptions debugOptions { MapDebugOptions::NoDebug };
+ std::shared_ptr<FileSource> fileSource;
+
std::unique_ptr<style::Style> style;
AnnotationManager annotationManager;
diff --git a/src/mbgl/map/map_options.cpp b/src/mbgl/map/map_options.cpp
index 118fcaf3df..4cebb6adab 100644
--- a/src/mbgl/map/map_options.cpp
+++ b/src/mbgl/map/map_options.cpp
@@ -1,7 +1,4 @@
#include <mbgl/map/map_options.hpp>
-#include <mbgl/util/constants.hpp>
-
-#include <cassert>
namespace mbgl {
@@ -10,14 +7,16 @@ public:
MapMode mapMode = MapMode::Continuous;
ConstrainMode constrainMode = ConstrainMode::HeightOnly;
ViewportMode viewportMode = ViewportMode::Default;
- std::string cachePath;
- std::string assetRoot;
- uint64_t maximumSize{mbgl::util::DEFAULT_MAX_CACHE_SIZE};
+ NorthOrientation orientation = NorthOrientation::Upwards;
bool crossSourceCollisions = true;
+ Size size = { 64, 64 };
+ float pixelRatio = 1.0;
};
-MapOptions::MapOptions() : impl_(std::make_shared<MapOptions::Impl>()) {}
+// These requires the complete type of Impl.
+MapOptions::MapOptions() : impl_(std::make_unique<Impl>()) {}
MapOptions::~MapOptions() = default;
+MapOptions::MapOptions(MapOptions&&) noexcept = default;
MapOptions& MapOptions::withMapMode(MapMode mode) {
impl_->mapMode = mode;
@@ -46,40 +45,40 @@ ViewportMode MapOptions::viewportMode() const {
return impl_->viewportMode;
}
-MapOptions& MapOptions::withCachePath(std::string path) {
- impl_->cachePath = std::move(path);
+MapOptions& MapOptions::withCrossSourceCollisions(bool enableCollisions) {
+ impl_->crossSourceCollisions = enableCollisions;
return *this;
}
-const std::string& MapOptions::cachePath() const {
- return impl_->cachePath;
+bool MapOptions::crossSourceCollisions() const {
+ return impl_->crossSourceCollisions;
}
-MapOptions& MapOptions::withAssetRoot(std::string path) {
- impl_->assetRoot = std::move(path);
+MapOptions& MapOptions::withNorthOrientation(NorthOrientation orientation) {
+ impl_->orientation = orientation;
return *this;
}
-const std::string& MapOptions::assetRoot() const {
- return impl_->assetRoot;
+NorthOrientation MapOptions::northOrientation() const {
+ return impl_->orientation;
}
-MapOptions& MapOptions::withMaximumCacheSize(uint64_t size) {
- impl_->maximumSize = size;
+MapOptions& MapOptions::withSize(Size size_) {
+ impl_->size = size_;
return *this;
}
-uint64_t MapOptions::maximumCacheSize() const {
- return impl_->maximumSize;
+Size MapOptions::size() const {
+ return impl_->size;
}
-MapOptions& MapOptions::withCrossSourceCollisions(bool enableCollisions) {
- impl_->crossSourceCollisions = enableCollisions;
+MapOptions& MapOptions::withPixelRatio(float ratio) {
+ impl_->pixelRatio = ratio;
return *this;
}
-bool MapOptions::crossSourceCollisions() const {
- return impl_->crossSourceCollisions;
+float MapOptions::pixelRatio() const {
+ return impl_->pixelRatio;
}
} // namespace mbgl
diff --git a/src/mbgl/programs/attributes.hpp b/src/mbgl/programs/attributes.hpp
index 6106eedb53..803a9db503 100644
--- a/src/mbgl/programs/attributes.hpp
+++ b/src/mbgl/programs/attributes.hpp
@@ -7,52 +7,54 @@ namespace attributes {
// Layout attributes
-MBGL_DEFINE_ATTRIBUTE(int16_t, 2, a_pos);
-MBGL_DEFINE_ATTRIBUTE(int16_t, 2, a_extrude);
-MBGL_DEFINE_ATTRIBUTE(int16_t, 4, a_pos_offset);
-MBGL_DEFINE_ATTRIBUTE(int16_t, 4, a_pos_normal);
-MBGL_DEFINE_ATTRIBUTE(float, 3, a_projected_pos);
-MBGL_DEFINE_ATTRIBUTE(int16_t, 2, a_label_pos);
-MBGL_DEFINE_ATTRIBUTE(int16_t, 2, a_anchor_pos);
-MBGL_DEFINE_ATTRIBUTE(uint16_t, 2, a_texture_pos);
-MBGL_DEFINE_ATTRIBUTE(int16_t, 4, a_normal_ed);
-MBGL_DEFINE_ATTRIBUTE(uint8_t, 1, a_fade_opacity);
-MBGL_DEFINE_ATTRIBUTE(uint8_t, 2, a_placed);
-MBGL_DEFINE_ATTRIBUTE(uint16_t, 3, a_size);
-MBGL_DEFINE_ATTRIBUTE(float, 1, a_offset);
-MBGL_DEFINE_ATTRIBUTE(float, 2, a_shift);
+MBGL_DEFINE_ATTRIBUTE(int16_t, 2, pos);
+MBGL_DEFINE_ATTRIBUTE(int16_t, 2, extrude);
+MBGL_DEFINE_ATTRIBUTE(int16_t, 4, pos_offset);
+MBGL_DEFINE_ATTRIBUTE(int16_t, 4, pos_normal);
+MBGL_DEFINE_ATTRIBUTE(float, 3, projected_pos);
+MBGL_DEFINE_ATTRIBUTE(int16_t, 2, label_pos);
+MBGL_DEFINE_ATTRIBUTE(int16_t, 2, anchor_pos);
+MBGL_DEFINE_ATTRIBUTE(uint16_t, 2, texture_pos);
+MBGL_DEFINE_ATTRIBUTE(int16_t, 4, normal_ed);
+MBGL_DEFINE_ATTRIBUTE(uint8_t, 1, fade_opacity);
+MBGL_DEFINE_ATTRIBUTE(uint8_t, 2, placed);
+MBGL_DEFINE_ATTRIBUTE(uint16_t, 3, size);
+MBGL_DEFINE_ATTRIBUTE(float, 1, offset);
+MBGL_DEFINE_ATTRIBUTE(float, 2, shift);
template <typename T, std::size_t N>
-struct a_data {
+struct data {
using Type = gfx::AttributeType<T, N>;
- static auto name() { return "a_data"; }
+ static constexpr auto name() {
+ return "data";
+ }
};
// Paint attributes
-MBGL_DEFINE_ATTRIBUTE(float, 2, a_color);
-MBGL_DEFINE_ATTRIBUTE(float, 2, a_fill_color);
-MBGL_DEFINE_ATTRIBUTE(float, 2, a_halo_color);
-MBGL_DEFINE_ATTRIBUTE(float, 2, a_stroke_color);
-MBGL_DEFINE_ATTRIBUTE(float, 2, a_outline_color);
-MBGL_DEFINE_ATTRIBUTE(float, 1, a_opacity);
-MBGL_DEFINE_ATTRIBUTE(float, 1, a_stroke_opacity);
-MBGL_DEFINE_ATTRIBUTE(float, 1, a_blur);
-MBGL_DEFINE_ATTRIBUTE(float, 1, a_radius);
-MBGL_DEFINE_ATTRIBUTE(float, 1, a_width);
-MBGL_DEFINE_ATTRIBUTE(float, 1, a_floorwidth);
-MBGL_DEFINE_ATTRIBUTE(float, 1, a_height);
-MBGL_DEFINE_ATTRIBUTE(float, 1, a_base);
-MBGL_DEFINE_ATTRIBUTE(float, 1, a_gapwidth);
-MBGL_DEFINE_ATTRIBUTE(float, 1, a_stroke_width);
-MBGL_DEFINE_ATTRIBUTE(float, 1, a_halo_width);
-MBGL_DEFINE_ATTRIBUTE(float, 1, a_halo_blur);
-MBGL_DEFINE_ATTRIBUTE(float, 1, a_weight);
-MBGL_DEFINE_ATTRIBUTE(uint16_t, 4, a_pattern_to);
-MBGL_DEFINE_ATTRIBUTE(uint16_t, 4, a_pattern_from);
+MBGL_DEFINE_ATTRIBUTE(float, 2, color);
+MBGL_DEFINE_ATTRIBUTE(float, 2, fill_color);
+MBGL_DEFINE_ATTRIBUTE(float, 2, halo_color);
+MBGL_DEFINE_ATTRIBUTE(float, 2, stroke_color);
+MBGL_DEFINE_ATTRIBUTE(float, 2, outline_color);
+MBGL_DEFINE_ATTRIBUTE(float, 1, opacity);
+MBGL_DEFINE_ATTRIBUTE(float, 1, stroke_opacity);
+MBGL_DEFINE_ATTRIBUTE(float, 1, blur);
+MBGL_DEFINE_ATTRIBUTE(float, 1, radius);
+MBGL_DEFINE_ATTRIBUTE(float, 1, width);
+MBGL_DEFINE_ATTRIBUTE(float, 1, floorwidth);
+MBGL_DEFINE_ATTRIBUTE(float, 1, height);
+MBGL_DEFINE_ATTRIBUTE(float, 1, base);
+MBGL_DEFINE_ATTRIBUTE(float, 1, gapwidth);
+MBGL_DEFINE_ATTRIBUTE(float, 1, stroke_width);
+MBGL_DEFINE_ATTRIBUTE(float, 1, halo_width);
+MBGL_DEFINE_ATTRIBUTE(float, 1, halo_blur);
+MBGL_DEFINE_ATTRIBUTE(float, 1, weight);
+MBGL_DEFINE_ATTRIBUTE(uint16_t, 4, pattern_to);
+MBGL_DEFINE_ATTRIBUTE(uint16_t, 4, pattern_from);
} // namespace attributes
-using PositionOnlyLayoutAttributes = TypeList<attributes::a_pos>;
+using PositionOnlyLayoutAttributes = TypeList<attributes::pos>;
} // namespace mbgl
diff --git a/src/mbgl/programs/background_program.cpp b/src/mbgl/programs/background_program.cpp
index 7d68f62fb1..772d481578 100644
--- a/src/mbgl/programs/background_program.cpp
+++ b/src/mbgl/programs/background_program.cpp
@@ -28,21 +28,21 @@ BackgroundPatternProgram::layoutUniformValues(mat4 matrix,
int32_t pixelY = tileSizeAtNearestZoom * tileID.canonical.y;
return {
- uniforms::u_matrix::Value( matrix ),
- uniforms::u_opacity::Value( opacity ),
- uniforms::u_texsize::Value( atlasSize ),
- uniforms::u_pattern_tl_a::Value( a.tl() ),
- uniforms::u_pattern_br_a::Value( a.br() ),
- uniforms::u_pattern_tl_b::Value( b.tl() ),
- uniforms::u_pattern_br_b::Value( b.br() ),
- uniforms::u_pattern_size_a::Value( a.displaySize() ),
- uniforms::u_pattern_size_b::Value( b.displaySize() ),
- uniforms::u_scale_a::Value( fading.fromScale ),
- uniforms::u_scale_b::Value( fading.toScale ),
- uniforms::u_mix::Value( fading.t ),
- uniforms::u_pixel_coord_upper::Value( std::array<float, 2> {{ float(pixelX >> 16), float(pixelY >> 16) }}),
- uniforms::u_pixel_coord_lower::Value( std::array<float, 2> {{ float(pixelX & 0xFFFF), float(pixelY & 0xFFFF)}}),
- uniforms::u_tile_units_to_pixels::Value( 1.0f / tileID.pixelsToTileUnits(1.0f, state.getIntegerZoom()) ),
+ uniforms::matrix::Value( matrix ),
+ uniforms::opacity::Value( opacity ),
+ uniforms::texsize::Value( atlasSize ),
+ uniforms::pattern_tl_a::Value( a.tl() ),
+ uniforms::pattern_br_a::Value( a.br() ),
+ uniforms::pattern_tl_b::Value( b.tl() ),
+ uniforms::pattern_br_b::Value( b.br() ),
+ uniforms::pattern_size_a::Value( a.displaySize() ),
+ uniforms::pattern_size_b::Value( b.displaySize() ),
+ uniforms::scale_a::Value( fading.fromScale ),
+ uniforms::scale_b::Value( fading.toScale ),
+ uniforms::mix::Value( fading.t ),
+ uniforms::pixel_coord_upper::Value( std::array<float, 2> {{ float(pixelX >> 16), float(pixelY >> 16) }}),
+ uniforms::pixel_coord_lower::Value( std::array<float, 2> {{ float(pixelX & 0xFFFF), float(pixelY & 0xFFFF)}}),
+ uniforms::tile_units_to_pixels::Value( 1.0f / tileID.pixelsToTileUnits(1.0f, state.getIntegerZoom()) ),
};
}
diff --git a/src/mbgl/programs/background_program.hpp b/src/mbgl/programs/background_program.hpp
index b1ade6dc84..dd0683776c 100644
--- a/src/mbgl/programs/background_program.hpp
+++ b/src/mbgl/programs/background_program.hpp
@@ -18,26 +18,26 @@ template <class> class Faded;
using BackgroundLayoutAttributes = PositionOnlyLayoutAttributes;
using BackgroundUniforms = TypeList<
- uniforms::u_matrix,
- uniforms::u_color,
- uniforms::u_opacity>;
+ uniforms::matrix,
+ uniforms::color,
+ uniforms::opacity>;
using BackgroundPatternUniforms = TypeList<
- uniforms::u_matrix,
- uniforms::u_opacity,
- uniforms::u_texsize,
- uniforms::u_pattern_tl_a,
- uniforms::u_pattern_br_a,
- uniforms::u_pattern_tl_b,
- uniforms::u_pattern_br_b,
- uniforms::u_pattern_size_a,
- uniforms::u_pattern_size_b,
- uniforms::u_scale_a,
- uniforms::u_scale_b,
- uniforms::u_mix,
- uniforms::u_pixel_coord_upper,
- uniforms::u_pixel_coord_lower,
- uniforms::u_tile_units_to_pixels>;
+ uniforms::matrix,
+ uniforms::opacity,
+ uniforms::texsize,
+ uniforms::pattern_tl_a,
+ uniforms::pattern_br_a,
+ uniforms::pattern_tl_b,
+ uniforms::pattern_br_b,
+ uniforms::pattern_size_a,
+ uniforms::pattern_size_b,
+ uniforms::scale_a,
+ uniforms::scale_b,
+ uniforms::mix,
+ uniforms::pixel_coord_upper,
+ uniforms::pixel_coord_lower,
+ uniforms::tile_units_to_pixels>;
class BackgroundProgram : public Program<
BackgroundProgram,
@@ -57,7 +57,7 @@ class BackgroundPatternProgram : public Program<
BackgroundLayoutAttributes,
BackgroundPatternUniforms,
TypeList<
- textures::u_image>,
+ textures::image>,
style::Properties<>>
{
public:
diff --git a/src/mbgl/programs/circle_program.hpp b/src/mbgl/programs/circle_program.hpp
index 0caa1b2a15..2b218d1768 100644
--- a/src/mbgl/programs/circle_program.hpp
+++ b/src/mbgl/programs/circle_program.hpp
@@ -9,20 +9,20 @@
namespace mbgl {
namespace uniforms {
-MBGL_DEFINE_UNIFORM_SCALAR(bool, u_scale_with_map);
+MBGL_DEFINE_UNIFORM_SCALAR(bool, scale_with_map);
} // namespace uniforms
class CircleProgram : public Program<
CircleProgram,
gfx::PrimitiveType::Triangle,
TypeList<
- attributes::a_pos>,
+ attributes::pos>,
TypeList<
- uniforms::u_matrix,
- uniforms::u_scale_with_map,
- uniforms::u_extrude_scale,
- uniforms::u_camera_to_center_distance,
- uniforms::u_pitch_with_map>,
+ uniforms::matrix,
+ uniforms::scale_with_map,
+ uniforms::extrude_scale,
+ uniforms::camera_to_center_distance,
+ uniforms::pitch_with_map>,
TypeList<>,
style::CirclePaintProperties>
{
@@ -52,7 +52,7 @@ class CircleLayerPrograms final : public LayerTypePrograms {
public:
CircleLayerPrograms(gfx::Context& context, const ProgramParameters& programParameters)
: circle(context, programParameters) {}
- ProgramMap<CircleProgram> circle;
+ CircleProgram circle;
};
} // namespace mbgl
diff --git a/src/mbgl/programs/clipping_mask_program.hpp b/src/mbgl/programs/clipping_mask_program.hpp
index 874708a52f..14d66a8703 100644
--- a/src/mbgl/programs/clipping_mask_program.hpp
+++ b/src/mbgl/programs/clipping_mask_program.hpp
@@ -12,7 +12,7 @@ class ClippingMaskProgram : public Program<
gfx::PrimitiveType::Triangle,
PositionOnlyLayoutAttributes,
TypeList<
- uniforms::u_matrix>,
+ uniforms::matrix>,
TypeList<>,
style::Properties<>>
{
diff --git a/src/mbgl/programs/collision_box_program.hpp b/src/mbgl/programs/collision_box_program.hpp
index 7b81752a94..677704b154 100644
--- a/src/mbgl/programs/collision_box_program.hpp
+++ b/src/mbgl/programs/collision_box_program.hpp
@@ -11,21 +11,20 @@
namespace mbgl {
using CollisionBoxLayoutAttributes = TypeList<
- attributes::a_pos,
- attributes::a_anchor_pos,
- attributes::a_extrude,
- attributes::a_shift>;
+ attributes::pos,
+ attributes::anchor_pos,
+ attributes::extrude>;
-using CollisionBoxDynamicAttributes = TypeList<attributes::a_placed>;
+using CollisionBoxDynamicAttributes = TypeList<attributes::placed, attributes::shift>;
class CollisionBoxProgram : public Program<
CollisionBoxProgram,
gfx::PrimitiveType::Line,
TypeListConcat<CollisionBoxLayoutAttributes, CollisionBoxDynamicAttributes>,
TypeList<
- uniforms::u_matrix,
- uniforms::u_extrude_scale,
- uniforms::u_camera_to_center_distance>,
+ uniforms::matrix,
+ uniforms::extrude_scale,
+ uniforms::camera_to_center_distance>,
TypeList<>,
style::Properties<>>
{
@@ -45,17 +44,14 @@ public:
{{
static_cast<int16_t>(::round(o.x)),
static_cast<int16_t>(::round(o.y))
- }},
- {{
- 0.0f,
- 0.0f
}}
};
}
- static gfx::Vertex<CollisionBoxDynamicAttributes> dynamicVertex(bool placed, bool notUsed) {
+ static gfx::Vertex<CollisionBoxDynamicAttributes> dynamicVertex(bool placed, bool notUsed, Point<float> shift) {
return {
- {{ static_cast<uint8_t>(placed), static_cast<uint8_t>(notUsed) }}
+ {{ static_cast<uint8_t>(placed), static_cast<uint8_t>(notUsed) }},
+ {{ shift.x, shift.y }}
};
}
@@ -116,10 +112,10 @@ class CollisionCircleProgram : public Program<
gfx::PrimitiveType::Triangle,
TypeListConcat<CollisionBoxLayoutAttributes, CollisionBoxDynamicAttributes>,
TypeList<
- uniforms::u_matrix,
- uniforms::u_extrude_scale,
- uniforms::u_overscale_factor,
- uniforms::u_camera_to_center_distance>,
+ uniforms::matrix,
+ uniforms::extrude_scale,
+ uniforms::overscale_factor,
+ uniforms::camera_to_center_distance>,
TypeList<>,
style::Properties<>>
{
@@ -139,10 +135,6 @@ public:
{{
static_cast<int16_t>(::round(o.x)),
static_cast<int16_t>(::round(o.y))
- }},
- {{
- 0.0f,
- 0.0f
}}
};
}
diff --git a/src/mbgl/programs/debug_program.hpp b/src/mbgl/programs/debug_program.hpp
index 61125b55bf..f1782e19e3 100644
--- a/src/mbgl/programs/debug_program.hpp
+++ b/src/mbgl/programs/debug_program.hpp
@@ -11,10 +11,10 @@ class DebugProgram : public Program<
DebugProgram,
gfx::PrimitiveType::Line,
TypeList<
- attributes::a_pos>,
+ attributes::pos>,
TypeList<
- uniforms::u_matrix,
- uniforms::u_color>,
+ uniforms::matrix,
+ uniforms::color>,
TypeList<>,
style::Properties<>>
{
diff --git a/src/mbgl/programs/extrusion_texture_program.hpp b/src/mbgl/programs/extrusion_texture_program.hpp
index bdeeabb8cd..10dfdc8a16 100644
--- a/src/mbgl/programs/extrusion_texture_program.hpp
+++ b/src/mbgl/programs/extrusion_texture_program.hpp
@@ -12,13 +12,13 @@ namespace mbgl {
class ExtrusionTextureProgram : public Program<
ExtrusionTextureProgram,
gfx::PrimitiveType::Triangle,
- TypeList<attributes::a_pos>,
+ TypeList<attributes::pos>,
TypeList<
- uniforms::u_matrix,
- uniforms::u_world,
- uniforms::u_opacity>,
+ uniforms::matrix,
+ uniforms::world,
+ uniforms::opacity>,
TypeList<
- textures::u_image>,
+ textures::image>,
style::Properties<>> {
public:
using Program::Program;
diff --git a/src/mbgl/programs/fill_extrusion_program.cpp b/src/mbgl/programs/fill_extrusion_program.cpp
index 7688d09299..d301f32707 100644
--- a/src/mbgl/programs/fill_extrusion_program.cpp
+++ b/src/mbgl/programs/fill_extrusion_program.cpp
@@ -38,10 +38,10 @@ float lightIntensity(const EvaluatedLight& light) {
FillExtrusionProgram::LayoutUniformValues FillExtrusionProgram::layoutUniformValues(
mat4 matrix, const TransformState& state, const EvaluatedLight& light) {
return {
- uniforms::u_matrix::Value( matrix ),
- uniforms::u_lightcolor::Value( lightColor(light) ),
- uniforms::u_lightpos::Value( lightPosition(light, state) ),
- uniforms::u_lightintensity::Value( lightIntensity(light) )
+ uniforms::matrix::Value( matrix ),
+ uniforms::lightcolor::Value( lightColor(light) ),
+ uniforms::lightpos::Value( lightPosition(light, state) ),
+ uniforms::lightintensity::Value( lightIntensity(light) )
};
}
@@ -60,16 +60,16 @@ FillExtrusionPatternProgram::layoutUniformValues(mat4 matrix,
int32_t pixelY = tileSizeAtNearestZoom * tileID.canonical.y;
return {
- uniforms::u_matrix::Value( matrix ),
- uniforms::u_scale::Value( {{pixelRatio, tileRatio, crossfade.fromScale, crossfade.toScale}} ),
- uniforms::u_texsize::Value( atlasSize ),
- uniforms::u_fade::Value( crossfade.t ),
- uniforms::u_pixel_coord_upper::Value( std::array<float, 2>{{ float(pixelX >> 16), float(pixelY >> 16) }} ),
- uniforms::u_pixel_coord_lower::Value( std::array<float, 2>{{ float(pixelX & 0xFFFF), float(pixelY & 0xFFFF) }} ),
- uniforms::u_height_factor::Value( heightFactor ),
- uniforms::u_lightcolor::Value( lightColor(light) ),
- uniforms::u_lightpos::Value( lightPosition(light, state) ),
- uniforms::u_lightintensity::Value( lightIntensity(light) ),
+ uniforms::matrix::Value( matrix ),
+ uniforms::scale::Value( {{pixelRatio, tileRatio, crossfade.fromScale, crossfade.toScale}} ),
+ uniforms::texsize::Value( atlasSize ),
+ uniforms::fade::Value( crossfade.t ),
+ uniforms::pixel_coord_upper::Value( std::array<float, 2>{{ float(pixelX >> 16), float(pixelY >> 16) }} ),
+ uniforms::pixel_coord_lower::Value( std::array<float, 2>{{ float(pixelX & 0xFFFF), float(pixelY & 0xFFFF) }} ),
+ uniforms::height_factor::Value( heightFactor ),
+ uniforms::lightcolor::Value( lightColor(light) ),
+ uniforms::lightpos::Value( lightPosition(light, state) ),
+ uniforms::lightintensity::Value( lightIntensity(light) ),
};
}
diff --git a/src/mbgl/programs/fill_extrusion_program.hpp b/src/mbgl/programs/fill_extrusion_program.hpp
index e1c3ca7f17..85e2ff3caf 100644
--- a/src/mbgl/programs/fill_extrusion_program.hpp
+++ b/src/mbgl/programs/fill_extrusion_program.hpp
@@ -22,33 +22,33 @@ class TransformState;
template <class> class Faded;
namespace uniforms {
-MBGL_DEFINE_UNIFORM_VECTOR(float, 3, u_lightpos);
-MBGL_DEFINE_UNIFORM_VECTOR(float, 3, u_lightcolor);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_lightintensity);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_height_factor);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 3, lightpos);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 3, lightcolor);
+MBGL_DEFINE_UNIFORM_SCALAR(float, lightintensity);
+MBGL_DEFINE_UNIFORM_SCALAR(float, height_factor);
} // namespace uniforms
using FillExtrusionLayoutAttributes = TypeList<
- attributes::a_pos,
- attributes::a_normal_ed>;
+ attributes::pos,
+ attributes::normal_ed>;
using FillExtrusionUniforms = TypeList<
- uniforms::u_matrix,
- uniforms::u_lightcolor,
- uniforms::u_lightpos,
- uniforms::u_lightintensity>;
+ uniforms::matrix,
+ uniforms::lightcolor,
+ uniforms::lightpos,
+ uniforms::lightintensity>;
using FillExtrusionPatternUniforms = TypeList<
- uniforms::u_matrix,
- uniforms::u_scale,
- uniforms::u_texsize,
- uniforms::u_fade,
- uniforms::u_pixel_coord_upper,
- uniforms::u_pixel_coord_lower,
- uniforms::u_height_factor,
- uniforms::u_lightcolor,
- uniforms::u_lightpos,
- uniforms::u_lightintensity>;
+ uniforms::matrix,
+ uniforms::scale,
+ uniforms::texsize,
+ uniforms::fade,
+ uniforms::pixel_coord_upper,
+ uniforms::pixel_coord_lower,
+ uniforms::height_factor,
+ uniforms::lightcolor,
+ uniforms::lightpos,
+ uniforms::lightintensity>;
class FillExtrusionProgram : public Program<
FillExtrusionProgram,
@@ -91,7 +91,7 @@ class FillExtrusionPatternProgram : public Program<
FillExtrusionLayoutAttributes,
FillExtrusionPatternUniforms,
TypeList<
- textures::u_image>,
+ textures::image>,
style::FillExtrusionPaintProperties>
{
public:
@@ -117,8 +117,8 @@ public:
: fillExtrusion(context, programParameters),
fillExtrusionPattern(context, programParameters),
extrusionTexture(context, programParameters) {}
- ProgramMap<FillExtrusionProgram> fillExtrusion;
- ProgramMap<FillExtrusionPatternProgram> fillExtrusionPattern;
+ FillExtrusionProgram fillExtrusion;
+ FillExtrusionPatternProgram fillExtrusionPattern;
ExtrusionTextureProgram extrusionTexture;
};
diff --git a/src/mbgl/programs/fill_program.cpp b/src/mbgl/programs/fill_program.cpp
index e0dfc71f81..703d61399f 100644
--- a/src/mbgl/programs/fill_program.cpp
+++ b/src/mbgl/programs/fill_program.cpp
@@ -30,13 +30,13 @@ FillPatternProgram::layoutUniformValues(mat4 matrix,
int32_t pixelY = tileSizeAtNearestZoom * tileID.canonical.y;
return {
- uniforms::u_matrix::Value( matrix ),
- uniforms::u_world::Value( framebufferSize ),
- uniforms::u_texsize::Value( atlasSize ),
- uniforms::u_scale::Value({ {pixelRatio, tileRatio, crossfade.fromScale, crossfade.toScale} } ),
- uniforms::u_fade::Value( crossfade.t ),
- uniforms::u_pixel_coord_upper::Value( std::array<float, 2> {{ float(pixelX >> 16), float(pixelY >> 16) }}),
- uniforms::u_pixel_coord_lower::Value( std::array<float, 2> {{ float(pixelX & 0xFFFF), float(pixelY & 0xFFFF) }} )
+ uniforms::matrix::Value( matrix ),
+ uniforms::world::Value( framebufferSize ),
+ uniforms::texsize::Value( atlasSize ),
+ uniforms::scale::Value({ {pixelRatio, tileRatio, crossfade.fromScale, crossfade.toScale} } ),
+ uniforms::fade::Value( crossfade.t ),
+ uniforms::pixel_coord_upper::Value( std::array<float, 2> {{ float(pixelX >> 16), float(pixelY >> 16) }}),
+ uniforms::pixel_coord_lower::Value( std::array<float, 2> {{ float(pixelX & 0xFFFF), float(pixelY & 0xFFFF) }} )
};
}
diff --git a/src/mbgl/programs/fill_program.hpp b/src/mbgl/programs/fill_program.hpp
index 8519e482d6..99314c51b0 100644
--- a/src/mbgl/programs/fill_program.hpp
+++ b/src/mbgl/programs/fill_program.hpp
@@ -21,17 +21,17 @@ template <class> class Faded;
using FillLayoutAttributes = PositionOnlyLayoutAttributes;
using FillUniforms = TypeList<
- uniforms::u_matrix,
- uniforms::u_world>;
+ uniforms::matrix,
+ uniforms::world>;
using FillPatternUniforms = TypeList<
- uniforms::u_matrix,
- uniforms::u_world,
- uniforms::u_texsize,
- uniforms::u_scale,
- uniforms::u_fade,
- uniforms::u_pixel_coord_upper,
- uniforms::u_pixel_coord_lower>;
+ uniforms::matrix,
+ uniforms::world,
+ uniforms::texsize,
+ uniforms::scale,
+ uniforms::fade,
+ uniforms::pixel_coord_upper,
+ uniforms::pixel_coord_lower>;
class FillProgram : public Program<
FillProgram,
@@ -60,7 +60,7 @@ class FillPatternProgram : public Program<
FillLayoutAttributes,
FillPatternUniforms,
TypeList<
- textures::u_image>,
+ textures::image>,
style::FillPaintProperties>
{
public:
@@ -93,7 +93,7 @@ class FillOutlinePatternProgram : public Program<
FillLayoutAttributes,
FillPatternUniforms,
TypeList<
- textures::u_image>,
+ textures::image>,
style::FillPaintProperties>
{
public:
@@ -110,10 +110,10 @@ public:
fillPattern(context, programParameters),
fillOutline(context, programParameters),
fillOutlinePattern(context, programParameters) {}
- ProgramMap<FillProgram> fill;
- ProgramMap<FillPatternProgram> fillPattern;
- ProgramMap<FillOutlineProgram> fillOutline;
- ProgramMap<FillOutlinePatternProgram> fillOutlinePattern;
+ FillProgram fill;
+ FillPatternProgram fillPattern;
+ FillOutlineProgram fillOutline;
+ FillOutlinePatternProgram fillOutlinePattern;
};
} // namespace mbgl
diff --git a/src/mbgl/programs/gl/background.cpp b/src/mbgl/programs/gl/background.cpp
index da5ea25410..78074d670f 100644
--- a/src/mbgl/programs/gl/background.cpp
+++ b/src/mbgl/programs/gl/background.cpp
@@ -1,18 +1,37 @@
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
#include <mbgl/programs/background_program.hpp>
+#include <mbgl/programs/gl/preludes.hpp>
#include <mbgl/programs/gl/shader_source.hpp>
#include <mbgl/gl/program.hpp>
namespace mbgl {
+namespace programs {
+namespace gl {
+
+template <typename>
+struct ShaderSource;
+
+template <>
+struct ShaderSource<BackgroundProgram> {
+ static constexpr const char* name = "background";
+ static constexpr const uint8_t hash[8] = { 0x2d, 0xef, 0x97, 0xa2, 0xec, 0xb5, 0x67, 0xef };
+ static constexpr const auto vertexOffset = 1429;
+ static constexpr const auto fragmentOffset = 1525;
+};
+
+constexpr const char* ShaderSource<BackgroundProgram>::name;
+constexpr const uint8_t ShaderSource<BackgroundProgram>::hash[8];
+
+} // namespace gl
+} // namespace programs
+
namespace gfx {
template <>
std::unique_ptr<Program<BackgroundProgram>>
Context::createProgram<gl::Context>(const ProgramParameters& programParameters) {
- return gl::Program<BackgroundProgram>::createProgram(
- reinterpret_cast<gl::Context&>(*this), programParameters, "background",
- programs::gl::shaderSource() + 1429, programs::gl::shaderSource() + 1525);
+ return std::make_unique<gl::Program<BackgroundProgram>>(programParameters);
}
} // namespace gfx
diff --git a/src/mbgl/programs/gl/background_pattern.cpp b/src/mbgl/programs/gl/background_pattern.cpp
index af5d87129e..04111c7abd 100644
--- a/src/mbgl/programs/gl/background_pattern.cpp
+++ b/src/mbgl/programs/gl/background_pattern.cpp
@@ -1,18 +1,37 @@
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
#include <mbgl/programs/background_pattern_program.hpp>
+#include <mbgl/programs/gl/preludes.hpp>
#include <mbgl/programs/gl/shader_source.hpp>
#include <mbgl/gl/program.hpp>
namespace mbgl {
+namespace programs {
+namespace gl {
+
+template <typename>
+struct ShaderSource;
+
+template <>
+struct ShaderSource<BackgroundPatternProgram> {
+ static constexpr const char* name = "background_pattern";
+ static constexpr const uint8_t hash[8] = { 0x70, 0x13, 0xc8, 0x7e, 0xba, 0x18, 0xf5, 0x19 };
+ static constexpr const auto vertexOffset = 1675;
+ static constexpr const auto fragmentOffset = 2266;
+};
+
+constexpr const char* ShaderSource<BackgroundPatternProgram>::name;
+constexpr const uint8_t ShaderSource<BackgroundPatternProgram>::hash[8];
+
+} // namespace gl
+} // namespace programs
+
namespace gfx {
template <>
std::unique_ptr<Program<BackgroundPatternProgram>>
Context::createProgram<gl::Context>(const ProgramParameters& programParameters) {
- return gl::Program<BackgroundPatternProgram>::createProgram(
- reinterpret_cast<gl::Context&>(*this), programParameters, "background_pattern",
- programs::gl::shaderSource() + 1675, programs::gl::shaderSource() + 2266);
+ return std::make_unique<gl::Program<BackgroundPatternProgram>>(programParameters);
}
} // namespace gfx
diff --git a/src/mbgl/programs/gl/circle.cpp b/src/mbgl/programs/gl/circle.cpp
index 04c3f60870..d1f1e29d33 100644
--- a/src/mbgl/programs/gl/circle.cpp
+++ b/src/mbgl/programs/gl/circle.cpp
@@ -1,18 +1,37 @@
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
#include <mbgl/programs/circle_program.hpp>
+#include <mbgl/programs/gl/preludes.hpp>
#include <mbgl/programs/gl/shader_source.hpp>
#include <mbgl/gl/program.hpp>
namespace mbgl {
+namespace programs {
+namespace gl {
+
+template <typename>
+struct ShaderSource;
+
+template <>
+struct ShaderSource<CircleProgram> {
+ static constexpr const char* name = "circle";
+ static constexpr const uint8_t hash[8] = { 0xf0, 0x3e, 0x18, 0xb7, 0x75, 0xb2, 0xde, 0xa9 };
+ static constexpr const auto vertexOffset = 2927;
+ static constexpr const auto fragmentOffset = 6093;
+};
+
+constexpr const char* ShaderSource<CircleProgram>::name;
+constexpr const uint8_t ShaderSource<CircleProgram>::hash[8];
+
+} // namespace gl
+} // namespace programs
+
namespace gfx {
template <>
std::unique_ptr<Program<CircleProgram>>
Context::createProgram<gl::Context>(const ProgramParameters& programParameters) {
- return gl::Program<CircleProgram>::createProgram(
- reinterpret_cast<gl::Context&>(*this), programParameters, "circle",
- programs::gl::shaderSource() + 2927, programs::gl::shaderSource() + 6093);
+ return std::make_unique<gl::Program<CircleProgram>>(programParameters);
}
} // namespace gfx
@@ -30,7 +49,7 @@ attribute vec2 a_pos;
#ifndef HAS_UNIFORM_u_color
-uniform lowp float a_color_t;
+uniform lowp float u_color_t;
attribute highp vec4 a_color;
varying highp vec4 color;
#else
@@ -39,7 +58,7 @@ uniform highp vec4 u_color;
#ifndef HAS_UNIFORM_u_radius
-uniform lowp float a_radius_t;
+uniform lowp float u_radius_t;
attribute mediump vec2 a_radius;
varying mediump float radius;
#else
@@ -48,7 +67,7 @@ uniform mediump float u_radius;
#ifndef HAS_UNIFORM_u_blur
-uniform lowp float a_blur_t;
+uniform lowp float u_blur_t;
attribute lowp vec2 a_blur;
varying lowp float blur;
#else
@@ -57,7 +76,7 @@ uniform lowp float u_blur;
#ifndef HAS_UNIFORM_u_opacity
-uniform lowp float a_opacity_t;
+uniform lowp float u_opacity_t;
attribute lowp vec2 a_opacity;
varying lowp float opacity;
#else
@@ -66,7 +85,7 @@ uniform lowp float u_opacity;
#ifndef HAS_UNIFORM_u_stroke_color
-uniform lowp float a_stroke_color_t;
+uniform lowp float u_stroke_color_t;
attribute highp vec4 a_stroke_color;
varying highp vec4 stroke_color;
#else
@@ -75,7 +94,7 @@ uniform highp vec4 u_stroke_color;
#ifndef HAS_UNIFORM_u_stroke_width
-uniform lowp float a_stroke_width_t;
+uniform lowp float u_stroke_width_t;
attribute mediump vec2 a_stroke_width;
varying mediump float stroke_width;
#else
@@ -84,7 +103,7 @@ uniform mediump float u_stroke_width;
#ifndef HAS_UNIFORM_u_stroke_opacity
-uniform lowp float a_stroke_opacity_t;
+uniform lowp float u_stroke_opacity_t;
attribute lowp vec2 a_stroke_opacity;
varying lowp float stroke_opacity;
#else
@@ -97,49 +116,49 @@ varying vec3 v_data;
void main(void) {
#ifndef HAS_UNIFORM_u_color
- color = unpack_mix_color(a_color, a_color_t);
+ color = unpack_mix_color(a_color, u_color_t);
#else
highp vec4 color = u_color;
#endif
#ifndef HAS_UNIFORM_u_radius
- radius = unpack_mix_vec2(a_radius, a_radius_t);
+ radius = unpack_mix_vec2(a_radius, u_radius_t);
#else
mediump float radius = u_radius;
#endif
#ifndef HAS_UNIFORM_u_blur
- blur = unpack_mix_vec2(a_blur, a_blur_t);
+ blur = unpack_mix_vec2(a_blur, u_blur_t);
#else
lowp float blur = u_blur;
#endif
#ifndef HAS_UNIFORM_u_opacity
- opacity = unpack_mix_vec2(a_opacity, a_opacity_t);
+ opacity = unpack_mix_vec2(a_opacity, u_opacity_t);
#else
lowp float opacity = u_opacity;
#endif
#ifndef HAS_UNIFORM_u_stroke_color
- stroke_color = unpack_mix_color(a_stroke_color, a_stroke_color_t);
+ stroke_color = unpack_mix_color(a_stroke_color, u_stroke_color_t);
#else
highp vec4 stroke_color = u_stroke_color;
#endif
#ifndef HAS_UNIFORM_u_stroke_width
- stroke_width = unpack_mix_vec2(a_stroke_width, a_stroke_width_t);
+ stroke_width = unpack_mix_vec2(a_stroke_width, u_stroke_width_t);
#else
mediump float stroke_width = u_stroke_width;
#endif
#ifndef HAS_UNIFORM_u_stroke_opacity
- stroke_opacity = unpack_mix_vec2(a_stroke_opacity, a_stroke_opacity_t);
+ stroke_opacity = unpack_mix_vec2(a_stroke_opacity, u_stroke_opacity_t);
#else
lowp float stroke_opacity = u_stroke_opacity;
#endif
diff --git a/src/mbgl/programs/gl/clipping_mask.cpp b/src/mbgl/programs/gl/clipping_mask.cpp
index 311877f065..3179ab0c13 100644
--- a/src/mbgl/programs/gl/clipping_mask.cpp
+++ b/src/mbgl/programs/gl/clipping_mask.cpp
@@ -1,18 +1,37 @@
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
#include <mbgl/programs/clipping_mask_program.hpp>
+#include <mbgl/programs/gl/preludes.hpp>
#include <mbgl/programs/gl/shader_source.hpp>
#include <mbgl/gl/program.hpp>
namespace mbgl {
+namespace programs {
+namespace gl {
+
+template <typename>
+struct ShaderSource;
+
+template <>
+struct ShaderSource<ClippingMaskProgram> {
+ static constexpr const char* name = "clipping_mask";
+ static constexpr const uint8_t hash[8] = { 0x3e, 0x17, 0xc2, 0x3a, 0x1f, 0xf0, 0xa8, 0xa3 };
+ static constexpr const auto vertexOffset = 7848;
+ static constexpr const auto fragmentOffset = 7944;
+};
+
+constexpr const char* ShaderSource<ClippingMaskProgram>::name;
+constexpr const uint8_t ShaderSource<ClippingMaskProgram>::hash[8];
+
+} // namespace gl
+} // namespace programs
+
namespace gfx {
template <>
std::unique_ptr<Program<ClippingMaskProgram>>
Context::createProgram<gl::Context>(const ProgramParameters& programParameters) {
- return gl::Program<ClippingMaskProgram>::createProgram(
- reinterpret_cast<gl::Context&>(*this), programParameters, "clipping_mask",
- programs::gl::shaderSource() + 7848, programs::gl::shaderSource() + 7944);
+ return std::make_unique<gl::Program<ClippingMaskProgram>>(programParameters);
}
} // namespace gfx
diff --git a/src/mbgl/programs/gl/collision_box.cpp b/src/mbgl/programs/gl/collision_box.cpp
index 9af67f7981..f7ac4d4d67 100644
--- a/src/mbgl/programs/gl/collision_box.cpp
+++ b/src/mbgl/programs/gl/collision_box.cpp
@@ -1,18 +1,37 @@
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
#include <mbgl/programs/collision_box_program.hpp>
+#include <mbgl/programs/gl/preludes.hpp>
#include <mbgl/programs/gl/shader_source.hpp>
#include <mbgl/gl/program.hpp>
namespace mbgl {
+namespace programs {
+namespace gl {
+
+template <typename>
+struct ShaderSource;
+
+template <>
+struct ShaderSource<CollisionBoxProgram> {
+ static constexpr const char* name = "collision_box";
+ static constexpr const uint8_t hash[8] = { 0xcb, 0x6a, 0x9b, 0xd1, 0x1f, 0x31, 0xf8, 0x5b };
+ static constexpr const auto vertexOffset = 9956;
+ static constexpr const auto fragmentOffset = 10635;
+};
+
+constexpr const char* ShaderSource<CollisionBoxProgram>::name;
+constexpr const uint8_t ShaderSource<CollisionBoxProgram>::hash[8];
+
+} // namespace gl
+} // namespace programs
+
namespace gfx {
template <>
std::unique_ptr<Program<CollisionBoxProgram>>
Context::createProgram<gl::Context>(const ProgramParameters& programParameters) {
- return gl::Program<CollisionBoxProgram>::createProgram(
- reinterpret_cast<gl::Context&>(*this), programParameters, "collision_box",
- programs::gl::shaderSource() + 9956, programs::gl::shaderSource() + 10635);
+ return std::make_unique<gl::Program<CollisionBoxProgram>>(programParameters);
}
} // namespace gfx
diff --git a/src/mbgl/programs/gl/collision_circle.cpp b/src/mbgl/programs/gl/collision_circle.cpp
index 843f9161bb..8f1b5726fe 100644
--- a/src/mbgl/programs/gl/collision_circle.cpp
+++ b/src/mbgl/programs/gl/collision_circle.cpp
@@ -1,18 +1,37 @@
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
#include <mbgl/programs/collision_circle_program.hpp>
+#include <mbgl/programs/gl/preludes.hpp>
#include <mbgl/programs/gl/shader_source.hpp>
#include <mbgl/gl/program.hpp>
namespace mbgl {
+namespace programs {
+namespace gl {
+
+template <typename>
+struct ShaderSource;
+
+template <>
+struct ShaderSource<CollisionCircleProgram> {
+ static constexpr const char* name = "collision_circle";
+ static constexpr const uint8_t hash[8] = { 0x99, 0x2e, 0xad, 0x8c, 0xd3, 0x88, 0xae, 0x82 };
+ static constexpr const auto vertexOffset = 10858;
+ static constexpr const auto fragmentOffset = 11774;
+};
+
+constexpr const char* ShaderSource<CollisionCircleProgram>::name;
+constexpr const uint8_t ShaderSource<CollisionCircleProgram>::hash[8];
+
+} // namespace gl
+} // namespace programs
+
namespace gfx {
template <>
std::unique_ptr<Program<CollisionCircleProgram>>
Context::createProgram<gl::Context>(const ProgramParameters& programParameters) {
- return gl::Program<CollisionCircleProgram>::createProgram(
- reinterpret_cast<gl::Context&>(*this), programParameters, "collision_circle",
- programs::gl::shaderSource() + 10858, programs::gl::shaderSource() + 11774);
+ return std::make_unique<gl::Program<CollisionCircleProgram>>(programParameters);
}
} // namespace gfx
diff --git a/src/mbgl/programs/gl/debug.cpp b/src/mbgl/programs/gl/debug.cpp
index 8b7aee5a0b..ad23f420ab 100644
--- a/src/mbgl/programs/gl/debug.cpp
+++ b/src/mbgl/programs/gl/debug.cpp
@@ -1,18 +1,37 @@
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
#include <mbgl/programs/debug_program.hpp>
+#include <mbgl/programs/gl/preludes.hpp>
#include <mbgl/programs/gl/shader_source.hpp>
#include <mbgl/gl/program.hpp>
namespace mbgl {
+namespace programs {
+namespace gl {
+
+template <typename>
+struct ShaderSource;
+
+template <>
+struct ShaderSource<DebugProgram> {
+ static constexpr const char* name = "debug";
+ static constexpr const uint8_t hash[8] = { 0xa8, 0x7d, 0x87, 0x6e, 0x36, 0xa8, 0x81, 0xe3 };
+ static constexpr const auto vertexOffset = 12450;
+ static constexpr const auto fragmentOffset = 12546;
+};
+
+constexpr const char* ShaderSource<DebugProgram>::name;
+constexpr const uint8_t ShaderSource<DebugProgram>::hash[8];
+
+} // namespace gl
+} // namespace programs
+
namespace gfx {
template <>
std::unique_ptr<Program<DebugProgram>>
Context::createProgram<gl::Context>(const ProgramParameters& programParameters) {
- return gl::Program<DebugProgram>::createProgram(
- reinterpret_cast<gl::Context&>(*this), programParameters, "debug",
- programs::gl::shaderSource() + 12450, programs::gl::shaderSource() + 12546);
+ return std::make_unique<gl::Program<DebugProgram>>(programParameters);
}
} // namespace gfx
diff --git a/src/mbgl/programs/gl/extrusion_texture.cpp b/src/mbgl/programs/gl/extrusion_texture.cpp
index bd320d52cf..bca533a788 100644
--- a/src/mbgl/programs/gl/extrusion_texture.cpp
+++ b/src/mbgl/programs/gl/extrusion_texture.cpp
@@ -1,18 +1,37 @@
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
#include <mbgl/programs/extrusion_texture_program.hpp>
+#include <mbgl/programs/gl/preludes.hpp>
#include <mbgl/programs/gl/shader_source.hpp>
#include <mbgl/gl/program.hpp>
namespace mbgl {
+namespace programs {
+namespace gl {
+
+template <typename>
+struct ShaderSource;
+
+template <>
+struct ShaderSource<ExtrusionTextureProgram> {
+ static constexpr const char* name = "extrusion_texture";
+ static constexpr const uint8_t hash[8] = { 0xd9, 0x77, 0x11, 0xd2, 0x03, 0xc7, 0x27, 0xcb };
+ static constexpr const auto vertexOffset = 27554;
+ static constexpr const auto fragmentOffset = 27734;
+};
+
+constexpr const char* ShaderSource<ExtrusionTextureProgram>::name;
+constexpr const uint8_t ShaderSource<ExtrusionTextureProgram>::hash[8];
+
+} // namespace gl
+} // namespace programs
+
namespace gfx {
template <>
std::unique_ptr<Program<ExtrusionTextureProgram>>
Context::createProgram<gl::Context>(const ProgramParameters& programParameters) {
- return gl::Program<ExtrusionTextureProgram>::createProgram(
- reinterpret_cast<gl::Context&>(*this), programParameters, "extrusion_texture",
- programs::gl::shaderSource() + 27554, programs::gl::shaderSource() + 27734);
+ return std::make_unique<gl::Program<ExtrusionTextureProgram>>(programParameters);
}
} // namespace gfx
diff --git a/src/mbgl/programs/gl/fill.cpp b/src/mbgl/programs/gl/fill.cpp
index c15c2774ab..a699f82609 100644
--- a/src/mbgl/programs/gl/fill.cpp
+++ b/src/mbgl/programs/gl/fill.cpp
@@ -1,18 +1,37 @@
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
#include <mbgl/programs/fill_program.hpp>
+#include <mbgl/programs/gl/preludes.hpp>
#include <mbgl/programs/gl/shader_source.hpp>
#include <mbgl/gl/program.hpp>
namespace mbgl {
+namespace programs {
+namespace gl {
+
+template <typename>
+struct ShaderSource;
+
+template <>
+struct ShaderSource<FillProgram> {
+ static constexpr const char* name = "fill";
+ static constexpr const uint8_t hash[8] = { 0x87, 0xea, 0x65, 0x7f, 0x0c, 0x9b, 0x97, 0x5d };
+ static constexpr const auto vertexOffset = 12610;
+ static constexpr const auto fragmentOffset = 13254;
+};
+
+constexpr const char* ShaderSource<FillProgram>::name;
+constexpr const uint8_t ShaderSource<FillProgram>::hash[8];
+
+} // namespace gl
+} // namespace programs
+
namespace gfx {
template <>
std::unique_ptr<Program<FillProgram>>
Context::createProgram<gl::Context>(const ProgramParameters& programParameters) {
- return gl::Program<FillProgram>::createProgram(
- reinterpret_cast<gl::Context&>(*this), programParameters, "fill",
- programs::gl::shaderSource() + 12610, programs::gl::shaderSource() + 13254);
+ return std::make_unique<gl::Program<FillProgram>>(programParameters);
}
} // namespace gfx
@@ -26,7 +45,7 @@ uniform mat4 u_matrix;
#ifndef HAS_UNIFORM_u_color
-uniform lowp float a_color_t;
+uniform lowp float u_color_t;
attribute highp vec4 a_color;
varying highp vec4 color;
#else
@@ -35,7 +54,7 @@ uniform highp vec4 u_color;
#ifndef HAS_UNIFORM_u_opacity
-uniform lowp float a_opacity_t;
+uniform lowp float u_opacity_t;
attribute lowp vec2 a_opacity;
varying lowp float opacity;
#else
@@ -46,14 +65,14 @@ uniform lowp float u_opacity;
void main() {
#ifndef HAS_UNIFORM_u_color
- color = unpack_mix_color(a_color, a_color_t);
+ color = unpack_mix_color(a_color, u_color_t);
#else
highp vec4 color = u_color;
#endif
#ifndef HAS_UNIFORM_u_opacity
- opacity = unpack_mix_vec2(a_opacity, a_opacity_t);
+ opacity = unpack_mix_vec2(a_opacity, u_opacity_t);
#else
lowp float opacity = u_opacity;
#endif
diff --git a/src/mbgl/programs/gl/fill_extrusion.cpp b/src/mbgl/programs/gl/fill_extrusion.cpp
index 45ebb68dd4..83a8eadee6 100644
--- a/src/mbgl/programs/gl/fill_extrusion.cpp
+++ b/src/mbgl/programs/gl/fill_extrusion.cpp
@@ -1,18 +1,37 @@
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
#include <mbgl/programs/fill_extrusion_program.hpp>
+#include <mbgl/programs/gl/preludes.hpp>
#include <mbgl/programs/gl/shader_source.hpp>
#include <mbgl/gl/program.hpp>
namespace mbgl {
+namespace programs {
+namespace gl {
+
+template <typename>
+struct ShaderSource;
+
+template <>
+struct ShaderSource<FillExtrusionProgram> {
+ static constexpr const char* name = "fill_extrusion";
+ static constexpr const uint8_t hash[8] = { 0x49, 0x8a, 0xa2, 0x8b, 0x21, 0x74, 0x27, 0x93 };
+ static constexpr const auto vertexOffset = 21238;
+ static constexpr const auto fragmentOffset = 23121;
+};
+
+constexpr const char* ShaderSource<FillExtrusionProgram>::name;
+constexpr const uint8_t ShaderSource<FillExtrusionProgram>::hash[8];
+
+} // namespace gl
+} // namespace programs
+
namespace gfx {
template <>
std::unique_ptr<Program<FillExtrusionProgram>>
Context::createProgram<gl::Context>(const ProgramParameters& programParameters) {
- return gl::Program<FillExtrusionProgram>::createProgram(
- reinterpret_cast<gl::Context&>(*this), programParameters, "fill_extrusion",
- programs::gl::shaderSource() + 21238, programs::gl::shaderSource() + 23121);
+ return std::make_unique<gl::Program<FillExtrusionProgram>>(programParameters);
}
} // namespace gfx
@@ -33,7 +52,7 @@ varying vec4 v_color;
#ifndef HAS_UNIFORM_u_base
-uniform lowp float a_base_t;
+uniform lowp float u_base_t;
attribute highp vec2 a_base;
#else
uniform highp float u_base;
@@ -41,7 +60,7 @@ uniform highp float u_base;
#ifndef HAS_UNIFORM_u_height
-uniform lowp float a_height_t;
+uniform lowp float u_height_t;
attribute highp vec2 a_height;
#else
uniform highp float u_height;
@@ -50,7 +69,7 @@ uniform highp float u_height;
#ifndef HAS_UNIFORM_u_color
-uniform lowp float a_color_t;
+uniform lowp float u_color_t;
attribute highp vec4 a_color;
#else
uniform highp vec4 u_color;
@@ -60,21 +79,21 @@ uniform highp vec4 u_color;
void main() {
#ifndef HAS_UNIFORM_u_base
- highp float base = unpack_mix_vec2(a_base, a_base_t);
+ highp float base = unpack_mix_vec2(a_base, u_base_t);
#else
highp float base = u_base;
#endif
#ifndef HAS_UNIFORM_u_height
- highp float height = unpack_mix_vec2(a_height, a_height_t);
+ highp float height = unpack_mix_vec2(a_height, u_height_t);
#else
highp float height = u_height;
#endif
#ifndef HAS_UNIFORM_u_color
- highp vec4 color = unpack_mix_color(a_color, a_color_t);
+ highp vec4 color = unpack_mix_color(a_color, u_color_t);
#else
highp vec4 color = u_color;
#endif
diff --git a/src/mbgl/programs/gl/fill_extrusion_pattern.cpp b/src/mbgl/programs/gl/fill_extrusion_pattern.cpp
index 9c2da87b11..45068d84b8 100644
--- a/src/mbgl/programs/gl/fill_extrusion_pattern.cpp
+++ b/src/mbgl/programs/gl/fill_extrusion_pattern.cpp
@@ -1,18 +1,37 @@
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
#include <mbgl/programs/fill_extrusion_pattern_program.hpp>
+#include <mbgl/programs/gl/preludes.hpp>
#include <mbgl/programs/gl/shader_source.hpp>
#include <mbgl/gl/program.hpp>
namespace mbgl {
+namespace programs {
+namespace gl {
+
+template <typename>
+struct ShaderSource;
+
+template <>
+struct ShaderSource<FillExtrusionPatternProgram> {
+ static constexpr const char* name = "fill_extrusion_pattern";
+ static constexpr const uint8_t hash[8] = { 0x93, 0x2b, 0xd1, 0xab, 0xa3, 0xf2, 0x24, 0x63 };
+ static constexpr const auto vertexOffset = 23237;
+ static constexpr const auto fragmentOffset = 26157;
+};
+
+constexpr const char* ShaderSource<FillExtrusionPatternProgram>::name;
+constexpr const uint8_t ShaderSource<FillExtrusionPatternProgram>::hash[8];
+
+} // namespace gl
+} // namespace programs
+
namespace gfx {
template <>
std::unique_ptr<Program<FillExtrusionPatternProgram>>
Context::createProgram<gl::Context>(const ProgramParameters& programParameters) {
- return gl::Program<FillExtrusionPatternProgram>::createProgram(
- reinterpret_cast<gl::Context&>(*this), programParameters, "fill_extrusion_pattern",
- programs::gl::shaderSource() + 23237, programs::gl::shaderSource() + 26157);
+ return std::make_unique<gl::Program<FillExtrusionPatternProgram>>(programParameters);
}
} // namespace gfx
@@ -40,7 +59,7 @@ varying vec4 v_lighting;
#ifndef HAS_UNIFORM_u_base
-uniform lowp float a_base_t;
+uniform lowp float u_base_t;
attribute lowp vec2 a_base;
varying lowp float base;
#else
@@ -49,7 +68,7 @@ uniform lowp float u_base;
#ifndef HAS_UNIFORM_u_height
-uniform lowp float a_height_t;
+uniform lowp float u_height_t;
attribute lowp vec2 a_height;
varying lowp float height;
#else
@@ -58,7 +77,7 @@ uniform lowp float u_height;
#ifndef HAS_UNIFORM_u_pattern_from
-uniform lowp float a_pattern_from_t;
+uniform lowp float u_pattern_from_t;
attribute lowp vec4 a_pattern_from;
varying lowp vec4 pattern_from;
#else
@@ -67,7 +86,7 @@ uniform lowp vec4 u_pattern_from;
#ifndef HAS_UNIFORM_u_pattern_to
-uniform lowp float a_pattern_to_t;
+uniform lowp float u_pattern_to_t;
attribute lowp vec4 a_pattern_to;
varying lowp vec4 pattern_to;
#else
@@ -78,14 +97,14 @@ uniform lowp vec4 u_pattern_to;
void main() {
#ifndef HAS_UNIFORM_u_base
- base = unpack_mix_vec2(a_base, a_base_t);
+ base = unpack_mix_vec2(a_base, u_base_t);
#else
lowp float base = u_base;
#endif
#ifndef HAS_UNIFORM_u_height
- height = unpack_mix_vec2(a_height, a_height_t);
+ height = unpack_mix_vec2(a_height, u_height_t);
#else
lowp float height = u_height;
#endif
diff --git a/src/mbgl/programs/gl/fill_outline.cpp b/src/mbgl/programs/gl/fill_outline.cpp
index 07615b2138..e7644468a5 100644
--- a/src/mbgl/programs/gl/fill_outline.cpp
+++ b/src/mbgl/programs/gl/fill_outline.cpp
@@ -1,18 +1,37 @@
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
#include <mbgl/programs/fill_outline_program.hpp>
+#include <mbgl/programs/gl/preludes.hpp>
#include <mbgl/programs/gl/shader_source.hpp>
#include <mbgl/gl/program.hpp>
namespace mbgl {
+namespace programs {
+namespace gl {
+
+template <typename>
+struct ShaderSource;
+
+template <>
+struct ShaderSource<FillOutlineProgram> {
+ static constexpr const char* name = "fill_outline";
+ static constexpr const uint8_t hash[8] = { 0x56, 0x65, 0x69, 0x4b, 0x70, 0x2d, 0x3d, 0xc4 };
+ static constexpr const auto vertexOffset = 13678;
+ static constexpr const auto fragmentOffset = 14503;
+};
+
+constexpr const char* ShaderSource<FillOutlineProgram>::name;
+constexpr const uint8_t ShaderSource<FillOutlineProgram>::hash[8];
+
+} // namespace gl
+} // namespace programs
+
namespace gfx {
template <>
std::unique_ptr<Program<FillOutlineProgram>>
Context::createProgram<gl::Context>(const ProgramParameters& programParameters) {
- return gl::Program<FillOutlineProgram>::createProgram(
- reinterpret_cast<gl::Context&>(*this), programParameters, "fill_outline",
- programs::gl::shaderSource() + 13678, programs::gl::shaderSource() + 14503);
+ return std::make_unique<gl::Program<FillOutlineProgram>>(programParameters);
}
} // namespace gfx
@@ -29,7 +48,7 @@ varying vec2 v_pos;
#ifndef HAS_UNIFORM_u_outline_color
-uniform lowp float a_outline_color_t;
+uniform lowp float u_outline_color_t;
attribute highp vec4 a_outline_color;
varying highp vec4 outline_color;
#else
@@ -38,7 +57,7 @@ uniform highp vec4 u_outline_color;
#ifndef HAS_UNIFORM_u_opacity
-uniform lowp float a_opacity_t;
+uniform lowp float u_opacity_t;
attribute lowp vec2 a_opacity;
varying lowp float opacity;
#else
@@ -49,14 +68,14 @@ uniform lowp float u_opacity;
void main() {
#ifndef HAS_UNIFORM_u_outline_color
- outline_color = unpack_mix_color(a_outline_color, a_outline_color_t);
+ outline_color = unpack_mix_color(a_outline_color, u_outline_color_t);
#else
highp vec4 outline_color = u_outline_color;
#endif
#ifndef HAS_UNIFORM_u_opacity
- opacity = unpack_mix_vec2(a_opacity, a_opacity_t);
+ opacity = unpack_mix_vec2(a_opacity, u_opacity_t);
#else
lowp float opacity = u_opacity;
#endif
diff --git a/src/mbgl/programs/gl/fill_outline_pattern.cpp b/src/mbgl/programs/gl/fill_outline_pattern.cpp
index 7e0bf19655..40aa5ea2de 100644
--- a/src/mbgl/programs/gl/fill_outline_pattern.cpp
+++ b/src/mbgl/programs/gl/fill_outline_pattern.cpp
@@ -1,18 +1,37 @@
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
#include <mbgl/programs/fill_outline_pattern_program.hpp>
+#include <mbgl/programs/gl/preludes.hpp>
#include <mbgl/programs/gl/shader_source.hpp>
#include <mbgl/gl/program.hpp>
namespace mbgl {
+namespace programs {
+namespace gl {
+
+template <typename>
+struct ShaderSource;
+
+template <>
+struct ShaderSource<FillOutlinePatternProgram> {
+ static constexpr const char* name = "fill_outline_pattern";
+ static constexpr const uint8_t hash[8] = { 0x56, 0x9c, 0x2f, 0x58, 0x6b, 0x31, 0xff, 0x84 };
+ static constexpr const auto vertexOffset = 15092;
+ static constexpr const auto fragmentOffset = 16952;
+};
+
+constexpr const char* ShaderSource<FillOutlinePatternProgram>::name;
+constexpr const uint8_t ShaderSource<FillOutlinePatternProgram>::hash[8];
+
+} // namespace gl
+} // namespace programs
+
namespace gfx {
template <>
std::unique_ptr<Program<FillOutlinePatternProgram>>
Context::createProgram<gl::Context>(const ProgramParameters& programParameters) {
- return gl::Program<FillOutlinePatternProgram>::createProgram(
- reinterpret_cast<gl::Context&>(*this), programParameters, "fill_outline_pattern",
- programs::gl::shaderSource() + 15092, programs::gl::shaderSource() + 16952);
+ return std::make_unique<gl::Program<FillOutlinePatternProgram>>(programParameters);
}
} // namespace gfx
@@ -34,7 +53,7 @@ varying vec2 v_pos;
#ifndef HAS_UNIFORM_u_opacity
-uniform lowp float a_opacity_t;
+uniform lowp float u_opacity_t;
attribute lowp vec2 a_opacity;
varying lowp float opacity;
#else
@@ -43,7 +62,7 @@ uniform lowp float u_opacity;
#ifndef HAS_UNIFORM_u_pattern_from
-uniform lowp float a_pattern_from_t;
+uniform lowp float u_pattern_from_t;
attribute lowp vec4 a_pattern_from;
varying lowp vec4 pattern_from;
#else
@@ -52,7 +71,7 @@ uniform lowp vec4 u_pattern_from;
#ifndef HAS_UNIFORM_u_pattern_to
-uniform lowp float a_pattern_to_t;
+uniform lowp float u_pattern_to_t;
attribute lowp vec4 a_pattern_to;
varying lowp vec4 pattern_to;
#else
@@ -63,7 +82,7 @@ uniform lowp vec4 u_pattern_to;
void main() {
#ifndef HAS_UNIFORM_u_opacity
- opacity = unpack_mix_vec2(a_opacity, a_opacity_t);
+ opacity = unpack_mix_vec2(a_opacity, u_opacity_t);
#else
lowp float opacity = u_opacity;
#endif
diff --git a/src/mbgl/programs/gl/fill_pattern.cpp b/src/mbgl/programs/gl/fill_pattern.cpp
index 256b1ede99..fd16d8bfc9 100644
--- a/src/mbgl/programs/gl/fill_pattern.cpp
+++ b/src/mbgl/programs/gl/fill_pattern.cpp
@@ -1,18 +1,37 @@
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
#include <mbgl/programs/fill_pattern_program.hpp>
+#include <mbgl/programs/gl/preludes.hpp>
#include <mbgl/programs/gl/shader_source.hpp>
#include <mbgl/gl/program.hpp>
namespace mbgl {
+namespace programs {
+namespace gl {
+
+template <typename>
+struct ShaderSource;
+
+template <>
+struct ShaderSource<FillPatternProgram> {
+ static constexpr const char* name = "fill_pattern";
+ static constexpr const uint8_t hash[8] = { 0x74, 0xa9, 0x97, 0x01, 0x96, 0xbd, 0x87, 0x36 };
+ static constexpr const auto vertexOffset = 18259;
+ static constexpr const auto fragmentOffset = 20038;
+};
+
+constexpr const char* ShaderSource<FillPatternProgram>::name;
+constexpr const uint8_t ShaderSource<FillPatternProgram>::hash[8];
+
+} // namespace gl
+} // namespace programs
+
namespace gfx {
template <>
std::unique_ptr<Program<FillPatternProgram>>
Context::createProgram<gl::Context>(const ProgramParameters& programParameters) {
- return gl::Program<FillPatternProgram>::createProgram(
- reinterpret_cast<gl::Context&>(*this), programParameters, "fill_pattern",
- programs::gl::shaderSource() + 18259, programs::gl::shaderSource() + 20038);
+ return std::make_unique<gl::Program<FillPatternProgram>>(programParameters);
}
} // namespace gfx
@@ -32,7 +51,7 @@ varying vec2 v_pos_b;
#ifndef HAS_UNIFORM_u_opacity
-uniform lowp float a_opacity_t;
+uniform lowp float u_opacity_t;
attribute lowp vec2 a_opacity;
varying lowp float opacity;
#else
@@ -41,7 +60,7 @@ uniform lowp float u_opacity;
#ifndef HAS_UNIFORM_u_pattern_from
-uniform lowp float a_pattern_from_t;
+uniform lowp float u_pattern_from_t;
attribute lowp vec4 a_pattern_from;
varying lowp vec4 pattern_from;
#else
@@ -50,7 +69,7 @@ uniform lowp vec4 u_pattern_from;
#ifndef HAS_UNIFORM_u_pattern_to
-uniform lowp float a_pattern_to_t;
+uniform lowp float u_pattern_to_t;
attribute lowp vec4 a_pattern_to;
varying lowp vec4 pattern_to;
#else
@@ -61,7 +80,7 @@ uniform lowp vec4 u_pattern_to;
void main() {
#ifndef HAS_UNIFORM_u_opacity
- opacity = unpack_mix_vec2(a_opacity, a_opacity_t);
+ opacity = unpack_mix_vec2(a_opacity, u_opacity_t);
#else
lowp float opacity = u_opacity;
#endif
diff --git a/src/mbgl/programs/gl/heatmap.cpp b/src/mbgl/programs/gl/heatmap.cpp
index 59f8ad9f69..3b960f1bda 100644
--- a/src/mbgl/programs/gl/heatmap.cpp
+++ b/src/mbgl/programs/gl/heatmap.cpp
@@ -1,18 +1,37 @@
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
#include <mbgl/programs/heatmap_program.hpp>
+#include <mbgl/programs/gl/preludes.hpp>
#include <mbgl/programs/gl/shader_source.hpp>
#include <mbgl/gl/program.hpp>
namespace mbgl {
+namespace programs {
+namespace gl {
+
+template <typename>
+struct ShaderSource;
+
+template <>
+struct ShaderSource<HeatmapProgram> {
+ static constexpr const char* name = "heatmap";
+ static constexpr const uint8_t hash[8] = { 0xab, 0x97, 0x81, 0x5c, 0xa2, 0x88, 0xaa, 0x7e };
+ static constexpr const auto vertexOffset = 7983;
+ static constexpr const auto fragmentOffset = 9030;
+};
+
+constexpr const char* ShaderSource<HeatmapProgram>::name;
+constexpr const uint8_t ShaderSource<HeatmapProgram>::hash[8];
+
+} // namespace gl
+} // namespace programs
+
namespace gfx {
template <>
std::unique_ptr<Program<HeatmapProgram>>
Context::createProgram<gl::Context>(const ProgramParameters& programParameters) {
- return gl::Program<HeatmapProgram>::createProgram(
- reinterpret_cast<gl::Context&>(*this), programParameters, "heatmap",
- programs::gl::shaderSource() + 7983, programs::gl::shaderSource() + 9030);
+ return std::make_unique<gl::Program<HeatmapProgram>>(programParameters);
}
} // namespace gfx
@@ -22,7 +41,7 @@ Context::createProgram<gl::Context>(const ProgramParameters& programParameters)
/*
#ifndef HAS_UNIFORM_u_weight
-uniform lowp float a_weight_t;
+uniform lowp float u_weight_t;
attribute highp vec2 a_weight;
varying highp float weight;
#else
@@ -31,7 +50,7 @@ uniform highp float u_weight;
#ifndef HAS_UNIFORM_u_radius
-uniform lowp float a_radius_t;
+uniform lowp float u_radius_t;
attribute mediump vec2 a_radius;
#else
uniform mediump float u_radius;
@@ -58,14 +77,14 @@ const highp float ZERO = 1.0 / 255.0 / 16.0;
void main(void) {
#ifndef HAS_UNIFORM_u_weight
- weight = unpack_mix_vec2(a_weight, a_weight_t);
+ weight = unpack_mix_vec2(a_weight, u_weight_t);
#else
highp float weight = u_weight;
#endif
#ifndef HAS_UNIFORM_u_radius
- mediump float radius = unpack_mix_vec2(a_radius, a_radius_t);
+ mediump float radius = unpack_mix_vec2(a_radius, u_radius_t);
#else
mediump float radius = u_radius;
#endif
diff --git a/src/mbgl/programs/gl/heatmap_texture.cpp b/src/mbgl/programs/gl/heatmap_texture.cpp
index 530e9fa18b..57b033d55c 100644
--- a/src/mbgl/programs/gl/heatmap_texture.cpp
+++ b/src/mbgl/programs/gl/heatmap_texture.cpp
@@ -1,18 +1,37 @@
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
#include <mbgl/programs/heatmap_texture_program.hpp>
+#include <mbgl/programs/gl/preludes.hpp>
#include <mbgl/programs/gl/shader_source.hpp>
#include <mbgl/gl/program.hpp>
namespace mbgl {
+namespace programs {
+namespace gl {
+
+template <typename>
+struct ShaderSource;
+
+template <>
+struct ShaderSource<HeatmapTextureProgram> {
+ static constexpr const char* name = "heatmap_texture";
+ static constexpr const uint8_t hash[8] = { 0x9f, 0xc7, 0x56, 0xb2, 0x9e, 0x8f, 0x15, 0xff };
+ static constexpr const auto vertexOffset = 9491;
+ static constexpr const auto fragmentOffset = 9671;
+};
+
+constexpr const char* ShaderSource<HeatmapTextureProgram>::name;
+constexpr const uint8_t ShaderSource<HeatmapTextureProgram>::hash[8];
+
+} // namespace gl
+} // namespace programs
+
namespace gfx {
template <>
std::unique_ptr<Program<HeatmapTextureProgram>>
Context::createProgram<gl::Context>(const ProgramParameters& programParameters) {
- return gl::Program<HeatmapTextureProgram>::createProgram(
- reinterpret_cast<gl::Context&>(*this), programParameters, "heatmap_texture",
- programs::gl::shaderSource() + 9491, programs::gl::shaderSource() + 9671);
+ return std::make_unique<gl::Program<HeatmapTextureProgram>>(programParameters);
}
} // namespace gfx
diff --git a/src/mbgl/programs/gl/hillshade.cpp b/src/mbgl/programs/gl/hillshade.cpp
index dcf90f1149..a33ddb4326 100644
--- a/src/mbgl/programs/gl/hillshade.cpp
+++ b/src/mbgl/programs/gl/hillshade.cpp
@@ -1,18 +1,37 @@
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
#include <mbgl/programs/hillshade_program.hpp>
+#include <mbgl/programs/gl/preludes.hpp>
#include <mbgl/programs/gl/shader_source.hpp>
#include <mbgl/gl/program.hpp>
namespace mbgl {
+namespace programs {
+namespace gl {
+
+template <typename>
+struct ShaderSource;
+
+template <>
+struct ShaderSource<HillshadeProgram> {
+ static constexpr const char* name = "hillshade";
+ static constexpr const uint8_t hash[8] = { 0x8a, 0x11, 0x29, 0x18, 0x52, 0x7f, 0x3b, 0xbb };
+ static constexpr const auto vertexOffset = 29340;
+ static constexpr const auto fragmentOffset = 29511;
+};
+
+constexpr const char* ShaderSource<HillshadeProgram>::name;
+constexpr const uint8_t ShaderSource<HillshadeProgram>::hash[8];
+
+} // namespace gl
+} // namespace programs
+
namespace gfx {
template <>
std::unique_ptr<Program<HillshadeProgram>>
Context::createProgram<gl::Context>(const ProgramParameters& programParameters) {
- return gl::Program<HillshadeProgram>::createProgram(
- reinterpret_cast<gl::Context&>(*this), programParameters, "hillshade",
- programs::gl::shaderSource() + 29340, programs::gl::shaderSource() + 29511);
+ return std::make_unique<gl::Program<HillshadeProgram>>(programParameters);
}
} // namespace gfx
diff --git a/src/mbgl/programs/gl/hillshade_prepare.cpp b/src/mbgl/programs/gl/hillshade_prepare.cpp
index b445713530..a302db5feb 100644
--- a/src/mbgl/programs/gl/hillshade_prepare.cpp
+++ b/src/mbgl/programs/gl/hillshade_prepare.cpp
@@ -1,18 +1,37 @@
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
#include <mbgl/programs/hillshade_prepare_program.hpp>
+#include <mbgl/programs/gl/preludes.hpp>
#include <mbgl/programs/gl/shader_source.hpp>
#include <mbgl/gl/program.hpp>
namespace mbgl {
+namespace programs {
+namespace gl {
+
+template <typename>
+struct ShaderSource;
+
+template <>
+struct ShaderSource<HillshadePrepareProgram> {
+ static constexpr const char* name = "hillshade_prepare";
+ static constexpr const uint8_t hash[8] = { 0xe6, 0x01, 0xf2, 0xbb, 0xa0, 0x77, 0x1d, 0xeb };
+ static constexpr const auto vertexOffset = 27925;
+ static constexpr const auto fragmentOffset = 28218;
+};
+
+constexpr const char* ShaderSource<HillshadePrepareProgram>::name;
+constexpr const uint8_t ShaderSource<HillshadePrepareProgram>::hash[8];
+
+} // namespace gl
+} // namespace programs
+
namespace gfx {
template <>
std::unique_ptr<Program<HillshadePrepareProgram>>
Context::createProgram<gl::Context>(const ProgramParameters& programParameters) {
- return gl::Program<HillshadePrepareProgram>::createProgram(
- reinterpret_cast<gl::Context&>(*this), programParameters, "hillshade_prepare",
- programs::gl::shaderSource() + 27925, programs::gl::shaderSource() + 28218);
+ return std::make_unique<gl::Program<HillshadePrepareProgram>>(programParameters);
}
} // namespace gfx
diff --git a/src/mbgl/programs/gl/line.cpp b/src/mbgl/programs/gl/line.cpp
index c25679ae1f..e59cb07cb9 100644
--- a/src/mbgl/programs/gl/line.cpp
+++ b/src/mbgl/programs/gl/line.cpp
@@ -1,18 +1,37 @@
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
#include <mbgl/programs/line_program.hpp>
+#include <mbgl/programs/gl/preludes.hpp>
#include <mbgl/programs/gl/shader_source.hpp>
#include <mbgl/gl/program.hpp>
namespace mbgl {
+namespace programs {
+namespace gl {
+
+template <typename>
+struct ShaderSource;
+
+template <>
+struct ShaderSource<LineProgram> {
+ static constexpr const char* name = "line";
+ static constexpr const uint8_t hash[8] = { 0x44, 0x46, 0x9e, 0x59, 0x02, 0xbb, 0xaa, 0xae };
+ static constexpr const auto vertexOffset = 30585;
+ static constexpr const auto fragmentOffset = 33509;
+};
+
+constexpr const char* ShaderSource<LineProgram>::name;
+constexpr const uint8_t ShaderSource<LineProgram>::hash[8];
+
+} // namespace gl
+} // namespace programs
+
namespace gfx {
template <>
std::unique_ptr<Program<LineProgram>>
Context::createProgram<gl::Context>(const ProgramParameters& programParameters) {
- return gl::Program<LineProgram>::createProgram(
- reinterpret_cast<gl::Context&>(*this), programParameters, "line",
- programs::gl::shaderSource() + 30585, programs::gl::shaderSource() + 33509);
+ return std::make_unique<gl::Program<LineProgram>>(programParameters);
}
} // namespace gfx
@@ -48,7 +67,7 @@ varying highp float v_linesofar;
#ifndef HAS_UNIFORM_u_color
-uniform lowp float a_color_t;
+uniform lowp float u_color_t;
attribute highp vec4 a_color;
varying highp vec4 color;
#else
@@ -57,7 +76,7 @@ uniform highp vec4 u_color;
#ifndef HAS_UNIFORM_u_blur
-uniform lowp float a_blur_t;
+uniform lowp float u_blur_t;
attribute lowp vec2 a_blur;
varying lowp float blur;
#else
@@ -66,7 +85,7 @@ uniform lowp float u_blur;
#ifndef HAS_UNIFORM_u_opacity
-uniform lowp float a_opacity_t;
+uniform lowp float u_opacity_t;
attribute lowp vec2 a_opacity;
varying lowp float opacity;
#else
@@ -75,7 +94,7 @@ uniform lowp float u_opacity;
#ifndef HAS_UNIFORM_u_gapwidth
-uniform lowp float a_gapwidth_t;
+uniform lowp float u_gapwidth_t;
attribute mediump vec2 a_gapwidth;
#else
uniform mediump float u_gapwidth;
@@ -83,7 +102,7 @@ uniform mediump float u_gapwidth;
#ifndef HAS_UNIFORM_u_offset
-uniform lowp float a_offset_t;
+uniform lowp float u_offset_t;
attribute lowp vec2 a_offset;
#else
uniform lowp float u_offset;
@@ -91,7 +110,7 @@ uniform lowp float u_offset;
#ifndef HAS_UNIFORM_u_width
-uniform lowp float a_width_t;
+uniform lowp float u_width_t;
attribute mediump vec2 a_width;
#else
uniform mediump float u_width;
@@ -101,42 +120,42 @@ uniform mediump float u_width;
void main() {
#ifndef HAS_UNIFORM_u_color
- color = unpack_mix_color(a_color, a_color_t);
+ color = unpack_mix_color(a_color, u_color_t);
#else
highp vec4 color = u_color;
#endif
#ifndef HAS_UNIFORM_u_blur
- blur = unpack_mix_vec2(a_blur, a_blur_t);
+ blur = unpack_mix_vec2(a_blur, u_blur_t);
#else
lowp float blur = u_blur;
#endif
#ifndef HAS_UNIFORM_u_opacity
- opacity = unpack_mix_vec2(a_opacity, a_opacity_t);
+ opacity = unpack_mix_vec2(a_opacity, u_opacity_t);
#else
lowp float opacity = u_opacity;
#endif
#ifndef HAS_UNIFORM_u_gapwidth
- mediump float gapwidth = unpack_mix_vec2(a_gapwidth, a_gapwidth_t);
+ mediump float gapwidth = unpack_mix_vec2(a_gapwidth, u_gapwidth_t);
#else
mediump float gapwidth = u_gapwidth;
#endif
#ifndef HAS_UNIFORM_u_offset
- lowp float offset = unpack_mix_vec2(a_offset, a_offset_t);
+ lowp float offset = unpack_mix_vec2(a_offset, u_offset_t);
#else
lowp float offset = u_offset;
#endif
#ifndef HAS_UNIFORM_u_width
- mediump float width = unpack_mix_vec2(a_width, a_width_t);
+ mediump float width = unpack_mix_vec2(a_width, u_width_t);
#else
mediump float width = u_width;
#endif
diff --git a/src/mbgl/programs/gl/line_gradient.cpp b/src/mbgl/programs/gl/line_gradient.cpp
index fae94b4596..f5325f84ba 100644
--- a/src/mbgl/programs/gl/line_gradient.cpp
+++ b/src/mbgl/programs/gl/line_gradient.cpp
@@ -1,18 +1,37 @@
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
#include <mbgl/programs/line_gradient_program.hpp>
+#include <mbgl/programs/gl/preludes.hpp>
#include <mbgl/programs/gl/shader_source.hpp>
#include <mbgl/gl/program.hpp>
namespace mbgl {
+namespace programs {
+namespace gl {
+
+template <typename>
+struct ShaderSource;
+
+template <>
+struct ShaderSource<LineGradientProgram> {
+ static constexpr const char* name = "line_gradient";
+ static constexpr const uint8_t hash[8] = { 0xee, 0xdd, 0x10, 0x3d, 0x1a, 0x21, 0x26, 0x25 };
+ static constexpr const auto vertexOffset = 34335;
+ static constexpr const auto fragmentOffset = 37054;
+};
+
+constexpr const char* ShaderSource<LineGradientProgram>::name;
+constexpr const uint8_t ShaderSource<LineGradientProgram>::hash[8];
+
+} // namespace gl
+} // namespace programs
+
namespace gfx {
template <>
std::unique_ptr<Program<LineGradientProgram>>
Context::createProgram<gl::Context>(const ProgramParameters& programParameters) {
- return gl::Program<LineGradientProgram>::createProgram(
- reinterpret_cast<gl::Context&>(*this), programParameters, "line_gradient",
- programs::gl::shaderSource() + 34335, programs::gl::shaderSource() + 37054);
+ return std::make_unique<gl::Program<LineGradientProgram>>(programParameters);
}
} // namespace gfx
@@ -50,7 +69,7 @@ varying highp float v_lineprogress;
#ifndef HAS_UNIFORM_u_blur
-uniform lowp float a_blur_t;
+uniform lowp float u_blur_t;
attribute lowp vec2 a_blur;
varying lowp float blur;
#else
@@ -59,7 +78,7 @@ uniform lowp float u_blur;
#ifndef HAS_UNIFORM_u_opacity
-uniform lowp float a_opacity_t;
+uniform lowp float u_opacity_t;
attribute lowp vec2 a_opacity;
varying lowp float opacity;
#else
@@ -68,7 +87,7 @@ uniform lowp float u_opacity;
#ifndef HAS_UNIFORM_u_gapwidth
-uniform lowp float a_gapwidth_t;
+uniform lowp float u_gapwidth_t;
attribute mediump vec2 a_gapwidth;
#else
uniform mediump float u_gapwidth;
@@ -76,7 +95,7 @@ uniform mediump float u_gapwidth;
#ifndef HAS_UNIFORM_u_offset
-uniform lowp float a_offset_t;
+uniform lowp float u_offset_t;
attribute lowp vec2 a_offset;
#else
uniform lowp float u_offset;
@@ -84,7 +103,7 @@ uniform lowp float u_offset;
#ifndef HAS_UNIFORM_u_width
-uniform lowp float a_width_t;
+uniform lowp float u_width_t;
attribute mediump vec2 a_width;
#else
uniform mediump float u_width;
@@ -94,35 +113,35 @@ uniform mediump float u_width;
void main() {
#ifndef HAS_UNIFORM_u_blur
- blur = unpack_mix_vec2(a_blur, a_blur_t);
+ blur = unpack_mix_vec2(a_blur, u_blur_t);
#else
lowp float blur = u_blur;
#endif
#ifndef HAS_UNIFORM_u_opacity
- opacity = unpack_mix_vec2(a_opacity, a_opacity_t);
+ opacity = unpack_mix_vec2(a_opacity, u_opacity_t);
#else
lowp float opacity = u_opacity;
#endif
#ifndef HAS_UNIFORM_u_gapwidth
- mediump float gapwidth = unpack_mix_vec2(a_gapwidth, a_gapwidth_t);
+ mediump float gapwidth = unpack_mix_vec2(a_gapwidth, u_gapwidth_t);
#else
mediump float gapwidth = u_gapwidth;
#endif
#ifndef HAS_UNIFORM_u_offset
- lowp float offset = unpack_mix_vec2(a_offset, a_offset_t);
+ lowp float offset = unpack_mix_vec2(a_offset, u_offset_t);
#else
lowp float offset = u_offset;
#endif
#ifndef HAS_UNIFORM_u_width
- mediump float width = unpack_mix_vec2(a_width, a_width_t);
+ mediump float width = unpack_mix_vec2(a_width, u_width_t);
#else
mediump float width = u_width;
#endif
diff --git a/src/mbgl/programs/gl/line_pattern.cpp b/src/mbgl/programs/gl/line_pattern.cpp
index 2e9ebaf5ea..e323b16785 100644
--- a/src/mbgl/programs/gl/line_pattern.cpp
+++ b/src/mbgl/programs/gl/line_pattern.cpp
@@ -1,18 +1,37 @@
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
#include <mbgl/programs/line_pattern_program.hpp>
+#include <mbgl/programs/gl/preludes.hpp>
#include <mbgl/programs/gl/shader_source.hpp>
#include <mbgl/gl/program.hpp>
namespace mbgl {
+namespace programs {
+namespace gl {
+
+template <typename>
+struct ShaderSource;
+
+template <>
+struct ShaderSource<LinePatternProgram> {
+ static constexpr const char* name = "line_pattern";
+ static constexpr const uint8_t hash[8] = { 0x73, 0xa0, 0x59, 0x46, 0x57, 0xa5, 0x60, 0x25 };
+ static constexpr const auto vertexOffset = 37841;
+ static constexpr const auto fragmentOffset = 41162;
+};
+
+constexpr const char* ShaderSource<LinePatternProgram>::name;
+constexpr const uint8_t ShaderSource<LinePatternProgram>::hash[8];
+
+} // namespace gl
+} // namespace programs
+
namespace gfx {
template <>
std::unique_ptr<Program<LinePatternProgram>>
Context::createProgram<gl::Context>(const ProgramParameters& programParameters) {
- return gl::Program<LinePatternProgram>::createProgram(
- reinterpret_cast<gl::Context&>(*this), programParameters, "line_pattern",
- programs::gl::shaderSource() + 37841, programs::gl::shaderSource() + 41162);
+ return std::make_unique<gl::Program<LinePatternProgram>>(programParameters);
}
} // namespace gfx
@@ -50,7 +69,7 @@ varying float v_gamma_scale;
#ifndef HAS_UNIFORM_u_blur
-uniform lowp float a_blur_t;
+uniform lowp float u_blur_t;
attribute lowp vec2 a_blur;
varying lowp float blur;
#else
@@ -59,7 +78,7 @@ uniform lowp float u_blur;
#ifndef HAS_UNIFORM_u_opacity
-uniform lowp float a_opacity_t;
+uniform lowp float u_opacity_t;
attribute lowp vec2 a_opacity;
varying lowp float opacity;
#else
@@ -68,7 +87,7 @@ uniform lowp float u_opacity;
#ifndef HAS_UNIFORM_u_offset
-uniform lowp float a_offset_t;
+uniform lowp float u_offset_t;
attribute lowp vec2 a_offset;
#else
uniform lowp float u_offset;
@@ -76,7 +95,7 @@ uniform lowp float u_offset;
#ifndef HAS_UNIFORM_u_gapwidth
-uniform lowp float a_gapwidth_t;
+uniform lowp float u_gapwidth_t;
attribute mediump vec2 a_gapwidth;
#else
uniform mediump float u_gapwidth;
@@ -84,7 +103,7 @@ uniform mediump float u_gapwidth;
#ifndef HAS_UNIFORM_u_width
-uniform lowp float a_width_t;
+uniform lowp float u_width_t;
attribute mediump vec2 a_width;
#else
uniform mediump float u_width;
@@ -92,7 +111,7 @@ uniform mediump float u_width;
#ifndef HAS_UNIFORM_u_pattern_from
-uniform lowp float a_pattern_from_t;
+uniform lowp float u_pattern_from_t;
attribute lowp vec4 a_pattern_from;
varying lowp vec4 pattern_from;
#else
@@ -101,7 +120,7 @@ uniform lowp vec4 u_pattern_from;
#ifndef HAS_UNIFORM_u_pattern_to
-uniform lowp float a_pattern_to_t;
+uniform lowp float u_pattern_to_t;
attribute lowp vec4 a_pattern_to;
varying lowp vec4 pattern_to;
#else
@@ -112,35 +131,35 @@ uniform lowp vec4 u_pattern_to;
void main() {
#ifndef HAS_UNIFORM_u_blur
- blur = unpack_mix_vec2(a_blur, a_blur_t);
+ blur = unpack_mix_vec2(a_blur, u_blur_t);
#else
lowp float blur = u_blur;
#endif
#ifndef HAS_UNIFORM_u_opacity
- opacity = unpack_mix_vec2(a_opacity, a_opacity_t);
+ opacity = unpack_mix_vec2(a_opacity, u_opacity_t);
#else
lowp float opacity = u_opacity;
#endif
#ifndef HAS_UNIFORM_u_offset
- lowp float offset = unpack_mix_vec2(a_offset, a_offset_t);
+ lowp float offset = unpack_mix_vec2(a_offset, u_offset_t);
#else
lowp float offset = u_offset;
#endif
#ifndef HAS_UNIFORM_u_gapwidth
- mediump float gapwidth = unpack_mix_vec2(a_gapwidth, a_gapwidth_t);
+ mediump float gapwidth = unpack_mix_vec2(a_gapwidth, u_gapwidth_t);
#else
mediump float gapwidth = u_gapwidth;
#endif
#ifndef HAS_UNIFORM_u_width
- mediump float width = unpack_mix_vec2(a_width, a_width_t);
+ mediump float width = unpack_mix_vec2(a_width, u_width_t);
#else
mediump float width = u_width;
#endif
diff --git a/src/mbgl/programs/gl/line_sdf.cpp b/src/mbgl/programs/gl/line_sdf.cpp
index 0886bfcdf0..a7b4e7e3b7 100644
--- a/src/mbgl/programs/gl/line_sdf.cpp
+++ b/src/mbgl/programs/gl/line_sdf.cpp
@@ -1,18 +1,37 @@
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
#include <mbgl/programs/line_sdf_program.hpp>
+#include <mbgl/programs/gl/preludes.hpp>
#include <mbgl/programs/gl/shader_source.hpp>
#include <mbgl/gl/program.hpp>
namespace mbgl {
+namespace programs {
+namespace gl {
+
+template <typename>
+struct ShaderSource;
+
+template <>
+struct ShaderSource<LineSDFProgram> {
+ static constexpr const char* name = "line_sdf";
+ static constexpr const uint8_t hash[8] = { 0x66, 0x20, 0x75, 0x4e, 0xbe, 0x02, 0x9e, 0x67 };
+ static constexpr const auto vertexOffset = 43475;
+ static constexpr const auto fragmentOffset = 47089;
+};
+
+constexpr const char* ShaderSource<LineSDFProgram>::name;
+constexpr const uint8_t ShaderSource<LineSDFProgram>::hash[8];
+
+} // namespace gl
+} // namespace programs
+
namespace gfx {
template <>
std::unique_ptr<Program<LineSDFProgram>>
Context::createProgram<gl::Context>(const ProgramParameters& programParameters) {
- return gl::Program<LineSDFProgram>::createProgram(
- reinterpret_cast<gl::Context&>(*this), programParameters, "line_sdf",
- programs::gl::shaderSource() + 43475, programs::gl::shaderSource() + 47089);
+ return std::make_unique<gl::Program<LineSDFProgram>>(programParameters);
}
} // namespace gfx
@@ -55,7 +74,7 @@ varying float v_gamma_scale;
#ifndef HAS_UNIFORM_u_color
-uniform lowp float a_color_t;
+uniform lowp float u_color_t;
attribute highp vec4 a_color;
varying highp vec4 color;
#else
@@ -64,7 +83,7 @@ uniform highp vec4 u_color;
#ifndef HAS_UNIFORM_u_blur
-uniform lowp float a_blur_t;
+uniform lowp float u_blur_t;
attribute lowp vec2 a_blur;
varying lowp float blur;
#else
@@ -73,7 +92,7 @@ uniform lowp float u_blur;
#ifndef HAS_UNIFORM_u_opacity
-uniform lowp float a_opacity_t;
+uniform lowp float u_opacity_t;
attribute lowp vec2 a_opacity;
varying lowp float opacity;
#else
@@ -82,7 +101,7 @@ uniform lowp float u_opacity;
#ifndef HAS_UNIFORM_u_gapwidth
-uniform lowp float a_gapwidth_t;
+uniform lowp float u_gapwidth_t;
attribute mediump vec2 a_gapwidth;
#else
uniform mediump float u_gapwidth;
@@ -90,7 +109,7 @@ uniform mediump float u_gapwidth;
#ifndef HAS_UNIFORM_u_offset
-uniform lowp float a_offset_t;
+uniform lowp float u_offset_t;
attribute lowp vec2 a_offset;
#else
uniform lowp float u_offset;
@@ -98,7 +117,7 @@ uniform lowp float u_offset;
#ifndef HAS_UNIFORM_u_width
-uniform lowp float a_width_t;
+uniform lowp float u_width_t;
attribute mediump vec2 a_width;
varying mediump float width;
#else
@@ -107,7 +126,7 @@ uniform mediump float u_width;
#ifndef HAS_UNIFORM_u_floorwidth
-uniform lowp float a_floorwidth_t;
+uniform lowp float u_floorwidth_t;
attribute lowp vec2 a_floorwidth;
varying lowp float floorwidth;
#else
@@ -118,49 +137,49 @@ uniform lowp float u_floorwidth;
void main() {
#ifndef HAS_UNIFORM_u_color
- color = unpack_mix_color(a_color, a_color_t);
+ color = unpack_mix_color(a_color, u_color_t);
#else
highp vec4 color = u_color;
#endif
#ifndef HAS_UNIFORM_u_blur
- blur = unpack_mix_vec2(a_blur, a_blur_t);
+ blur = unpack_mix_vec2(a_blur, u_blur_t);
#else
lowp float blur = u_blur;
#endif
#ifndef HAS_UNIFORM_u_opacity
- opacity = unpack_mix_vec2(a_opacity, a_opacity_t);
+ opacity = unpack_mix_vec2(a_opacity, u_opacity_t);
#else
lowp float opacity = u_opacity;
#endif
#ifndef HAS_UNIFORM_u_gapwidth
- mediump float gapwidth = unpack_mix_vec2(a_gapwidth, a_gapwidth_t);
+ mediump float gapwidth = unpack_mix_vec2(a_gapwidth, u_gapwidth_t);
#else
mediump float gapwidth = u_gapwidth;
#endif
#ifndef HAS_UNIFORM_u_offset
- lowp float offset = unpack_mix_vec2(a_offset, a_offset_t);
+ lowp float offset = unpack_mix_vec2(a_offset, u_offset_t);
#else
lowp float offset = u_offset;
#endif
#ifndef HAS_UNIFORM_u_width
- width = unpack_mix_vec2(a_width, a_width_t);
+ width = unpack_mix_vec2(a_width, u_width_t);
#else
mediump float width = u_width;
#endif
#ifndef HAS_UNIFORM_u_floorwidth
- floorwidth = unpack_mix_vec2(a_floorwidth, a_floorwidth_t);
+ floorwidth = unpack_mix_vec2(a_floorwidth, u_floorwidth_t);
#else
lowp float floorwidth = u_floorwidth;
#endif
diff --git a/src/mbgl/programs/gl/preludes.cpp b/src/mbgl/programs/gl/preludes.cpp
deleted file mode 100644
index 6c895c0d36..0000000000
--- a/src/mbgl/programs/gl/preludes.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
-
-#include <mbgl/programs/gl/preludes.hpp>
-#include <mbgl/programs/gl/shader_source.hpp>
-
-namespace mbgl {
-namespace programs {
-namespace gl {
-
-const char* vertexShaderPrelude = programs::gl::shaderSource() + 0;
-const char* fragmentShaderPrelude = programs::gl::shaderSource() + 1252;
-
-} // namespace gl
-} // namespace programs
-} // namespace mbgl
diff --git a/src/mbgl/programs/gl/preludes.hpp b/src/mbgl/programs/gl/preludes.hpp
index 6d86ee45c5..e796f1655b 100644
--- a/src/mbgl/programs/gl/preludes.hpp
+++ b/src/mbgl/programs/gl/preludes.hpp
@@ -2,12 +2,15 @@
#pragma once
+#include <cstdint>
+
namespace mbgl {
namespace programs {
namespace gl {
-extern const char* vertexShaderPrelude;
-extern const char* fragmentShaderPrelude;
+constexpr const uint8_t preludeHash[8] = { 0x24, 0x91, 0x82, 0x37, 0x02, 0xad, 0x98, 0x0a };
+constexpr const auto vertexPreludeOffset = 0;
+constexpr const auto fragmentPreludeOffset = 1252;
} // namespace gl
} // namespace programs
diff --git a/src/mbgl/programs/gl/raster.cpp b/src/mbgl/programs/gl/raster.cpp
index 512dc81a30..1867a48f1c 100644
--- a/src/mbgl/programs/gl/raster.cpp
+++ b/src/mbgl/programs/gl/raster.cpp
@@ -1,18 +1,37 @@
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
#include <mbgl/programs/raster_program.hpp>
+#include <mbgl/programs/gl/preludes.hpp>
#include <mbgl/programs/gl/shader_source.hpp>
#include <mbgl/gl/program.hpp>
namespace mbgl {
+namespace programs {
+namespace gl {
+
+template <typename>
+struct ShaderSource;
+
+template <>
+struct ShaderSource<RasterProgram> {
+ static constexpr const char* name = "raster";
+ static constexpr const uint8_t hash[8] = { 0x40, 0x3d, 0x6c, 0xf4, 0xd0, 0x41, 0x51, 0x0e };
+ static constexpr const auto vertexOffset = 48592;
+ static constexpr const auto fragmentOffset = 48941;
+};
+
+constexpr const char* ShaderSource<RasterProgram>::name;
+constexpr const uint8_t ShaderSource<RasterProgram>::hash[8];
+
+} // namespace gl
+} // namespace programs
+
namespace gfx {
template <>
std::unique_ptr<Program<RasterProgram>>
Context::createProgram<gl::Context>(const ProgramParameters& programParameters) {
- return gl::Program<RasterProgram>::createProgram(
- reinterpret_cast<gl::Context&>(*this), programParameters, "raster",
- programs::gl::shaderSource() + 48592, programs::gl::shaderSource() + 48941);
+ return std::make_unique<gl::Program<RasterProgram>>(programParameters);
}
} // namespace gfx
diff --git a/src/mbgl/programs/gl/shader_source.cpp b/src/mbgl/programs/gl/shader_source.cpp
index 4a986403f7..00e70f749a 100644
--- a/src/mbgl/programs/gl/shader_source.cpp
+++ b/src/mbgl/programs/gl/shader_source.cpp
@@ -70,395 +70,395 @@ constexpr const uint8_t compressedShaderSource[] = {
0x3a, 0x0f, 0xf2, 0x3e, 0x9e, 0xa4, 0xf3, 0x18, 0x26, 0x4d, 0x2f, 0x9d, 0xa2, 0x4e, 0xec, 0xf6,
0x47, 0x8b, 0x3c, 0x9e, 0xf6, 0x52, 0xb3, 0x64, 0x82, 0x06, 0x4f, 0xa1, 0xc5, 0xff, 0x7d, 0x72,
0xd1, 0xfd, 0xfd, 0xcb, 0xd9, 0xe7, 0xaf, 0xdf, 0x7e, 0xed, 0x52, 0xd9, 0x7f, 0xc0, 0x6a, 0x80,
- 0xc5, 0x91, 0x56, 0x10, 0x93, 0xac, 0x6e, 0x2e, 0xa1, 0x23, 0x04, 0xe0, 0xe1, 0xa0, 0xd9, 0x9c,
- 0x7b, 0xa5, 0x2c, 0x92, 0x41, 0x57, 0x62, 0x95, 0x76, 0x65, 0xa9, 0x92, 0x16, 0x56, 0x03, 0x61,
- 0xf3, 0x18, 0xad, 0xbe, 0x0b, 0x33, 0x65, 0x24, 0x4f, 0x21, 0x8d, 0xa9, 0x01, 0xb4, 0xc5, 0x04,
- 0x82, 0x53, 0xa7, 0x28, 0x09, 0x35, 0x9a, 0xa9, 0x51, 0xa8, 0xc2, 0x30, 0x02, 0xd6, 0x50, 0x99,
- 0x8c, 0xaf, 0x2c, 0xbd, 0x07, 0x39, 0x0a, 0x85, 0x38, 0x97, 0x92, 0x07, 0x99, 0x9c, 0x38, 0xa9,
- 0x18, 0x4e, 0xd7, 0xe8, 0x92, 0xb2, 0x49, 0x7d, 0x6b, 0x48, 0xa2, 0x1c, 0x6e, 0xa6, 0x8a, 0x66,
- 0x5a, 0x09, 0xe3, 0xea, 0x42, 0x91, 0x36, 0x31, 0x73, 0xec, 0xe4, 0x49, 0x30, 0x25, 0x14, 0x2e,
- 0xf2, 0x79, 0xf6, 0xef, 0xb4, 0x8c, 0xf5, 0x64, 0x08, 0x3b, 0x07, 0xca, 0x50, 0x26, 0x46, 0x54,
- 0xf2, 0xcb, 0xf8, 0x51, 0x07, 0x5c, 0x4f, 0xfb, 0xcd, 0xa8, 0x9f, 0x0f, 0x4b, 0x69, 0xc7, 0x10,
- 0x65, 0x2c, 0x2a, 0xc3, 0x59, 0x18, 0x55, 0x01, 0x59, 0xc3, 0xae, 0x3a, 0xec, 0xfa, 0x36, 0x94,
- 0x32, 0x8a, 0x0a, 0x63, 0xe5, 0x17, 0x15, 0xcc, 0xc4, 0x36, 0x1a, 0x44, 0x19, 0xf7, 0x14, 0x41,
- 0x89, 0xbb, 0x40, 0x2c, 0x90, 0x87, 0x68, 0x81, 0xec, 0xc7, 0x79, 0x2c, 0xad, 0x8f, 0xf0, 0x0b,
- 0xad, 0x91, 0xa5, 0xe2, 0xad, 0x47, 0x14, 0x5d, 0xdd, 0xc4, 0xa4, 0x32, 0xcc, 0xe7, 0xa2, 0xce,
- 0x65, 0xe4, 0xe9, 0xd2, 0x2c, 0xda, 0x48, 0x66, 0x91, 0x3f, 0x91, 0x6e, 0x3b, 0x33, 0xa9, 0xe4,
- 0x0b, 0x01, 0xc6, 0x2b, 0x34, 0x09, 0xa8, 0x68, 0x13, 0x19, 0x04, 0xff, 0x18, 0x6a, 0x84, 0x64,
- 0x9f, 0x09, 0x23, 0x5e, 0x9b, 0x26, 0x71, 0xa2, 0x8d, 0xe4, 0x0a, 0xfd, 0x6b, 0xa8, 0x8c, 0xe6,
- 0xf8, 0x92, 0x98, 0x31, 0x55, 0xc9, 0x11, 0x6c, 0x23, 0x2e, 0xe4, 0x0f, 0xd3, 0x88, 0xca, 0xf9,
- 0xbe, 0x2e, 0x48, 0x4c, 0xe3, 0xab, 0x22, 0xdc, 0x5a, 0x14, 0xc8, 0x1f, 0x86, 0xae, 0x91, 0xb3,
- 0x7d, 0x5d, 0x46, 0x58, 0xb8, 0x40, 0x45, 0x79, 0x8f, 0x09, 0xae, 0x7e, 0xda, 0xa9, 0x13, 0xe3,
- 0xa7, 0xcf, 0x7e, 0xd3, 0x30, 0xea, 0x58, 0xad, 0xd3, 0x17, 0xfb, 0xac, 0x88, 0x42, 0x13, 0xe1,
- 0x0a, 0x41, 0x5d, 0x24, 0x76, 0x0d, 0xb8, 0xbb, 0x3c, 0xf4, 0x4f, 0x43, 0x68, 0x8d, 0xbd, 0xd1,
- 0xbc, 0x87, 0xf4, 0x26, 0xa2, 0xd3, 0x44, 0xa8, 0x2a, 0x3c, 0xac, 0x08, 0xd8, 0x6b, 0x35, 0x8f,
- 0xdd, 0x10, 0x19, 0xe1, 0x8e, 0xae, 0x3d, 0x31, 0x15, 0xb9, 0x97, 0xcd, 0xa7, 0x48, 0x0f, 0x9a,
- 0x31, 0x4b, 0x4a, 0x41, 0x45, 0x4b, 0xaa, 0x5a, 0x19, 0x2a, 0xa9, 0x15, 0xaa, 0x47, 0x94, 0x54,
- 0xcf, 0x21, 0x93, 0xaf, 0x2e, 0xf7, 0x3b, 0x68, 0x90, 0xaa, 0x6e, 0x76, 0x57, 0x83, 0x7e, 0xa1,
- 0x6e, 0xa8, 0xd9, 0x3c, 0xfb, 0x57, 0xda, 0xcb, 0xd3, 0x3e, 0x23, 0x5f, 0xb5, 0xe5, 0x14, 0x7a,
- 0x88, 0x4d, 0x77, 0xbf, 0xda, 0x3d, 0x47, 0xaf, 0xb1, 0x79, 0x13, 0x94, 0x68, 0x86, 0xc8, 0xa2,
- 0xb2, 0x5b, 0x9a, 0x1a, 0x29, 0xd4, 0xcd, 0x40, 0x9b, 0x57, 0x52, 0xac, 0xd8, 0x28, 0x4b, 0x4f,
- 0x4b, 0x38, 0x9a, 0xcb, 0xd5, 0xa6, 0x4d, 0x2d, 0x53, 0x78, 0x0d, 0x54, 0x6e, 0x51, 0x83, 0x5c,
- 0xfa, 0x26, 0xbc, 0xbb, 0x93, 0xd7, 0xc3, 0x69, 0x3e, 0x8a, 0xc7, 0xa3, 0x78, 0x81, 0xc5, 0x25,
- 0x62, 0xd6, 0xe0, 0xd3, 0xe9, 0x1f, 0x67, 0x1f, 0x4f, 0xbb, 0xe7, 0x67, 0x7f, 0x9e, 0xfe, 0xd2,
- 0xfd, 0x76, 0xf2, 0xdb, 0xd9, 0xd7, 0xc0, 0x58, 0x4b, 0x48, 0x16, 0x2c, 0x60, 0xfc, 0x43, 0x87,
- 0xd6, 0xd7, 0x5c, 0xfa, 0xec, 0x17, 0x9a, 0x6c, 0x32, 0x6a, 0x97, 0x3a, 0xba, 0xac, 0x2b, 0xd9,
- 0x63, 0xab, 0xdb, 0xbb, 0x51, 0x98, 0x1f, 0x59, 0xf3, 0xdd, 0x9d, 0xf2, 0xfa, 0x14, 0x4a, 0xe7,
- 0x53, 0xaa, 0x8a, 0x4f, 0xa0, 0xdf, 0x51, 0xdd, 0xce, 0x36, 0x21, 0xaa, 0x68, 0x6a, 0x56, 0x6e,
- 0xaf, 0xac, 0x75, 0x59, 0xf8, 0x78, 0xbd, 0x1e, 0x65, 0x67, 0xd2, 0xaa, 0x0a, 0xd1, 0x1a, 0x0e,
- 0xdc, 0x5c, 0x93, 0x59, 0xc3, 0x5e, 0x5b, 0xe9, 0x20, 0x6b, 0x19, 0xe7, 0xde, 0x7a, 0x03, 0x66,
- 0x0b, 0x24, 0xd4, 0x43, 0x82, 0x84, 0x49, 0xee, 0x71, 0x3a, 0x1d, 0x20, 0xca, 0xc8, 0x1f, 0x26,
- 0x5f, 0xdd, 0xd0, 0x2a, 0xba, 0x29, 0x9e, 0xdb, 0x50, 0xcb, 0x44, 0x0b, 0x28, 0xce, 0x6f, 0x4c,
- 0xe2, 0xa5, 0x43, 0x94, 0x66, 0x55, 0x2e, 0x2b, 0x23, 0xd5, 0xcd, 0xa3, 0xc5, 0x24, 0xcb, 0xf2,
- 0xe1, 0x22, 0x4f, 0x67, 0x4e, 0xab, 0xd9, 0xf2, 0x75, 0x44, 0xbe, 0x4a, 0x20, 0xd1, 0x6f, 0x08,
- 0x0e, 0xaa, 0x8b, 0x46, 0x72, 0x5f, 0xd6, 0xfe, 0x51, 0x43, 0x58, 0xda, 0xb5, 0x9f, 0xe0, 0x4f,
- 0xed, 0x43, 0x4d, 0xc2, 0x5e, 0xc0, 0x0c, 0xd5, 0x69, 0xd8, 0x09, 0xc3, 0x9a, 0x17, 0x20, 0xcd,
- 0x35, 0xc6, 0x5b, 0xe0, 0x71, 0x27, 0x99, 0xc7, 0xf4, 0x3e, 0x99, 0x63, 0x3c, 0x4d, 0x27, 0x94,
- 0x34, 0xe8, 0x7b, 0x38, 0xce, 0x1e, 0x7b, 0x4b, 0xc4, 0xbe, 0xcb, 0x21, 0xc8, 0xb1, 0xae, 0xb0,
- 0x37, 0x29, 0x9a, 0x4b, 0xb9, 0xd9, 0x1c, 0x26, 0x79, 0x66, 0x57, 0x44, 0x87, 0xe7, 0x6b, 0x4e,
- 0x08, 0x52, 0x98, 0x66, 0x19, 0x97, 0x02, 0x26, 0x19, 0x05, 0xcc, 0x63, 0x7b, 0xc4, 0x36, 0x5b,
- 0xc3, 0xcb, 0x1d, 0x9d, 0xac, 0x90, 0xd9, 0x5b, 0x69, 0x73, 0x8b, 0xb3, 0xf4, 0x11, 0xd2, 0xe1,
- 0xa6, 0x0b, 0xc8, 0xa9, 0xb2, 0x93, 0x42, 0xeb, 0x08, 0xc9, 0x0e, 0xa6, 0xdc, 0x7b, 0xff, 0x3c,
- 0xfd, 0xf6, 0x15, 0xab, 0x64, 0x78, 0xeb, 0x3a, 0x68, 0xbf, 0x69, 0xb6, 0x42, 0xbe, 0x31, 0xf7,
- 0xf3, 0xc9, 0xef, 0x17, 0x17, 0xdd, 0x8f, 0x5f, 0x4f, 0x3f, 0xa3, 0x99, 0x75, 0xf8, 0xfe, 0xdd,
- 0xfb, 0xa3, 0x4e, 0xe7, 0x5d, 0xeb, 0xa8, 0xd5, 0x3e, 0x3a, 0xec, 0xbc, 0x3d, 0xa8, 0xea, 0x45,
- 0xa0, 0x9c, 0x41, 0xfe, 0x18, 0xec, 0x27, 0x92, 0xe1, 0x0b, 0x36, 0xd1, 0x0c, 0x4d, 0x99, 0x11,
- 0xa2, 0xcd, 0x46, 0xdb, 0xbc, 0x44, 0x3d, 0xb8, 0x67, 0x81, 0x9e, 0x80, 0xc0, 0x23, 0xd8, 0xef,
- 0x56, 0xb2, 0xd6, 0x08, 0xc2, 0x8b, 0x68, 0xf1, 0xbf, 0xf3, 0xdc, 0x69, 0xa0, 0x64, 0x6f, 0x9c,
- 0x0d, 0x1c, 0x18, 0x8d, 0x80, 0x34, 0x30, 0x90, 0xc6, 0x38, 0x10, 0x03, 0xe1, 0xba, 0xc1, 0x21,
- 0x1a, 0x22, 0x3e, 0xa4, 0xd1, 0x85, 0xa7, 0x57, 0x1c, 0x6a, 0xb2, 0x9f, 0xe9, 0xf1, 0x84, 0xe8,
- 0x82, 0x0d, 0x46, 0x6c, 0xaf, 0x6c, 0x41, 0x26, 0xb9, 0x6e, 0x32, 0xd6, 0x29, 0x30, 0x11, 0x12,
- 0x46, 0x49, 0x02, 0xfc, 0xb6, 0x4e, 0x2c, 0x3c, 0xd0, 0xd4, 0x36, 0x03, 0x89, 0xb9, 0x60, 0x61,
- 0xfb, 0x8d, 0x19, 0xda, 0xaa, 0x36, 0xd1, 0xe6, 0x54, 0x61, 0x4c, 0x92, 0xdb, 0x8f, 0x1a, 0xa8,
- 0x1b, 0x3d, 0x34, 0x66, 0xf8, 0xff, 0x7e, 0x96, 0x3b, 0x9c, 0x2e, 0x9f, 0xff, 0x62, 0xfc, 0x70,
- 0x1d, 0x8f, 0x23, 0x82, 0xc6, 0x93, 0x9a, 0xe5, 0x09, 0xb2, 0xbd, 0x74, 0x39, 0x73, 0xfa, 0xda,
- 0xaa, 0x84, 0x07, 0x0e, 0x15, 0x85, 0xdd, 0x23, 0xf6, 0xbf, 0xbb, 0x83, 0x7d, 0xe8, 0x9b, 0x6c,
- 0x3e, 0xee, 0x57, 0xdd, 0xc9, 0xdd, 0x68, 0x49, 0xf2, 0x28, 0x72, 0x69, 0xeb, 0xb6, 0xb9, 0x8c,
- 0x62, 0xf2, 0x97, 0x7e, 0xaf, 0x40, 0x6c, 0x35, 0x48, 0xda, 0x4a, 0xde, 0xec, 0x2c, 0xee, 0x1c,
- 0x9a, 0x72, 0xc8, 0x92, 0x3c, 0x47, 0x29, 0xf6, 0x5d, 0xff, 0x35, 0x8d, 0xa0, 0x47, 0x45, 0x0c,
- 0xbb, 0x6a, 0x18, 0xd8, 0x6d, 0xce, 0xa5, 0xcd, 0x37, 0x05, 0x4a, 0x54, 0xee, 0x63, 0x29, 0x91,
- 0xfb, 0x30, 0xd7, 0xb4, 0x61, 0xbd, 0xd7, 0xc1, 0x82, 0x56, 0x15, 0xdd, 0xa1, 0x90, 0x18, 0x4f,
- 0x7b, 0xc3, 0x6c, 0x6e, 0xce, 0x63, 0x93, 0xa9, 0x88, 0x69, 0x1c, 0xf7, 0x52, 0x03, 0x1f, 0x2c,
- 0x86, 0xa3, 0xcb, 0x3c, 0xac, 0xc4, 0x49, 0xe5, 0x6b, 0xa0, 0xdd, 0x75, 0xc1, 0x46, 0x88, 0xce,
- 0x1e, 0x46, 0x8a, 0x9e, 0x3c, 0xcd, 0xf2, 0xdf, 0x17, 0x90, 0xae, 0xed, 0x0b, 0x4b, 0x3e, 0xa7,
- 0xf3, 0x0c, 0x4d, 0xb7, 0x02, 0x2b, 0x8a, 0xfe, 0x20, 0x9c, 0x28, 0xcf, 0x7b, 0x41, 0x15, 0x85,
- 0x62, 0x54, 0x45, 0x2a, 0xd2, 0xe6, 0x8d, 0x5a, 0x2c, 0x1b, 0x8f, 0xf1, 0xd9, 0x9b, 0xee, 0x2c,
- 0x9d, 0x2f, 0x66, 0x08, 0x6e, 0x74, 0x9d, 0x22, 0x56, 0x40, 0x53, 0x21, 0xea, 0x8d, 0x11, 0x47,
- 0xa0, 0xa1, 0x3b, 0xae, 0x83, 0xcc, 0x70, 0x4a, 0x5a, 0x1e, 0x58, 0x6b, 0x77, 0xb1, 0x8a, 0x7b,
- 0x04, 0xc3, 0xbf, 0x56, 0xef, 0x63, 0xa2, 0x42, 0xf7, 0xfc, 0x38, 0x7c, 0xb4, 0xeb, 0x74, 0x18,
- 0xd7, 0xf8, 0x7b, 0xbc, 0x92, 0x56, 0x85, 0x6c, 0x58, 0x22, 0xc6, 0x2a, 0x78, 0x0a, 0xd3, 0x31,
- 0x11, 0x89, 0x78, 0x0e, 0xdf, 0x67, 0x40, 0xa9, 0x36, 0x37, 0x9e, 0x0d, 0xe3, 0x08, 0xf5, 0x5f,
- 0x68, 0x94, 0x72, 0xb8, 0xd1, 0xac, 0xe1, 0x1e, 0x06, 0xc6, 0x1e, 0x37, 0x56, 0x55, 0xed, 0xbf,
- 0x6a, 0x30, 0x15, 0x4d, 0xfa, 0xaf, 0x54, 0x12, 0x4f, 0x57, 0x5a, 0xfa, 0x8e, 0x14, 0xa7, 0x24,
- 0x19, 0xcb, 0x7b, 0x51, 0xb3, 0x1d, 0xde, 0xed, 0x64, 0x16, 0x3e, 0xab, 0xe9, 0xa6, 0xa5, 0x6b,
- 0xdb, 0xca, 0xda, 0x22, 0x6d, 0x4e, 0x66, 0x4a, 0xca, 0x7e, 0xe6, 0x1a, 0x67, 0xae, 0x4c, 0xdf,
- 0x2c, 0xee, 0xf7, 0x51, 0x07, 0x76, 0x2f, 0xe3, 0x5e, 0x9e, 0x81, 0x9f, 0xb5, 0x53, 0x98, 0xd8,
- 0x9c, 0x7f, 0x0a, 0xd3, 0x59, 0x2d, 0xfc, 0x18, 0xb3, 0x9b, 0x8d, 0x7f, 0x14, 0x27, 0x0b, 0x21,
- 0x60, 0x9a, 0x2b, 0x57, 0x52, 0x66, 0x05, 0x7d, 0x2a, 0x3d, 0xa1, 0xc6, 0x0f, 0xd1, 0x06, 0xfe,
- 0xed, 0x52, 0xea, 0x25, 0xb5, 0x81, 0xaf, 0xfe, 0xd7, 0x08, 0x0a, 0x7b, 0xdf, 0x59, 0xdd, 0xcf,
- 0x83, 0xeb, 0x75, 0xf1, 0x26, 0xa9, 0x16, 0x1b, 0x0b, 0xb7, 0xde, 0xb6, 0x52, 0xad, 0x47, 0xc5,
- 0x59, 0x87, 0x1d, 0x71, 0x56, 0x08, 0xd6, 0x1c, 0x4a, 0x5a, 0x73, 0xdc, 0x52, 0xef, 0x93, 0xd0,
- 0x85, 0x3d, 0x13, 0xce, 0xd0, 0xe0, 0x51, 0x6b, 0x23, 0x8b, 0xd5, 0x08, 0x1c, 0x18, 0x46, 0x51,
- 0xb1, 0xe0, 0xd8, 0xa8, 0x94, 0x55, 0xc5, 0xf8, 0x07, 0x58, 0x2a, 0xed, 0x0f, 0x52, 0xcc, 0xb7,
- 0x46, 0xd7, 0x51, 0xa9, 0x7f, 0xab, 0xa1, 0x6c, 0x5e, 0x42, 0x4f, 0x37, 0x74, 0xcc, 0x56, 0x27,
- 0x13, 0xf1, 0x3e, 0xde, 0xed, 0xee, 0x30, 0xac, 0x61, 0xe3, 0x63, 0xed, 0xd1, 0xd7, 0x0d, 0xe9,
- 0x7b, 0x69, 0x27, 0xa9, 0x9e, 0xd3, 0x81, 0xa0, 0x82, 0x81, 0xfa, 0xe4, 0x67, 0x36, 0x76, 0x70,
- 0xac, 0xa1, 0x2a, 0x0f, 0x3f, 0xc9, 0xc6, 0xdf, 0x03, 0x6f, 0x9a, 0x3d, 0xf2, 0xc6, 0xcd, 0x46,
- 0xbb, 0x27, 0x06, 0x5b, 0xf4, 0x41, 0x8e, 0x7f, 0x6e, 0x20, 0x2b, 0x8c, 0xfe, 0x06, 0x83, 0x55,
- 0x6e, 0x1b, 0x9c, 0xab, 0x7c, 0x3c, 0x9a, 0x96, 0x1e, 0x95, 0x53, 0x40, 0xec, 0x32, 0x46, 0x01,
- 0x33, 0xc9, 0x1a, 0x15, 0xa0, 0x8c, 0xab, 0x0a, 0x90, 0xaf, 0x48, 0xf6, 0xa8, 0x1d, 0xae, 0x7c,
- 0x99, 0x64, 0x91, 0x02, 0xe0, 0x17, 0x06, 0xc3, 0x24, 0x9b, 0x34, 0x9c, 0x5b, 0xf5, 0xe6, 0x53,
- 0xcb, 0x2a, 0xcc, 0xb3, 0x91, 0xa3, 0xea, 0xe6, 0x81, 0xa2, 0x71, 0xd7, 0x61, 0xd2, 0x04, 0xe0,
- 0x15, 0x66, 0x5c, 0x6f, 0x15, 0x70, 0x6a, 0x9f, 0xef, 0x9c, 0x35, 0x1f, 0x8a, 0xbb, 0xd6, 0xb8,
- 0xda, 0x2c, 0xf2, 0x4c, 0x69, 0xfb, 0x36, 0x6c, 0x72, 0x4f, 0x19, 0x29, 0x34, 0x45, 0xa1, 0xc6,
- 0x22, 0xda, 0x1b, 0x5c, 0x0a, 0x66, 0x73, 0x64, 0x0f, 0xad, 0x98, 0x82, 0x48, 0x94, 0x77, 0x70,
- 0x5b, 0x6a, 0x1b, 0xa0, 0xa0, 0x7c, 0x03, 0x16, 0x5d, 0x13, 0x94, 0xc9, 0xf6, 0x1c, 0x5c, 0x9c,
- 0x09, 0xe1, 0xdd, 0x39, 0x78, 0x1f, 0xee, 0x06, 0x11, 0x3b, 0xbb, 0x81, 0x8d, 0x9b, 0xfb, 0xde,
- 0x00, 0xaa, 0xbe, 0x0c, 0x3c, 0xfb, 0x23, 0xdd, 0xec, 0x1e, 0xc7, 0xe5, 0x3c, 0x9b, 0x98, 0xc9,
- 0x94, 0x21, 0x8c, 0xb4, 0x1e, 0x69, 0x40, 0x2a, 0xc1, 0xf4, 0x22, 0xa8, 0x94, 0x6d, 0x22, 0x9a,
- 0x0e, 0x8f, 0x0e, 0x57, 0x81, 0xf0, 0x3c, 0x2b, 0x27, 0x1b, 0x19, 0x3a, 0xeb, 0x88, 0xce, 0xb3,
- 0x12, 0x92, 0x51, 0x66, 0x05, 0x82, 0x09, 0x54, 0xf5, 0xd5, 0xea, 0xa9, 0x8e, 0xe4, 0x2a, 0xc3,
- 0x2d, 0x7f, 0x44, 0x71, 0xd7, 0x34, 0x48, 0xd2, 0x5e, 0xb4, 0x3a, 0x8a, 0xd1, 0xb6, 0x83, 0x25,
- 0x7e, 0x46, 0x71, 0xb7, 0xd8, 0xc9, 0xc6, 0x0a, 0x11, 0xac, 0xb9, 0xab, 0xe5, 0x8b, 0xb4, 0x70,
- 0x69, 0x2a, 0x92, 0x69, 0x82, 0x43, 0x27, 0x0a, 0x04, 0xdc, 0x9e, 0x52, 0x21, 0x6e, 0x6f, 0x42,
- 0x1d, 0x47, 0x12, 0x89, 0x8a, 0x4c, 0x18, 0x94, 0x7c, 0x54, 0x9e, 0x3a, 0xc0, 0x40, 0xf0, 0x7c,
- 0xc3, 0xfe, 0x38, 0x2a, 0x64, 0x9a, 0xcb, 0x50, 0xdc, 0xe7, 0x55, 0x73, 0xd8, 0x59, 0x18, 0x20,
- 0xe1, 0x82, 0xfa, 0x94, 0x48, 0x0e, 0x3b, 0xde, 0x92, 0x67, 0x6a, 0xfa, 0x4d, 0x58, 0x6d, 0x79,
- 0x07, 0x5a, 0x91, 0x30, 0x9f, 0x8d, 0xe3, 0x15, 0xbd, 0x21, 0x48, 0xb6, 0x82, 0x1d, 0xb9, 0x0b,
- 0x9a, 0xcb, 0x86, 0xdc, 0x67, 0xcd, 0xa5, 0x1b, 0x08, 0xf2, 0x7d, 0x15, 0x74, 0xa5, 0x82, 0xae,
- 0x64, 0x50, 0x53, 0x7d, 0x49, 0xb1, 0xbe, 0x44, 0xad, 0x2f, 0x29, 0xa9, 0x2f, 0x51, 0xeb, 0x4b,
- 0x0a, 0xf5, 0xdd, 0xf3, 0x22, 0x25, 0xef, 0x70, 0x4f, 0xed, 0x24, 0x9f, 0x8f, 0xd1, 0x43, 0xdd,
- 0x9c, 0xa4, 0x03, 0xa8, 0xd6, 0x93, 0x58, 0xea, 0xd9, 0x42, 0x21, 0x5b, 0x73, 0xdb, 0xd1, 0xbe,
- 0x0f, 0xc9, 0x56, 0x87, 0xcb, 0xb8, 0x9f, 0x3e, 0xea, 0x92, 0xb7, 0xbb, 0x55, 0x6b, 0xd7, 0xcb,
- 0xcd, 0x63, 0xae, 0x15, 0x8f, 0x71, 0xec, 0x50, 0xe9, 0xac, 0x6d, 0x04, 0x7a, 0x69, 0x6f, 0xbc,
- 0x38, 0x81, 0xbd, 0xd9, 0xa5, 0x5c, 0xcb, 0x95, 0xdc, 0x27, 0xba, 0x90, 0x6b, 0xb9, 0x8e, 0xfb,
- 0x60, 0x97, 0x71, 0x1f, 0xd9, 0xa8, 0x30, 0x5d, 0xef, 0x05, 0x41, 0x44, 0x3d, 0xff, 0xde, 0x0e,
- 0xe3, 0x18, 0x3c, 0x0f, 0x4b, 0x62, 0x6f, 0x36, 0xec, 0xcd, 0x86, 0xbd, 0xd9, 0xb0, 0x37, 0x1b,
- 0x2c, 0x66, 0xc3, 0x3f, 0xb3, 0x6c, 0x72, 0x7f, 0xd3, 0xe1, 0xb5, 0x5b, 0x05, 0x3b, 0x89, 0xc1,
- 0x52, 0x6a, 0x3a, 0xf0, 0x71, 0xda, 0x81, 0xf9, 0x50, 0xa8, 0x6b, 0xbd, 0x35, 0xa0, 0xe8, 0xfc,
- 0x0f, 0x11, 0xe4, 0x64, 0xaf, 0xfa, 0xef, 0x55, 0xff, 0xbd, 0xea, 0xff, 0xba, 0x54, 0xff, 0x8a,
- 0x8a, 0xfa, 0x6e, 0x54, 0xf4, 0x43, 0x94, 0x3a, 0x86, 0xb3, 0xe8, 0x6a, 0x6c, 0x34, 0x36, 0xa5,
- 0x78, 0xb6, 0xbc, 0x7f, 0xab, 0xc8, 0x12, 0x9c, 0x2b, 0x0e, 0xe7, 0xeb, 0x92, 0xf0, 0x3a, 0x9d,
- 0xe7, 0x23, 0x24, 0x61, 0xbb, 0x03, 0x38, 0x46, 0x93, 0x4e, 0xf3, 0x70, 0xfd, 0xf1, 0x48, 0x50,
- 0xfd, 0xa6, 0x08, 0x09, 0x2a, 0x95, 0x2a, 0x5b, 0xc1, 0x47, 0x48, 0x2e, 0xb2, 0xdd, 0x1d, 0xf3,
- 0xd5, 0xd9, 0xd8, 0x2c, 0xf2, 0x62, 0x9c, 0x63, 0xbf, 0x9b, 0x04, 0xb9, 0xe5, 0x77, 0x14, 0x18,
- 0x44, 0x89, 0xf4, 0x1a, 0x96, 0x5c, 0x8e, 0x1a, 0xae, 0xb9, 0x1c, 0x35, 0xac, 0x70, 0x4d, 0x62,
- 0x58, 0xe5, 0x4e, 0xcc, 0x7d, 0x8f, 0xd8, 0x54, 0x3f, 0x2b, 0x51, 0x45, 0x8d, 0xc6, 0xe3, 0x21,
- 0xb7, 0x02, 0x12, 0x4c, 0x31, 0x38, 0x50, 0xb2, 0xcf, 0x06, 0xc9, 0x78, 0x33, 0x88, 0x14, 0xdc,
- 0x60, 0x18, 0xe4, 0xc2, 0x43, 0xdb, 0xad, 0xa4, 0x21, 0xbb, 0x95, 0x34, 0x2c, 0xbb, 0x95, 0xc4,
- 0x8a, 0x6f, 0x32, 0x02, 0xc5, 0xb3, 0x1b, 0x0f, 0x78, 0x4c, 0x07, 0x4f, 0x4c, 0x32, 0x43, 0x22,
- 0x69, 0xaa, 0x20, 0xc1, 0x7c, 0x1b, 0xe2, 0x8e, 0x82, 0x2b, 0x9a, 0xe0, 0x1d, 0x80, 0x0f, 0x37,
- 0xa4, 0xf4, 0xb3, 0x44, 0xf2, 0xc9, 0x3c, 0x0b, 0x24, 0xa8, 0x25, 0xc1, 0xd1, 0x5c, 0xe2, 0x0b,
- 0x4c, 0x6b, 0xf5, 0xbc, 0x1c, 0x1f, 0x15, 0x6c, 0xd5, 0x7e, 0xa2, 0x5d, 0x53, 0xfb, 0x80, 0xc7,
- 0x07, 0xb4, 0x3f, 0xe9, 0x02, 0xe7, 0x35, 0x0e, 0x45, 0x8b, 0x7f, 0x36, 0xe7, 0x5e, 0xab, 0xd9,
- 0x69, 0x77, 0xde, 0xd4, 0xc9, 0xe7, 0x00, 0x7d, 0xbe, 0x6d, 0x1f, 0x77, 0xe8, 0x67, 0x82, 0x3e,
- 0x5b, 0x6f, 0x3b, 0x9d, 0x90, 0x4e, 0x6f, 0xf5, 0xd0, 0x22, 0x3f, 0x07, 0x4b, 0x18, 0x75, 0x92,
- 0x80, 0x18, 0xc1, 0x62, 0x87, 0xc3, 0x1d, 0xfa, 0xe2, 0x1f, 0x0c, 0x8a, 0xd1, 0xd4, 0x23, 0x19,
- 0x98, 0xbb, 0x5c, 0xe6, 0x70, 0x38, 0x34, 0x9b, 0xa2, 0xbe, 0x23, 0x07, 0x7a, 0xe1, 0xba, 0x0e,
- 0x69, 0x7f, 0xd0, 0x7e, 0x73, 0xf8, 0xee, 0x08, 0x02, 0xc0, 0x72, 0xa1, 0xe7, 0x8a, 0xea, 0xe5,
- 0x92, 0x20, 0xb6, 0x41, 0xd8, 0x36, 0x74, 0x01, 0xe8, 0x42, 0x54, 0x53, 0x92, 0x25, 0x3a, 0xa1,
- 0x5e, 0x84, 0x02, 0x8c, 0xbe, 0x84, 0x91, 0x84, 0x84, 0xa0, 0xc3, 0xb0, 0xaa, 0xfd, 0x10, 0xc1,
- 0xdd, 0x8e, 0xda, 0x7f, 0x24, 0x08, 0x2f, 0x62, 0x35, 0x16, 0x64, 0xaa, 0x5b, 0x77, 0x0c, 0xa9,
- 0x1e, 0x69, 0x9e, 0x93, 0xd7, 0x31, 0x1b, 0x78, 0xb3, 0xec, 0xc6, 0x21, 0xe3, 0x15, 0xb4, 0x8f,
- 0x5b, 0xf4, 0x24, 0xa8, 0x0f, 0x2d, 0x41, 0x83, 0x81, 0x3e, 0xde, 0xbf, 0xf3, 0xcd, 0x2d, 0x02,
- 0x5a, 0x71, 0xc8, 0xdd, 0x2e, 0x1d, 0xcc, 0x3a, 0xed, 0x39, 0x36, 0xb6, 0x32, 0x95, 0xf2, 0x72,
- 0xd2, 0x9c, 0x53, 0xf4, 0x50, 0xd7, 0xa1, 0x8c, 0x9d, 0x66, 0xbb, 0x74, 0x60, 0x29, 0xe2, 0x81,
- 0x8a, 0x78, 0x60, 0x47, 0x3c, 0x28, 0x47, 0x3c, 0xd0, 0x10, 0x27, 0x2a, 0xe2, 0xc4, 0x8e, 0x38,
- 0x29, 0x47, 0x9c, 0x50, 0xc4, 0xd2, 0x2d, 0x06, 0x65, 0x5d, 0x2a, 0xb9, 0x5d, 0x2b, 0xad, 0x5c,
- 0xcf, 0xd6, 0xe3, 0xa6, 0x2e, 0x35, 0xec, 0x54, 0xad, 0xd1, 0x1f, 0xb7, 0x7e, 0xa1, 0x7f, 0x44,
- 0x2d, 0xe3, 0x1e, 0x3a, 0x44, 0xf5, 0xed, 0x17, 0x18, 0x55, 0x5a, 0xef, 0xe0, 0x01, 0x14, 0x0e,
- 0x25, 0xb8, 0x1d, 0x2c, 0x63, 0xa6, 0x10, 0x1f, 0x06, 0x3d, 0x44, 0x0d, 0xf1, 0xf1, 0xe0, 0x6a,
- 0x88, 0x4c, 0xd6, 0x50, 0xbd, 0xa2, 0x2d, 0x15, 0x35, 0xeb, 0x27, 0x0a, 0x69, 0x95, 0x16, 0xc7,
- 0xbd, 0x37, 0xf3, 0x29, 0xbc, 0x99, 0x98, 0x4b, 0x37, 0x52, 0xbd, 0x34, 0x9e, 0xdc, 0x4c, 0xf3,
- 0xda, 0x5c, 0xdb, 0x2a, 0x70, 0x5a, 0xb4, 0x0d, 0x3f, 0xed, 0xdd, 0xa5, 0x2f, 0xe7, 0x94, 0x45,
- 0x99, 0x0a, 0x4b, 0x6f, 0x90, 0xf4, 0x07, 0x29, 0xbf, 0xb3, 0x25, 0x83, 0xbc, 0x7e, 0x3f, 0xeb,
- 0x43, 0xe8, 0xf0, 0x24, 0xe7, 0x36, 0xb2, 0xe8, 0xea, 0x6b, 0x75, 0xfc, 0x5b, 0x7e, 0xcc, 0x05,
- 0xbc, 0x34, 0x0c, 0x77, 0x04, 0x7b, 0x90, 0xb5, 0xbf, 0xff, 0xbd, 0xc6, 0x34, 0xd5, 0x08, 0x14,
- 0x55, 0x29, 0xe1, 0x16, 0x41, 0x10, 0x25, 0xfa, 0xe0, 0x27, 0xb2, 0x2e, 0x1f, 0x7c, 0x20, 0x2f,
- 0x3c, 0xc8, 0xe3, 0xe9, 0xdf, 0x7a, 0x9a, 0x92, 0xb1, 0x93, 0x23, 0x27, 0xbb, 0x39, 0x70, 0x42,
- 0x6b, 0x61, 0xaa, 0x83, 0xc5, 0x98, 0xa9, 0x68, 0x8d, 0x1c, 0x3e, 0x84, 0x35, 0x02, 0x57, 0x16,
- 0x5f, 0x8b, 0x09, 0xc2, 0xba, 0xb5, 0x39, 0x1f, 0x70, 0xad, 0xde, 0xa6, 0xcd, 0x63, 0xcc, 0x38,
- 0xac, 0x1c, 0x34, 0xc5, 0xa7, 0xbf, 0x0e, 0xdd, 0x82, 0x5e, 0x4f, 0xf3, 0xda, 0xe4, 0x69, 0x91,
- 0xdd, 0xbb, 0xf9, 0xb7, 0xd1, 0x3a, 0x1f, 0x57, 0x7d, 0xdc, 0x95, 0x0e, 0xf8, 0xba, 0xf7, 0x15,
- 0xf0, 0x40, 0xad, 0xd7, 0xa5, 0xac, 0xa3, 0x50, 0x4d, 0x2f, 0xda, 0xef, 0x46, 0xec, 0x77, 0x23,
- 0xb6, 0xde, 0x8d, 0xa0, 0x8f, 0x03, 0x2d, 0xe9, 0x73, 0x3d, 0xf6, 0x0d, 0x89, 0xc2, 0xbe, 0x05,
- 0x2d, 0xe1, 0x69, 0xf2, 0x6a, 0x1f, 0x8e, 0xc6, 0x78, 0x0c, 0xb4, 0x6a, 0xbc, 0x19, 0xa5, 0x9f,
- 0x6c, 0x41, 0x67, 0x1e, 0x2a, 0x60, 0x4c, 0xa5, 0x2e, 0xef, 0x8f, 0x26, 0xb0, 0x0c, 0x67, 0xd3,
- 0xb0, 0x5a, 0x64, 0x0b, 0x4a, 0xf4, 0x43, 0x8c, 0x89, 0x1c, 0xd6, 0x81, 0x04, 0xbc, 0x9a, 0x2d,
- 0x46, 0x63, 0x04, 0x0b, 0xc1, 0xcc, 0x64, 0xca, 0xe8, 0xc5, 0x71, 0x6c, 0x64, 0x38, 0x52, 0x06,
- 0xd2, 0xc9, 0x41, 0x1b, 0x0e, 0x94, 0x24, 0x76, 0x16, 0x58, 0x21, 0x35, 0x78, 0xd7, 0x7e, 0x8f,
- 0xa3, 0x77, 0x61, 0x24, 0x75, 0x5a, 0x51, 0xc9, 0xab, 0x4a, 0xda, 0xcb, 0x71, 0x4a, 0xe8, 0xaa,
- 0x2a, 0xba, 0x80, 0xbd, 0x9b, 0x75, 0xd6, 0xb9, 0xcd, 0x90, 0x70, 0x2e, 0x3c, 0xaf, 0x12, 0x2f,
- 0x71, 0x3a, 0xf9, 0x46, 0xca, 0xec, 0xe9, 0x38, 0xbd, 0x06, 0xfd, 0x73, 0xea, 0xd0, 0x48, 0xcf,
- 0x48, 0x08, 0xf8, 0x74, 0xd9, 0x19, 0xc5, 0x0b, 0x16, 0x52, 0x03, 0x87, 0xda, 0x2d, 0xf2, 0x15,
- 0x91, 0x60, 0x1e, 0x0e, 0x10, 0xc7, 0x1f, 0xa0, 0xc2, 0x81, 0x20, 0xe7, 0x75, 0xfc, 0x67, 0x40,
- 0x1f, 0xaf, 0xc2, 0x1f, 0x09, 0xf9, 0x20, 0xff, 0xba, 0x01, 0xd2, 0xf6, 0x91, 0x6a, 0x56, 0x78,
- 0x8f, 0xa5, 0x7c, 0xb0, 0xb0, 0xa6, 0x2f, 0x11, 0x0d, 0x7d, 0x52, 0xc7, 0x96, 0x42, 0x83, 0x16,
- 0x44, 0xa6, 0x0c, 0xff, 0xb9, 0xc2, 0xaa, 0x2f, 0x53, 0x9b, 0x13, 0x6b, 0xd9, 0x96, 0xad, 0x48,
- 0xcf, 0x5a, 0x64, 0x6d, 0x6d, 0xfd, 0x2a, 0x94, 0xb6, 0x94, 0x22, 0xa9, 0xa1, 0x88, 0x9c, 0x7f,
- 0x59, 0x81, 0x1a, 0x15, 0xe3, 0xa0, 0x0a, 0x11, 0x66, 0xfa, 0x87, 0x25, 0xbd, 0x65, 0x2e, 0x31,
- 0xaa, 0x40, 0x9e, 0xb9, 0x64, 0xba, 0x8c, 0x07, 0x83, 0x14, 0xc7, 0xdd, 0x80, 0x19, 0x0d, 0x2c,
- 0x5a, 0xfb, 0x47, 0xad, 0x83, 0x0d, 0xd0, 0x56, 0xf3, 0x08, 0x59, 0x9f, 0x3c, 0xf1, 0xa8, 0x79,
- 0x8c, 0x13, 0x0f, 0x8f, 0x51, 0x2a, 0xfa, 0x43, 0xcd, 0xec, 0x74, 0x3e, 0xba, 0xa6, 0xd6, 0x75,
- 0xaf, 0x7e, 0x89, 0xfe, 0x1b, 0xb9, 0x0d, 0x27, 0xae, 0xf7, 0xd1, 0x7f, 0x03, 0xd7, 0x77, 0x06,
- 0xf5, 0x21, 0xfa, 0x8f, 0xa4, 0x25, 0xe8, 0xbf, 0x9e, 0xeb, 0x06, 0x35, 0xb0, 0x2b, 0x50, 0x1d,
- 0xbe, 0x43, 0x90, 0x37, 0xf8, 0xf4, 0x80, 0x38, 0x13, 0x82, 0xa0, 0x7a, 0xfb, 0x7d, 0x13, 0xb1,
- 0x6c, 0xa7, 0x41, 0xc0, 0xf4, 0x50, 0x5c, 0xd8, 0x96, 0xc0, 0xc2, 0x07, 0x13, 0xd1, 0x5c, 0xc2,
- 0x5d, 0x00, 0x88, 0xf5, 0xe2, 0x93, 0xef, 0x15, 0xff, 0x66, 0xf1, 0xd7, 0x84, 0x39, 0xf6, 0x08,
- 0x2b, 0xdf, 0x13, 0x49, 0x5b, 0x22, 0x1c, 0x4d, 0xb2, 0xb1, 0x7c, 0xc1, 0x5b, 0x2f, 0xe1, 0xc6,
- 0xa8, 0xc2, 0x78, 0x2a, 0xad, 0x8d, 0x2c, 0x1d, 0x2b, 0xb4, 0xfa, 0x2e, 0xc3, 0x30, 0xee, 0x67,
- 0x37, 0x7a, 0x2a, 0x08, 0x5d, 0x23, 0x78, 0xdc, 0x83, 0x88, 0x30, 0x22, 0x08, 0xe0, 0xf9, 0x59,
- 0xed, 0xb0, 0xd9, 0x3e, 0x6a, 0x1f, 0xbf, 0xef, 0xbc, 0x39, 0x3e, 0x3c, 0x7e, 0xf7, 0xfe, 0xed,
- 0xfb, 0xc3, 0x03, 0x43, 0x80, 0x21, 0x30, 0xef, 0xad, 0xcb, 0xac, 0xcc, 0x91, 0x0e, 0x79, 0xf0,
- 0x0f, 0x99, 0x9d, 0x10, 0xdf, 0xd1, 0x95, 0x03, 0x3c, 0xe2, 0x15, 0xe3, 0x33, 0x09, 0xc8, 0xd3,
- 0xcb, 0x16, 0x38, 0xc6, 0x6c, 0x3c, 0x5d, 0x38, 0x8e, 0x68, 0xf2, 0x5f, 0xad, 0xef, 0x0d, 0xe9,
- 0xab, 0xfd, 0xdd, 0xf5, 0xb0, 0x25, 0x4d, 0xd5, 0x0a, 0xb7, 0xae, 0x66, 0x72, 0xcc, 0xe3, 0x6c,
- 0x96, 0x46, 0x48, 0xe2, 0x4e, 0x11, 0x74, 0xe7, 0xd8, 0xa3, 0x47, 0xc5, 0x31, 0x45, 0x6e, 0x20,
- 0xd5, 0xcb, 0xcf, 0x89, 0xe3, 0xd0, 0x37, 0x11, 0xe5, 0x5f, 0x62, 0xc3, 0xa3, 0x49, 0x86, 0x31,
- 0x50, 0x26, 0xf6, 0x1b, 0x34, 0xd7, 0x45, 0xd3, 0xee, 0xfc, 0x0c, 0xdf, 0x77, 0x61, 0x79, 0xdc,
- 0x57, 0x04, 0x5e, 0x9e, 0x0f, 0x72, 0x1b, 0xb9, 0x2d, 0x1e, 0xd1, 0xf1, 0xe2, 0xfe, 0xc0, 0xf8,
- 0x76, 0x34, 0xb9, 0xc2, 0xa1, 0x8f, 0x49, 0xfa, 0xaa, 0x7e, 0x7e, 0x16, 0x4a, 0xe6, 0x4e, 0xbb,
- 0xf9, 0xee, 0xed, 0x71, 0x43, 0xc4, 0x39, 0x6c, 0x37, 0xdf, 0x1e, 0xd3, 0x7c, 0x34, 0x49, 0xc9,
- 0x7b, 0xa5, 0x10, 0x4f, 0x89, 0x97, 0x22, 0x81, 0x2e, 0x2f, 0x70, 0xd3, 0x79, 0x31, 0xdc, 0x14,
- 0x90, 0x17, 0x68, 0x1c, 0xd0, 0x64, 0xc7, 0x5e, 0x6b, 0xdc, 0x3b, 0x64, 0x24, 0x02, 0x91, 0xca,
- 0x90, 0x92, 0x0c, 0xd7, 0x63, 0xdf, 0x10, 0x33, 0x18, 0x0a, 0x30, 0xb2, 0x31, 0xc3, 0xe0, 0xf1,
- 0x92, 0x2a, 0x64, 0x9b, 0xcc, 0x38, 0x93, 0x6e, 0x46, 0xe3, 0x81, 0x22, 0x29, 0xa0, 0x78, 0x91,
- 0x5f, 0xd4, 0xb3, 0x21, 0x9a, 0xd5, 0x29, 0x3a, 0x77, 0x80, 0x85, 0x49, 0x44, 0x19, 0xd0, 0xf1,
- 0x1d, 0x32, 0x36, 0x75, 0xda, 0x5f, 0x6e, 0x70, 0x7e, 0x86, 0x65, 0x89, 0xe0, 0x26, 0x12, 0xa2,
- 0x1a, 0x0a, 0xd1, 0x9a, 0xc9, 0xcb, 0x60, 0x64, 0x26, 0xf8, 0x12, 0xf3, 0xfb, 0x18, 0x08, 0xa9,
- 0x2a, 0x88, 0x93, 0x65, 0xe2, 0xcb, 0x89, 0x52, 0xe4, 0x90, 0xdc, 0x42, 0xc2, 0x8a, 0x52, 0xc5,
- 0xcd, 0xd8, 0xad, 0x4b, 0x9f, 0xf7, 0x13, 0x6e, 0x7c, 0x4a, 0x9e, 0x7c, 0xf9, 0xed, 0xec, 0xe4,
- 0x97, 0xb3, 0x93, 0x8b, 0xb3, 0x2f, 0x3f, 0xd7, 0x2c, 0x0f, 0x04, 0x20, 0x82, 0x39, 0x3c, 0x6e,
- 0x19, 0x0e, 0xfa, 0x7c, 0xfc, 0xee, 0xed, 0x61, 0xab, 0xfd, 0xe6, 0xa0, 0xb0, 0xc3, 0x07, 0x56,
- 0x13, 0x71, 0x58, 0x15, 0x77, 0xff, 0x70, 0x90, 0xf4, 0x72, 0x05, 0xb7, 0x18, 0xda, 0x17, 0xc2,
- 0x45, 0x69, 0xd2, 0x09, 0xb5, 0x50, 0x7f, 0xd7, 0x50, 0x13, 0x75, 0x94, 0x02, 0x2d, 0x15, 0xc7,
- 0x02, 0xea, 0x14, 0x22, 0x45, 0x0d, 0xe2, 0xc9, 0x24, 0x66, 0xa1, 0x9f, 0x0c, 0x01, 0x53, 0xc1,
- 0x9a, 0x9a, 0xa6, 0x8b, 0xec, 0x32, 0x9e, 0xbf, 0xb8, 0x30, 0x3a, 0xfb, 0xa7, 0xbe, 0xb6, 0x38,
- 0x66, 0x3b, 0x88, 0x67, 0x25, 0x4f, 0x65, 0xb1, 0xdc, 0xb2, 0xb8, 0xd5, 0x0c, 0x66, 0x5d, 0xe4,
- 0x6a, 0x19, 0xae, 0xac, 0xcb, 0xf0, 0xeb, 0xb2, 0x96, 0x1e, 0xc3, 0x79, 0xf6, 0x0e, 0xc3, 0xd9,
- 0xe5, 0x9d, 0xc2, 0x41, 0x4a, 0x48, 0x28, 0xe9, 0x90, 0xb5, 0xbd, 0x51, 0xa9, 0x2b, 0xd4, 0x7e,
- 0x78, 0x7e, 0x21, 0x97, 0x5e, 0xfb, 0x83, 0x55, 0x9c, 0xe9, 0xd5, 0x81, 0x61, 0xc9, 0x06, 0x42,
- 0x58, 0x96, 0x2f, 0xcf, 0x09, 0x4b, 0x08, 0x6f, 0x81, 0x66, 0x43, 0x9e, 0x97, 0x5b, 0x44, 0x5e,
- 0x7c, 0x36, 0xf4, 0x08, 0xce, 0xf0, 0xc5, 0x5c, 0x30, 0xf6, 0x07, 0x2d, 0xbd, 0x09, 0xbb, 0xab,
- 0x6d, 0xb0, 0xf5, 0x03, 0xeb, 0x84, 0xf2, 0x1e, 0x60, 0xcd, 0xd7, 0xf8, 0x5c, 0x09, 0x2f, 0x1a,
- 0xc5, 0xec, 0xc5, 0x88, 0x46, 0xbb, 0xf3, 0x0e, 0xa9, 0xf7, 0x6c, 0x8a, 0xf1, 0xed, 0x94, 0x88,
- 0x04, 0x36, 0x27, 0xef, 0x41, 0xe0, 0xa0, 0x95, 0xa0, 0xa8, 0x84, 0xd2, 0x12, 0x15, 0xf1, 0x58,
- 0xe2, 0x04, 0x08, 0x5c, 0x01, 0x6e, 0x9d, 0x7e, 0xdd, 0x78, 0x6f, 0x8e, 0x68, 0x3c, 0x74, 0xe1,
- 0x61, 0x95, 0x17, 0x6d, 0xf0, 0xdd, 0x2a, 0xb3, 0x97, 0x6f, 0x08, 0x4b, 0x30, 0xe0, 0xbf, 0xa5,
- 0xbf, 0xe9, 0x36, 0x64, 0xc8, 0xc7, 0x97, 0xfd, 0x00, 0xbd, 0x81, 0x19, 0xbb, 0xf1, 0xf8, 0x92,
- 0x64, 0x8a, 0x1c, 0x3a, 0x1a, 0x40, 0xbc, 0x47, 0x07, 0x84, 0x69, 0xb5, 0x90, 0xce, 0xb0, 0xd4,
- 0x1d, 0xf6, 0x8b, 0xeb, 0xc1, 0x8a, 0xce, 0x02, 0x56, 0x2a, 0x57, 0xee, 0xb2, 0xab, 0x5c, 0x29,
- 0xcb, 0xeb, 0xf5, 0x8a, 0x58, 0x3a, 0xf8, 0xc5, 0x0a, 0x50, 0x8c, 0xea, 0x8e, 0xa0, 0x8f, 0xea,
- 0xe6, 0xe4, 0x39, 0x0b, 0xb9, 0x22, 0x57, 0xed, 0x14, 0x7c, 0x49, 0x94, 0x54, 0xe7, 0x89, 0xd8,
- 0x99, 0x44, 0x83, 0xd0, 0xe4, 0x1a, 0x56, 0xa4, 0xa5, 0x01, 0xd4, 0xf2, 0x73, 0xe2, 0xbe, 0x44,
- 0x0a, 0xe9, 0x95, 0x56, 0x07, 0xe9, 0x95, 0x4e, 0x44, 0xfe, 0xea, 0xd5, 0x78, 0x6c, 0x53, 0x10,
- 0x29, 0xd3, 0x39, 0x04, 0xb2, 0x6e, 0x5c, 0xf9, 0x57, 0xf0, 0x6a, 0xbb, 0xf6, 0xa4, 0x17, 0x63,
- 0x2c, 0xd5, 0xb6, 0x04, 0xfa, 0x03, 0xaa, 0x5c, 0xb1, 0x3d, 0xd0, 0xb2, 0x33, 0xa6, 0xe2, 0x85,
- 0xf3, 0x8e, 0x52, 0x0c, 0xf7, 0x5f, 0xa1, 0x32, 0x63, 0xbc, 0x49, 0xfc, 0xa6, 0x16, 0xea, 0x32,
- 0x39, 0x18, 0x28, 0xbb, 0x67, 0x4b, 0x6e, 0xcb, 0x5a, 0x4b, 0x99, 0x8a, 0x14, 0x2a, 0x2d, 0x84,
- 0x0e, 0xf0, 0x4c, 0x7a, 0x22, 0xd8, 0xd2, 0x92, 0xba, 0x17, 0xad, 0xa7, 0x31, 0x58, 0x43, 0x50,
- 0xc8, 0xd4, 0x4a, 0xe2, 0x20, 0x21, 0x4c, 0xe1, 0x63, 0x2e, 0x7e, 0xba, 0xf0, 0x78, 0x2f, 0xe8,
- 0xbd, 0xaa, 0x72, 0x15, 0xdd, 0xac, 0xce, 0x1b, 0x15, 0xf7, 0xc7, 0x0d, 0xe1, 0xb7, 0x9b, 0x97,
- 0x93, 0x4c, 0x57, 0xd0, 0x49, 0xdb, 0x5d, 0x8f, 0xf5, 0x4d, 0x73, 0x11, 0x0a, 0x12, 0x3a, 0x11,
- 0x7e, 0xf7, 0xa7, 0x6e, 0xb6, 0xdd, 0xa0, 0x90, 0xdc, 0x47, 0xf2, 0xc5, 0x75, 0x62, 0x97, 0x4e,
- 0x50, 0x7f, 0x41, 0x75, 0x0d, 0x87, 0xa3, 0xcf, 0x1b, 0x18, 0xb1, 0xeb, 0x8b, 0x0a, 0x71, 0xe4,
- 0x54, 0x37, 0xc0, 0xe9, 0x16, 0xe3, 0xf5, 0x11, 0x42, 0x65, 0x71, 0xab, 0xf3, 0xd7, 0x93, 0x3f,
- 0xbb, 0xbf, 0x9c, 0x7d, 0x39, 0xed, 0x7e, 0x3a, 0xbb, 0xf8, 0xed, 0xe4, 0xcb, 0xc7, 0xd3, 0xda,
- 0x61, 0xe7, 0xed, 0x9b, 0xb7, 0x92, 0x5d, 0xba, 0xb7, 0x63, 0xab, 0xdb, 0xb1, 0x48, 0x72, 0x0e,
- 0xe6, 0xe9, 0xc2, 0x1a, 0xc3, 0x64, 0x6f, 0x31, 0xee, 0x2d, 0xc6, 0xd7, 0x6a, 0x31, 0xee, 0x6d,
- 0xb8, 0xbd, 0x0d, 0xf7, 0xcc, 0x6d, 0x38, 0x26, 0x9e, 0xab, 0x9a, 0x71, 0x41, 0x61, 0x75, 0xdc,
- 0x1b, 0x76, 0x7b, 0xc3, 0x6e, 0x6f, 0xd8, 0x3d, 0x91, 0x61, 0xf7, 0x82, 0x2c, 0xaf, 0xca, 0xfb,
- 0xc6, 0xdb, 0xdb, 0x64, 0xeb, 0x95, 0xd0, 0x2a, 0x27, 0x36, 0xf7, 0xa6, 0x97, 0x6e, 0x7a, 0x59,
- 0x9e, 0x37, 0xa3, 0x1b, 0xe5, 0xc0, 0xae, 0x6a, 0x37, 0xdb, 0x9f, 0x39, 0x7b, 0x1c, 0x8b, 0xad,
- 0x68, 0x5f, 0xb1, 0x1c, 0x65, 0xa5, 0xea, 0x5e, 0x7c, 0x3c, 0xf9, 0xe5, 0xb4, 0xd6, 0xd9, 0xc2,
- 0x92, 0x7b, 0x68, 0x7b, 0xcd, 0x6e, 0x91, 0x95, 0x5b, 0x74, 0xf7, 0xb1, 0xd7, 0xc4, 0xae, 0x62,
- 0xd9, 0x24, 0xda, 0x9b, 0x69, 0x0f, 0x67, 0xa6, 0x3d, 0x03, 0xab, 0xe8, 0xd9, 0x59, 0x8a, 0x3b,
- 0x36, 0xd3, 0xf6, 0x97, 0x50, 0x9f, 0xd1, 0x25, 0xd4, 0x57, 0x6e, 0x0e, 0x3f, 0xad, 0xf9, 0xf9,
- 0xdc, 0x8c, 0xf1, 0x5d, 0x99, 0xc3, 0xff, 0x6f, 0xae, 0x05, 0xdf, 0xdf, 0xe4, 0x67, 0x70, 0x9b,
- 0x6d, 0xde, 0x1a, 0x74, 0xa8, 0xbd, 0xcd, 0xbf, 0xb7, 0xf9, 0xf7, 0x36, 0xff, 0x43, 0xd8, 0xfc,
- 0x62, 0x2a, 0xc6, 0xb2, 0x82, 0x5e, 0xee, 0x0b, 0xd8, 0xe6, 0x72, 0xaa, 0x22, 0x6f, 0xf4, 0x10,
- 0x2e, 0x6b, 0x6d, 0xf2, 0xdd, 0x19, 0x1a, 0xaf, 0xe5, 0x6e, 0xe8, 0xcb, 0xdf, 0x29, 0x5f, 0xef,
- 0x2a, 0x79, 0x46, 0x97, 0x4c, 0x9f, 0xd0, 0x95, 0xb3, 0x0f, 0x71, 0xfc, 0xba, 0x1e, 0x3e, 0x91,
- 0xbb, 0x5a, 0x6e, 0x9f, 0xda, 0xe6, 0xe6, 0xd2, 0xe3, 0xbd, 0x16, 0xa8, 0xc1, 0x82, 0x35, 0xc0,
- 0x95, 0x09, 0x67, 0x62, 0xc0, 0x89, 0xa8, 0xf6, 0x68, 0x7f, 0x97, 0x61, 0x04, 0x8a, 0xc3, 0x17,
- 0xe5, 0x3f, 0x24, 0xd8, 0x96, 0xa8, 0x23, 0xc9, 0x55, 0x67, 0xbe, 0x40, 0x04, 0x6a, 0x3f, 0x37,
- 0x97, 0x2a, 0x7c, 0x52, 0x0e, 0x9f, 0xa8, 0xf0, 0xab, 0x2e, 0x7e, 0x31, 0xb9, 0xce, 0x7b, 0x02,
- 0x29, 0x38, 0xf4, 0x46, 0x17, 0xa7, 0x0f, 0xd3, 0xe4, 0x68, 0xb5, 0xae, 0xea, 0x1d, 0xfa, 0xec,
- 0x8b, 0xab, 0x13, 0xb4, 0x12, 0xc8, 0x93, 0x6d, 0x90, 0x27, 0x76, 0xe4, 0x89, 0x60, 0x0c, 0x1c,
- 0xf5, 0x64, 0xf3, 0x8b, 0xe7, 0x98, 0x83, 0x50, 0xaf, 0xfa, 0xa8, 0xe5, 0xae, 0x84, 0x2b, 0xd9,
- 0xe2, 0xda, 0x38, 0xc5, 0x95, 0x20, 0x5c, 0x89, 0xab, 0x78, 0x7c, 0x01, 0x97, 0xf1, 0xea, 0x38,
- 0xaa, 0xd4, 0x37, 0x67, 0x24, 0xae, 0xf9, 0xca, 0x38, 0xf1, 0x01, 0x3f, 0xe0, 0xfb, 0x13, 0x2f,
- 0xd8, 0x03, 0x5c, 0xe9, 0xc4, 0x0e, 0x1d, 0x2c, 0xf2, 0x6c, 0x75, 0x5c, 0x50, 0xf0, 0x50, 0xef,
- 0x77, 0x57, 0x52, 0xba, 0xa9, 0x54, 0x62, 0x29, 0x95, 0x3c, 0xd2, 0xe9, 0x20, 0x9a, 0x0a, 0x95,
- 0xc4, 0xa6, 0xc4, 0x64, 0x1b, 0xa5, 0x70, 0x7f, 0xdf, 0x65, 0x7f, 0x7a, 0x69, 0x7f, 0x7a, 0xa9,
- 0xdc, 0x2d, 0xce, 0x86, 0xcc, 0xe0, 0x33, 0x7b, 0x08, 0x97, 0x39, 0x76, 0x14, 0x95, 0x50, 0x29,
- 0xf2, 0xad, 0x7d, 0x25, 0x40, 0x4c, 0xfc, 0x25, 0xe5, 0x96, 0xf5, 0xa6, 0x0a, 0xb6, 0xbf, 0xbc,
- 0xb3, 0x3f, 0xf8, 0xf5, 0x4c, 0x0e, 0x7e, 0xed, 0xce, 0xb7, 0x2d, 0x4d, 0x45, 0xf1, 0xd3, 0x50,
- 0xb3, 0xc8, 0xf4, 0xd5, 0xf9, 0x69, 0x6a, 0xb2, 0x8c, 0xc9, 0x38, 0xc9, 0xf6, 0x2e, 0xe8, 0xbd,
- 0x0b, 0x7a, 0xef, 0x82, 0x7e, 0x85, 0x2e, 0x68, 0xac, 0xaa, 0x47, 0x54, 0x66, 0xf0, 0x79, 0xe9,
- 0xe9, 0xd6, 0x47, 0x73, 0x19, 0x48, 0x02, 0x85, 0x8f, 0x5f, 0x01, 0x6c, 0x55, 0xe7, 0x86, 0x89,
- 0x4b, 0xb1, 0x27, 0x6b, 0xb1, 0x27, 0xd5, 0xb0, 0x27, 0x12, 0x76, 0x88, 0x6e, 0x56, 0xcd, 0x4d,
- 0xbe, 0x3e, 0x34, 0xd7, 0xa2, 0x7f, 0x89, 0xbb, 0xb5, 0x18, 0x63, 0x09, 0x59, 0x6c, 0xcf, 0xcc,
- 0x0a, 0xda, 0xdf, 0xe2, 0x2a, 0x5f, 0x87, 0x77, 0xa7, 0x07, 0x3f, 0xae, 0x12, 0xfb, 0x12, 0x2f,
- 0x94, 0x19, 0x31, 0x94, 0x1c, 0x04, 0x28, 0xf6, 0x78, 0x69, 0x87, 0x6f, 0xa0, 0xae, 0xbc, 0x40,
- 0xff, 0x28, 0x12, 0x42, 0x90, 0xdb, 0x8d, 0x8d, 0xd1, 0x88, 0xb0, 0x28, 0x71, 0x9b, 0xb1, 0x06,
- 0x9c, 0x58, 0x81, 0x93, 0x02, 0x30, 0x76, 0xe5, 0xf1, 0x5a, 0x7c, 0x8e, 0xc2, 0xc7, 0x72, 0xce,
- 0x0d, 0x89, 0x63, 0x2e, 0x52, 0xde, 0x97, 0x3d, 0x6e, 0x08, 0xe9, 0x28, 0x4b, 0x68, 0x12, 0x50,
- 0xd8, 0x94, 0x43, 0xd1, 0x3e, 0xfe, 0xf1, 0xcf, 0x4a, 0x27, 0x2c, 0xf3, 0x31, 0x5a, 0x41, 0xe6,
- 0xf2, 0x63, 0x14, 0x5c, 0xe6, 0xe3, 0x15, 0xc5, 0x92, 0x99, 0x5c, 0x5d, 0x5e, 0xa6, 0xf3, 0xb2,
- 0x87, 0x67, 0x37, 0x0c, 0xc3, 0xd5, 0x32, 0xa4, 0xb5, 0xb7, 0x8d, 0xcd, 0xd5, 0x8a, 0x1c, 0xc7,
- 0x1c, 0xbb, 0xb0, 0x01, 0x27, 0x6f, 0x03, 0x95, 0xfe, 0x9a, 0x0b, 0x51, 0x86, 0x48, 0xc9, 0x76,
- 0x44, 0x42, 0xb9, 0xc1, 0x03, 0xe7, 0x72, 0x07, 0x40, 0xf8, 0x29, 0xd1, 0x55, 0x52, 0xe7, 0xca,
- 0x7b, 0xc9, 0xdd, 0xdc, 0x1a, 0xd3, 0xd2, 0xba, 0xd4, 0xb6, 0xec, 0x59, 0xed, 0xca, 0xdd, 0x54,
- 0x18, 0x9d, 0x39, 0xc4, 0x40, 0x42, 0xaa, 0xc4, 0x02, 0x22, 0x72, 0x97, 0x65, 0x83, 0xb0, 0x2c,
- 0x8e, 0x7c, 0x8c, 0xba, 0x0d, 0x87, 0x83, 0xd3, 0xdf, 0x37, 0x61, 0x10, 0xbd, 0x6c, 0x9a, 0xcf,
- 0xe3, 0x85, 0xe9, 0xfd, 0x13, 0x78, 0xa9, 0x64, 0x31, 0x1b, 0x4d, 0xbb, 0x37, 0x38, 0x0a, 0xaf,
- 0x76, 0xa4, 0x5c, 0x88, 0xe5, 0x56, 0x71, 0x62, 0xb6, 0x48, 0x50, 0xb1, 0xd6, 0x9a, 0x30, 0xb1,
- 0x6d, 0x02, 0xd6, 0x26, 0xd1, 0xb8, 0x09, 0xb2, 0x66, 0x4c, 0x54, 0x7f, 0x54, 0x05, 0x4d, 0x98,
- 0x0f, 0x92, 0x48, 0xfc, 0x0c, 0x18, 0x58, 0x78, 0xc7, 0x0b, 0xb5, 0xf5, 0x42, 0x6d, 0x51, 0xa8,
- 0x2d, 0x0a, 0xb5, 0xa1, 0x90, 0xe6, 0xef, 0x27, 0xd8, 0x7c, 0x1a, 0x05, 0x96, 0x8d, 0x3e, 0x7d,
- 0x54, 0xa9, 0x89, 0x64, 0x84, 0x14, 0xcd, 0x14, 0xba, 0x84, 0xe3, 0x05, 0xb4, 0x21, 0x7c, 0xe1,
- 0x68, 0xda, 0x10, 0xc9, 0x1c, 0x7d, 0xf8, 0x6a, 0x8f, 0x41, 0x84, 0x7f, 0xd7, 0xb7, 0xe4, 0xdd,
- 0x2e, 0x57, 0xd6, 0xbc, 0xd5, 0xed, 0x92, 0xc7, 0x45, 0x8b, 0xaf, 0x53, 0x24, 0x1d, 0xd2, 0x88,
- 0xbd, 0x40, 0xc4, 0x9e, 0x95, 0x62, 0xef, 0x49, 0xb9, 0xc1, 0x21, 0x84, 0xb1, 0x84, 0x08, 0xe1,
- 0x0e, 0x85, 0x6d, 0xa0, 0x2f, 0x08, 0xdf, 0x55, 0x1c, 0x7e, 0x20, 0x18, 0x2a, 0xc4, 0xb3, 0xc7,
- 0x2b, 0x0c, 0x3f, 0x99, 0x3e, 0x64, 0xe8, 0x81, 0xa1, 0xc0, 0xbe, 0x26, 0x0d, 0xd4, 0x59, 0xd1,
- 0x5f, 0x9b, 0xe0, 0x32, 0x44, 0xe8, 0xb7, 0x05, 0x0f, 0x54, 0xe1, 0x57, 0x48, 0xd1, 0x24, 0x2c,
- 0x96, 0x14, 0x24, 0x5e, 0x18, 0x23, 0xd2, 0xe7, 0xd5, 0xf8, 0xb8, 0xed, 0x74, 0xf8, 0x7c, 0x16,
- 0xe2, 0xeb, 0x7e, 0xf2, 0x17, 0xf5, 0xd2, 0x22, 0xa7, 0x53, 0xe6, 0xfc, 0x2c, 0x2a, 0x04, 0xdb,
- 0x0b, 0x8d, 0x5b, 0x26, 0xd4, 0x5a, 0x36, 0x6f, 0x99, 0x28, 0xa9, 0x87, 0x50, 0x82, 0xdb, 0x49,
- 0xaa, 0xcc, 0xe5, 0x5e, 0x47, 0x60, 0x4c, 0x5d, 0x08, 0x25, 0x59, 0x36, 0x06, 0x21, 0xb3, 0x20,
- 0x1b, 0x6d, 0x10, 0xe8, 0xb1, 0x8b, 0x89, 0x8d, 0x25, 0x49, 0xaf, 0x01, 0x5d, 0xa6, 0x31, 0x96,
- 0xa5, 0x05, 0x38, 0xf5, 0x05, 0x3e, 0x0c, 0x5b, 0x96, 0x69, 0xc9, 0xea, 0xc5, 0x13, 0xc4, 0x83,
- 0x60, 0xc8, 0x41, 0xd0, 0x35, 0x24, 0x99, 0xd9, 0x3b, 0x08, 0x16, 0xf8, 0xd9, 0x28, 0xef, 0x0d,
- 0x75, 0x5a, 0xe7, 0x59, 0x1e, 0xe7, 0x69, 0x77, 0xb1, 0x9a, 0x24, 0xd9, 0xd8, 0x52, 0x90, 0x84,
- 0x98, 0xd3, 0x76, 0x93, 0x14, 0x21, 0xde, 0x1b, 0xe2, 0x08, 0x8c, 0x2f, 0x60, 0xf7, 0x60, 0xcd,
- 0x06, 0x1a, 0x49, 0x1d, 0xc7, 0x49, 0x8a, 0x16, 0xae, 0x71, 0x3c, 0x4d, 0x2d, 0x10, 0x03, 0xf6,
- 0x7a, 0x83, 0x96, 0x2d, 0x38, 0x00, 0x44, 0xb0, 0x9e, 0x8c, 0x47, 0x80, 0x98, 0xcb, 0x93, 0x78,
- 0x16, 0x5a, 0x8e, 0x5c, 0x15, 0x4d, 0xbb, 0x82, 0x61, 0xa7, 0xb0, 0xe8, 0x33, 0x79, 0x79, 0x5c,
- 0xe8, 0x31, 0x91, 0x3c, 0x2b, 0xf9, 0x49, 0x13, 0xe6, 0x1d, 0x55, 0x73, 0xd9, 0x39, 0x15, 0xac,
- 0x79, 0x08, 0x0f, 0x20, 0x4b, 0x84, 0x0e, 0x61, 0xa9, 0x08, 0x54, 0xe6, 0xcb, 0x45, 0x3a, 0x98,
- 0x40, 0xb0, 0x41, 0xc4, 0x79, 0xe3, 0x34, 0x6a, 0x68, 0xf3, 0xfa, 0xaf, 0xce, 0x77, 0xa6, 0xa8,
- 0x42, 0x9f, 0xc2, 0x02, 0xf6, 0x83, 0x65, 0xfa, 0xc2, 0x3b, 0x23, 0x3f, 0xd8, 0x67, 0x2d, 0xea,
- 0x54, 0x4c, 0x05, 0x88, 0x41, 0x42, 0xd0, 0x5f, 0xad, 0xef, 0x3e, 0xfd, 0xd5, 0xfe, 0xee, 0xb3,
- 0x09, 0xec, 0x06, 0x38, 0x6e, 0x71, 0x78, 0x57, 0x83, 0x3e, 0xab, 0x41, 0x8d, 0xf7, 0xab, 0x90,
- 0x57, 0x56, 0x44, 0x5c, 0xd6, 0x94, 0xf5, 0x88, 0xa9, 0x54, 0xa1, 0xf8, 0xd4, 0x34, 0xd5, 0x57,
- 0x76, 0x9e, 0x8d, 0xa6, 0xf9, 0xba, 0x10, 0xda, 0x34, 0x12, 0x32, 0x97, 0x46, 0x48, 0x04, 0x0d,
- 0x33, 0x21, 0x8d, 0x22, 0x15, 0x5b, 0x53, 0x1d, 0x45, 0x06, 0x45, 0xa4, 0x4b, 0xa4, 0xcf, 0x91,
- 0xda, 0x4f, 0x07, 0x56, 0xc4, 0x41, 0x89, 0x08, 0xac, 0x7d, 0x38, 0x28, 0xc9, 0x0d, 0xac, 0x38,
- 0x15, 0xda, 0x24, 0x97, 0x16, 0x25, 0x8f, 0x98, 0x65, 0x60, 0xa7, 0x80, 0x0b, 0x53, 0xa5, 0x1d,
- 0x9b, 0x5e, 0xe0, 0x59, 0x0e, 0xa1, 0x27, 0xbd, 0xa8, 0x50, 0x9a, 0x9d, 0x8b, 0x42, 0x8a, 0x00,
- 0x3b, 0xff, 0x44, 0xe5, 0x44, 0xed, 0x27, 0xcc, 0xa5, 0x41, 0xe7, 0x08, 0x7b, 0x59, 0xf1, 0x48,
- 0x28, 0xac, 0x8e, 0xa5, 0x33, 0x91, 0xd5, 0xa0, 0xc9, 0xa3, 0x9a, 0x42, 0xc2, 0x5f, 0x8a, 0xf8,
- 0x66, 0xba, 0x22, 0x99, 0x5a, 0xe7, 0x6b, 0x07, 0x91, 0xc4, 0x5e, 0x6e, 0xe3, 0x90, 0xd0, 0xfc,
- 0x5d, 0x9e, 0x58, 0x1f, 0xaf, 0xe5, 0x2a, 0x28, 0x8c, 0x20, 0x86, 0x4c, 0x22, 0x53, 0x45, 0x00,
- 0x6f, 0x4c, 0xbf, 0x09, 0xf5, 0x66, 0xe0, 0xf8, 0xb1, 0x0e, 0x9c, 0x9d, 0xc2, 0x07, 0xb4, 0xd4,
- 0x85, 0xc6, 0x87, 0xe3, 0x57, 0x70, 0xc6, 0x2b, 0xbc, 0x93, 0xbb, 0x02, 0xcf, 0x76, 0xc4, 0xab,
- 0xd3, 0x08, 0x87, 0x29, 0x95, 0x65, 0x40, 0x5d, 0xc3, 0xaf, 0xf2, 0x27, 0x29, 0xd8, 0x43, 0xd2,
- 0x09, 0x07, 0x67, 0x2d, 0x2f, 0x08, 0x0e, 0xe4, 0x1a, 0xfb, 0xa4, 0x1d, 0x17, 0x61, 0xaf, 0x32,
- 0x47, 0xe3, 0x63, 0x3f, 0x3d, 0x27, 0xc7, 0xd7, 0x7f, 0xf5, 0x68, 0xa4, 0x5f, 0xd9, 0xf3, 0x0c,
- 0xb2, 0xd1, 0xb4, 0xba, 0xf0, 0x31, 0x91, 0x21, 0x51, 0x47, 0x2a, 0x81, 0x6a, 0x24, 0x3b, 0x4e,
- 0x5b, 0x7d, 0xa8, 0x43, 0x5a, 0x2b, 0x1c, 0xa8, 0x09, 0x37, 0x75, 0xad, 0x3d, 0x1e, 0xdf, 0xb8,
- 0x0a, 0x0e, 0x21, 0x5a, 0x2f, 0xe7, 0x4b, 0x29, 0xfe, 0xf4, 0x35, 0x95, 0xca, 0xe8, 0xdf, 0x40,
- 0x5a, 0xa0, 0x60, 0xf4, 0xe5, 0x25, 0x88, 0x2d, 0x27, 0xf4, 0xd3, 0x51, 0x75, 0x28, 0x1e, 0x9d,
- 0x5c, 0x68, 0x0a, 0x91, 0x9c, 0x8f, 0x84, 0x28, 0xb6, 0x29, 0x20, 0x0e, 0xaf, 0xa2, 0x4f, 0xd4,
- 0x3e, 0x34, 0x54, 0xfd, 0x42, 0x5d, 0xf8, 0xf8, 0xb3, 0x55, 0xe0, 0x26, 0x81, 0xd8, 0xd9, 0x0a,
- 0xd2, 0xd6, 0xf7, 0xba, 0x54, 0xd4, 0xb5, 0x3a, 0x6f, 0xa9, 0xa9, 0x14, 0x3e, 0x49, 0xa8, 0xa8,
- 0xcd, 0xd7, 0xf6, 0x7b, 0x3a, 0xd3, 0x64, 0xd5, 0x0b, 0x3b, 0x9a, 0x28, 0x80, 0xa7, 0xd5, 0x6b,
- 0x7d, 0x2f, 0x82, 0xfe, 0x26, 0xfe, 0x20, 0x97, 0x9c, 0xbb, 0xda, 0xab, 0xfc, 0x0f, 0xaf, 0xf2,
- 0xdb, 0x3c, 0xc5, 0xa3, 0xf1, 0xb8, 0xec, 0xe4, 0x92, 0xc8, 0xb7, 0x1f, 0x5f, 0x12, 0x30, 0xa6,
- 0x33, 0x4c, 0x52, 0x6e, 0x99, 0xf3, 0x5f, 0x05, 0x2b, 0x7b, 0xf9, 0x29, 0x1e, 0x67, 0x65, 0x14,
- 0x8b, 0x7c, 0x3b, 0xc5, 0x02, 0xc6, 0x44, 0xb1, 0x94, 0x5b, 0x46, 0xb1, 0x0a, 0xf6, 0xa2, 0x0f,
- 0x3b, 0xe1, 0xa6, 0x94, 0x9c, 0x9b, 0x11, 0xf9, 0xf6, 0x47, 0x59, 0x39, 0x88, 0xf1, 0x61, 0x56,
- 0x91, 0x5b, 0xfa, 0x30, 0x97, 0x02, 0xb6, 0x8e, 0x60, 0xfb, 0xb9, 0x36, 0x9e, 0x5d, 0x4e, 0xae,
- 0xed, 0x84, 0x9b, 0xc8, 0x5c, 0x4b, 0xac, 0xb2, 0x37, 0xf1, 0x1c, 0x6d, 0xc1, 0xc7, 0x34, 0xd9,
- 0x37, 0x75, 0x1f, 0x98, 0x4c, 0xfc, 0x6a, 0x36, 0x2b, 0x48, 0x61, 0xc5, 0xed, 0x7a, 0x48, 0x13,
- 0xdb, 0x95, 0xac, 0x55, 0x49, 0xca, 0x89, 0x9f, 0xa6, 0x23, 0x56, 0x22, 0xd7, 0x57, 0x65, 0x9f,
- 0xe9, 0xb0, 0x95, 0x8c, 0x6a, 0x2b, 0xf9, 0x25, 0x7e, 0x9a, 0x68, 0x11, 0xb9, 0xbe, 0x2a, 0xd5,
- 0x4c, 0xb4, 0xc8, 0xa8, 0x36, 0x97, 0x4c, 0x3b, 0x3f, 0x9b, 0x25, 0x09, 0x1c, 0xf1, 0xd3, 0xf4,
- 0x16, 0x2f, 0xcf, 0xf4, 0x55, 0x29, 0x64, 0x7c, 0x93, 0x57, 0xc2, 0xb4, 0x8d, 0x28, 0xe1, 0xbf,
- 0x6c, 0x84, 0xd0, 0x53, 0x71, 0x92, 0x74, 0xb1, 0x92, 0x41, 0xb7, 0x2e, 0x8b, 0x32, 0x62, 0xef,
- 0xd5, 0xd8, 0x7b, 0x35, 0xf6, 0x5e, 0x8d, 0xbd, 0x57, 0x63, 0xef, 0xd5, 0x78, 0x3d, 0x5e, 0x0d,
- 0x76, 0x22, 0x58, 0x9c, 0x79, 0x53, 0x4e, 0xc9, 0x11, 0x3e, 0x78, 0x56, 0x8e, 0x0f, 0xf1, 0x5a,
- 0xd2, 0x7c, 0x96, 0x8d, 0x63, 0x68, 0xfd, 0x3d, 0x3c, 0x21, 0x54, 0x3f, 0x23, 0x27, 0xdc, 0x50,
- 0xdb, 0x9a, 0x4b, 0xb8, 0x73, 0x85, 0xaf, 0x8e, 0x11, 0x25, 0x8d, 0x6c, 0x20, 0x4a, 0x1d, 0xe4,
- 0x93, 0x67, 0x40, 0x6d, 0xf5, 0x93, 0x60, 0x72, 0xf4, 0xf2, 0xd3, 0xc5, 0xa7, 0xcf, 0xdd, 0xf3,
- 0x3f, 0x6b, 0xef, 0xa4, 0xfb, 0x50, 0xa7, 0x9f, 0x7e, 0x3e, 0xed, 0xfe, 0x7c, 0xf2, 0xeb, 0xaf,
- 0x27, 0xa8, 0xb5, 0xed, 0xd6, 0xb1, 0xe1, 0x30, 0xcc, 0x41, 0x51, 0x6b, 0x86, 0xc5, 0xb8, 0x82,
- 0x1d, 0xbc, 0x5b, 0x1b, 0x76, 0x87, 0xf6, 0xe7, 0xae, 0x4c, 0xc8, 0x9d, 0xda, 0x7f, 0x8f, 0x60,
- 0xbe, 0x99, 0xbc, 0x79, 0x66, 0x93, 0x47, 0x3e, 0x6d, 0x65, 0xb1, 0xd2, 0xee, 0x61, 0xc8, 0x94,
- 0x72, 0xe9, 0x66, 0x76, 0x48, 0xb9, 0x19, 0xb2, 0x91, 0x19, 0xf1, 0x18, 0xa7, 0xef, 0x24, 0xe6,
- 0xd9, 0x4c, 0x9f, 0x2f, 0xe3, 0x8c, 0xcd, 0x54, 0x72, 0x10, 0xcf, 0x74, 0x78, 0x40, 0xb1, 0x2e,
- 0x8a, 0x74, 0x3a, 0x4c, 0xfc, 0xb2, 0x3a, 0xd6, 0x07, 0x59, 0xe2, 0x4a, 0x96, 0xcc, 0xac, 0xf1,
- 0x34, 0x53, 0xe8, 0xd8, 0x15, 0x75, 0x1a, 0x11, 0xb4, 0x81, 0x8c, 0x84, 0x34, 0xa4, 0x32, 0xfb,
- 0x61, 0xe2, 0x22, 0x21, 0x0a, 0x03, 0x87, 0xe3, 0xf7, 0x14, 0xd6, 0x74, 0x43, 0xf9, 0x4c, 0xe5,
- 0xd5, 0xe5, 0x65, 0xe4, 0x60, 0x55, 0xb9, 0x81, 0xef, 0x2d, 0x50, 0xb5, 0x99, 0x2b, 0xe2, 0xd0,
- 0x3f, 0xec, 0x30, 0x4e, 0x24, 0xb1, 0x00, 0xa9, 0xce, 0xe1, 0xdd, 0xe7, 0xb5, 0x9b, 0xed, 0xf7,
- 0x01, 0x11, 0xce, 0x75, 0x41, 0x85, 0x5b, 0x42, 0x06, 0xa9, 0x1b, 0x6a, 0x16, 0xa3, 0x19, 0x88,
- 0x05, 0x95, 0x22, 0x0b, 0xef, 0x24, 0x72, 0xf1, 0x91, 0x40, 0x93, 0xbf, 0x18, 0xbc, 0xc5, 0xcd,
- 0xb8, 0xd8, 0x21, 0xa4, 0xae, 0x7e, 0x84, 0x3f, 0x3c, 0x79, 0x82, 0x2a, 0x6a, 0x0e, 0xf6, 0x55,
- 0x4b, 0x87, 0x08, 0x81, 0xb4, 0x86, 0x8c, 0xc0, 0x87, 0x94, 0xba, 0x92, 0x52, 0xf1, 0xc4, 0xa0,
- 0xa7, 0xae, 0x64, 0xf7, 0xf2, 0x65, 0xff, 0x1f, 0x03, 0x90, 0xfe, 0x1c
+ 0xc5, 0x51, 0x54, 0x00, 0x59, 0xdd, 0x5c, 0x42, 0x47, 0x08, 0xc0, 0xc3, 0x11, 0xd3, 0xf5, 0x86,
+ 0x71, 0xaf, 0x94, 0x45, 0x32, 0xe8, 0x4a, 0xac, 0xd2, 0xae, 0x2c, 0x55, 0xd2, 0xc2, 0x6a, 0x20,
+ 0x6c, 0x1e, 0xa3, 0xd5, 0x77, 0x61, 0xa6, 0x8c, 0xe4, 0x29, 0xa4, 0x31, 0x35, 0x80, 0xb6, 0x98,
+ 0x40, 0x70, 0xea, 0x14, 0x25, 0xa1, 0x46, 0x33, 0x35, 0x0a, 0x55, 0x18, 0x56, 0xc9, 0x1a, 0x2a,
+ 0x93, 0xf1, 0x95, 0xa5, 0xf7, 0x20, 0x47, 0xa1, 0x10, 0xe7, 0x52, 0xf2, 0x20, 0x93, 0x13, 0x27,
+ 0x15, 0xc3, 0xe9, 0x1a, 0x5d, 0x05, 0xac, 0x6b, 0x48, 0xa2, 0x1c, 0x6e, 0x2e, 0x4f, 0x33, 0xad,
+ 0x84, 0x71, 0x75, 0xa1, 0x48, 0x9b, 0x98, 0x39, 0x76, 0xf2, 0x24, 0x98, 0x12, 0x0a, 0x17, 0xf9,
+ 0x3c, 0xfb, 0x77, 0x5a, 0xc6, 0x7a, 0x32, 0x84, 0x9d, 0x03, 0x65, 0x28, 0x13, 0x23, 0x2a, 0xf9,
+ 0x65, 0xfc, 0xa8, 0x03, 0xae, 0xa7, 0xfd, 0x66, 0xd4, 0xcf, 0x87, 0xa5, 0xb4, 0x63, 0x88, 0x32,
+ 0x16, 0x95, 0xe1, 0x2c, 0x8c, 0xaa, 0x80, 0xac, 0x61, 0x57, 0x1d, 0x76, 0x7d, 0x1b, 0x4a, 0x19,
+ 0x45, 0x85, 0xb1, 0xf2, 0x8b, 0x0a, 0x66, 0x62, 0x1b, 0x0d, 0xa2, 0x8c, 0x7b, 0x8a, 0xa0, 0xc4,
+ 0x5d, 0x20, 0x16, 0xc8, 0x43, 0xb4, 0x40, 0xf6, 0xe3, 0x3c, 0x96, 0xd6, 0x47, 0xf8, 0x85, 0xd6,
+ 0xc8, 0x52, 0xf1, 0xd6, 0x23, 0x8a, 0xae, 0x6e, 0x62, 0x52, 0x19, 0xe6, 0x73, 0x51, 0xe7, 0x32,
+ 0xf2, 0x74, 0x69, 0x16, 0x6d, 0x24, 0xb3, 0xc8, 0x9f, 0x48, 0xb7, 0x9d, 0x99, 0x54, 0xf2, 0x85,
+ 0x00, 0xe3, 0x15, 0x9a, 0x04, 0x54, 0xb4, 0x89, 0x0c, 0x82, 0x7f, 0x0c, 0x35, 0x42, 0xb2, 0xcf,
+ 0x84, 0x11, 0xaf, 0x4d, 0x93, 0x38, 0xd1, 0x46, 0x72, 0x85, 0xfe, 0x35, 0x54, 0x46, 0x73, 0x7c,
+ 0x49, 0xcc, 0x98, 0xaa, 0xe4, 0x08, 0xb6, 0x11, 0x17, 0xf2, 0x87, 0x69, 0x44, 0xe5, 0x7c, 0x5f,
+ 0x17, 0x24, 0xa6, 0xf1, 0x55, 0x11, 0x6e, 0x2d, 0x0a, 0xe4, 0x0f, 0x43, 0xd7, 0xc8, 0xd9, 0xbe,
+ 0x2e, 0x23, 0x2c, 0x5c, 0xa0, 0xa2, 0xbc, 0xc7, 0x04, 0x57, 0x3f, 0xed, 0xd4, 0x89, 0xf1, 0xd3,
+ 0x67, 0xbf, 0x69, 0x18, 0x75, 0xac, 0xd6, 0xe9, 0x8b, 0x7d, 0x56, 0x44, 0xa1, 0x89, 0x70, 0x85,
+ 0xa0, 0x2e, 0x12, 0xbb, 0x06, 0xdc, 0x5d, 0x1e, 0xfa, 0xa7, 0x21, 0xb4, 0xc6, 0xde, 0x68, 0xde,
+ 0x43, 0x7a, 0x13, 0xd1, 0x69, 0x22, 0x54, 0x15, 0x1e, 0x56, 0x04, 0xec, 0xb5, 0x9a, 0xc7, 0x6e,
+ 0x88, 0x8c, 0x70, 0x47, 0xd7, 0x9e, 0x98, 0x8a, 0xdc, 0xcb, 0xe6, 0x53, 0xa4, 0x07, 0xcd, 0x98,
+ 0x25, 0xa5, 0xa0, 0xa2, 0x25, 0x55, 0xad, 0x0c, 0x95, 0xd4, 0x0a, 0xd5, 0x23, 0x4a, 0xaa, 0xe7,
+ 0x90, 0xc9, 0x57, 0x97, 0xfb, 0x1d, 0x34, 0x48, 0x55, 0x37, 0xbb, 0xab, 0x41, 0xbf, 0x50, 0x37,
+ 0xd4, 0x6c, 0x9e, 0xfd, 0x2b, 0xed, 0xe5, 0x69, 0x9f, 0x91, 0xaf, 0xda, 0x72, 0x0a, 0x3d, 0xc4,
+ 0xa6, 0xbb, 0x5f, 0xed, 0x9e, 0xa3, 0xd7, 0xd8, 0xbc, 0x09, 0x4a, 0x34, 0x43, 0x64, 0x51, 0xd9,
+ 0x2d, 0x4d, 0x8d, 0x14, 0xea, 0x66, 0xa0, 0xcd, 0x2b, 0x29, 0x56, 0x6c, 0x94, 0xa5, 0xa7, 0x25,
+ 0x1c, 0xcd, 0xe5, 0x6a, 0xd3, 0xa6, 0x96, 0x29, 0xbc, 0x06, 0x2a, 0xb7, 0xa8, 0x41, 0x2e, 0x7d,
+ 0x13, 0xde, 0xdd, 0x49, 0xbc, 0x1e, 0x4f, 0xf3, 0x51, 0x3c, 0x1e, 0xc5, 0x0b, 0x2c, 0x2e, 0x11,
+ 0xb3, 0x06, 0x9f, 0x4e, 0xff, 0x38, 0xfb, 0x78, 0xda, 0x3d, 0x3f, 0xfb, 0xf3, 0xf4, 0x97, 0xee,
+ 0xb7, 0x93, 0xdf, 0xce, 0xbe, 0x06, 0xc6, 0x5a, 0x42, 0xb2, 0x60, 0x01, 0xe3, 0x1f, 0x3a, 0xb4,
+ 0xbe, 0xe6, 0xd2, 0x67, 0xbf, 0x56, 0xbe, 0x82, 0xda, 0xa5, 0x8e, 0x2e, 0xeb, 0x4a, 0xf6, 0xd8,
+ 0xea, 0xf6, 0x6e, 0x14, 0xe6, 0x47, 0xd6, 0x7c, 0x77, 0xa7, 0xbc, 0x3e, 0x85, 0xd2, 0xf9, 0x94,
+ 0xaa, 0xe2, 0x13, 0xe8, 0x77, 0x54, 0xb7, 0xb3, 0x4d, 0x88, 0x2a, 0x9a, 0x9a, 0x95, 0xdb, 0x2b,
+ 0x6b, 0x5d, 0x16, 0x3e, 0x5e, 0xaf, 0x47, 0xd9, 0x99, 0xb4, 0xaa, 0x42, 0xb4, 0x86, 0x03, 0x37,
+ 0xd7, 0x64, 0xd6, 0xb0, 0xd7, 0x56, 0x3a, 0xc8, 0x5a, 0xc6, 0xb9, 0xb7, 0xde, 0x80, 0xd9, 0x02,
+ 0x09, 0xf5, 0x90, 0x20, 0x61, 0x92, 0x7b, 0x9c, 0x4e, 0x07, 0x88, 0x32, 0xf2, 0x87, 0xc9, 0x57,
+ 0x37, 0xb4, 0x8a, 0x6e, 0x8a, 0xe7, 0x36, 0xd4, 0x32, 0xd1, 0x02, 0x8a, 0xf3, 0x1b, 0x93, 0x78,
+ 0xe9, 0x60, 0xa5, 0x59, 0x93, 0xcb, 0xca, 0x48, 0x75, 0xf3, 0x68, 0x31, 0xc9, 0xb2, 0x7c, 0xb8,
+ 0xc8, 0xd3, 0x99, 0xd3, 0x6a, 0xb6, 0x7c, 0x1d, 0x91, 0xaf, 0x12, 0x48, 0xf4, 0x1b, 0x82, 0x83,
+ 0xea, 0xa2, 0x91, 0xdc, 0x97, 0xb5, 0x7f, 0xd4, 0x10, 0x96, 0x76, 0xed, 0x27, 0xf8, 0x53, 0xfb,
+ 0x50, 0x93, 0xb0, 0x17, 0x30, 0x43, 0x75, 0x1a, 0x76, 0xc2, 0xb0, 0xe6, 0x05, 0x48, 0x73, 0x8d,
+ 0xf1, 0x16, 0x78, 0xdc, 0x49, 0xe6, 0x31, 0xbd, 0x4f, 0xe6, 0x18, 0x4f, 0xd3, 0x09, 0x25, 0x0d,
+ 0xfa, 0x1e, 0x8e, 0xb3, 0xc7, 0xde, 0x12, 0xb1, 0xef, 0x72, 0x08, 0x72, 0xac, 0x2b, 0xec, 0x4d,
+ 0x8a, 0xe6, 0x52, 0x6e, 0x16, 0x5d, 0x24, 0xcf, 0xec, 0x8a, 0x80, 0x76, 0x90, 0x7c, 0xcd, 0x09,
+ 0x41, 0x0a, 0xd3, 0x2c, 0xe3, 0x52, 0xa0, 0xa2, 0xdf, 0x85, 0x47, 0x6c, 0xb3, 0x35, 0xbc, 0xdc,
+ 0xd1, 0xc9, 0x0a, 0x99, 0xbd, 0x95, 0x36, 0xb7, 0x38, 0x4b, 0x1f, 0x21, 0x1d, 0x6e, 0xba, 0x80,
+ 0x9c, 0x2a, 0x3b, 0x29, 0xb4, 0x8e, 0x90, 0xec, 0x60, 0xca, 0xbd, 0xf7, 0xcf, 0xd3, 0x6f, 0x5f,
+ 0xb1, 0x4a, 0x86, 0xb7, 0xae, 0x83, 0xf6, 0x9b, 0x66, 0x2b, 0xe4, 0x1b, 0x73, 0x3f, 0x9f, 0xfc,
+ 0x7e, 0x71, 0xd1, 0xfd, 0xf8, 0xf5, 0xf4, 0x33, 0x9a, 0x59, 0x87, 0xef, 0xdf, 0xbd, 0x3f, 0xea,
+ 0x74, 0xde, 0xb5, 0x8e, 0x5a, 0xed, 0xa3, 0xc3, 0xce, 0xdb, 0x83, 0xaa, 0x5e, 0x04, 0xca, 0x19,
+ 0xe4, 0x8f, 0xc1, 0x7e, 0x22, 0x19, 0xbe, 0x60, 0x13, 0xcd, 0xd0, 0x94, 0x19, 0x21, 0xda, 0x6c,
+ 0xb4, 0xcd, 0x4b, 0xd4, 0x83, 0x7b, 0x16, 0xe8, 0x09, 0x08, 0x3c, 0x82, 0xfd, 0x6e, 0x25, 0x6b,
+ 0x8d, 0x20, 0xbc, 0x88, 0x16, 0xff, 0x3b, 0xcf, 0x9d, 0x06, 0x4a, 0xf6, 0xc6, 0xd9, 0xc0, 0x81,
+ 0xd1, 0x08, 0x48, 0x03, 0x03, 0x69, 0x8c, 0x03, 0x31, 0x10, 0xae, 0x1b, 0x1c, 0xa2, 0x21, 0xe2,
+ 0x43, 0x1a, 0x5d, 0x78, 0x7a, 0xc5, 0xa1, 0x26, 0xfb, 0x99, 0x1e, 0x4f, 0x88, 0x2e, 0xd8, 0x60,
+ 0xc4, 0xf6, 0xca, 0x16, 0x64, 0x92, 0xeb, 0x26, 0x63, 0x9d, 0x02, 0x13, 0x21, 0x61, 0x94, 0x24,
+ 0xc0, 0x6f, 0xeb, 0xc4, 0xc2, 0x03, 0x4d, 0x6d, 0x33, 0x90, 0x98, 0x0b, 0x16, 0xb6, 0xdf, 0x98,
+ 0xa1, 0xad, 0x6a, 0x13, 0x6d, 0x4e, 0x15, 0xc6, 0x24, 0xb9, 0xfd, 0xa8, 0x81, 0xba, 0xd1, 0x43,
+ 0x63, 0x86, 0xff, 0xef, 0x67, 0xb9, 0xc3, 0xe9, 0xf2, 0xf9, 0x2f, 0xc6, 0x0f, 0xd7, 0xf1, 0x38,
+ 0x22, 0x68, 0x3c, 0xa9, 0x59, 0x9e, 0x20, 0xdb, 0x4b, 0x97, 0x33, 0xa7, 0xaf, 0xad, 0x4a, 0x78,
+ 0xe0, 0x50, 0x51, 0xd8, 0x3d, 0x62, 0xff, 0xbb, 0x3b, 0xd8, 0x87, 0xbe, 0xc9, 0xe6, 0xe3, 0x7e,
+ 0xd5, 0x9d, 0xdc, 0x8d, 0x96, 0x24, 0x8f, 0x22, 0x97, 0xb6, 0x6e, 0x9b, 0xcb, 0x28, 0x26, 0x7f,
+ 0xe9, 0xf7, 0x0a, 0xc4, 0x56, 0x83, 0xa4, 0xad, 0xe4, 0xcd, 0xce, 0xe2, 0xce, 0xa1, 0x29, 0x87,
+ 0x2c, 0xc9, 0x73, 0x94, 0x62, 0xdf, 0xf5, 0x5f, 0xd3, 0x08, 0x7a, 0x54, 0xc4, 0xb0, 0xab, 0x86,
+ 0x81, 0xdd, 0xe6, 0x5c, 0xda, 0x7c, 0x53, 0xa0, 0x44, 0xe5, 0x3e, 0x96, 0x12, 0xb9, 0x0f, 0x73,
+ 0x4d, 0x1b, 0xd6, 0x7b, 0x1d, 0x2c, 0x68, 0x55, 0xd1, 0x1d, 0x0a, 0x89, 0xf1, 0xb4, 0x37, 0xcc,
+ 0xe6, 0xe6, 0x3c, 0x36, 0x99, 0x8a, 0x98, 0xc6, 0x71, 0x2f, 0x35, 0xf0, 0xc1, 0x62, 0x38, 0xba,
+ 0xcc, 0xc3, 0x4a, 0x9c, 0x54, 0xbe, 0x06, 0xda, 0x5d, 0x17, 0x6c, 0x84, 0xe8, 0xec, 0x61, 0xa4,
+ 0xe8, 0xc9, 0xd3, 0x2c, 0xff, 0x7d, 0x01, 0xe9, 0xda, 0xbe, 0xb0, 0xe4, 0x73, 0x3a, 0xcf, 0xd0,
+ 0x74, 0x2b, 0xb0, 0xa2, 0xe8, 0x0f, 0xc2, 0x89, 0xf2, 0xbc, 0x17, 0x54, 0x51, 0x28, 0x46, 0x55,
+ 0xa4, 0x22, 0x6d, 0xde, 0xa8, 0xc5, 0xb2, 0xf1, 0x18, 0x9f, 0xbd, 0xe9, 0xce, 0xd2, 0xf9, 0x62,
+ 0x86, 0xe0, 0x46, 0xd7, 0x29, 0x62, 0x05, 0x34, 0x15, 0xa2, 0xde, 0x18, 0x71, 0x04, 0x1a, 0xba,
+ 0xe3, 0x3a, 0xc8, 0x0c, 0xa7, 0xa4, 0xe5, 0x81, 0xb5, 0x76, 0x17, 0xab, 0xb8, 0x47, 0x30, 0xfc,
+ 0x6b, 0xf5, 0x3e, 0x26, 0x2a, 0x74, 0xcf, 0x8f, 0xc3, 0x47, 0xbb, 0x4e, 0x87, 0x71, 0x8d, 0xbf,
+ 0xc7, 0x2b, 0x69, 0x55, 0xc8, 0x86, 0x25, 0x62, 0xac, 0x82, 0xa7, 0x30, 0x1d, 0x13, 0x91, 0x88,
+ 0xe7, 0xf0, 0x7d, 0x06, 0x94, 0x1a, 0x25, 0xe3, 0xd9, 0x30, 0x8e, 0x50, 0xff, 0x85, 0x46, 0x29,
+ 0x87, 0x1b, 0xcd, 0x1a, 0xee, 0x61, 0x60, 0xec, 0x71, 0x63, 0x55, 0xd5, 0xfe, 0xab, 0x06, 0x53,
+ 0xd1, 0xa4, 0xff, 0x4a, 0x25, 0xf1, 0x74, 0xa5, 0xa5, 0xef, 0x48, 0x71, 0x4a, 0x92, 0xb1, 0xbc,
+ 0x17, 0x35, 0xdb, 0xe1, 0xdd, 0x4e, 0x66, 0xe1, 0xb3, 0x9a, 0x6e, 0x5a, 0xba, 0xb6, 0xad, 0xac,
+ 0x2d, 0xd2, 0xe6, 0x64, 0xa6, 0xa4, 0xec, 0x67, 0xae, 0x71, 0xe6, 0xca, 0xf4, 0xcd, 0xe2, 0x7e,
+ 0x1f, 0x75, 0x60, 0xf7, 0x32, 0xee, 0xe5, 0x19, 0xf8, 0x59, 0x3b, 0x85, 0x89, 0xcd, 0xf9, 0xa7,
+ 0x30, 0x9d, 0xd5, 0xc2, 0x8f, 0x31, 0xbb, 0xd9, 0xf8, 0x47, 0x71, 0xb2, 0x10, 0x02, 0xa6, 0xb9,
+ 0x72, 0x25, 0x65, 0x56, 0xd0, 0xa7, 0xd2, 0x13, 0x6a, 0xfc, 0x10, 0x6d, 0xe0, 0xdf, 0x2e, 0xa5,
+ 0x5e, 0x52, 0x1b, 0xf8, 0xea, 0x7f, 0x8d, 0xa0, 0xb0, 0xf7, 0x9d, 0xd5, 0xfd, 0x3c, 0xb8, 0x5e,
+ 0x17, 0x6f, 0x92, 0x6a, 0xb1, 0xb1, 0x70, 0xeb, 0x6d, 0x2b, 0xd5, 0x7a, 0x54, 0x9c, 0x75, 0xd8,
+ 0x11, 0x67, 0x85, 0x60, 0xcd, 0xa1, 0xa4, 0x35, 0xc7, 0x2d, 0xf5, 0x3e, 0x09, 0x5d, 0xd8, 0x33,
+ 0xe1, 0x0c, 0x0d, 0x1e, 0xb5, 0x36, 0xb2, 0x58, 0x8d, 0xc0, 0x81, 0x61, 0x14, 0x15, 0x0b, 0x8e,
+ 0x8d, 0x4a, 0x59, 0x55, 0x8c, 0x7f, 0x80, 0xa5, 0xd2, 0xfe, 0x20, 0xc5, 0x7c, 0x6b, 0x74, 0x1d,
+ 0x95, 0xfa, 0xb7, 0x1a, 0xca, 0xe6, 0x25, 0xf4, 0x74, 0x43, 0xc7, 0x6c, 0x75, 0x32, 0x11, 0xef,
+ 0xe3, 0xdd, 0xee, 0x0e, 0xc3, 0x1a, 0x36, 0x3e, 0xd6, 0x1e, 0x7d, 0xdd, 0x90, 0xbe, 0x97, 0x76,
+ 0x92, 0xea, 0x39, 0x1d, 0x08, 0x2a, 0x18, 0xa8, 0x4f, 0x7e, 0x66, 0x63, 0x07, 0xc7, 0x1a, 0xaa,
+ 0xf2, 0xf0, 0x93, 0x6c, 0xfc, 0x3d, 0xf0, 0xa6, 0xd9, 0x23, 0x6f, 0xdc, 0x6c, 0xb4, 0x7b, 0x62,
+ 0xb0, 0x45, 0x1f, 0xe4, 0xf8, 0xe7, 0x06, 0xb2, 0xc2, 0xe8, 0x6f, 0x30, 0x58, 0xe5, 0xb6, 0xc1,
+ 0xb9, 0xca, 0xc7, 0xa3, 0x69, 0xe9, 0x51, 0x39, 0x05, 0xc4, 0x2e, 0x63, 0x14, 0x30, 0x93, 0xac,
+ 0x51, 0x01, 0xca, 0xb8, 0xaa, 0x00, 0xf9, 0x8a, 0x64, 0x8f, 0xda, 0xe1, 0xca, 0x97, 0x49, 0x16,
+ 0x29, 0x00, 0x7e, 0x61, 0x30, 0x4c, 0xb2, 0x49, 0xc3, 0xb9, 0x55, 0x6f, 0x3e, 0xb5, 0xac, 0xc2,
+ 0x3c, 0x1b, 0x39, 0xaa, 0x6e, 0x1e, 0x28, 0x1a, 0x77, 0x1d, 0x26, 0x4d, 0x00, 0x5e, 0x61, 0xc6,
+ 0xf5, 0x56, 0x01, 0xa7, 0xf6, 0xf9, 0xce, 0x59, 0xf3, 0xa1, 0xb8, 0x6b, 0x8d, 0xab, 0xcd, 0x22,
+ 0xcf, 0x94, 0xb6, 0x6f, 0xc3, 0x26, 0xf7, 0x94, 0x91, 0x42, 0x53, 0x14, 0x6a, 0x2c, 0xa2, 0xbd,
+ 0xc1, 0xa5, 0x60, 0x36, 0x47, 0xf6, 0xd0, 0x8a, 0x29, 0x88, 0x44, 0x79, 0x07, 0xb7, 0xa5, 0xb6,
+ 0x01, 0x0a, 0xca, 0x37, 0x60, 0xd1, 0x35, 0x41, 0x99, 0x6c, 0xcf, 0xc1, 0xc5, 0x99, 0x10, 0xde,
+ 0x9d, 0x83, 0xf7, 0xe1, 0x6e, 0x10, 0xb1, 0xb3, 0x1b, 0xd8, 0xb8, 0xb9, 0xef, 0x0d, 0xa0, 0xea,
+ 0xcb, 0xc0, 0xb3, 0x3f, 0xd2, 0xcd, 0xee, 0x71, 0x5c, 0xce, 0xb3, 0x89, 0x19, 0x8f, 0x0c, 0x61,
+ 0xa4, 0x15, 0x56, 0x29, 0x19, 0x48, 0x25, 0x98, 0x5e, 0x04, 0x95, 0xb2, 0x4d, 0x44, 0xd3, 0xe1,
+ 0xd1, 0xe1, 0x2a, 0x10, 0x9e, 0x67, 0xe5, 0x64, 0x23, 0x43, 0x67, 0x1d, 0xd1, 0x79, 0x56, 0x42,
+ 0x32, 0xca, 0xac, 0x40, 0x30, 0x81, 0xaa, 0xbe, 0x5a, 0x3d, 0xd5, 0x91, 0x5c, 0x65, 0xb8, 0xe5,
+ 0x8f, 0x28, 0xee, 0x9a, 0x06, 0x49, 0xda, 0x8b, 0x56, 0x47, 0x31, 0xda, 0x76, 0xb0, 0xc4, 0xcf,
+ 0x28, 0xee, 0x16, 0x3b, 0xd9, 0x58, 0x21, 0x82, 0x35, 0x77, 0xb5, 0x7c, 0x91, 0x16, 0x2e, 0x4d,
+ 0x45, 0x32, 0x4d, 0x70, 0xe8, 0x44, 0x81, 0x80, 0xdb, 0x53, 0x2a, 0xc4, 0xed, 0x4d, 0xa8, 0xe3,
+ 0x48, 0x22, 0x51, 0x91, 0x09, 0x83, 0x92, 0x8f, 0xca, 0x53, 0x07, 0x18, 0x08, 0x9e, 0x6f, 0xd8,
+ 0x1f, 0x47, 0x85, 0x4c, 0x73, 0x19, 0x8a, 0xfb, 0xbc, 0x6a, 0x0e, 0x3b, 0x0b, 0x03, 0x24, 0x5c,
+ 0x50, 0x9f, 0x12, 0xc9, 0x61, 0xc7, 0x5b, 0xf2, 0x4c, 0x4d, 0xbf, 0x09, 0xab, 0x2d, 0xef, 0x40,
+ 0x2b, 0x12, 0xe6, 0xb3, 0x71, 0xbc, 0xa2, 0x37, 0x04, 0xc9, 0x56, 0xb0, 0x23, 0x77, 0x41, 0x73,
+ 0xd9, 0x90, 0xfb, 0xac, 0xb9, 0x74, 0x03, 0x41, 0xbe, 0xaf, 0x82, 0xae, 0x54, 0xd0, 0x95, 0x0c,
+ 0x6a, 0xaa, 0x2f, 0x29, 0xd6, 0x97, 0xa8, 0xf5, 0x25, 0x25, 0xf5, 0x25, 0x6a, 0x7d, 0x49, 0xa1,
+ 0xbe, 0x7b, 0x5e, 0xa4, 0xe4, 0x1d, 0xee, 0xa9, 0x9d, 0xe4, 0xf3, 0x31, 0x7a, 0xa8, 0x9b, 0x93,
+ 0x74, 0x00, 0xd5, 0x7a, 0x12, 0x4b, 0x3d, 0x5b, 0x28, 0x64, 0x6b, 0x6e, 0x3b, 0xda, 0xf7, 0x21,
+ 0x99, 0x78, 0xbc, 0x8c, 0xfb, 0xe9, 0xa3, 0x2e, 0x79, 0xbb, 0x5b, 0xb5, 0x76, 0xbd, 0xdc, 0x3c,
+ 0xe6, 0x5a, 0xf1, 0x18, 0xc7, 0x0e, 0x95, 0xce, 0xda, 0x46, 0xa0, 0x97, 0xf6, 0xc6, 0x8b, 0x13,
+ 0xd8, 0x9b, 0x5d, 0xca, 0xb5, 0x5c, 0xc9, 0x7d, 0xa2, 0x0b, 0xb9, 0x96, 0xeb, 0xb8, 0x0f, 0x76,
+ 0x19, 0xf7, 0x91, 0x8d, 0x0a, 0xd3, 0xf5, 0x5e, 0x10, 0x44, 0xd4, 0xf3, 0xef, 0xed, 0x30, 0x8e,
+ 0xc1, 0xf3, 0xb0, 0x24, 0xf6, 0x66, 0xc3, 0xde, 0x6c, 0xd8, 0x9b, 0x0d, 0x7b, 0xb3, 0xc1, 0x62,
+ 0x36, 0xfc, 0x33, 0xcb, 0x26, 0xf7, 0x37, 0x1d, 0x5e, 0xbb, 0x55, 0xb0, 0x93, 0x18, 0x2c, 0xa5,
+ 0xa6, 0x03, 0x1f, 0xa7, 0x1d, 0x98, 0x0f, 0x85, 0xba, 0xd6, 0x5b, 0x03, 0x8a, 0xce, 0xff, 0x10,
+ 0x41, 0x4e, 0xf6, 0xaa, 0xff, 0x5e, 0xf5, 0xdf, 0xab, 0xfe, 0xaf, 0x4b, 0xf5, 0xaf, 0xa8, 0xa8,
+ 0xef, 0x46, 0x45, 0x3f, 0x44, 0xa9, 0x63, 0x38, 0x8b, 0xae, 0xc6, 0x46, 0x63, 0x53, 0x8a, 0x67,
+ 0xcb, 0xfb, 0xb7, 0x8a, 0x2c, 0xc1, 0xb9, 0xe2, 0x70, 0xbe, 0x2e, 0x09, 0xaf, 0xd3, 0x79, 0x3e,
+ 0x42, 0x12, 0xb6, 0x3b, 0x80, 0x63, 0x34, 0xe9, 0x34, 0x0f, 0xd7, 0x1f, 0x8f, 0x04, 0xd5, 0x6f,
+ 0x8a, 0x90, 0xa0, 0x52, 0xa9, 0xb2, 0x15, 0x7c, 0x84, 0xe4, 0x22, 0xdb, 0xdd, 0x31, 0x5f, 0x9d,
+ 0x8d, 0xad, 0x77, 0x63, 0x51, 0x8e, 0xfd, 0x6e, 0x12, 0xe4, 0x96, 0xdf, 0x51, 0x60, 0x10, 0x25,
+ 0xd2, 0x6b, 0x58, 0x72, 0x39, 0x6a, 0xb8, 0xe6, 0x72, 0xd4, 0xb0, 0xc2, 0x35, 0x89, 0x61, 0x95,
+ 0x3b, 0x31, 0xf7, 0x3d, 0x62, 0x53, 0xfd, 0xac, 0x44, 0x15, 0x35, 0x1a, 0x8f, 0x87, 0xdc, 0x0a,
+ 0x48, 0x30, 0xc5, 0xe0, 0x40, 0xc9, 0x3e, 0x1b, 0x24, 0xe3, 0xcd, 0x20, 0x52, 0x70, 0x83, 0x61,
+ 0x90, 0x0b, 0x0f, 0x6d, 0xb7, 0x92, 0x86, 0xec, 0x56, 0xd2, 0xb0, 0xec, 0x56, 0x12, 0x2b, 0xbe,
+ 0xc9, 0x08, 0x14, 0xcf, 0x6e, 0x3c, 0xe0, 0x31, 0x1d, 0x3c, 0x31, 0xc9, 0x0c, 0x89, 0xa4, 0xa9,
+ 0x82, 0x04, 0xf3, 0x6d, 0x88, 0x3b, 0x0a, 0xae, 0x68, 0x82, 0x77, 0x00, 0x3e, 0xdc, 0x90, 0xd2,
+ 0xcf, 0x12, 0xc9, 0x27, 0xf3, 0x2c, 0x90, 0xa0, 0x96, 0x04, 0x47, 0x73, 0x89, 0x2f, 0x30, 0xad,
+ 0xd5, 0xf3, 0x72, 0x7c, 0x54, 0xb0, 0x55, 0xfb, 0x89, 0x76, 0x4d, 0xed, 0x03, 0x1e, 0x1f, 0xd0,
+ 0xfe, 0xa4, 0x0b, 0x9c, 0xd7, 0x38, 0x14, 0x2d, 0xfe, 0xd9, 0x9c, 0x7b, 0xad, 0x66, 0xa7, 0xdd,
+ 0x79, 0x53, 0x27, 0x9f, 0x03, 0xf4, 0xf9, 0xb6, 0x7d, 0xdc, 0xa1, 0x9f, 0x09, 0xfa, 0x6c, 0xbd,
+ 0xed, 0x74, 0x42, 0x3a, 0xbd, 0xd5, 0x43, 0x8b, 0xfc, 0x1c, 0x2c, 0x61, 0xd4, 0x49, 0x02, 0x62,
+ 0x04, 0x8b, 0x1d, 0x0e, 0x77, 0xe8, 0x8b, 0x7f, 0x30, 0x28, 0x46, 0x53, 0x8f, 0x64, 0x60, 0xee,
+ 0x72, 0x99, 0xc3, 0xe1, 0xd0, 0x6c, 0x8a, 0xfa, 0x8e, 0x1c, 0xe8, 0x85, 0xeb, 0x3a, 0xa4, 0xfd,
+ 0x41, 0xfb, 0xcd, 0xe1, 0xbb, 0x23, 0x08, 0x00, 0xcb, 0x85, 0x9e, 0x2b, 0xaa, 0x97, 0x4b, 0x82,
+ 0xd8, 0x06, 0x61, 0xdb, 0xd0, 0x05, 0xa0, 0x0b, 0x51, 0x4d, 0x49, 0x96, 0xe8, 0x84, 0x7a, 0x11,
+ 0x0a, 0x30, 0xfa, 0x12, 0x46, 0x12, 0x12, 0x82, 0x0e, 0xc3, 0xaa, 0xf6, 0x43, 0x04, 0x77, 0x3b,
+ 0x6a, 0xff, 0x91, 0x20, 0xbc, 0x88, 0xd5, 0x58, 0x90, 0xa9, 0x6e, 0xdd, 0x31, 0xa4, 0x7a, 0xa4,
+ 0x79, 0x4e, 0x5e, 0xc7, 0x6c, 0xe0, 0xcd, 0xb2, 0x1b, 0x87, 0x8c, 0x57, 0xd0, 0x3e, 0x6e, 0xd1,
+ 0x93, 0xa0, 0x3e, 0xb4, 0x04, 0x0d, 0x06, 0xfa, 0x78, 0xff, 0xce, 0x37, 0xb7, 0x08, 0x68, 0xc5,
+ 0x21, 0x77, 0xbb, 0x74, 0x30, 0xeb, 0xb4, 0xe7, 0xd8, 0xd8, 0xca, 0x54, 0xca, 0xcb, 0x49, 0x73,
+ 0x4e, 0xd1, 0x43, 0x5d, 0x87, 0x32, 0x76, 0x9a, 0xed, 0xd2, 0x81, 0xa5, 0x88, 0x07, 0x2a, 0xe2,
+ 0x81, 0x1d, 0xf1, 0xa0, 0x1c, 0xf1, 0x40, 0x43, 0x9c, 0xa8, 0x88, 0x13, 0x3b, 0xe2, 0xa4, 0x1c,
+ 0x71, 0x42, 0x11, 0x4b, 0xb7, 0x18, 0x94, 0x75, 0xa9, 0xe4, 0x76, 0xad, 0xb4, 0x72, 0x3d, 0x5b,
+ 0x8f, 0x9b, 0xb6, 0x5c, 0xd1, 0x53, 0xb5, 0x46, 0x7f, 0xdc, 0xfa, 0x85, 0xfe, 0x11, 0xb5, 0x8c,
+ 0x7b, 0xe8, 0x10, 0xd5, 0xb7, 0x5f, 0x60, 0x54, 0x69, 0xbd, 0x83, 0x07, 0x50, 0x38, 0x94, 0xe0,
+ 0x76, 0xb0, 0x8c, 0x99, 0x42, 0x7c, 0x18, 0xf4, 0x90, 0x02, 0xd6, 0x87, 0x55, 0x43, 0x64, 0xb2,
+ 0x86, 0xea, 0x15, 0x6d, 0xa9, 0xa8, 0x59, 0x3f, 0x31, 0xe0, 0xde, 0x7b, 0x33, 0x9f, 0xa1, 0x37,
+ 0x13, 0x73, 0xe9, 0x46, 0xaa, 0x97, 0xc6, 0x93, 0x9b, 0x69, 0x5e, 0x9b, 0x6b, 0x5b, 0x05, 0x4e,
+ 0x8b, 0xb6, 0xe1, 0xa7, 0xbd, 0xbb, 0xf4, 0xe5, 0x9c, 0xb2, 0x28, 0x53, 0x61, 0xe9, 0x0d, 0x92,
+ 0xfe, 0x20, 0xe5, 0x77, 0xb6, 0x64, 0x90, 0xd7, 0xef, 0x67, 0x7d, 0x08, 0x1d, 0x9e, 0xe4, 0xdc,
+ 0x46, 0x16, 0x5d, 0x7d, 0xad, 0x8e, 0x7f, 0xcb, 0x8f, 0xb9, 0x80, 0x97, 0x86, 0xe1, 0x8e, 0x60,
+ 0x0f, 0xb2, 0xf6, 0xf7, 0xbf, 0xd7, 0x98, 0xa6, 0x1a, 0x81, 0xa2, 0x2a, 0x25, 0xdc, 0x22, 0x08,
+ 0xa2, 0x44, 0x1f, 0xfc, 0x44, 0xd6, 0xe5, 0x83, 0x0f, 0xe4, 0x85, 0x07, 0x79, 0x3c, 0xfd, 0x5b,
+ 0x4f, 0x53, 0x32, 0x76, 0x72, 0xe4, 0x64, 0x37, 0x07, 0x4e, 0x68, 0x2d, 0x4c, 0x75, 0xb0, 0x18,
+ 0x33, 0x15, 0xad, 0x91, 0xc3, 0x87, 0xb0, 0x46, 0xe0, 0xca, 0xe2, 0x6b, 0x31, 0x41, 0x58, 0xb7,
+ 0x36, 0xe7, 0x03, 0xae, 0xd5, 0xdb, 0xb4, 0x79, 0x8c, 0x19, 0x87, 0x95, 0x83, 0xa6, 0xf8, 0xf4,
+ 0xd7, 0xa1, 0x5b, 0xd0, 0xeb, 0x69, 0x5e, 0x9b, 0x3c, 0x2d, 0xb2, 0x7b, 0x37, 0xff, 0x36, 0x5a,
+ 0xe7, 0xe3, 0xaa, 0x8f, 0xbb, 0xd2, 0x01, 0x5f, 0xf7, 0xbe, 0x02, 0x1e, 0xa8, 0xf5, 0xba, 0x94,
+ 0x75, 0x14, 0xaa, 0xe9, 0x45, 0xfb, 0xdd, 0x88, 0xfd, 0x6e, 0xc4, 0xd6, 0xbb, 0x11, 0xf4, 0x71,
+ 0xa0, 0x25, 0x7d, 0xae, 0xc7, 0xbe, 0x21, 0x51, 0xd8, 0xb7, 0xa0, 0x25, 0x3c, 0x4d, 0x5e, 0xed,
+ 0xc3, 0xd1, 0x18, 0x8f, 0x81, 0x56, 0x8d, 0x37, 0xa3, 0xf4, 0x93, 0x2d, 0xe8, 0xcc, 0x43, 0x05,
+ 0x8c, 0xa9, 0xd4, 0xe5, 0xfd, 0xd1, 0x04, 0x96, 0xe1, 0x6c, 0x1a, 0x56, 0x8b, 0x6c, 0x41, 0x89,
+ 0x7e, 0x88, 0x31, 0x91, 0xc3, 0x3a, 0x90, 0x80, 0x57, 0xb3, 0xc5, 0x68, 0x8c, 0x60, 0x21, 0x98,
+ 0x99, 0x4c, 0x19, 0xbd, 0x38, 0x8e, 0x8d, 0x0c, 0x47, 0xca, 0x40, 0x3a, 0x39, 0x68, 0xc3, 0x81,
+ 0x92, 0xc4, 0xce, 0x02, 0x2b, 0xa4, 0x06, 0xef, 0xda, 0xef, 0x71, 0xf4, 0x2e, 0x8c, 0xa4, 0x4e,
+ 0x2b, 0x2a, 0x79, 0x55, 0x49, 0x7b, 0x39, 0x4e, 0x09, 0x5d, 0x55, 0x45, 0x17, 0xb0, 0x77, 0xb3,
+ 0xce, 0x3a, 0xb7, 0x19, 0x12, 0xce, 0x85, 0xe7, 0x55, 0xe2, 0x25, 0x4e, 0x27, 0xdf, 0x48, 0x99,
+ 0x3d, 0x1d, 0xa7, 0xd7, 0xa0, 0x7f, 0x4e, 0x1d, 0x1a, 0xe9, 0x19, 0x09, 0x01, 0x9f, 0x2e, 0x3b,
+ 0xa3, 0x78, 0xc1, 0x42, 0x6a, 0xe0, 0x50, 0xbb, 0x45, 0xbe, 0x22, 0x12, 0xcc, 0xc3, 0x01, 0xe2,
+ 0xf8, 0x03, 0x54, 0x38, 0x10, 0xe4, 0xbc, 0x8e, 0xff, 0x0c, 0xe8, 0xe3, 0x55, 0xf8, 0x23, 0x21,
+ 0x1f, 0xe4, 0x5f, 0x37, 0x40, 0xda, 0x3e, 0x52, 0xcd, 0x0a, 0xef, 0xb1, 0x94, 0x0f, 0x16, 0xd6,
+ 0xf4, 0x25, 0xa2, 0xa1, 0x4f, 0xea, 0xd8, 0x52, 0x68, 0xd0, 0x82, 0xc8, 0x94, 0xe1, 0x3f, 0x57,
+ 0x58, 0xf5, 0x65, 0x6a, 0x73, 0x62, 0x2d, 0xdb, 0xb2, 0x15, 0xe9, 0x59, 0x8b, 0xac, 0xad, 0xad,
+ 0x5f, 0x85, 0xd2, 0x96, 0x52, 0x24, 0x35, 0x14, 0x91, 0xf3, 0x2f, 0x2b, 0x50, 0xa3, 0x62, 0x1c,
+ 0x54, 0x21, 0xc2, 0x4c, 0xff, 0xb0, 0xa4, 0xb7, 0xcc, 0x25, 0x46, 0x15, 0xc8, 0x33, 0x97, 0x4c,
+ 0x97, 0xf1, 0x60, 0x90, 0xe2, 0xb8, 0x1b, 0x30, 0xa3, 0x81, 0x45, 0x6b, 0xff, 0xa8, 0x75, 0xb0,
+ 0x01, 0xda, 0x6a, 0x1e, 0x21, 0xeb, 0x93, 0x27, 0x1e, 0x35, 0x8f, 0x71, 0xe2, 0xe1, 0x31, 0x4a,
+ 0x45, 0x7f, 0xa8, 0x99, 0x9d, 0xce, 0x47, 0xd7, 0xd4, 0xba, 0xee, 0xd5, 0x2f, 0xd1, 0x7f, 0x23,
+ 0xb7, 0xe1, 0xc4, 0xf5, 0x3e, 0xfa, 0x6f, 0xe0, 0xfa, 0xce, 0xa0, 0x3e, 0x44, 0xff, 0x91, 0xb4,
+ 0x04, 0xfd, 0xd7, 0x73, 0xdd, 0xa0, 0x06, 0x76, 0x05, 0xaa, 0xc3, 0x77, 0x08, 0xf2, 0x06, 0x9f,
+ 0x1e, 0x10, 0x67, 0x42, 0x10, 0x54, 0x6f, 0xbf, 0x6f, 0x22, 0x96, 0xed, 0x34, 0x08, 0x98, 0x1e,
+ 0x8a, 0x0b, 0xdb, 0x12, 0x58, 0xf8, 0x60, 0x22, 0x9a, 0x4b, 0xb8, 0x0b, 0x00, 0xb1, 0x5e, 0x7c,
+ 0xf2, 0xbd, 0xe2, 0xdf, 0x2c, 0xfe, 0x9a, 0x30, 0xc7, 0x1e, 0x61, 0xe5, 0x7b, 0x22, 0x69, 0x4b,
+ 0x84, 0xa3, 0x49, 0x36, 0x96, 0x2f, 0x78, 0xeb, 0x25, 0xdc, 0x18, 0x55, 0x18, 0x4f, 0xa5, 0xb5,
+ 0x91, 0xa5, 0x63, 0x85, 0x56, 0xdf, 0x65, 0x18, 0xc6, 0xfd, 0xec, 0x46, 0x4f, 0x05, 0xa1, 0x6b,
+ 0x04, 0x8f, 0x7b, 0x10, 0x11, 0x46, 0x04, 0x01, 0x3c, 0x3f, 0xab, 0x1d, 0x36, 0xdb, 0x47, 0xed,
+ 0xe3, 0xf7, 0x9d, 0x37, 0xc7, 0x87, 0xc7, 0xef, 0xde, 0xbf, 0x7d, 0x7f, 0x78, 0x60, 0x08, 0x30,
+ 0x04, 0xe6, 0xbd, 0x75, 0x99, 0x95, 0x39, 0xd2, 0x21, 0x0f, 0xfe, 0x21, 0xb3, 0x13, 0xe2, 0x3b,
+ 0xba, 0x72, 0x80, 0x47, 0xbc, 0x62, 0x7c, 0x26, 0x01, 0x79, 0x7a, 0xd9, 0x02, 0xc7, 0x98, 0x8d,
+ 0xa7, 0x0b, 0xc7, 0x11, 0x4d, 0xfe, 0xab, 0xf5, 0xbd, 0x21, 0x7d, 0xb5, 0xbf, 0xbb, 0x1e, 0xb6,
+ 0xa4, 0xa9, 0x5a, 0xe1, 0xd6, 0xd5, 0x4c, 0x8e, 0x79, 0x9c, 0xcd, 0xd2, 0x08, 0x49, 0xdc, 0x29,
+ 0x82, 0xee, 0x1c, 0x7b, 0xf4, 0xa8, 0x38, 0xa6, 0xc8, 0x0d, 0xa4, 0x7a, 0xf9, 0x39, 0x71, 0x1c,
+ 0xfa, 0x26, 0xa2, 0xfc, 0x4b, 0x6c, 0x78, 0x34, 0xc9, 0x30, 0x06, 0xca, 0xc4, 0x7e, 0x83, 0xe6,
+ 0xba, 0x68, 0xda, 0x9d, 0x9f, 0xe1, 0xfb, 0x2e, 0x2c, 0x8f, 0xfb, 0x8a, 0xc0, 0xcb, 0xf3, 0x41,
+ 0x6e, 0x23, 0xb7, 0xc5, 0x23, 0x3a, 0x5e, 0xdc, 0x1f, 0x18, 0xdf, 0x8e, 0x26, 0x57, 0x38, 0xf4,
+ 0x31, 0x49, 0x5f, 0xd5, 0xcf, 0xcf, 0x42, 0xc9, 0xdc, 0x69, 0x37, 0xdf, 0xbd, 0x3d, 0x6e, 0x88,
+ 0x38, 0x87, 0xed, 0xe6, 0xdb, 0x63, 0x9a, 0x8f, 0x26, 0x29, 0x79, 0xaf, 0x14, 0xe2, 0x29, 0xf1,
+ 0x52, 0x24, 0xd0, 0xe5, 0x05, 0x6e, 0x3a, 0x2f, 0x86, 0x9b, 0x02, 0xf2, 0x02, 0x8d, 0x03, 0x9a,
+ 0xec, 0xd8, 0x6b, 0x8d, 0x7b, 0x87, 0x8c, 0x44, 0x20, 0x52, 0x19, 0x52, 0x92, 0xe1, 0x7a, 0xec,
+ 0x1b, 0x62, 0x06, 0x43, 0x01, 0x46, 0x36, 0x66, 0x18, 0x3c, 0x5e, 0x52, 0x85, 0x6c, 0x93, 0x19,
+ 0x67, 0xd2, 0xcd, 0x68, 0x3c, 0x50, 0x24, 0x05, 0x14, 0x2f, 0xf2, 0x8b, 0x7a, 0x36, 0x44, 0xb3,
+ 0x3a, 0x45, 0xe7, 0x0e, 0xb0, 0x30, 0x89, 0x28, 0x03, 0x3a, 0xbe, 0x43, 0xc6, 0xa6, 0x4e, 0xfb,
+ 0xcb, 0x0d, 0xce, 0xcf, 0xb0, 0x2c, 0x11, 0xdc, 0x44, 0x42, 0x54, 0x43, 0x21, 0x5a, 0x33, 0x79,
+ 0x19, 0x8c, 0xcc, 0x04, 0x5f, 0x62, 0x7e, 0x1f, 0x03, 0x21, 0x55, 0x05, 0x71, 0xb2, 0x4c, 0x7c,
+ 0x39, 0x51, 0x8a, 0x1c, 0x92, 0x5b, 0x48, 0x58, 0x51, 0xaa, 0xb8, 0x19, 0xbb, 0x75, 0xe9, 0xf3,
+ 0x7e, 0xc2, 0x8d, 0x4f, 0xc9, 0x93, 0x2f, 0xbf, 0x9d, 0x9d, 0xfc, 0x72, 0x76, 0x72, 0x71, 0xf6,
+ 0xe5, 0xe7, 0x9a, 0xe5, 0x81, 0x00, 0x44, 0x30, 0x87, 0xc7, 0x2d, 0xc3, 0x41, 0x9f, 0x8f, 0xdf,
+ 0xbd, 0x3d, 0x6c, 0xb5, 0xdf, 0x1c, 0x14, 0x76, 0xf8, 0xc0, 0x6a, 0x22, 0x0e, 0xab, 0xe2, 0xee,
+ 0x1f, 0x0e, 0x92, 0x5e, 0xae, 0xe0, 0x16, 0x43, 0xfb, 0x42, 0xb8, 0x28, 0x4d, 0x3a, 0xa1, 0x16,
+ 0xea, 0xef, 0x1a, 0x6a, 0xa2, 0x8e, 0x52, 0xa0, 0xa5, 0xe2, 0x58, 0x40, 0x9d, 0x42, 0xa4, 0xa8,
+ 0x41, 0x3c, 0x99, 0xc4, 0x2c, 0xf4, 0x93, 0x21, 0x60, 0x2a, 0x58, 0x53, 0xd3, 0x74, 0x91, 0x5d,
+ 0xc6, 0xf3, 0x17, 0x17, 0x46, 0x67, 0xff, 0xd4, 0xd7, 0x16, 0xc7, 0x6c, 0x07, 0xf1, 0xac, 0xe4,
+ 0xa9, 0x2c, 0x96, 0x5b, 0x16, 0xb7, 0x9a, 0xc1, 0xac, 0x8b, 0x5c, 0x2d, 0xc3, 0x95, 0x75, 0x19,
+ 0x7e, 0x5d, 0xd6, 0xd2, 0x24, 0x9c, 0x67, 0xef, 0x30, 0x9c, 0x5d, 0xde, 0x29, 0x1c, 0xa4, 0x84,
+ 0x84, 0x92, 0x0e, 0x59, 0xdb, 0x1b, 0x95, 0xba, 0x42, 0xed, 0x87, 0xe7, 0x17, 0x72, 0xe9, 0xb5,
+ 0x3f, 0x58, 0xc5, 0x99, 0x5e, 0x1d, 0x18, 0x96, 0x6c, 0x20, 0x84, 0x65, 0xf9, 0xf2, 0x9c, 0xb0,
+ 0x84, 0xf0, 0x16, 0x68, 0x36, 0xe4, 0x79, 0xb9, 0x45, 0xe4, 0xc5, 0x67, 0x43, 0x8f, 0xe0, 0x0c,
+ 0x5f, 0xcc, 0x05, 0x63, 0x7f, 0xd0, 0xd2, 0x9b, 0xb0, 0xbb, 0xda, 0x06, 0x5b, 0x3f, 0xb0, 0x4e,
+ 0x28, 0xef, 0x01, 0xd6, 0x7c, 0x8d, 0xcf, 0x95, 0xf0, 0xa2, 0x51, 0xcc, 0x5e, 0x8c, 0x68, 0xb4,
+ 0x3b, 0xef, 0x90, 0x7a, 0x4f, 0x15, 0xa3, 0x2e, 0xdf, 0x4e, 0x89, 0x48, 0x60, 0x73, 0xf2, 0x1e,
+ 0x04, 0x0e, 0x5a, 0x09, 0x8a, 0x4a, 0x28, 0x2d, 0x51, 0x11, 0x8f, 0x25, 0x4e, 0x80, 0xc0, 0x15,
+ 0xe0, 0xd6, 0xe9, 0xd7, 0x8d, 0xf7, 0xe6, 0x88, 0xc6, 0x43, 0x17, 0x1e, 0x56, 0x79, 0xd1, 0x06,
+ 0xdf, 0xad, 0x32, 0x7b, 0xf9, 0x86, 0xb0, 0x04, 0x03, 0xfe, 0x5b, 0xfa, 0x9b, 0x6e, 0x43, 0x86,
+ 0x7c, 0x7c, 0xd9, 0x0f, 0xd0, 0x1b, 0x98, 0xb1, 0x1b, 0x8f, 0x2f, 0x49, 0xa6, 0xc8, 0xa1, 0xa3,
+ 0x01, 0xc4, 0x7b, 0x74, 0x40, 0x98, 0x56, 0x0b, 0xe9, 0x0c, 0x4b, 0xdd, 0x61, 0xbf, 0xb8, 0x1e,
+ 0xac, 0xe8, 0x2c, 0x60, 0xa5, 0x72, 0xe5, 0x2e, 0xbb, 0xca, 0x95, 0xb2, 0xbc, 0x5e, 0xaf, 0x88,
+ 0xa5, 0x83, 0x5f, 0xac, 0x00, 0xc5, 0xa8, 0xee, 0x08, 0xfa, 0xa8, 0x6e, 0x4e, 0x9e, 0xb3, 0x90,
+ 0x2b, 0x72, 0xd5, 0x4e, 0xc1, 0x97, 0x44, 0x49, 0x75, 0x9e, 0x88, 0x9d, 0x49, 0x34, 0x08, 0x4d,
+ 0xae, 0x61, 0x45, 0x5a, 0x1a, 0x40, 0x2d, 0x3f, 0x27, 0xee, 0x4b, 0xa4, 0x90, 0x5e, 0x69, 0x75,
+ 0x90, 0x5e, 0xe9, 0x44, 0xe4, 0xaf, 0x5e, 0x8d, 0xc7, 0x36, 0x05, 0x91, 0x32, 0x9d, 0x43, 0x20,
+ 0xeb, 0xc6, 0x95, 0x7f, 0x05, 0xaf, 0xb6, 0x6b, 0x4f, 0x7a, 0x31, 0xc6, 0x52, 0x6d, 0x4b, 0xa0,
+ 0x3f, 0xa0, 0xca, 0x15, 0xdb, 0x03, 0x2d, 0x3b, 0x63, 0x2a, 0x5e, 0x38, 0xef, 0x28, 0xc5, 0x70,
+ 0xff, 0x15, 0x2a, 0x33, 0xc6, 0x9b, 0xc4, 0x6f, 0x6a, 0xa1, 0x2e, 0x93, 0x83, 0x81, 0xb2, 0x7b,
+ 0xb6, 0xe4, 0xb6, 0xac, 0xb5, 0x94, 0xa9, 0x48, 0xa1, 0xd2, 0x42, 0xe8, 0x00, 0xcf, 0xa4, 0x27,
+ 0x82, 0x2d, 0x2d, 0xa9, 0x7b, 0xd1, 0x7a, 0x1a, 0x83, 0x35, 0x04, 0x85, 0x4c, 0xad, 0x24, 0x0e,
+ 0x12, 0xc2, 0x14, 0x3e, 0xe6, 0xe2, 0xa7, 0x0b, 0x8f, 0xf7, 0x82, 0xde, 0xab, 0x2a, 0x57, 0xd1,
+ 0xcd, 0xea, 0xbc, 0x51, 0x71, 0x7f, 0xdc, 0x10, 0x7e, 0xbb, 0x79, 0x39, 0xc9, 0x74, 0x05, 0x9d,
+ 0xb4, 0xdd, 0xf5, 0x58, 0xdf, 0x34, 0x17, 0xa1, 0x20, 0xa1, 0x13, 0xe1, 0x77, 0x7f, 0xea, 0x66,
+ 0xdb, 0x0d, 0x0a, 0xc9, 0x7d, 0x24, 0x5f, 0x5c, 0x27, 0x76, 0xe9, 0x04, 0xf5, 0x17, 0x54, 0xd7,
+ 0x70, 0x38, 0xfa, 0xbc, 0x81, 0x11, 0xbb, 0xbe, 0xa8, 0x10, 0x47, 0x4e, 0x75, 0x03, 0x9c, 0x6e,
+ 0x31, 0x5e, 0x1f, 0x21, 0x54, 0x16, 0xb7, 0x3a, 0x7f, 0x3d, 0xf9, 0xb3, 0xfb, 0xcb, 0xd9, 0x97,
+ 0xd3, 0xee, 0xa7, 0xb3, 0x8b, 0xdf, 0x4e, 0xbe, 0x7c, 0x3c, 0xad, 0x1d, 0x76, 0xde, 0xbe, 0x79,
+ 0x2b, 0xd9, 0xa5, 0x7b, 0x3b, 0xb6, 0xba, 0x1d, 0x8b, 0x24, 0xe7, 0x60, 0x9e, 0x2e, 0xac, 0x31,
+ 0x4c, 0xf6, 0x16, 0xe3, 0xde, 0x62, 0x7c, 0xad, 0x16, 0xe3, 0xde, 0x86, 0xdb, 0xdb, 0x70, 0xcf,
+ 0xdc, 0x86, 0x63, 0xe2, 0xb9, 0xaa, 0x19, 0x17, 0x14, 0x56, 0xc7, 0xbd, 0x61, 0xb7, 0x37, 0xec,
+ 0xf6, 0x86, 0xdd, 0x13, 0x19, 0x76, 0x2f, 0xc8, 0xf2, 0xaa, 0xbc, 0x6f, 0xbc, 0xbd, 0x4d, 0xb6,
+ 0x5e, 0x09, 0xad, 0x72, 0x62, 0x73, 0x6f, 0x7a, 0xe9, 0xa6, 0x97, 0xe5, 0x79, 0x33, 0xba, 0x51,
+ 0x0e, 0xec, 0xaa, 0x76, 0xb3, 0xfd, 0x99, 0xb3, 0xc7, 0xb1, 0xd8, 0x8a, 0xf6, 0x15, 0xcb, 0x51,
+ 0x56, 0xaa, 0xee, 0xc5, 0xc7, 0x93, 0x5f, 0x4e, 0x6b, 0x9d, 0x2d, 0x2c, 0xb9, 0x87, 0xb6, 0xd7,
+ 0xec, 0x16, 0x59, 0xb9, 0x45, 0x77, 0x1f, 0x7b, 0x4d, 0xec, 0x2a, 0x96, 0x4d, 0xa2, 0xbd, 0x99,
+ 0xf6, 0x70, 0x66, 0xda, 0x33, 0xb0, 0x8a, 0x9e, 0x9d, 0xa5, 0xb8, 0x63, 0x33, 0x6d, 0x7f, 0x09,
+ 0xf5, 0x19, 0x5d, 0x42, 0x7d, 0xe5, 0xe6, 0xf0, 0xd3, 0x9a, 0x9f, 0xcf, 0xcd, 0x18, 0xdf, 0x95,
+ 0x39, 0xfc, 0xff, 0xe6, 0x5a, 0xf0, 0xfd, 0x4d, 0x7e, 0x06, 0xb7, 0xd9, 0xe6, 0xad, 0x41, 0x87,
+ 0xda, 0xdb, 0xfc, 0x7b, 0x9b, 0x7f, 0x6f, 0xf3, 0x3f, 0x84, 0xcd, 0x2f, 0xa6, 0x62, 0x2c, 0x2b,
+ 0xe8, 0xe5, 0xbe, 0x80, 0x6d, 0x2e, 0xa7, 0x2a, 0xf2, 0x46, 0x0f, 0xe1, 0xb2, 0xd6, 0x26, 0xdf,
+ 0x9d, 0xa1, 0xf1, 0x5a, 0xee, 0x86, 0xbe, 0xfc, 0x9d, 0xf2, 0xf5, 0xae, 0x92, 0x67, 0x74, 0xc9,
+ 0xf4, 0x09, 0x5d, 0x39, 0xfb, 0x10, 0xc7, 0xaf, 0xeb, 0xe1, 0x13, 0xb9, 0xab, 0xe5, 0xf6, 0xa9,
+ 0x6d, 0x6e, 0x2e, 0x3d, 0xde, 0x6b, 0x81, 0x1a, 0x2c, 0x58, 0x03, 0x5c, 0x99, 0x70, 0x26, 0x06,
+ 0x9c, 0x88, 0x6a, 0x8f, 0xf6, 0x77, 0x19, 0x46, 0xa0, 0x38, 0x7c, 0x51, 0xfe, 0x43, 0x82, 0x6d,
+ 0x89, 0x3a, 0x92, 0x5c, 0x75, 0xe6, 0x0b, 0x44, 0xa0, 0xf6, 0x73, 0x73, 0xa9, 0xc2, 0x27, 0xe5,
+ 0xf0, 0x89, 0x0a, 0xbf, 0xea, 0xe2, 0x17, 0x93, 0xeb, 0xbc, 0x27, 0x90, 0x82, 0x43, 0x6f, 0x74,
+ 0x71, 0xfa, 0x30, 0x4d, 0x8e, 0x56, 0xeb, 0xaa, 0xde, 0xa1, 0xcf, 0xbe, 0xb8, 0x3a, 0x41, 0x2b,
+ 0x81, 0x3c, 0xd9, 0x06, 0x79, 0x62, 0x47, 0x9e, 0x08, 0xc6, 0xc0, 0x51, 0x4f, 0x36, 0xbf, 0x78,
+ 0x8e, 0x39, 0x08, 0xf5, 0xaa, 0x8f, 0x5a, 0xee, 0x4a, 0xb8, 0x92, 0x2d, 0xae, 0x8d, 0x53, 0x5c,
+ 0x09, 0xc2, 0x95, 0xb8, 0x8a, 0xc7, 0x17, 0x70, 0x19, 0xaf, 0x8e, 0xa3, 0x4a, 0x7d, 0x73, 0x46,
+ 0xe2, 0x9a, 0xaf, 0x8c, 0x13, 0x1f, 0xf0, 0x03, 0xbe, 0x3f, 0xf1, 0x82, 0x3d, 0xc0, 0x95, 0x4e,
+ 0xec, 0xd0, 0xc1, 0x22, 0xcf, 0x56, 0xc7, 0x05, 0x05, 0x0f, 0xf5, 0x7e, 0x77, 0x25, 0xa5, 0x9b,
+ 0x4a, 0x25, 0x96, 0x52, 0xc9, 0x23, 0x9d, 0x0e, 0xa2, 0xa9, 0x50, 0x49, 0x6c, 0x4a, 0x4c, 0xb6,
+ 0x51, 0x0a, 0xf7, 0xf7, 0x5d, 0xf6, 0xa7, 0x97, 0xf6, 0xa7, 0x97, 0xca, 0xdd, 0xe2, 0x6c, 0xc8,
+ 0x0c, 0x3e, 0xb3, 0x87, 0x70, 0x99, 0x63, 0x47, 0x51, 0x09, 0x95, 0x22, 0xdf, 0xda, 0x57, 0x02,
+ 0xc4, 0xc4, 0x5f, 0x52, 0x6e, 0x59, 0x6f, 0xaa, 0x60, 0xfb, 0xcb, 0x3b, 0xfb, 0x83, 0x5f, 0xcf,
+ 0xe4, 0xe0, 0xd7, 0xee, 0x7c, 0xdb, 0xd2, 0x54, 0x14, 0x3f, 0x0d, 0x35, 0x8b, 0x4c, 0x5f, 0x9d,
+ 0x9f, 0xa6, 0x26, 0xcb, 0x98, 0x8c, 0x93, 0x6c, 0xef, 0x82, 0xde, 0xbb, 0xa0, 0xf7, 0x2e, 0xe8,
+ 0x57, 0xe8, 0x82, 0xc6, 0xaa, 0x7a, 0x44, 0x65, 0x06, 0x9f, 0x97, 0x9e, 0x6e, 0x7d, 0x34, 0x97,
+ 0x81, 0x24, 0x50, 0xf8, 0xf8, 0x15, 0xc0, 0x56, 0x75, 0x6e, 0x98, 0xb8, 0x14, 0x7b, 0xb2, 0x16,
+ 0x7b, 0x52, 0x0d, 0x7b, 0x22, 0x61, 0x87, 0xe8, 0x66, 0xd5, 0xdc, 0xe4, 0xeb, 0x43, 0x73, 0x2d,
+ 0xfa, 0x97, 0xb8, 0x5b, 0x8b, 0x31, 0x96, 0x90, 0xc5, 0xf6, 0xcc, 0xac, 0xa0, 0xfd, 0x2d, 0xae,
+ 0xf2, 0x75, 0x78, 0x77, 0x7a, 0xf0, 0xe3, 0x2a, 0xb1, 0x2f, 0xf1, 0x42, 0x99, 0x11, 0x43, 0xc9,
+ 0x41, 0x80, 0x62, 0x8f, 0x97, 0x76, 0xf8, 0x06, 0xea, 0xca, 0x0b, 0xf4, 0x8f, 0x22, 0x21, 0x04,
+ 0xb9, 0xdd, 0xd8, 0x18, 0x8d, 0x08, 0x8b, 0x12, 0xb7, 0x19, 0x6b, 0xc0, 0x89, 0x15, 0x38, 0x29,
+ 0x00, 0x63, 0x57, 0x1e, 0xaf, 0xc5, 0xe7, 0x28, 0x7c, 0x2c, 0xe7, 0xdc, 0x90, 0x38, 0xe6, 0x22,
+ 0xe5, 0x7d, 0xd9, 0xe3, 0x86, 0x90, 0x8e, 0xb2, 0x84, 0x26, 0x01, 0x85, 0x4d, 0x39, 0x14, 0xed,
+ 0xe3, 0x1f, 0xff, 0xac, 0x74, 0xc2, 0x32, 0x1f, 0xa3, 0x15, 0x64, 0x2e, 0x3f, 0x46, 0xc1, 0x65,
+ 0x3e, 0x5e, 0x51, 0x2c, 0x99, 0xc9, 0xd5, 0xe5, 0x65, 0x3a, 0x2f, 0x7b, 0x78, 0x76, 0xc3, 0x30,
+ 0x5c, 0x2d, 0x43, 0x5a, 0x7b, 0xdb, 0xd8, 0x5c, 0xad, 0xc8, 0x71, 0xcc, 0xb1, 0x0b, 0x1b, 0x70,
+ 0xf2, 0x36, 0x50, 0xe9, 0xaf, 0xb9, 0x10, 0x65, 0x88, 0x94, 0x6c, 0x47, 0x24, 0x94, 0x1b, 0x3c,
+ 0x70, 0x2e, 0x77, 0x00, 0x84, 0x9f, 0x12, 0x5d, 0x25, 0x75, 0xae, 0xbc, 0x97, 0xdc, 0xcd, 0xad,
+ 0x31, 0x2d, 0xad, 0x4b, 0x6d, 0xcb, 0x9e, 0xd5, 0xae, 0xdc, 0x4d, 0x85, 0xd1, 0x99, 0x43, 0x0c,
+ 0x24, 0xa4, 0x4a, 0x2c, 0x20, 0x22, 0x77, 0x59, 0x36, 0x08, 0xcb, 0xe2, 0xc8, 0xc7, 0xa8, 0xdb,
+ 0x70, 0x38, 0x38, 0xfd, 0x7d, 0x13, 0xe1, 0x54, 0x9c, 0xe6, 0xf3, 0x78, 0x61, 0x7a, 0xff, 0x04,
+ 0x5e, 0x2a, 0x59, 0xcc, 0x46, 0xd3, 0xee, 0x0d, 0x8e, 0xc2, 0xab, 0x1d, 0x29, 0x17, 0x62, 0xb9,
+ 0x55, 0x9c, 0x98, 0x2d, 0x12, 0x54, 0xac, 0xb5, 0x26, 0x4c, 0x6c, 0x9b, 0x80, 0xb5, 0x49, 0x34,
+ 0x6e, 0x82, 0xac, 0x19, 0x13, 0xd5, 0x1f, 0x55, 0x41, 0x13, 0xe6, 0x83, 0x24, 0x12, 0x3f, 0x03,
+ 0x06, 0x16, 0xde, 0xf1, 0x42, 0x6d, 0xbd, 0x50, 0x5b, 0x14, 0x6a, 0x8b, 0x42, 0x6d, 0x28, 0xa4,
+ 0xf9, 0xfb, 0x09, 0x36, 0x9f, 0x46, 0x81, 0x65, 0xa3, 0x4f, 0x1f, 0x55, 0x6a, 0x22, 0x19, 0x21,
+ 0x45, 0x33, 0x85, 0x2e, 0xe1, 0x78, 0x01, 0x6d, 0x08, 0x5f, 0x38, 0x9a, 0x36, 0x44, 0x32, 0x47,
+ 0x1f, 0xbe, 0xda, 0x63, 0x10, 0xe1, 0xdf, 0xf5, 0x2d, 0x79, 0xb7, 0xcb, 0x95, 0x35, 0x6f, 0x75,
+ 0xbb, 0xe4, 0x71, 0xd1, 0xe2, 0xeb, 0x14, 0x49, 0x87, 0x34, 0x62, 0x2f, 0x10, 0xb1, 0x67, 0xa5,
+ 0xd8, 0x7b, 0x52, 0x6e, 0x70, 0x08, 0x61, 0x2c, 0x21, 0x42, 0xb8, 0x43, 0x61, 0x1b, 0xe8, 0x0b,
+ 0xc2, 0x77, 0x15, 0x87, 0x1f, 0x08, 0x86, 0x0a, 0xf1, 0xec, 0xf1, 0x0a, 0xc3, 0x4f, 0xa6, 0x0f,
+ 0x19, 0x7a, 0x60, 0x28, 0xb0, 0xaf, 0x49, 0x03, 0x75, 0x56, 0xf4, 0xd7, 0x26, 0xb8, 0x0c, 0x11,
+ 0xfa, 0x6d, 0xc1, 0x03, 0x55, 0xf8, 0x15, 0x52, 0x34, 0x09, 0x8b, 0x25, 0x05, 0x89, 0x17, 0xc6,
+ 0x88, 0xf4, 0x79, 0x35, 0x3e, 0x6e, 0x3b, 0x1d, 0x3e, 0x9f, 0x85, 0xf8, 0xba, 0x9f, 0xfc, 0x45,
+ 0xbd, 0xb4, 0xc8, 0xe9, 0x94, 0x39, 0x3f, 0x8b, 0x0a, 0xc1, 0xf6, 0x42, 0xe3, 0x96, 0x09, 0xb5,
+ 0x96, 0xcd, 0x5b, 0x26, 0x4a, 0xea, 0x21, 0x94, 0xe0, 0x76, 0x92, 0x2a, 0x73, 0x99, 0x1b, 0x01,
+ 0x33, 0xa6, 0x2e, 0x84, 0x92, 0x2c, 0x1b, 0x83, 0x90, 0x59, 0x90, 0x8d, 0x36, 0x08, 0xf4, 0xd8,
+ 0xc5, 0xc4, 0xc6, 0x92, 0xa4, 0xd7, 0x80, 0x2e, 0xd3, 0x18, 0xcb, 0xd2, 0x02, 0x9c, 0xfa, 0x02,
+ 0x1f, 0x86, 0x2d, 0xcb, 0xb4, 0x64, 0xf5, 0xe2, 0x09, 0xe2, 0x41, 0x30, 0xe4, 0x20, 0xe8, 0x1a,
+ 0x92, 0xcc, 0xec, 0x1d, 0x04, 0x0b, 0xfc, 0x6c, 0x94, 0xf7, 0x86, 0x3a, 0xad, 0xf3, 0x2c, 0x8f,
+ 0xf3, 0xb4, 0xbb, 0x58, 0x4d, 0x92, 0x6c, 0x6c, 0x29, 0x48, 0x42, 0xcc, 0x69, 0xbb, 0x49, 0x8a,
+ 0x10, 0xef, 0x0d, 0x71, 0x04, 0xc6, 0x17, 0xb0, 0x7b, 0xb0, 0x66, 0x03, 0x8d, 0xa4, 0x8e, 0xe3,
+ 0x24, 0x45, 0x0b, 0xd7, 0x38, 0x9e, 0xa6, 0x16, 0x88, 0x01, 0x7b, 0xbd, 0x41, 0xcb, 0x16, 0x1c,
+ 0x00, 0x22, 0x58, 0x4f, 0xc6, 0x23, 0x40, 0xcc, 0xe5, 0x49, 0x3c, 0x0b, 0x2d, 0x47, 0xae, 0x8a,
+ 0xa6, 0x5d, 0xc1, 0xb0, 0x53, 0x58, 0xf4, 0x99, 0xbc, 0x3c, 0x2e, 0xf4, 0x98, 0x48, 0x9e, 0x95,
+ 0xfc, 0xa4, 0x09, 0x73, 0x93, 0xaa, 0xb9, 0xec, 0x9c, 0x0a, 0xd6, 0x3c, 0x84, 0x07, 0x90, 0x25,
+ 0x42, 0x87, 0xb0, 0x54, 0x04, 0x2a, 0xf3, 0xe5, 0x22, 0x1d, 0x4c, 0x20, 0xd8, 0x20, 0xe2, 0xbc,
+ 0x71, 0x1a, 0x35, 0xb4, 0x79, 0xfd, 0x57, 0xe7, 0x3b, 0x53, 0x54, 0xa1, 0x4f, 0x61, 0x01, 0xfb,
+ 0xc1, 0x32, 0x7d, 0xe1, 0x9d, 0x91, 0x1f, 0xec, 0xb3, 0x16, 0x75, 0x2a, 0xa6, 0x02, 0xc4, 0x20,
+ 0x21, 0xe8, 0xaf, 0xd6, 0x77, 0x9f, 0xfe, 0x6a, 0x7f, 0xf7, 0xd9, 0x04, 0x76, 0x03, 0x1c, 0xb7,
+ 0x38, 0xbc, 0xab, 0x41, 0x9f, 0xd5, 0xa0, 0xc6, 0xfb, 0x55, 0xc8, 0x2b, 0x2b, 0x22, 0x2e, 0x6b,
+ 0xca, 0x7a, 0xc4, 0x54, 0xaa, 0x50, 0x7c, 0x6a, 0x9a, 0xea, 0x2b, 0x3b, 0xcf, 0x46, 0xd3, 0x7c,
+ 0x5d, 0x08, 0x6d, 0x1a, 0x09, 0x99, 0x4b, 0x23, 0x24, 0x82, 0x86, 0x99, 0x90, 0x46, 0x91, 0x8a,
+ 0xad, 0xa9, 0x8e, 0x22, 0x83, 0x22, 0xd2, 0x25, 0xd2, 0xe7, 0x48, 0xed, 0xa7, 0x03, 0x2b, 0xe2,
+ 0xa0, 0x44, 0x04, 0xd6, 0x3e, 0x1c, 0x94, 0xe4, 0x06, 0x56, 0x9c, 0x0a, 0x6d, 0x92, 0x4b, 0x8b,
+ 0x92, 0x47, 0xcc, 0x32, 0xb0, 0x53, 0xc0, 0x85, 0xa9, 0xd2, 0x8e, 0x4d, 0x2f, 0xf0, 0x2c, 0x87,
+ 0xd0, 0x93, 0x5e, 0x54, 0x28, 0xcd, 0xce, 0x45, 0x21, 0x45, 0x80, 0x9d, 0x7f, 0xa2, 0x72, 0xa2,
+ 0xf6, 0x13, 0xe6, 0xd2, 0xa0, 0x73, 0x84, 0xbd, 0xac, 0x78, 0x24, 0x14, 0x56, 0xc7, 0xd2, 0x99,
+ 0xc8, 0x6a, 0xd0, 0xe4, 0x51, 0x4d, 0x21, 0xe1, 0x2f, 0x45, 0x7c, 0x33, 0x5d, 0x91, 0x4c, 0xad,
+ 0xf3, 0xb5, 0x83, 0x48, 0x62, 0x2f, 0xb7, 0x71, 0x48, 0x68, 0xfe, 0x2e, 0x4f, 0xac, 0x8f, 0xd7,
+ 0x72, 0x15, 0x14, 0x46, 0x10, 0x43, 0x26, 0x91, 0xa9, 0x22, 0x80, 0x37, 0xa6, 0xdf, 0x84, 0x7a,
+ 0x33, 0x70, 0xfc, 0x58, 0x07, 0xce, 0x4e, 0xe1, 0x03, 0x5a, 0xea, 0x42, 0xe3, 0xc3, 0xf1, 0x2b,
+ 0x38, 0xe3, 0x15, 0xde, 0xc9, 0x5d, 0x81, 0x67, 0x3b, 0xe2, 0xd5, 0x69, 0x84, 0xc3, 0x94, 0xca,
+ 0x32, 0xa0, 0xae, 0xe1, 0x57, 0xf9, 0x93, 0x14, 0xec, 0x21, 0xe9, 0x84, 0x83, 0xb3, 0x96, 0x17,
+ 0x04, 0x07, 0x72, 0x8d, 0x7d, 0xd2, 0x8e, 0x8b, 0xb0, 0x57, 0x99, 0xa3, 0xf1, 0xb1, 0x9f, 0x9e,
+ 0x93, 0xe3, 0xeb, 0xbf, 0x7a, 0x34, 0xd2, 0xaf, 0xec, 0x79, 0x06, 0xd9, 0x68, 0x5a, 0x5d, 0xf8,
+ 0x98, 0xc8, 0x90, 0xa8, 0x23, 0x95, 0x40, 0x35, 0x92, 0x1d, 0xa7, 0xad, 0x3e, 0xd4, 0x21, 0xad,
+ 0x15, 0x0e, 0xd4, 0x84, 0x9b, 0xba, 0xd6, 0x1e, 0x8f, 0x6f, 0x5c, 0x05, 0x87, 0x10, 0xad, 0x97,
+ 0xf3, 0xa5, 0x14, 0x7f, 0xfa, 0x9a, 0x4a, 0x65, 0xf4, 0x6f, 0x20, 0x2d, 0x50, 0x30, 0xfa, 0xf2,
+ 0x12, 0xc4, 0x96, 0x13, 0xfa, 0xe9, 0xa8, 0x3a, 0x14, 0x8f, 0x4e, 0x2e, 0x34, 0x85, 0x48, 0xce,
+ 0x47, 0x42, 0x14, 0xdb, 0x14, 0x10, 0x87, 0x57, 0xd1, 0x27, 0x6a, 0x1f, 0x1a, 0xaa, 0x7e, 0xa1,
+ 0x2e, 0x7c, 0xfc, 0xd9, 0x2a, 0x70, 0x93, 0x40, 0xec, 0x6c, 0x05, 0x69, 0xeb, 0x7b, 0x5d, 0x2a,
+ 0xea, 0x5a, 0x9d, 0xb7, 0xd4, 0x54, 0x0a, 0x9f, 0x24, 0x54, 0xd4, 0xe6, 0x6b, 0xfb, 0x3d, 0x9d,
+ 0x69, 0x12, 0x10, 0x71, 0x34, 0x51, 0x00, 0x4f, 0xab, 0xd7, 0xfa, 0x5e, 0x04, 0xfd, 0x4d, 0xfc,
+ 0x41, 0x2e, 0x39, 0x77, 0xb5, 0x57, 0xf9, 0x1f, 0x5e, 0xe5, 0xb7, 0x79, 0x8a, 0x47, 0xe3, 0x71,
+ 0xd9, 0xc9, 0x25, 0x91, 0x6f, 0x3f, 0xbe, 0x24, 0x60, 0x4c, 0x67, 0x98, 0xa4, 0xdc, 0x32, 0xe7,
+ 0xbf, 0x0a, 0x56, 0xf6, 0xf2, 0x53, 0x3c, 0xce, 0xca, 0x28, 0x16, 0xf9, 0x76, 0x8a, 0x05, 0x8c,
+ 0x89, 0x62, 0x29, 0xb7, 0x8c, 0x62, 0x15, 0xec, 0x45, 0x1f, 0x76, 0xc2, 0x4d, 0x29, 0x39, 0x37,
+ 0x23, 0xf2, 0xed, 0x8f, 0xb2, 0x72, 0x10, 0xe3, 0xc3, 0xac, 0x22, 0xb7, 0xf4, 0x61, 0x2e, 0x05,
+ 0x6c, 0x1d, 0xc1, 0xf6, 0x73, 0x6d, 0x3c, 0xbb, 0x9c, 0x5c, 0xdb, 0x09, 0x37, 0x91, 0xb9, 0x96,
+ 0x58, 0x65, 0x6f, 0xe2, 0x39, 0xda, 0x82, 0x8f, 0x69, 0xb2, 0x6f, 0xea, 0x3e, 0x30, 0x99, 0xf8,
+ 0xd5, 0x6c, 0x56, 0x90, 0xc2, 0x8a, 0xdb, 0xf5, 0x90, 0x26, 0xb6, 0x2b, 0x59, 0xab, 0x92, 0x94,
+ 0x13, 0x3f, 0x4d, 0x47, 0xac, 0x44, 0xae, 0xaf, 0xca, 0x3e, 0xd3, 0x61, 0x2b, 0x19, 0xd5, 0x56,
+ 0xf2, 0x4b, 0xfc, 0x34, 0xd1, 0x22, 0x72, 0x7d, 0x55, 0xaa, 0x99, 0x68, 0x91, 0x51, 0x6d, 0x2e,
+ 0x99, 0x76, 0x7e, 0x36, 0x4b, 0x12, 0x38, 0xe2, 0xa7, 0xe9, 0x2d, 0x5e, 0x9e, 0xe9, 0xab, 0x52,
+ 0xc8, 0xf8, 0x26, 0xaf, 0x84, 0x69, 0x1b, 0x51, 0xc2, 0x7f, 0xd9, 0x08, 0xa1, 0xa7, 0xe2, 0x24,
+ 0xe9, 0x62, 0x25, 0x83, 0x6e, 0x5d, 0x16, 0x65, 0xc4, 0xde, 0xab, 0xb1, 0xf7, 0x6a, 0xec, 0xbd,
+ 0x1a, 0x7b, 0xaf, 0xc6, 0xde, 0xab, 0xf1, 0x7a, 0xbc, 0x1a, 0xec, 0x44, 0xb0, 0x38, 0xf3, 0xa6,
+ 0x9c, 0x92, 0x23, 0x7c, 0xf0, 0xac, 0x1c, 0x1f, 0xe2, 0xb5, 0xa4, 0xf9, 0x2c, 0x1b, 0xc7, 0xd0,
+ 0xfa, 0x7b, 0x78, 0x42, 0xa8, 0x7e, 0x46, 0x4e, 0xb8, 0xa1, 0xb6, 0x35, 0x97, 0x70, 0xe7, 0x0a,
+ 0x5f, 0x1d, 0x23, 0x4a, 0x1a, 0xd9, 0x40, 0x94, 0x3a, 0xc8, 0x27, 0xcf, 0x80, 0xda, 0xea, 0x27,
+ 0xc1, 0xe4, 0xe8, 0xe5, 0xa7, 0x8b, 0x4f, 0x9f, 0xbb, 0xe7, 0x7f, 0xd6, 0xde, 0x49, 0xf7, 0xa1,
+ 0x4e, 0x3f, 0xfd, 0x7c, 0xda, 0xfd, 0xf9, 0xe4, 0xd7, 0x5f, 0x4f, 0x50, 0x6b, 0xdb, 0xad, 0x63,
+ 0xc3, 0x61, 0x98, 0x83, 0xa2, 0xd6, 0x0c, 0x8b, 0x71, 0x05, 0x3b, 0x78, 0xb7, 0x36, 0xec, 0x0e,
+ 0xed, 0xcf, 0x5d, 0x99, 0x90, 0x3b, 0xb5, 0xff, 0x1e, 0xc1, 0x7c, 0x33, 0x79, 0xf3, 0xcc, 0x26,
+ 0x8f, 0x7c, 0xda, 0xca, 0x62, 0xa5, 0xdd, 0xc3, 0x90, 0x29, 0xe5, 0xd2, 0xcd, 0xec, 0x90, 0x72,
+ 0x33, 0x64, 0x23, 0x33, 0xe2, 0x31, 0x4e, 0xdf, 0x49, 0xcc, 0xb3, 0x99, 0x3e, 0x5f, 0xc6, 0x19,
+ 0x9b, 0xa9, 0xe4, 0x20, 0x9e, 0xe9, 0xf0, 0x80, 0x62, 0x5d, 0x14, 0xe9, 0x74, 0x98, 0xf8, 0x65,
+ 0x75, 0xac, 0x0f, 0xb2, 0xc4, 0x95, 0x2c, 0x99, 0x59, 0xe3, 0x69, 0xa6, 0xd0, 0xb1, 0x2b, 0xea,
+ 0x34, 0x22, 0x68, 0x03, 0x19, 0x09, 0x69, 0x48, 0x65, 0xf6, 0xc3, 0xc4, 0x45, 0x42, 0x14, 0x06,
+ 0x0e, 0xc7, 0xef, 0x29, 0xac, 0xe9, 0x86, 0xf2, 0x99, 0xca, 0xab, 0xcb, 0xcb, 0xc8, 0xc1, 0xaa,
+ 0x72, 0x03, 0xdf, 0x5b, 0xa0, 0x6a, 0x33, 0x57, 0xc4, 0xa1, 0x7f, 0xd8, 0x61, 0x9c, 0x48, 0x62,
+ 0x01, 0x52, 0x9d, 0xc3, 0xbb, 0xcf, 0x6b, 0x37, 0xdb, 0xef, 0x03, 0x22, 0x9c, 0xeb, 0x82, 0x0a,
+ 0xb7, 0x84, 0x0c, 0x52, 0x37, 0xd4, 0x2c, 0x46, 0x33, 0x10, 0x0b, 0x2a, 0x45, 0x16, 0xde, 0x49,
+ 0xe4, 0xe2, 0x23, 0x81, 0x26, 0x7f, 0x31, 0x78, 0x8b, 0x9b, 0x71, 0xb1, 0x43, 0x48, 0x5d, 0xfd,
+ 0x08, 0x7f, 0x78, 0xf2, 0x04, 0x55, 0xd4, 0x1c, 0xec, 0xab, 0x96, 0x0e, 0x11, 0x02, 0x69, 0x0d,
+ 0x19, 0x81, 0x0f, 0x29, 0x75, 0x25, 0xa5, 0xe2, 0x89, 0x41, 0x4f, 0x5d, 0xc9, 0xee, 0xe5, 0xcb,
+ 0xfe, 0x3f, 0x2f, 0x9e, 0x06, 0x73
};
const char* shaderSource() {
diff --git a/src/mbgl/programs/gl/shader_source.hpp b/src/mbgl/programs/gl/shader_source.hpp
index f6de8a56cc..1a5fbddae3 100644
--- a/src/mbgl/programs/gl/shader_source.hpp
+++ b/src/mbgl/programs/gl/shader_source.hpp
@@ -8,6 +8,9 @@ namespace gl {
const char* shaderSource();
+template <typename>
+struct ShaderSource;
+
} // namespace gl
} // namespace programs
} // namespace mbgl
diff --git a/src/mbgl/programs/gl/shaders.cpp b/src/mbgl/programs/gl/shaders.cpp
index 3cc33992de..6fb4d70db9 100644
--- a/src/mbgl/programs/gl/shaders.cpp
+++ b/src/mbgl/programs/gl/shaders.cpp
@@ -1,4 +1,5 @@
#include <mbgl/programs/gl/shaders.hpp>
+#include <mbgl/programs/gl/shader_source.hpp>
#include <mbgl/programs/gl/preludes.hpp>
#include <mbgl/programs/program_parameters.hpp>
#include <mbgl/util/string.hpp>
@@ -9,20 +10,17 @@ namespace mbgl {
namespace programs {
namespace gl {
-std::string fragmentSource(const ProgramParameters& parameters, const char* fragmentSource) {
- return parameters.getDefines() + fragmentShaderPrelude + fragmentSource;
-}
-
-std::string vertexSource(const ProgramParameters& parameters, const char* vertexSource) {
- return parameters.getDefines() + vertexShaderPrelude + vertexSource;
-}
-
-std::string programIdentifier(const std::string& vertexSource, const std::string& fragmentSource) {
+std::string programIdentifier(const std::string& defines1,
+ const std::string& defines2,
+ const uint8_t hash1[8],
+ const uint8_t hash2[8]) {
std::string result;
- result.reserve((sizeof(size_t) * 2) * 2 + 2); // 2 size_t hex values + "v2"
- result += util::toHex(std::hash<std::string>()(vertexSource));
- result += util::toHex(std::hash<std::string>()(fragmentSource));
- result += "v3";
+ result.reserve(8 + 8 + (sizeof(size_t) * 2) * 2 + 2);
+ result.append(util::toHex(std::hash<std::string>()(defines1)));
+ result.append(util::toHex(std::hash<std::string>()(defines2)));
+ result.append(hash1, hash2 + 8);
+ result.append(hash2, hash2 + 8);
+ result.append("v3");
return result;
}
diff --git a/src/mbgl/programs/gl/shaders.hpp b/src/mbgl/programs/gl/shaders.hpp
index 5278ea54da..46a87f4af8 100644
--- a/src/mbgl/programs/gl/shaders.hpp
+++ b/src/mbgl/programs/gl/shaders.hpp
@@ -9,9 +9,10 @@ class ProgramParameters;
namespace programs {
namespace gl {
-std::string fragmentSource(const ProgramParameters&, const char* fragmentSource);
-std::string vertexSource(const ProgramParameters&, const char* vertexSource);
-std::string programIdentifier(const std::string& vertexSource, const std::string& fragmentSource);
+std::string programIdentifier(const std::string& defines1,
+ const std::string& defines2,
+ const uint8_t hash1[8],
+ const uint8_t hash2[8]);
} // namespace gl
} // namespace programs
diff --git a/src/mbgl/programs/gl/symbol_icon.cpp b/src/mbgl/programs/gl/symbol_icon.cpp
index 733d3b7ebd..6cb2b88543 100644
--- a/src/mbgl/programs/gl/symbol_icon.cpp
+++ b/src/mbgl/programs/gl/symbol_icon.cpp
@@ -1,18 +1,37 @@
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
#include <mbgl/programs/symbol_icon_program.hpp>
+#include <mbgl/programs/gl/preludes.hpp>
#include <mbgl/programs/gl/shader_source.hpp>
#include <mbgl/gl/program.hpp>
namespace mbgl {
+namespace programs {
+namespace gl {
+
+template <typename>
+struct ShaderSource;
+
+template <>
+struct ShaderSource<SymbolIconProgram> {
+ static constexpr const char* name = "symbol_icon";
+ static constexpr const uint8_t hash[8] = { 0x96, 0x0c, 0xef, 0xec, 0x37, 0x23, 0xf9, 0xb1 };
+ static constexpr const auto vertexOffset = 50000;
+ static constexpr const auto fragmentOffset = 52654;
+};
+
+constexpr const char* ShaderSource<SymbolIconProgram>::name;
+constexpr const uint8_t ShaderSource<SymbolIconProgram>::hash[8];
+
+} // namespace gl
+} // namespace programs
+
namespace gfx {
template <>
std::unique_ptr<Program<SymbolIconProgram>>
Context::createProgram<gl::Context>(const ProgramParameters& programParameters) {
- return gl::Program<SymbolIconProgram>::createProgram(
- reinterpret_cast<gl::Context&>(*this), programParameters, "symbol_icon",
- programs::gl::shaderSource() + 50000, programs::gl::shaderSource() + 52654);
+ return std::make_unique<gl::Program<SymbolIconProgram>>(programParameters);
}
} // namespace gfx
@@ -39,7 +58,7 @@ uniform float u_fade_change;
#ifndef HAS_UNIFORM_u_opacity
-uniform lowp float a_opacity_t;
+uniform lowp float u_opacity_t;
attribute lowp vec2 a_opacity;
varying lowp float opacity;
#else
@@ -62,7 +81,7 @@ varying float v_fade_opacity;
void main() {
#ifndef HAS_UNIFORM_u_opacity
- opacity = unpack_mix_vec2(a_opacity, a_opacity_t);
+ opacity = unpack_mix_vec2(a_opacity, u_opacity_t);
#else
lowp float opacity = u_opacity;
#endif
diff --git a/src/mbgl/programs/gl/symbol_sdf_icon.cpp b/src/mbgl/programs/gl/symbol_sdf_icon.cpp
index ef3ecd138c..d98554099f 100644
--- a/src/mbgl/programs/gl/symbol_sdf_icon.cpp
+++ b/src/mbgl/programs/gl/symbol_sdf_icon.cpp
@@ -1,18 +1,37 @@
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
#include <mbgl/programs/symbol_sdf_icon_program.hpp>
+#include <mbgl/programs/gl/preludes.hpp>
#include <mbgl/programs/gl/shader_source.hpp>
#include <mbgl/gl/program.hpp>
namespace mbgl {
+namespace programs {
+namespace gl {
+
+template <typename>
+struct ShaderSource;
+
+template <>
+struct ShaderSource<SymbolSDFIconProgram> {
+ static constexpr const char* name = "symbol_sdf_icon";
+ static constexpr const uint8_t hash[8] = { 0x13, 0xfc, 0x05, 0x2a, 0xd1, 0x93, 0xfb, 0x7d };
+ static constexpr const auto vertexOffset = 53059;
+ static constexpr const auto fragmentOffset = 57099;
+};
+
+constexpr const char* ShaderSource<SymbolSDFIconProgram>::name;
+constexpr const uint8_t ShaderSource<SymbolSDFIconProgram>::hash[8];
+
+} // namespace gl
+} // namespace programs
+
namespace gfx {
template <>
std::unique_ptr<Program<SymbolSDFIconProgram>>
Context::createProgram<gl::Context>(const ProgramParameters& programParameters) {
- return gl::Program<SymbolSDFIconProgram>::createProgram(
- reinterpret_cast<gl::Context&>(*this), programParameters, "symbol_sdf_icon",
- programs::gl::shaderSource() + 53059, programs::gl::shaderSource() + 57099);
+ return std::make_unique<gl::Program<SymbolSDFIconProgram>>(programParameters);
}
} // namespace gfx
@@ -41,7 +60,7 @@ uniform highp float u_size; // used when size is both zoom and feature constant
#ifndef HAS_UNIFORM_u_fill_color
-uniform lowp float a_fill_color_t;
+uniform lowp float u_fill_color_t;
attribute highp vec4 a_fill_color;
varying highp vec4 fill_color;
#else
@@ -50,7 +69,7 @@ uniform highp vec4 u_fill_color;
#ifndef HAS_UNIFORM_u_halo_color
-uniform lowp float a_halo_color_t;
+uniform lowp float u_halo_color_t;
attribute highp vec4 a_halo_color;
varying highp vec4 halo_color;
#else
@@ -59,7 +78,7 @@ uniform highp vec4 u_halo_color;
#ifndef HAS_UNIFORM_u_opacity
-uniform lowp float a_opacity_t;
+uniform lowp float u_opacity_t;
attribute lowp vec2 a_opacity;
varying lowp float opacity;
#else
@@ -68,7 +87,7 @@ uniform lowp float u_opacity;
#ifndef HAS_UNIFORM_u_halo_width
-uniform lowp float a_halo_width_t;
+uniform lowp float u_halo_width_t;
attribute lowp vec2 a_halo_width;
varying lowp float halo_width;
#else
@@ -77,7 +96,7 @@ uniform lowp float u_halo_width;
#ifndef HAS_UNIFORM_u_halo_blur
-uniform lowp float a_halo_blur_t;
+uniform lowp float u_halo_blur_t;
attribute lowp vec2 a_halo_blur;
varying lowp float halo_blur;
#else
@@ -105,35 +124,35 @@ varying vec3 v_data1;
void main() {
#ifndef HAS_UNIFORM_u_fill_color
- fill_color = unpack_mix_color(a_fill_color, a_fill_color_t);
+ fill_color = unpack_mix_color(a_fill_color, u_fill_color_t);
#else
highp vec4 fill_color = u_fill_color;
#endif
#ifndef HAS_UNIFORM_u_halo_color
- halo_color = unpack_mix_color(a_halo_color, a_halo_color_t);
+ halo_color = unpack_mix_color(a_halo_color, u_halo_color_t);
#else
highp vec4 halo_color = u_halo_color;
#endif
#ifndef HAS_UNIFORM_u_opacity
- opacity = unpack_mix_vec2(a_opacity, a_opacity_t);
+ opacity = unpack_mix_vec2(a_opacity, u_opacity_t);
#else
lowp float opacity = u_opacity;
#endif
#ifndef HAS_UNIFORM_u_halo_width
- halo_width = unpack_mix_vec2(a_halo_width, a_halo_width_t);
+ halo_width = unpack_mix_vec2(a_halo_width, u_halo_width_t);
#else
lowp float halo_width = u_halo_width;
#endif
#ifndef HAS_UNIFORM_u_halo_blur
- halo_blur = unpack_mix_vec2(a_halo_blur, a_halo_blur_t);
+ halo_blur = unpack_mix_vec2(a_halo_blur, u_halo_blur_t);
#else
lowp float halo_blur = u_halo_blur;
#endif
diff --git a/src/mbgl/programs/gl/symbol_sdf_text.cpp b/src/mbgl/programs/gl/symbol_sdf_text.cpp
index a0d810d1ce..81f3729d92 100644
--- a/src/mbgl/programs/gl/symbol_sdf_text.cpp
+++ b/src/mbgl/programs/gl/symbol_sdf_text.cpp
@@ -1,18 +1,37 @@
// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
#include <mbgl/programs/symbol_sdf_text_program.hpp>
+#include <mbgl/programs/gl/preludes.hpp>
#include <mbgl/programs/gl/shader_source.hpp>
#include <mbgl/gl/program.hpp>
namespace mbgl {
+namespace programs {
+namespace gl {
+
+template <typename>
+struct ShaderSource;
+
+template <>
+struct ShaderSource<SymbolSDFTextProgram> {
+ static constexpr const char* name = "symbol_sdf_text";
+ static constexpr const uint8_t hash[8] = { 0x13, 0xfc, 0x05, 0x2a, 0xd1, 0x93, 0xfb, 0x7d };
+ static constexpr const auto vertexOffset = 53059;
+ static constexpr const auto fragmentOffset = 57099;
+};
+
+constexpr const char* ShaderSource<SymbolSDFTextProgram>::name;
+constexpr const uint8_t ShaderSource<SymbolSDFTextProgram>::hash[8];
+
+} // namespace gl
+} // namespace programs
+
namespace gfx {
template <>
std::unique_ptr<Program<SymbolSDFTextProgram>>
Context::createProgram<gl::Context>(const ProgramParameters& programParameters) {
- return gl::Program<SymbolSDFTextProgram>::createProgram(
- reinterpret_cast<gl::Context&>(*this), programParameters, "symbol_sdf_text",
- programs::gl::shaderSource() + 53059, programs::gl::shaderSource() + 57099);
+ return std::make_unique<gl::Program<SymbolSDFTextProgram>>(programParameters);
}
} // namespace gfx
@@ -41,7 +60,7 @@ uniform highp float u_size; // used when size is both zoom and feature constant
#ifndef HAS_UNIFORM_u_fill_color
-uniform lowp float a_fill_color_t;
+uniform lowp float u_fill_color_t;
attribute highp vec4 a_fill_color;
varying highp vec4 fill_color;
#else
@@ -50,7 +69,7 @@ uniform highp vec4 u_fill_color;
#ifndef HAS_UNIFORM_u_halo_color
-uniform lowp float a_halo_color_t;
+uniform lowp float u_halo_color_t;
attribute highp vec4 a_halo_color;
varying highp vec4 halo_color;
#else
@@ -59,7 +78,7 @@ uniform highp vec4 u_halo_color;
#ifndef HAS_UNIFORM_u_opacity
-uniform lowp float a_opacity_t;
+uniform lowp float u_opacity_t;
attribute lowp vec2 a_opacity;
varying lowp float opacity;
#else
@@ -68,7 +87,7 @@ uniform lowp float u_opacity;
#ifndef HAS_UNIFORM_u_halo_width
-uniform lowp float a_halo_width_t;
+uniform lowp float u_halo_width_t;
attribute lowp vec2 a_halo_width;
varying lowp float halo_width;
#else
@@ -77,7 +96,7 @@ uniform lowp float u_halo_width;
#ifndef HAS_UNIFORM_u_halo_blur
-uniform lowp float a_halo_blur_t;
+uniform lowp float u_halo_blur_t;
attribute lowp vec2 a_halo_blur;
varying lowp float halo_blur;
#else
@@ -105,35 +124,35 @@ varying vec3 v_data1;
void main() {
#ifndef HAS_UNIFORM_u_fill_color
- fill_color = unpack_mix_color(a_fill_color, a_fill_color_t);
+ fill_color = unpack_mix_color(a_fill_color, u_fill_color_t);
#else
highp vec4 fill_color = u_fill_color;
#endif
#ifndef HAS_UNIFORM_u_halo_color
- halo_color = unpack_mix_color(a_halo_color, a_halo_color_t);
+ halo_color = unpack_mix_color(a_halo_color, u_halo_color_t);
#else
highp vec4 halo_color = u_halo_color;
#endif
#ifndef HAS_UNIFORM_u_opacity
- opacity = unpack_mix_vec2(a_opacity, a_opacity_t);
+ opacity = unpack_mix_vec2(a_opacity, u_opacity_t);
#else
lowp float opacity = u_opacity;
#endif
#ifndef HAS_UNIFORM_u_halo_width
- halo_width = unpack_mix_vec2(a_halo_width, a_halo_width_t);
+ halo_width = unpack_mix_vec2(a_halo_width, u_halo_width_t);
#else
lowp float halo_width = u_halo_width;
#endif
#ifndef HAS_UNIFORM_u_halo_blur
- halo_blur = unpack_mix_vec2(a_halo_blur, a_halo_blur_t);
+ halo_blur = unpack_mix_vec2(a_halo_blur, u_halo_blur_t);
#else
lowp float halo_blur = u_halo_blur;
#endif
diff --git a/src/mbgl/programs/heatmap_program.hpp b/src/mbgl/programs/heatmap_program.hpp
index 9563dd8d1b..537a9e9565 100644
--- a/src/mbgl/programs/heatmap_program.hpp
+++ b/src/mbgl/programs/heatmap_program.hpp
@@ -10,18 +10,18 @@
namespace mbgl {
namespace uniforms {
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_intensity);
+MBGL_DEFINE_UNIFORM_SCALAR(float, intensity);
} // namespace uniforms
class HeatmapProgram : public Program<
HeatmapProgram,
gfx::PrimitiveType::Triangle,
TypeList<
- attributes::a_pos>,
+ attributes::pos>,
TypeList<
- uniforms::u_intensity,
- uniforms::u_matrix,
- uniforms::heatmap::u_extrude_scale>,
+ uniforms::intensity,
+ uniforms::matrix,
+ uniforms::heatmap::extrude_scale>,
TypeList<>,
style::HeatmapPaintProperties>
{
@@ -52,7 +52,7 @@ public:
HeatmapLayerPrograms(gfx::Context& context, const ProgramParameters& programParameters)
: heatmap(context, programParameters),
heatmapTexture(context, programParameters) {}
- ProgramMap<HeatmapProgram> heatmap;
+ HeatmapProgram heatmap;
HeatmapTextureProgram heatmapTexture;
};
diff --git a/src/mbgl/programs/heatmap_texture_program.hpp b/src/mbgl/programs/heatmap_texture_program.hpp
index 954e03f9b6..6762f8c7f4 100644
--- a/src/mbgl/programs/heatmap_texture_program.hpp
+++ b/src/mbgl/programs/heatmap_texture_program.hpp
@@ -12,14 +12,14 @@ namespace mbgl {
class HeatmapTextureProgram : public Program<
HeatmapTextureProgram,
gfx::PrimitiveType::Triangle,
- TypeList<attributes::a_pos>,
+ TypeList<attributes::pos>,
TypeList<
- uniforms::u_matrix,
- uniforms::u_world,
- uniforms::u_opacity>,
+ uniforms::matrix,
+ uniforms::world,
+ uniforms::opacity>,
TypeList<
- textures::u_image,
- textures::u_color_ramp>,
+ textures::image,
+ textures::color_ramp>,
style::Properties<>> {
public:
using Program::Program;
diff --git a/src/mbgl/programs/hillshade_prepare_program.hpp b/src/mbgl/programs/hillshade_prepare_program.hpp
index 0243cc1879..2d76145bc3 100644
--- a/src/mbgl/programs/hillshade_prepare_program.hpp
+++ b/src/mbgl/programs/hillshade_prepare_program.hpp
@@ -9,23 +9,23 @@
namespace mbgl {
namespace uniforms {
-MBGL_DEFINE_UNIFORM_VECTOR(uint16_t, 2, u_dimension);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_maxzoom);
+MBGL_DEFINE_UNIFORM_VECTOR(uint16_t, 2, dimension);
+MBGL_DEFINE_UNIFORM_SCALAR(float, maxzoom);
} // namespace uniforms
class HillshadePrepareProgram : public Program<
HillshadePrepareProgram,
gfx::PrimitiveType::Triangle,
TypeList<
- attributes::a_pos,
- attributes::a_texture_pos>,
+ attributes::pos,
+ attributes::texture_pos>,
TypeList<
- uniforms::u_matrix,
- uniforms::u_dimension,
- uniforms::u_zoom,
- uniforms::u_maxzoom>,
+ uniforms::matrix,
+ uniforms::dimension,
+ uniforms::zoom,
+ uniforms::maxzoom>,
TypeList<
- textures::u_image>,
+ textures::image>,
style::Properties<>> {
public:
using Program::Program;
diff --git a/src/mbgl/programs/hillshade_program.hpp b/src/mbgl/programs/hillshade_program.hpp
index 68d67917df..33f91abef0 100644
--- a/src/mbgl/programs/hillshade_program.hpp
+++ b/src/mbgl/programs/hillshade_program.hpp
@@ -11,28 +11,28 @@
namespace mbgl {
namespace uniforms {
-MBGL_DEFINE_UNIFORM_SCALAR(Color, u_shadow);
-MBGL_DEFINE_UNIFORM_SCALAR(Color, u_highlight);
-MBGL_DEFINE_UNIFORM_SCALAR(Color, u_accent);
-MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_light);
-MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_latrange);
+MBGL_DEFINE_UNIFORM_SCALAR(Color, shadow);
+MBGL_DEFINE_UNIFORM_SCALAR(Color, highlight);
+MBGL_DEFINE_UNIFORM_SCALAR(Color, accent);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, light);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, latrange);
} // namespace uniforms
class HillshadeProgram : public Program<
HillshadeProgram,
gfx::PrimitiveType::Triangle,
TypeList<
- attributes::a_pos,
- attributes::a_texture_pos>,
+ attributes::pos,
+ attributes::texture_pos>,
TypeList<
- uniforms::u_matrix,
- uniforms::u_highlight,
- uniforms::u_shadow,
- uniforms::u_accent,
- uniforms::u_light,
- uniforms::u_latrange>,
+ uniforms::matrix,
+ uniforms::highlight,
+ uniforms::shadow,
+ uniforms::accent,
+ uniforms::light,
+ uniforms::latrange>,
TypeList<
- textures::u_image>,
+ textures::image>,
style::HillshadePaintProperties>{
public:
using Program::Program;
diff --git a/src/mbgl/programs/line_program.cpp b/src/mbgl/programs/line_program.cpp
index 74a1ba3162..9428b5d9d6 100644
--- a/src/mbgl/programs/line_program.cpp
+++ b/src/mbgl/programs/line_program.cpp
@@ -19,26 +19,26 @@ using namespace style;
static_assert(sizeof(LineLayoutVertex) == 12, "expected LineLayoutVertex size");
template <class Values, class...Args>
-Values makeValues(const RenderLinePaintProperties::PossiblyEvaluated& properties,
+Values makeValues(const style::LinePaintProperties::PossiblyEvaluated& properties,
const RenderTile& tile,
const TransformState& state,
const std::array<float, 2>& pixelsToGLUnits,
Args&&... args) {
return Values {
- uniforms::u_matrix::Value(
+ uniforms::matrix::Value(
tile.translatedMatrix(properties.get<LineTranslate>(),
properties.get<LineTranslateAnchor>(),
state)
),
- uniforms::u_ratio::Value( 1.0f / tile.id.pixelsToTileUnits(1.0, state.getZoom()) ),
- uniforms::u_gl_units_to_pixels::Value({ {1.0f / pixelsToGLUnits[0], 1.0f / pixelsToGLUnits[1]} }),
+ uniforms::ratio::Value( 1.0f / tile.id.pixelsToTileUnits(1.0, state.getZoom()) ),
+ uniforms::gl_units_to_pixels::Value({ {1.0f / pixelsToGLUnits[0], 1.0f / pixelsToGLUnits[1]} }),
std::forward<Args>(args)...
};
}
LineProgram::LayoutUniformValues
-LineProgram::layoutUniformValues(const RenderLinePaintProperties::PossiblyEvaluated& properties,
+LineProgram::layoutUniformValues(const style::LinePaintProperties::PossiblyEvaluated& properties,
const RenderTile& tile,
const TransformState& state,
const std::array<float, 2>& pixelsToGLUnits) {
@@ -51,7 +51,7 @@ LineProgram::layoutUniformValues(const RenderLinePaintProperties::PossiblyEvalua
}
LineSDFProgram::LayoutUniformValues
-LineSDFProgram::layoutUniformValues(const RenderLinePaintProperties::PossiblyEvaluated& properties,
+LineSDFProgram::layoutUniformValues(const style::LinePaintProperties::PossiblyEvaluated& properties,
float pixelRatio,
const RenderTile& tile,
const TransformState& state,
@@ -78,17 +78,17 @@ LineSDFProgram::layoutUniformValues(const RenderLinePaintProperties::PossiblyEva
tile,
state,
pixelsToGLUnits,
- uniforms::u_patternscale_a::Value( scaleA ),
- uniforms::u_patternscale_b::Value( scaleB ),
- uniforms::u_tex_y_a::Value( posA.y ),
- uniforms::u_tex_y_b::Value( posB.y ),
- uniforms::u_mix::Value( crossfade.t ),
- uniforms::u_sdfgamma::Value( atlasWidth / (std::min(widthA, widthB) * 256.0f * pixelRatio) / 2.0f )
+ uniforms::patternscale_a::Value( scaleA ),
+ uniforms::patternscale_b::Value( scaleB ),
+ uniforms::tex_y_a::Value( posA.y ),
+ uniforms::tex_y_b::Value( posB.y ),
+ uniforms::mix::Value( crossfade.t ),
+ uniforms::sdfgamma::Value( atlasWidth / (std::min(widthA, widthB) * 256.0f * pixelRatio) / 2.0f )
);
}
LinePatternProgram::LayoutUniformValues LinePatternProgram::layoutUniformValues(
- const RenderLinePaintProperties::PossiblyEvaluated& properties,
+ const style::LinePaintProperties::PossiblyEvaluated& properties,
const RenderTile& tile,
const TransformState& state,
const std::array<float, 2>& pixelsToGLUnits,
@@ -103,14 +103,14 @@ LinePatternProgram::LayoutUniformValues LinePatternProgram::layoutUniformValues(
tile,
state,
pixelsToGLUnits,
- uniforms::u_scale::Value ({ {pixelRatio, tileRatio, crossfade.fromScale, crossfade.toScale} }),
- uniforms::u_texsize::Value( atlasSize ),
- uniforms::u_fade::Value( crossfade.t )
+ uniforms::scale::Value ({ {pixelRatio, tileRatio, crossfade.fromScale, crossfade.toScale} }),
+ uniforms::texsize::Value( atlasSize ),
+ uniforms::fade::Value( crossfade.t )
);
}
LineGradientProgram::LayoutUniformValues LineGradientProgram::layoutUniformValues(
- const RenderLinePaintProperties::PossiblyEvaluated& properties,
+ const style::LinePaintProperties::PossiblyEvaluated& properties,
const RenderTile& tile,
const TransformState& state,
const std::array<float, 2>& pixelsToGLUnits) {
diff --git a/src/mbgl/programs/line_program.hpp b/src/mbgl/programs/line_program.hpp
index 05546e3cbe..ed149abb33 100644
--- a/src/mbgl/programs/line_program.hpp
+++ b/src/mbgl/programs/line_program.hpp
@@ -17,29 +17,29 @@ class LinePatternPos;
class ImagePosition;
namespace uniforms {
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_ratio);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_tex_y_a);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_tex_y_b);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_sdfgamma);
-MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_patternscale_a);
-MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_patternscale_b);
-MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_gl_units_to_pixels);
+MBGL_DEFINE_UNIFORM_SCALAR(float, ratio);
+MBGL_DEFINE_UNIFORM_SCALAR(float, tex_y_a);
+MBGL_DEFINE_UNIFORM_SCALAR(float, tex_y_b);
+MBGL_DEFINE_UNIFORM_SCALAR(float, sdfgamma);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, patternscale_a);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, patternscale_b);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, gl_units_to_pixels);
} // namespace uniforms
using LineLayoutAttributes = TypeList<
- attributes::a_pos_normal,
- attributes::a_data<uint8_t, 4>>;
+ attributes::pos_normal,
+ attributes::data<uint8_t, 4>>;
class LineProgram : public Program<
LineProgram,
gfx::PrimitiveType::Triangle,
LineLayoutAttributes,
TypeList<
- uniforms::u_matrix,
- uniforms::u_ratio,
- uniforms::u_gl_units_to_pixels>,
+ uniforms::matrix,
+ uniforms::ratio,
+ uniforms::gl_units_to_pixels>,
TypeList<>,
- RenderLinePaintProperties>
+ style::LinePaintProperties>
{
public:
using Program::Program;
@@ -90,7 +90,7 @@ public:
static const int8_t extrudeScale = 63;
static LayoutUniformValues
- layoutUniformValues(const RenderLinePaintProperties::PossiblyEvaluated&,
+ layoutUniformValues(const style::LinePaintProperties::PossiblyEvaluated&,
const RenderTile&,
const TransformState&,
const std::array<float, 2>& pixelsToGLUnits);
@@ -101,21 +101,21 @@ class LinePatternProgram : public Program<
gfx::PrimitiveType::Triangle,
LineLayoutAttributes,
TypeList<
- uniforms::u_matrix,
- uniforms::u_ratio,
- uniforms::u_gl_units_to_pixels,
- uniforms::u_scale,
- uniforms::u_texsize,
- uniforms::u_fade>,
+ uniforms::matrix,
+ uniforms::ratio,
+ uniforms::gl_units_to_pixels,
+ uniforms::scale,
+ uniforms::texsize,
+ uniforms::fade>,
TypeList<
- textures::u_image>,
- RenderLinePaintProperties>
+ textures::image>,
+ style::LinePaintProperties>
{
public:
using Program::Program;
static LayoutUniformValues
- layoutUniformValues(const RenderLinePaintProperties::PossiblyEvaluated&,
+ layoutUniformValues(const style::LinePaintProperties::PossiblyEvaluated&,
const RenderTile&,
const TransformState&,
const std::array<float, 2>& pixelsToGLUnits,
@@ -129,24 +129,24 @@ class LineSDFProgram : public Program<
gfx::PrimitiveType::Triangle,
LineLayoutAttributes,
TypeList<
- uniforms::u_matrix,
- uniforms::u_ratio,
- uniforms::u_gl_units_to_pixels,
- uniforms::u_patternscale_a,
- uniforms::u_patternscale_b,
- uniforms::u_tex_y_a,
- uniforms::u_tex_y_b,
- uniforms::u_mix,
- uniforms::u_sdfgamma>,
+ uniforms::matrix,
+ uniforms::ratio,
+ uniforms::gl_units_to_pixels,
+ uniforms::patternscale_a,
+ uniforms::patternscale_b,
+ uniforms::tex_y_a,
+ uniforms::tex_y_b,
+ uniforms::mix,
+ uniforms::sdfgamma>,
TypeList<
- textures::u_image>,
- RenderLinePaintProperties>
+ textures::image>,
+ style::LinePaintProperties>
{
public:
using Program::Program;
static LayoutUniformValues
- layoutUniformValues(const RenderLinePaintProperties::PossiblyEvaluated&,
+ layoutUniformValues(const style::LinePaintProperties::PossiblyEvaluated&,
float pixelRatio,
const RenderTile&,
const TransformState&,
@@ -162,18 +162,18 @@ class LineGradientProgram : public Program<
gfx::PrimitiveType::Triangle,
LineLayoutAttributes,
TypeList<
- uniforms::u_matrix,
- uniforms::u_ratio,
- uniforms::u_gl_units_to_pixels>,
+ uniforms::matrix,
+ uniforms::ratio,
+ uniforms::gl_units_to_pixels>,
TypeList<
- textures::u_image>,
- RenderLinePaintProperties>
+ textures::image>,
+ style::LinePaintProperties>
{
public:
using Program::Program;
static LayoutUniformValues
- layoutUniformValues(const RenderLinePaintProperties::PossiblyEvaluated&,
+ layoutUniformValues(const style::LinePaintProperties::PossiblyEvaluated&,
const RenderTile&,
const TransformState&,
const std::array<float, 2>& pixelsToGLUnits);
@@ -189,10 +189,10 @@ public:
lineGradient(context, programParameters),
lineSDF(context, programParameters),
linePattern(context, programParameters) {}
- ProgramMap<LineProgram> line;
- ProgramMap<LineGradientProgram> lineGradient;
- ProgramMap<LineSDFProgram> lineSDF;
- ProgramMap<LinePatternProgram> linePattern;
+ LineProgram line;
+ LineGradientProgram lineGradient;
+ LineSDFProgram lineSDF;
+ LinePatternProgram linePattern;
};
} // namespace mbgl
diff --git a/src/mbgl/programs/program.hpp b/src/mbgl/programs/program.hpp
index 240da22b4f..e4d2af95f8 100644
--- a/src/mbgl/programs/program.hpp
+++ b/src/mbgl/programs/program.hpp
@@ -109,36 +109,6 @@ public:
}
};
-template <class Program>
-class ProgramMap {
-public:
- using PaintProperties = typename Program::PaintProperties;
- using Binders = typename Program::Binders;
- using Bitset = typename Binders::Bitset;
-
- ProgramMap(gfx::Context& context_, ProgramParameters parameters_)
- : context(context_),
- parameters(std::move(parameters_)) {
- }
-
- Program& get(const typename PaintProperties::PossiblyEvaluated& currentProperties) {
- Bitset bits = Binders::constants(currentProperties);
- auto it = programs.find(bits);
- if (it != programs.end()) {
- return it->second;
- }
- return programs.emplace(std::piecewise_construct,
- std::forward_as_tuple(bits),
- std::forward_as_tuple(context,
- parameters.withAdditionalDefines(Binders::defines(currentProperties)))).first->second;
- }
-
-private:
- gfx::Context& context;
- ProgramParameters parameters;
- std::unordered_map<Bitset, Program> programs;
-};
-
class LayerTypePrograms {
public:
virtual ~LayerTypePrograms() = default;
diff --git a/src/mbgl/programs/program_parameters.cpp b/src/mbgl/programs/program_parameters.cpp
index 6b6c2bb2fe..e692b74e0e 100644
--- a/src/mbgl/programs/program_parameters.cpp
+++ b/src/mbgl/programs/program_parameters.cpp
@@ -40,13 +40,4 @@ optional<std::string> ProgramParameters::cachePath(const char* name) const {
}
}
-ProgramParameters ProgramParameters::withAdditionalDefines(const std::vector<std::string>& additionalDefines) const {
- ProgramParameters result(*this);
- for (const auto& define : additionalDefines) {
- result.defines += define;
- result.defines += "\n";
- }
- return result;
-}
-
} // namespace mbgl
diff --git a/src/mbgl/programs/program_parameters.hpp b/src/mbgl/programs/program_parameters.hpp
index e94e61c217..71ad454399 100644
--- a/src/mbgl/programs/program_parameters.hpp
+++ b/src/mbgl/programs/program_parameters.hpp
@@ -3,7 +3,6 @@
#include <mbgl/util/optional.hpp>
#include <string>
-#include <vector>
namespace mbgl {
@@ -14,8 +13,6 @@ public:
const std::string& getDefines() const;
optional<std::string> cachePath(const char* name) const;
- ProgramParameters withAdditionalDefines(const std::vector<std::string>& defines) const;
-
private:
std::string defines;
optional<std::string> cacheDir;
diff --git a/src/mbgl/programs/raster_program.hpp b/src/mbgl/programs/raster_program.hpp
index 55f1fb0a2e..e84ada0bdc 100644
--- a/src/mbgl/programs/raster_program.hpp
+++ b/src/mbgl/programs/raster_program.hpp
@@ -10,38 +10,38 @@
namespace mbgl {
namespace uniforms {
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_fade_t);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_buffer_scale);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_brightness_low);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_brightness_high);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_saturation_factor);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_contrast_factor);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_scale_parent);
-MBGL_DEFINE_UNIFORM_VECTOR(float, 3, u_spin_weights);
-MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_tl_parent);
+MBGL_DEFINE_UNIFORM_SCALAR(float, fade_t);
+MBGL_DEFINE_UNIFORM_SCALAR(float, buffer_scale);
+MBGL_DEFINE_UNIFORM_SCALAR(float, brightness_low);
+MBGL_DEFINE_UNIFORM_SCALAR(float, brightness_high);
+MBGL_DEFINE_UNIFORM_SCALAR(float, saturation_factor);
+MBGL_DEFINE_UNIFORM_SCALAR(float, contrast_factor);
+MBGL_DEFINE_UNIFORM_SCALAR(float, scale_parent);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 3, spin_weights);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, tl_parent);
} // namespace uniforms
class RasterProgram : public Program<
RasterProgram,
gfx::PrimitiveType::Triangle,
TypeList<
- attributes::a_pos,
- attributes::a_texture_pos>,
+ attributes::pos,
+ attributes::texture_pos>,
TypeList<
- uniforms::u_matrix,
- uniforms::u_opacity,
- uniforms::u_fade_t,
- uniforms::u_brightness_low,
- uniforms::u_brightness_high,
- uniforms::u_saturation_factor,
- uniforms::u_contrast_factor,
- uniforms::u_spin_weights,
- uniforms::u_buffer_scale,
- uniforms::u_scale_parent,
- uniforms::u_tl_parent>,
+ uniforms::matrix,
+ uniforms::opacity,
+ uniforms::fade_t,
+ uniforms::brightness_low,
+ uniforms::brightness_high,
+ uniforms::saturation_factor,
+ uniforms::contrast_factor,
+ uniforms::spin_weights,
+ uniforms::buffer_scale,
+ uniforms::scale_parent,
+ uniforms::tl_parent>,
TypeList<
- textures::u_image0,
- textures::u_image1>,
+ textures::image0,
+ textures::image1>,
style::RasterPaintProperties>
{
public:
diff --git a/src/mbgl/programs/symbol_program.cpp b/src/mbgl/programs/symbol_program.cpp
index 2300dedff3..d6a7a10368 100644
--- a/src/mbgl/programs/symbol_program.cpp
+++ b/src/mbgl/programs/symbol_program.cpp
@@ -42,6 +42,7 @@ std::unique_ptr<SymbolSizeBinder> SymbolSizeBinder::create(const float tileZoom,
template <class Values, class...Args>
Values makeValues(const bool isText,
+ const bool hasVariablePacement,
const style::SymbolPropertyValues& values,
const Size& texsize,
const std::array<float, 2>& pixelsToGLUnits,
@@ -71,7 +72,7 @@ Values makeValues(const bool isText,
const bool rotateInShader = rotateWithMap && !pitchWithMap && !alongLine;
mat4 labelPlaneMatrix;
- if (alongLine) {
+ if (alongLine || (isText && hasVariablePacement)) {
// For labels that follow lines the first part of the projection is handled on the cpu.
// Pass an identity matrix because no transformation needs to be done in the vertex shader.
matrix::identity(labelPlaneMatrix);
@@ -82,30 +83,31 @@ Values makeValues(const bool isText,
mat4 glCoordMatrix = getGlCoordMatrix(tile.matrix, pitchWithMap, rotateWithMap, state, pixelsToTileUnits);
return Values {
- uniforms::u_matrix::Value( tile.translatedMatrix(values.translate,
+ uniforms::matrix::Value( tile.translatedMatrix(values.translate,
values.translateAnchor,
state) ),
- uniforms::u_label_plane_matrix::Value(labelPlaneMatrix),
- uniforms::u_gl_coord_matrix::Value( tile.translateVtxMatrix(glCoordMatrix,
+ uniforms::label_plane_matrix::Value(labelPlaneMatrix),
+ uniforms::gl_coord_matrix::Value( tile.translateVtxMatrix(glCoordMatrix,
values.translate,
values.translateAnchor,
state,
true) ),
- uniforms::u_extrude_scale::Value( extrudeScale ),
- uniforms::u_texsize::Value( texsize ),
- uniforms::u_fade_change::Value( symbolFadeChange ),
- uniforms::u_is_text::Value( isText ),
- uniforms::u_camera_to_center_distance::Value( state.getCameraToCenterDistance() ),
- uniforms::u_pitch::Value( state.getPitch() ),
- uniforms::u_pitch_with_map::Value( pitchWithMap ),
- uniforms::u_rotate_symbol::Value( rotateInShader ),
- uniforms::u_aspect_ratio::Value( state.getSize().aspectRatio() ),
+ uniforms::extrude_scale::Value( extrudeScale ),
+ uniforms::texsize::Value( texsize ),
+ uniforms::fade_change::Value( symbolFadeChange ),
+ uniforms::is_text::Value( isText ),
+ uniforms::camera_to_center_distance::Value( state.getCameraToCenterDistance() ),
+ uniforms::pitch::Value( state.getPitch() ),
+ uniforms::pitch_with_map::Value( pitchWithMap ),
+ uniforms::rotate_symbol::Value( rotateInShader ),
+ uniforms::aspect_ratio::Value( state.getSize().aspectRatio() ),
std::forward<Args>(args)...
};
}
SymbolIconProgram::LayoutUniformValues
SymbolIconProgram::layoutUniformValues(const bool isText,
+ const bool hasVariablePacement,
const style::SymbolPropertyValues& values,
const Size& texsize,
const std::array<float, 2>& pixelsToGLUnits,
@@ -115,6 +117,7 @@ SymbolIconProgram::layoutUniformValues(const bool isText,
const float symbolFadeChange) {
return makeValues<SymbolIconProgram::LayoutUniformValues>(
isText,
+ hasVariablePacement,
values,
texsize,
pixelsToGLUnits,
@@ -128,6 +131,7 @@ SymbolIconProgram::layoutUniformValues(const bool isText,
template <class Name, class PaintProperties>
typename SymbolSDFProgram<Name, PaintProperties>::LayoutUniformValues
SymbolSDFProgram<Name, PaintProperties>::layoutUniformValues(const bool isText,
+ const bool hasVariablePacement,
const style::SymbolPropertyValues& values,
const Size& texsize,
const std::array<float, 2>& pixelsToGLUnits,
@@ -142,6 +146,7 @@ SymbolSDFProgram<Name, PaintProperties>::layoutUniformValues(const bool isText,
return makeValues<SymbolSDFProgram<Name, PaintProperties>::LayoutUniformValues>(
isText,
+ hasVariablePacement,
values,
texsize,
pixelsToGLUnits,
@@ -149,8 +154,8 @@ SymbolSDFProgram<Name, PaintProperties>::layoutUniformValues(const bool isText,
tile,
state,
symbolFadeChange,
- uniforms::u_gamma_scale::Value( gammaScale ),
- uniforms::u_is_halo::Value( part == SymbolSDFPart::Halo )
+ uniforms::gamma_scale::Value( gammaScale ),
+ uniforms::is_halo::Value( part == SymbolSDFPart::Halo )
);
}
diff --git a/src/mbgl/programs/symbol_program.hpp b/src/mbgl/programs/symbol_program.hpp
index 383f5162d8..d640eb74da 100644
--- a/src/mbgl/programs/symbol_program.hpp
+++ b/src/mbgl/programs/symbol_program.hpp
@@ -1,6 +1,5 @@
#pragma once
-#include <mbgl/gl/program.hpp>
#include <mbgl/math/clamp.hpp>
#include <mbgl/util/interpolate.hpp>
@@ -29,27 +28,27 @@ class RenderTile;
class TransformState;
namespace uniforms {
-MBGL_DEFINE_UNIFORM_MATRIX(double, 4, u_gl_coord_matrix);
-MBGL_DEFINE_UNIFORM_MATRIX(double, 4, u_label_plane_matrix);
-MBGL_DEFINE_UNIFORM_SCALAR(bool, u_is_halo);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_gamma_scale);
-
-MBGL_DEFINE_UNIFORM_SCALAR(bool, u_is_text);
-MBGL_DEFINE_UNIFORM_SCALAR(bool, u_is_size_zoom_constant);
-MBGL_DEFINE_UNIFORM_SCALAR(bool, u_is_size_feature_constant);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_size_t);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_size);
-MBGL_DEFINE_UNIFORM_SCALAR(bool, u_rotate_symbol);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_aspect_ratio);
+MBGL_DEFINE_UNIFORM_MATRIX(double, 4, gl_coord_matrix);
+MBGL_DEFINE_UNIFORM_MATRIX(double, 4, label_plane_matrix);
+MBGL_DEFINE_UNIFORM_SCALAR(bool, is_halo);
+MBGL_DEFINE_UNIFORM_SCALAR(float, gamma_scale);
+
+MBGL_DEFINE_UNIFORM_SCALAR(bool, is_text);
+MBGL_DEFINE_UNIFORM_SCALAR(bool, is_size_zoom_constant);
+MBGL_DEFINE_UNIFORM_SCALAR(bool, is_size_feature_constant);
+MBGL_DEFINE_UNIFORM_SCALAR(float, size_t);
+MBGL_DEFINE_UNIFORM_SCALAR(float, size);
+MBGL_DEFINE_UNIFORM_SCALAR(bool, rotate_symbol);
+MBGL_DEFINE_UNIFORM_SCALAR(float, aspect_ratio);
} // namespace uniforms
using SymbolLayoutAttributes = TypeList<
- attributes::a_pos_offset,
- attributes::a_data<uint16_t, 4>>;
+ attributes::pos_offset,
+ attributes::data<uint16_t, 4>>;
-using SymbolDynamicLayoutAttributes = TypeList<attributes::a_projected_pos>;
+using SymbolDynamicLayoutAttributes = TypeList<attributes::projected_pos>;
-using SymbolOpacityAttributes = TypeList<attributes::a_fade_opacity>;
+using SymbolOpacityAttributes = TypeList<attributes::fade_opacity>;
struct ZoomEvaluatedSize {
bool isZoomConstant;
@@ -67,10 +66,10 @@ public:
virtual ~SymbolSizeBinder() = default;
using UniformList = TypeList<
- uniforms::u_is_size_zoom_constant,
- uniforms::u_is_size_feature_constant,
- uniforms::u_size_t,
- uniforms::u_size>;
+ uniforms::is_size_zoom_constant,
+ uniforms::is_size_feature_constant,
+ uniforms::size_t,
+ uniforms::size>;
using UniformValues = gfx::UniformValues<UniformList>;
static std::unique_ptr<SymbolSizeBinder> create(const float tileZoom,
@@ -83,10 +82,10 @@ public:
UniformValues uniformValues(float currentZoom) const {
const ZoomEvaluatedSize u = evaluateForZoom(currentZoom);
return UniformValues {
- uniforms::u_is_size_zoom_constant::Value( u.isZoomConstant ),
- uniforms::u_is_size_feature_constant::Value( u.isFeatureConstant),
- uniforms::u_size_t::Value( u.sizeT ),
- uniforms::u_size::Value( u.size )
+ uniforms::is_size_zoom_constant::Value( u.isZoomConstant ),
+ uniforms::is_size_feature_constant::Value( u.isFeatureConstant),
+ uniforms::size_t::Value( u.sizeT ),
+ uniforms::size::Value( u.size )
};
}
};
@@ -348,26 +347,27 @@ class SymbolIconProgram : public SymbolProgram<
gfx::PrimitiveType::Triangle,
SymbolLayoutAttributes,
TypeList<
- uniforms::u_matrix,
- uniforms::u_label_plane_matrix,
- uniforms::u_gl_coord_matrix,
- uniforms::u_extrude_scale,
- uniforms::u_texsize,
- uniforms::u_fade_change,
- uniforms::u_is_text,
- uniforms::u_camera_to_center_distance,
- uniforms::u_pitch,
- uniforms::u_pitch_with_map,
- uniforms::u_rotate_symbol,
- uniforms::u_aspect_ratio>,
+ uniforms::matrix,
+ uniforms::label_plane_matrix,
+ uniforms::gl_coord_matrix,
+ uniforms::extrude_scale,
+ uniforms::texsize,
+ uniforms::fade_change,
+ uniforms::is_text,
+ uniforms::camera_to_center_distance,
+ uniforms::pitch,
+ uniforms::pitch_with_map,
+ uniforms::rotate_symbol,
+ uniforms::aspect_ratio>,
TypeList<
- textures::u_texture>,
+ textures::texture>,
style::IconPaintProperties>
{
public:
using SymbolProgram::SymbolProgram;
static LayoutUniformValues layoutUniformValues(const bool isText,
+ const bool hasVariablePacement,
const style::SymbolPropertyValues&,
const Size& texsize,
const std::array<float, 2>& pixelsToGLUnits,
@@ -388,22 +388,22 @@ class SymbolSDFProgram : public SymbolProgram<
gfx::PrimitiveType::Triangle,
SymbolLayoutAttributes,
TypeList<
- uniforms::u_matrix,
- uniforms::u_label_plane_matrix,
- uniforms::u_gl_coord_matrix,
- uniforms::u_extrude_scale,
- uniforms::u_texsize,
- uniforms::u_fade_change,
- uniforms::u_is_text,
- uniforms::u_camera_to_center_distance,
- uniforms::u_pitch,
- uniforms::u_pitch_with_map,
- uniforms::u_rotate_symbol,
- uniforms::u_aspect_ratio,
- uniforms::u_gamma_scale,
- uniforms::u_is_halo>,
+ uniforms::matrix,
+ uniforms::label_plane_matrix,
+ uniforms::gl_coord_matrix,
+ uniforms::extrude_scale,
+ uniforms::texsize,
+ uniforms::fade_change,
+ uniforms::is_text,
+ uniforms::camera_to_center_distance,
+ uniforms::pitch,
+ uniforms::pitch_with_map,
+ uniforms::rotate_symbol,
+ uniforms::aspect_ratio,
+ uniforms::gamma_scale,
+ uniforms::is_halo>,
TypeList<
- textures::u_texture>,
+ textures::texture>,
PaintProperties>
{
public:
@@ -412,22 +412,22 @@ public:
gfx::PrimitiveType::Triangle,
SymbolLayoutAttributes,
TypeList<
- uniforms::u_matrix,
- uniforms::u_label_plane_matrix,
- uniforms::u_gl_coord_matrix,
- uniforms::u_extrude_scale,
- uniforms::u_texsize,
- uniforms::u_fade_change,
- uniforms::u_is_text,
- uniforms::u_camera_to_center_distance,
- uniforms::u_pitch,
- uniforms::u_pitch_with_map,
- uniforms::u_rotate_symbol,
- uniforms::u_aspect_ratio,
- uniforms::u_gamma_scale,
- uniforms::u_is_halo>,
+ uniforms::matrix,
+ uniforms::label_plane_matrix,
+ uniforms::gl_coord_matrix,
+ uniforms::extrude_scale,
+ uniforms::texsize,
+ uniforms::fade_change,
+ uniforms::is_text,
+ uniforms::camera_to_center_distance,
+ uniforms::pitch,
+ uniforms::pitch_with_map,
+ uniforms::rotate_symbol,
+ uniforms::aspect_ratio,
+ uniforms::gamma_scale,
+ uniforms::is_halo>,
TypeList<
- textures::u_texture>,
+ textures::texture>,
PaintProperties>;
using LayoutUniformValues = typename BaseProgram::LayoutUniformValues;
@@ -437,6 +437,7 @@ public:
using BaseProgram::BaseProgram;
static LayoutUniformValues layoutUniformValues(const bool isText,
+ const bool hasVariablePacement,
const style::SymbolPropertyValues&,
const Size& texsize,
const std::array<float, 2>& pixelsToGLUnits,
@@ -469,9 +470,9 @@ public:
symbolGlyph(context, programParameters),
collisionBox(context, programParameters),
collisionCircle(context, programParameters) {}
- ProgramMap<SymbolIconProgram> symbolIcon;
- ProgramMap<SymbolSDFIconProgram> symbolIconSDF;
- ProgramMap<SymbolSDFTextProgram> symbolGlyph;
+ SymbolIconProgram symbolIcon;
+ SymbolSDFIconProgram symbolIconSDF;
+ SymbolSDFTextProgram symbolGlyph;
CollisionBoxProgram collisionBox;
CollisionCircleProgram collisionCircle;
};
diff --git a/src/mbgl/programs/textures.hpp b/src/mbgl/programs/textures.hpp
index 32bc4a4a35..4c9de53366 100644
--- a/src/mbgl/programs/textures.hpp
+++ b/src/mbgl/programs/textures.hpp
@@ -5,11 +5,11 @@
namespace mbgl {
namespace textures {
-MBGL_DEFINE_TEXTURE(u_image);
-MBGL_DEFINE_TEXTURE(u_image0);
-MBGL_DEFINE_TEXTURE(u_image1);
-MBGL_DEFINE_TEXTURE(u_color_ramp);
-MBGL_DEFINE_TEXTURE(u_texture);
+MBGL_DEFINE_TEXTURE(image);
+MBGL_DEFINE_TEXTURE(image0);
+MBGL_DEFINE_TEXTURE(image1);
+MBGL_DEFINE_TEXTURE(color_ramp);
+MBGL_DEFINE_TEXTURE(texture);
} // namespace textures
} // namespace mbgl
diff --git a/src/mbgl/programs/uniforms.hpp b/src/mbgl/programs/uniforms.hpp
index 79febf7f73..702b21def9 100644
--- a/src/mbgl/programs/uniforms.hpp
+++ b/src/mbgl/programs/uniforms.hpp
@@ -9,61 +9,61 @@ namespace uniforms {
// Uniforms common to several shaders.
-MBGL_DEFINE_UNIFORM_MATRIX(double, 4, u_matrix);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_opacity);
-MBGL_DEFINE_UNIFORM_SCALAR(Color, u_color);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_blur);
+MBGL_DEFINE_UNIFORM_MATRIX(double, 4, matrix);
+MBGL_DEFINE_UNIFORM_SCALAR(float, opacity);
+MBGL_DEFINE_UNIFORM_SCALAR(Color, color);
+MBGL_DEFINE_UNIFORM_SCALAR(float, blur);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_zoom);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_collision_y_stretch);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_pitch);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_bearing);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_radius);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_stroke_width);
-MBGL_DEFINE_UNIFORM_SCALAR(Color, u_stroke_color);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_stroke_opacity);
-MBGL_DEFINE_UNIFORM_SCALAR(Color, u_fill_color);
-MBGL_DEFINE_UNIFORM_SCALAR(Color, u_halo_color);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_halo_width);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_halo_blur);
-MBGL_DEFINE_UNIFORM_SCALAR(Color, u_outline_color);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_height);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_base);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_width);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_floorwidth);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_gapwidth);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_offset);
-MBGL_DEFINE_UNIFORM_SCALAR(Size, u_world);
-MBGL_DEFINE_UNIFORM_SCALAR(Size, u_texsize);
-MBGL_DEFINE_UNIFORM_SCALAR(bool, u_pitch_with_map);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_camera_to_center_distance);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_fade);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_fade_change);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_weight);
+MBGL_DEFINE_UNIFORM_SCALAR(float, zoom);
+MBGL_DEFINE_UNIFORM_SCALAR(float, collision_y_stretch);
+MBGL_DEFINE_UNIFORM_SCALAR(float, pitch);
+MBGL_DEFINE_UNIFORM_SCALAR(float, bearing);
+MBGL_DEFINE_UNIFORM_SCALAR(float, radius);
+MBGL_DEFINE_UNIFORM_SCALAR(float, stroke_width);
+MBGL_DEFINE_UNIFORM_SCALAR(Color, stroke_color);
+MBGL_DEFINE_UNIFORM_SCALAR(float, stroke_opacity);
+MBGL_DEFINE_UNIFORM_SCALAR(Color, fill_color);
+MBGL_DEFINE_UNIFORM_SCALAR(Color, halo_color);
+MBGL_DEFINE_UNIFORM_SCALAR(float, halo_width);
+MBGL_DEFINE_UNIFORM_SCALAR(float, halo_blur);
+MBGL_DEFINE_UNIFORM_SCALAR(Color, outline_color);
+MBGL_DEFINE_UNIFORM_SCALAR(float, height);
+MBGL_DEFINE_UNIFORM_SCALAR(float, base);
+MBGL_DEFINE_UNIFORM_SCALAR(float, width);
+MBGL_DEFINE_UNIFORM_SCALAR(float, floorwidth);
+MBGL_DEFINE_UNIFORM_SCALAR(float, gapwidth);
+MBGL_DEFINE_UNIFORM_SCALAR(float, offset);
+MBGL_DEFINE_UNIFORM_SCALAR(Size, world);
+MBGL_DEFINE_UNIFORM_SCALAR(Size, texsize);
+MBGL_DEFINE_UNIFORM_SCALAR(bool, pitch_with_map);
+MBGL_DEFINE_UNIFORM_SCALAR(float, camera_to_center_distance);
+MBGL_DEFINE_UNIFORM_SCALAR(float, fade);
+MBGL_DEFINE_UNIFORM_SCALAR(float, fade_change);
+MBGL_DEFINE_UNIFORM_SCALAR(float, weight);
-MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_extrude_scale);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, extrude_scale);
namespace heatmap {
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_extrude_scale);
+MBGL_DEFINE_UNIFORM_SCALAR(float, extrude_scale);
} // namespace heatmap
-MBGL_DEFINE_UNIFORM_VECTOR(uint16_t, 4, u_pattern_from);
-MBGL_DEFINE_UNIFORM_VECTOR(uint16_t, 4, u_pattern_to);
-MBGL_DEFINE_UNIFORM_VECTOR(float, 4, u_scale);
-MBGL_DEFINE_UNIFORM_VECTOR(uint16_t, 2, u_pattern_tl_a);
-MBGL_DEFINE_UNIFORM_VECTOR(uint16_t, 2, u_pattern_br_a);
-MBGL_DEFINE_UNIFORM_VECTOR(uint16_t, 2, u_pattern_tl_b);
-MBGL_DEFINE_UNIFORM_VECTOR(uint16_t, 2, u_pattern_br_b);
-MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_pattern_size_a);
-MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_pattern_size_b);
-MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_pixel_coord_upper);
-MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_pixel_coord_lower);
+MBGL_DEFINE_UNIFORM_VECTOR(uint16_t, 4, pattern_from);
+MBGL_DEFINE_UNIFORM_VECTOR(uint16_t, 4, pattern_to);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 4, scale);
+MBGL_DEFINE_UNIFORM_VECTOR(uint16_t, 2, pattern_tl_a);
+MBGL_DEFINE_UNIFORM_VECTOR(uint16_t, 2, pattern_br_a);
+MBGL_DEFINE_UNIFORM_VECTOR(uint16_t, 2, pattern_tl_b);
+MBGL_DEFINE_UNIFORM_VECTOR(uint16_t, 2, pattern_br_b);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, pattern_size_a);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, pattern_size_b);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, pixel_coord_upper);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 2, pixel_coord_lower);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_mix);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_scale_a);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_scale_b);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_tile_units_to_pixels);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_overscale_factor);
+MBGL_DEFINE_UNIFORM_SCALAR(float, mix);
+MBGL_DEFINE_UNIFORM_SCALAR(float, scale_a);
+MBGL_DEFINE_UNIFORM_SCALAR(float, scale_b);
+MBGL_DEFINE_UNIFORM_SCALAR(float, tile_units_to_pixels);
+MBGL_DEFINE_UNIFORM_SCALAR(float, overscale_factor);
} // namespace uniforms
} // namespace mbgl
diff --git a/src/mbgl/renderer/buckets/line_bucket.cpp b/src/mbgl/renderer/buckets/line_bucket.cpp
index 398a0b4c0f..13f575ba38 100644
--- a/src/mbgl/renderer/buckets/line_bucket.cpp
+++ b/src/mbgl/renderer/buckets/line_bucket.cpp
@@ -11,7 +11,7 @@ namespace mbgl {
using namespace style;
LineBucket::LineBucket(const style::LineLayoutProperties::PossiblyEvaluated layout_,
- std::map<std::string, RenderLinePaintProperties::PossiblyEvaluated> layerPaintProperties,
+ std::map<std::string, style::LinePaintProperties::PossiblyEvaluated> layerPaintProperties,
const float zoom_,
const uint32_t overscaling_)
: layout(layout_),
diff --git a/src/mbgl/renderer/buckets/line_bucket.hpp b/src/mbgl/renderer/buckets/line_bucket.hpp
index 6b8d7e786c..7ee8677e50 100644
--- a/src/mbgl/renderer/buckets/line_bucket.hpp
+++ b/src/mbgl/renderer/buckets/line_bucket.hpp
@@ -20,7 +20,7 @@ public:
// These aliases are used by the PatternLayout template
using RenderLayerType = RenderLineLayer;
- using PossiblyEvaluatedPaintProperties = RenderLinePaintProperties::PossiblyEvaluated;
+ using PossiblyEvaluatedPaintProperties = style::LinePaintProperties::PossiblyEvaluated;
using PossiblyEvaluatedLayoutProperties = style::LineLayoutProperties::PossiblyEvaluated;
LineBucket(const PossiblyEvaluatedLayoutProperties layout,
diff --git a/src/mbgl/renderer/buckets/symbol_bucket.cpp b/src/mbgl/renderer/buckets/symbol_bucket.cpp
index 9220235f1d..68f683c8d6 100644
--- a/src/mbgl/renderer/buckets/symbol_bucket.cpp
+++ b/src/mbgl/renderer/buckets/symbol_bucket.cpp
@@ -17,7 +17,8 @@ SymbolBucket::SymbolBucket(style::SymbolLayoutProperties::PossiblyEvaluated layo
bool iconsNeedLinear_,
bool sortFeaturesByY_,
const std::string bucketName_,
- const std::vector<SymbolInstance>&& symbolInstances_)
+ const std::vector<SymbolInstance>&& symbolInstances_,
+ float tilePixelRatio_)
: layout(std::move(layout_)),
sdfIcons(sdfIcons_),
iconsNeedLinear(iconsNeedLinear_ || iconSize.isDataDriven() || !iconSize.isZoomConstant()),
@@ -25,7 +26,8 @@ SymbolBucket::SymbolBucket(style::SymbolLayoutProperties::PossiblyEvaluated layo
bucketLeaderID(std::move(bucketName_)),
symbolInstances(std::move(symbolInstances_)),
textSizeBinder(SymbolSizeBinder::create(zoom, textSize, TextSize::defaultValue())),
- iconSizeBinder(SymbolSizeBinder::create(zoom, iconSize, IconSize::defaultValue())) {
+ iconSizeBinder(SymbolSizeBinder::create(zoom, iconSize, IconSize::defaultValue())),
+ tilePixelRatio(tilePixelRatio_) {
for (const auto& pair : paintProperties_) {
auto layerPaintProperties = pair.second;
@@ -218,12 +220,22 @@ void SymbolBucket::sortFeatures(const float angle) {
const SymbolInstance& symbolInstance = symbolInstances[i];
featureSortOrder->push_back(symbolInstance.dataFeatureIndex);
- if (symbolInstance.placedTextIndex) {
- addPlacedSymbol(text.triangles, text.placedSymbols[*symbolInstance.placedTextIndex]);
+ if (symbolInstance.placedRightTextIndex) {
+ addPlacedSymbol(text.triangles, text.placedSymbols[*symbolInstance.placedRightTextIndex]);
}
+
+ if (symbolInstance.placedCenterTextIndex && !symbolInstance.singleLine) {
+ addPlacedSymbol(text.triangles, text.placedSymbols[*symbolInstance.placedCenterTextIndex]);
+ }
+
+ if (symbolInstance.placedLeftTextIndex && !symbolInstance.singleLine) {
+ addPlacedSymbol(text.triangles, text.placedSymbols[*symbolInstance.placedLeftTextIndex]);
+ }
+
if (symbolInstance.placedVerticalTextIndex) {
addPlacedSymbol(text.triangles, text.placedSymbols[*symbolInstance.placedVerticalTextIndex]);
}
+
if (symbolInstance.placedIconIndex) {
addPlacedSymbol(icon.triangles, icon.placedSymbols[*symbolInstance.placedIconIndex]);
}
diff --git a/src/mbgl/renderer/buckets/symbol_bucket.hpp b/src/mbgl/renderer/buckets/symbol_bucket.hpp
index fafa2592fe..f8ffc1a8eb 100644
--- a/src/mbgl/renderer/buckets/symbol_bucket.hpp
+++ b/src/mbgl/renderer/buckets/symbol_bucket.hpp
@@ -35,6 +35,8 @@ public:
std::vector<float> glyphOffsets;
bool hidden;
size_t vertexStartIndex;
+ // The crossTileID is only filled/used on the foreground for variable text anchors
+ uint32_t crossTileID = 0u;
};
class SymbolBucket final : public Bucket {
@@ -48,7 +50,8 @@ public:
bool iconsNeedLinear,
bool sortFeaturesByY,
const std::string bucketLeaderID,
- const std::vector<SymbolInstance>&&);
+ const std::vector<SymbolInstance>&&,
+ const float tilePixelRatio);
~SymbolBucket() override;
void upload(gfx::Context&) override;
@@ -130,6 +133,7 @@ public:
optional<gfx::IndexBuffer> indexBuffer;
} collisionCircle;
+ const float tilePixelRatio;
uint32_t bucketInstanceId = 0;
bool justReloaded = false;
optional<bool> hasFormatSectionOverrides_;
diff --git a/src/mbgl/renderer/image_atlas.cpp b/src/mbgl/renderer/image_atlas.cpp
index b39c788ced..282f135ac9 100644
--- a/src/mbgl/renderer/image_atlas.cpp
+++ b/src/mbgl/renderer/image_atlas.cpp
@@ -1,4 +1,6 @@
#include <mbgl/renderer/image_atlas.hpp>
+#include <mbgl/gfx/context.hpp>
+#include <mbgl/renderer/image_manager.hpp>
#include <mapbox/shelf-pack.hpp>
@@ -6,14 +8,15 @@ namespace mbgl {
static constexpr uint32_t padding = 1;
-ImagePosition::ImagePosition(const mapbox::Bin& bin, const style::Image::Impl& image)
+ImagePosition::ImagePosition(const mapbox::Bin& bin, const style::Image::Impl& image, uint32_t version_)
: pixelRatio(image.pixelRatio),
textureRect(
bin.x + padding,
bin.y + padding,
bin.w - padding * 2,
bin.h - padding * 2
- ) {
+ ),
+ version(version_) {
}
const mapbox::Bin& _packImage(mapbox::ShelfPack& pack, const style::Image::Impl& image, ImageAtlas& resultImage, ImageType imageType) {
@@ -49,7 +52,30 @@ const mapbox::Bin& _packImage(mapbox::ShelfPack& pack, const style::Image::Impl&
return bin;
}
-ImageAtlas makeImageAtlas(const ImageMap& icons, const ImageMap& patterns) {
+void ImageAtlas::patchUpdatedImages(gfx::Context& context, gfx::Texture& atlasTexture, const ImageManager& imageManager) {
+ for (auto& updatedImageVersion : imageManager.updatedImageVersions) {
+ auto iconPosition = iconPositions.find(updatedImageVersion.first);
+ if (iconPosition != iconPositions.end()) {
+ patchUpdatedImage(context, atlasTexture, iconPosition->second, imageManager, updatedImageVersion.first, updatedImageVersion.second);
+ }
+ auto patternPosition = patternPositions.find(updatedImageVersion.first);
+ if (patternPosition != patternPositions.end()) {
+ patchUpdatedImage(context, atlasTexture, patternPosition->second, imageManager, updatedImageVersion.first, updatedImageVersion.second);
+ }
+ }
+}
+
+void ImageAtlas::patchUpdatedImage(gfx::Context& context, gfx::Texture& atlasTexture, ImagePosition& position, const ImageManager& imageManager, const std::string& name, uint16_t version) {
+ if (position.version == version) return;
+
+ auto updatedImage = imageManager.getImage(name);
+ if (updatedImage == nullptr) return;
+
+ context.updateTextureSub(atlasTexture, updatedImage->image, position.textureRect.x, position.textureRect.y);
+ position.version = version;
+}
+
+ImageAtlas makeImageAtlas(const ImageMap& icons, const ImageMap& patterns, const std::unordered_map<std::string, uint32_t>& versionMap) {
ImageAtlas result;
mapbox::ShelfPack::ShelfPackOptions options;
@@ -59,13 +85,17 @@ ImageAtlas makeImageAtlas(const ImageMap& icons, const ImageMap& patterns) {
for (const auto& entry : icons) {
const style::Image::Impl& image = *entry.second;
const mapbox::Bin& bin = _packImage(pack, image, result, ImageType::Icon);
- result.iconPositions.emplace(image.id, ImagePosition { bin, image });
+ auto it = versionMap.find(entry.first);
+ auto version = it != versionMap.end() ? it->second : 0;
+ result.iconPositions.emplace(image.id, ImagePosition { bin, image, version });
}
for (const auto& entry : patterns) {
const style::Image::Impl& image = *entry.second;
const mapbox::Bin& bin = _packImage(pack, image, result, ImageType::Pattern);
- result.patternPositions.emplace(image.id, ImagePosition { bin, image });
+ auto it = versionMap.find(entry.first);
+ auto version = it != versionMap.end() ? it->second : 0;
+ result.patternPositions.emplace(image.id, ImagePosition { bin, image, version });
}
pack.shrink();
diff --git a/src/mbgl/renderer/image_atlas.hpp b/src/mbgl/renderer/image_atlas.hpp
index 3af31a75f8..080a490ab2 100644
--- a/src/mbgl/renderer/image_atlas.hpp
+++ b/src/mbgl/renderer/image_atlas.hpp
@@ -9,12 +9,20 @@
namespace mbgl {
+namespace gfx {
+ class Texture;
+ class Context;
+} // namespace gfx
+
+class ImageManager;
+
class ImagePosition {
public:
- ImagePosition(const mapbox::Bin&, const style::Image::Impl&);
+ ImagePosition(const mapbox::Bin&, const style::Image::Impl&, uint32_t version = 0);
float pixelRatio;
Rect<uint16_t> textureRect;
+ uint32_t version;
std::array<uint16_t, 2> tl() const {
return {{
@@ -51,8 +59,12 @@ public:
PremultipliedImage image;
ImagePositions iconPositions;
ImagePositions patternPositions;
+
+ void patchUpdatedImages(gfx::Context&, gfx::Texture&, const ImageManager&);
+private:
+ void patchUpdatedImage(gfx::Context&, gfx::Texture&, ImagePosition& position, const ImageManager& imageManager, const std::string& name, uint16_t version);
};
-ImageAtlas makeImageAtlas(const ImageMap&, const ImageMap&);
+ImageAtlas makeImageAtlas(const ImageMap&, const ImageMap&, const std::unordered_map<std::string, uint32_t>& versionMap);
} // namespace mbgl
diff --git a/src/mbgl/renderer/image_manager.cpp b/src/mbgl/renderer/image_manager.cpp
index 9c9f6c6e08..d2994d6f2d 100644
--- a/src/mbgl/renderer/image_manager.cpp
+++ b/src/mbgl/renderer/image_manager.cpp
@@ -1,9 +1,16 @@
#include <mbgl/renderer/image_manager.hpp>
#include <mbgl/util/logging.hpp>
#include <mbgl/gfx/context.hpp>
+#include <mbgl/renderer/image_manager_observer.hpp>
namespace mbgl {
+static ImageManagerObserver nullObserver;
+
+void ImageManager::setObserver(ImageManagerObserver* observer_) {
+ observer = observer_ ? observer_ : &nullObserver;
+}
+
void ImageManager::setLoaded(bool loaded_) {
if (loaded == loaded_) {
return;
@@ -13,7 +20,7 @@ void ImageManager::setLoaded(bool loaded_) {
if (loaded) {
for (const auto& entry : requestors) {
- notify(*entry.first, entry.second);
+ checkMissingAndNotify(*entry.first, entry.second);
}
requestors.clear();
}
@@ -28,9 +35,23 @@ void ImageManager::addImage(Immutable<style::Image::Impl> image_) {
images.emplace(image_->id, std::move(image_));
}
-void ImageManager::updateImage(Immutable<style::Image::Impl> image_) {
+bool ImageManager::updateImage(Immutable<style::Image::Impl> image_) {
+ auto oldImage = images.find(image_->id);
+ assert(oldImage != images.end());
+ if (oldImage == images.end()) return false;
+
+ auto sizeChanged = oldImage->second->image.size != image_->image.size;
+
+ if (sizeChanged) {
+ updatedImageVersions.erase(image_->id);
+ } else {
+ updatedImageVersions[image_->id]++;
+ }
+
removeImage(image_->id);
addImage(std::move(image_));
+
+ return sizeChanged;
}
void ImageManager::removeImage(const std::string& id) {
@@ -60,10 +81,15 @@ const style::Image::Impl* ImageManager::getImage(const std::string& id) const {
}
void ImageManager::getImages(ImageRequestor& requestor, ImageRequestPair&& pair) {
- // If the sprite has been loaded, or if all the icon dependencies are already present
- // (i.e. if they've been addeded via runtime styling), then notify the requestor immediately.
- // Otherwise, delay notification until the sprite is loaded. At that point, if any of the
- // dependencies are still unavailable, we'll just assume they are permanently missing.
+ // remove previous requests from this tile
+ removeRequestor(requestor);
+
+ // If all the icon dependencies are already present ((i.e. if they've been addeded via
+ // runtime styling), then notify the requestor immediately. Otherwise, if the
+ // sprite has not loaded, then wait for it. When the sprite has loaded check
+ // if all icons are available. If any are missing, call `onStyleImageMissing`
+ // to give the user a chance to provide the icon. If they are not provided
+ // by the next frame we'll assume they are permanently missing.
bool hasAllDependencies = true;
if (!isLoaded()) {
for (const auto& dependency : pair.first) {
@@ -72,29 +98,83 @@ void ImageManager::getImages(ImageRequestor& requestor, ImageRequestPair&& pair)
}
}
}
- if (isLoaded() || hasAllDependencies) {
- notify(requestor, std::move(pair));
- } else {
+
+ if (hasAllDependencies) {
+ notify(requestor, pair);
+ } else if (!isLoaded()) {
requestors.emplace(&requestor, std::move(pair));
+ } else {
+ checkMissingAndNotify(requestor, std::move(pair));
}
}
void ImageManager::removeRequestor(ImageRequestor& requestor) {
requestors.erase(&requestor);
+ missingImageRequestors.erase(&requestor);
+}
+
+void ImageManager::notifyIfMissingImageAdded() {
+ for (auto it = missingImageRequestors.begin(); it != missingImageRequestors.end();) {
+ if (it->second.callbacksRemaining == 0) {
+ notify(*it->first, it->second.pair);
+ missingImageRequestors.erase(it++);
+ } else {
+ it++;
+ }
+ }
+}
+
+void ImageManager::checkMissingAndNotify(ImageRequestor& requestor, const ImageRequestPair& pair) {
+ unsigned int missing = 0;
+ for (const auto& dependency : pair.first) {
+ auto it = images.find(dependency.first);
+ if (it == images.end()) {
+ missing++;
+ }
+ }
+
+ if (missing > 0) {
+ ImageRequestor* requestorPtr = &requestor;
+
+ missingImageRequestors.emplace(requestorPtr, MissingImageRequestPair { std::move(pair), missing });
+
+ for (const auto& dependency : pair.first) {
+ auto it = images.find(dependency.first);
+ if (it == images.end()) {
+ assert(observer != nullptr);
+ observer->onStyleImageMissing(dependency.first, [this, requestorPtr]() {
+ auto requestorIt = missingImageRequestors.find(requestorPtr);
+ if (requestorIt != missingImageRequestors.end()) {
+ assert(requestorIt->second.callbacksRemaining > 0);
+ requestorIt->second.callbacksRemaining--;
+ }
+ });
+ }
+ }
+
+ } else {
+ notify(requestor, pair);
+ }
}
void ImageManager::notify(ImageRequestor& requestor, const ImageRequestPair& pair) const {
ImageMap iconMap;
ImageMap patternMap;
+ ImageVersionMap versionMap;
for (const auto& dependency : pair.first) {
auto it = images.find(dependency.first);
if (it != images.end()) {
dependency.second == ImageType::Pattern ? patternMap.emplace(*it) : iconMap.emplace(*it);
+
+ auto versionIt = updatedImageVersions.find(dependency.first);
+ if (versionIt != updatedImageVersions.end()) {
+ versionMap.emplace(versionIt->first, versionIt->second);
+ }
}
}
- requestor.onImagesAvailable(iconMap, patternMap, pair.second);
+ requestor.onImagesAvailable(iconMap, patternMap, std::move(versionMap), pair.second);
}
void ImageManager::dumpDebugLogs() const {
diff --git a/src/mbgl/renderer/image_manager.hpp b/src/mbgl/renderer/image_manager.hpp
index e56f30ac3f..99887ae384 100644
--- a/src/mbgl/renderer/image_manager.hpp
+++ b/src/mbgl/renderer/image_manager.hpp
@@ -6,6 +6,7 @@
#include <mbgl/util/immutable.hpp>
#include <mbgl/util/optional.hpp>
#include <mbgl/gfx/texture.hpp>
+#include <mbgl/renderer/image_manager_observer.hpp>
#include <mapbox/shelf-pack.hpp>
@@ -21,7 +22,7 @@ class Context;
class ImageRequestor {
public:
virtual ~ImageRequestor() = default;
- virtual void onImagesAvailable(ImageMap icons, ImageMap patterns, uint64_t imageCorrelationID) = 0;
+ virtual void onImagesAvailable(ImageMap icons, ImageMap patterns, ImageVersionMap versionMap, uint64_t imageCorrelationID) = 0;
};
/*
@@ -39,6 +40,8 @@ public:
ImageManager();
~ImageManager();
+ void setObserver(ImageManagerObserver*);
+
void setLoaded(bool);
bool isLoaded() const;
@@ -47,20 +50,31 @@ public:
const style::Image::Impl* getImage(const std::string&) const;
void addImage(Immutable<style::Image::Impl>);
- void updateImage(Immutable<style::Image::Impl>);
+ bool updateImage(Immutable<style::Image::Impl>);
void removeImage(const std::string&);
void getImages(ImageRequestor&, ImageRequestPair&&);
void removeRequestor(ImageRequestor&);
+ void notifyIfMissingImageAdded();
+
+ ImageVersionMap updatedImageVersions;
private:
+ void checkMissingAndNotify(ImageRequestor&, const ImageRequestPair&);
void notify(ImageRequestor&, const ImageRequestPair&) const;
bool loaded = false;
- std::unordered_map<ImageRequestor*, ImageRequestPair> requestors;
+ std::map<ImageRequestor*, ImageRequestPair> requestors;
+ struct MissingImageRequestPair {
+ ImageRequestPair pair;
+ unsigned int callbacksRemaining;
+ };
+ std::map<ImageRequestor*, MissingImageRequestPair> missingImageRequestors;
ImageMap images;
+ ImageManagerObserver* observer = nullptr;
+
// Pattern stuff
public:
optional<ImagePosition> getPattern(const std::string& name);
diff --git a/src/mbgl/renderer/image_manager_observer.hpp b/src/mbgl/renderer/image_manager_observer.hpp
new file mode 100644
index 0000000000..3dc53c9b66
--- /dev/null
+++ b/src/mbgl/renderer/image_manager_observer.hpp
@@ -0,0 +1,14 @@
+#pragma once
+
+#include <mbgl/renderer/renderer_observer.hpp>
+
+namespace mbgl {
+
+class ImageManagerObserver {
+public:
+ virtual ~ImageManagerObserver() = default;
+
+ virtual void onStyleImageMissing(const std::string&, std::function<void()> done) { done(); }
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/layers/render_background_layer.cpp b/src/mbgl/renderer/layers/render_background_layer.cpp
index 32e05a38ab..269b227a7d 100644
--- a/src/mbgl/renderer/layers/render_background_layer.cpp
+++ b/src/mbgl/renderer/layers/render_background_layer.cpp
@@ -9,7 +9,6 @@
#include <mbgl/util/tile_cover.hpp>
#include <mbgl/map/transform_state.hpp>
#include <mbgl/gfx/cull_face_mode.hpp>
-#include <mbgl/gl/context.hpp>
namespace mbgl {
@@ -103,7 +102,7 @@ void RenderBackgroundLayer::render(PaintParameters& parameters, RenderSource*) {
parameters.state
),
BackgroundPatternProgram::TextureBindings{
- textures::u_image::Value{ parameters.imageManager.textureBinding(parameters.context) },
+ textures::image::Value{ parameters.imageManager.textureBinding(parameters.context) },
}
);
}
@@ -112,9 +111,9 @@ void RenderBackgroundLayer::render(PaintParameters& parameters, RenderSource*) {
draw(
parameters.programs.getBackgroundLayerPrograms().background,
BackgroundProgram::LayoutUniformValues {
- uniforms::u_matrix::Value( parameters.matrixForTile(tileID) ),
- uniforms::u_color::Value( evaluated.get<BackgroundColor>() ),
- uniforms::u_opacity::Value( evaluated.get<BackgroundOpacity>() ),
+ uniforms::matrix::Value( parameters.matrixForTile(tileID) ),
+ uniforms::color::Value( evaluated.get<BackgroundColor>() ),
+ uniforms::opacity::Value( evaluated.get<BackgroundOpacity>() ),
},
BackgroundProgram::TextureBindings{}
);
diff --git a/src/mbgl/renderer/layers/render_circle_layer.cpp b/src/mbgl/renderer/layers/render_circle_layer.cpp
index 60a3bf8e01..1c13a6152b 100644
--- a/src/mbgl/renderer/layers/render_circle_layer.cpp
+++ b/src/mbgl/renderer/layers/render_circle_layer.cpp
@@ -8,7 +8,6 @@
#include <mbgl/style/layers/circle_layer_impl.hpp>
#include <mbgl/geometry/feature_index.hpp>
#include <mbgl/gfx/cull_face_mode.hpp>
-#include <mbgl/gl/context.hpp>
#include <mbgl/util/math.hpp>
#include <mbgl/util/intersection_tests.hpp>
@@ -66,23 +65,23 @@ void RenderCircleLayer::render(PaintParameters& parameters, RenderSource*) {
const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID());
- auto& programInstance = parameters.programs.getCircleLayerPrograms().circle.get(evaluated);
+ auto& programInstance = parameters.programs.getCircleLayerPrograms().circle;
const auto allUniformValues = programInstance.computeAllUniformValues(
CircleProgram::LayoutUniformValues {
- uniforms::u_matrix::Value(
+ uniforms::matrix::Value(
tile.translatedMatrix(evaluated.get<CircleTranslate>(),
evaluated.get<CircleTranslateAnchor>(),
parameters.state)
),
- uniforms::u_scale_with_map::Value( scaleWithMap ),
- uniforms::u_extrude_scale::Value( pitchWithMap
+ uniforms::scale_with_map::Value( scaleWithMap ),
+ uniforms::extrude_scale::Value( pitchWithMap
? std::array<float, 2> {{
tile.id.pixelsToTileUnits(1, parameters.state.getZoom()),
tile.id.pixelsToTileUnits(1, parameters.state.getZoom()) }}
: parameters.pixelsToGLUnits ),
- uniforms::u_camera_to_center_distance::Value( parameters.state.getCameraToCenterDistance() ),
- uniforms::u_pitch_with_map::Value( pitchWithMap )
+ uniforms::camera_to_center_distance::Value( parameters.state.getCameraToCenterDistance() ),
+ uniforms::pitch_with_map::Value( pitchWithMap )
},
paintPropertyBinders,
evaluated,
diff --git a/src/mbgl/renderer/layers/render_custom_layer.cpp b/src/mbgl/renderer/layers/render_custom_layer.cpp
index bcb0decb74..8ac7d29ff6 100644
--- a/src/mbgl/renderer/layers/render_custom_layer.cpp
+++ b/src/mbgl/renderer/layers/render_custom_layer.cpp
@@ -57,7 +57,8 @@ void RenderCustomLayer::render(PaintParameters& paintParameters, RenderSource*)
MBGL_CHECK_ERROR(host->initialize());
}
- gl::Context& glContext = paintParameters.context;
+ // TODO: remove cast
+ gl::Context& glContext = reinterpret_cast<gl::Context&>(paintParameters.context);
const TransformState& state = paintParameters.state;
// Reset GL state to a known state so the CustomLayer always has a clean slate.
diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp
index 5af4732aa3..13ef84f169 100644
--- a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp
+++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp
@@ -51,6 +51,9 @@ bool RenderFillExtrusionLayer::hasCrossfade() const {
}
void RenderFillExtrusionLayer::render(PaintParameters& parameters, RenderSource*) {
+ // TODO: remove cast
+ gl::Context& glContext = reinterpret_cast<gl::Context&>(parameters.context);
+
if (parameters.pass == RenderPass::Opaque) {
return;
}
@@ -69,8 +72,8 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters, RenderSource*
// Flag the depth buffer as no longer needing to be cleared for the remainder of this pass.
parameters.staticData.depthRenderbuffer->shouldClear(false);
- parameters.context.setStencilMode(gfx::StencilMode::disabled());
- parameters.context.clear(Color{ 0.0f, 0.0f, 0.0f, 0.0f }, depthClearValue, {});
+ glContext.setStencilMode(gfx::StencilMode::disabled());
+ glContext.clear(Color{ 0.0f, 0.0f, 0.0f, 0.0f }, depthClearValue, {});
auto draw = [&](auto& programInstance, const auto& tileBucket, auto&& uniformValues,
const optional<ImagePosition>& patternPositionA,
@@ -116,7 +119,7 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters, RenderSource*
FillExtrusionBucket& bucket = *bucket_;
draw(
- parameters.programs.getFillExtrusionLayerPrograms().fillExtrusion.get(evaluated),
+ parameters.programs.getFillExtrusionLayerPrograms().fillExtrusion,
bucket,
FillExtrusionProgram::layoutUniformValues(
tile.translatedClipMatrix(evaluated.get<FillExtrusionTranslate>(),
@@ -143,7 +146,7 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters, RenderSource*
FillExtrusionBucket& bucket = *bucket_;
draw(
- parameters.programs.getFillExtrusionLayerPrograms().fillExtrusionPattern.get(evaluated),
+ parameters.programs.getFillExtrusionLayerPrograms().fillExtrusionPattern,
bucket,
FillExtrusionPatternProgram::layoutUniformValues(
tile.translatedClipMatrix(evaluated.get<FillExtrusionTranslate>(),
@@ -160,7 +163,7 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters, RenderSource*
patternPosA,
patternPosB,
FillExtrusionPatternProgram::TextureBindings{
- textures::u_image::Value{ *geometryTile.iconAtlasTexture->resource, gfx::TextureFilterType::Linear },
+ textures::image::Value{ *geometryTile.iconAtlasTexture->resource, gfx::TextureFilterType::Linear },
}
);
}
@@ -179,9 +182,9 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters, RenderSource*
const auto allUniformValues = programInstance.computeAllUniformValues(
ExtrusionTextureProgram::LayoutUniformValues{
- uniforms::u_matrix::Value( viewportMat ),
- uniforms::u_world::Value( size ),
- uniforms::u_opacity::Value( evaluated.get<FillExtrusionOpacity>() )
+ uniforms::matrix::Value( viewportMat ),
+ uniforms::world::Value( size ),
+ uniforms::opacity::Value( evaluated.get<FillExtrusionOpacity>() )
},
paintAttributeData,
properties,
@@ -207,7 +210,7 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters, RenderSource*
allUniformValues,
allAttributeBindings,
ExtrusionTextureProgram::TextureBindings{
- textures::u_image::Value{ *renderTexture->getTexture().resource },
+ textures::image::Value{ *renderTexture->getTexture().resource },
},
getID());
}
diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp
index 64f3448c69..205a38e380 100644
--- a/src/mbgl/renderer/layers/render_fill_layer.cpp
+++ b/src/mbgl/renderer/layers/render_fill_layer.cpp
@@ -63,6 +63,9 @@ bool RenderFillLayer::hasCrossfade() const {
}
void RenderFillLayer::render(PaintParameters& parameters, RenderSource*) {
+ // TODO: remove cast
+ gl::Context& glContext = reinterpret_cast<gl::Context&>(parameters.context);
+
if (unevaluated.get<FillPattern>().isUndefined()) {
for (const RenderTile& tile : renderTiles) {
auto bucket_ = tile.tile.getBucket<FillBucket>(*baseImpl);
@@ -71,24 +74,22 @@ void RenderFillLayer::render(PaintParameters& parameters, RenderSource*) {
}
FillBucket& bucket = *bucket_;
- auto draw = [&] (auto& program,
+ auto draw = [&] (auto& programInstance,
const auto& drawMode,
const auto& depthMode,
const auto& indexBuffer,
const auto& segments,
auto&& textureBindings) {
- auto& programInstance = program.get(evaluated);
-
const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID());
const auto allUniformValues = programInstance.computeAllUniformValues(
FillProgram::LayoutUniformValues {
- uniforms::u_matrix::Value(
+ uniforms::matrix::Value(
tile.translatedMatrix(evaluated.get<FillTranslate>(),
evaluated.get<FillTranslateAnchor>(),
parameters.state)
),
- uniforms::u_world::Value( parameters.context.viewport.getCurrentValue().size ),
+ uniforms::world::Value( glContext.viewport.getCurrentValue().size ),
},
paintPropertyBinders,
evaluated,
@@ -159,14 +160,12 @@ void RenderFillLayer::render(PaintParameters& parameters, RenderSource*) {
}
FillBucket& bucket = *bucket_;
- auto draw = [&] (auto& program,
+ auto draw = [&] (auto& programInstance,
const auto& drawMode,
const auto& depthMode,
const auto& indexBuffer,
const auto& segments,
auto&& textureBindings) {
- auto& programInstance = program.get(evaluated);
-
const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID());
paintPropertyBinders.setPatternParameters(patternPosA, patternPosB, crossfade);
@@ -175,7 +174,7 @@ void RenderFillLayer::render(PaintParameters& parameters, RenderSource*) {
tile.translatedMatrix(evaluated.get<FillTranslate>(),
evaluated.get<FillTranslateAnchor>(),
parameters.state),
- parameters.context.viewport.getCurrentValue().size,
+ glContext.viewport.getCurrentValue().size,
geometryTile.iconAtlasTexture->size,
crossfade,
tile.id,
@@ -216,7 +215,7 @@ void RenderFillLayer::render(PaintParameters& parameters, RenderSource*) {
*bucket.triangleIndexBuffer,
bucket.triangleSegments,
FillPatternProgram::TextureBindings{
- textures::u_image::Value{ *geometryTile.iconAtlasTexture->resource, gfx::TextureFilterType::Linear },
+ textures::image::Value{ *geometryTile.iconAtlasTexture->resource, gfx::TextureFilterType::Linear },
});
if (evaluated.get<FillAntialias>() && unevaluated.get<FillOutlineColor>().isUndefined()) {
@@ -226,7 +225,7 @@ void RenderFillLayer::render(PaintParameters& parameters, RenderSource*) {
*bucket.lineIndexBuffer,
bucket.lineSegments,
FillOutlinePatternProgram::TextureBindings{
- textures::u_image::Value{ *geometryTile.iconAtlasTexture->resource, gfx::TextureFilterType::Linear },
+ textures::image::Value{ *geometryTile.iconAtlasTexture->resource, gfx::TextureFilterType::Linear },
});
}
}
diff --git a/src/mbgl/renderer/layers/render_heatmap_layer.cpp b/src/mbgl/renderer/layers/render_heatmap_layer.cpp
index efc16fb28a..f8ba68965e 100644
--- a/src/mbgl/renderer/layers/render_heatmap_layer.cpp
+++ b/src/mbgl/renderer/layers/render_heatmap_layer.cpp
@@ -52,12 +52,15 @@ void RenderHeatmapLayer::render(PaintParameters& parameters, RenderSource*) {
return;
}
+ // TODO: remove cast
+ gl::Context& glContext = reinterpret_cast<gl::Context&>(parameters.context);
+
if (parameters.pass == RenderPass::Pass3D) {
const auto& viewportSize = parameters.staticData.backendSize;
const auto size = Size{viewportSize.width / 4, viewportSize.height / 4};
if (!renderTexture || renderTexture->getSize() != size) {
- if (parameters.context.supportsHalfFloatTextures) {
+ if (glContext.supportsHalfFloatTextures) {
renderTexture = OffscreenTexture(parameters.context, size, gfx::TextureChannelDataType::HalfFloat);
try {
@@ -65,11 +68,11 @@ void RenderHeatmapLayer::render(PaintParameters& parameters, RenderSource*) {
} catch (const std::runtime_error& ex) {
// can't render to a half-float texture; falling back to unsigned byte one
renderTexture = nullopt;
- parameters.context.supportsHalfFloatTextures = false;
+ glContext.supportsHalfFloatTextures = false;
}
}
- if (!parameters.context.supportsHalfFloatTextures || !renderTexture) {
+ if (!glContext.supportsHalfFloatTextures || !renderTexture) {
renderTexture = OffscreenTexture(parameters.context, size, gfx::TextureChannelDataType::UnsignedByte);
renderTexture->bind();
}
@@ -82,7 +85,7 @@ void RenderHeatmapLayer::render(PaintParameters& parameters, RenderSource*) {
colorRampTexture = parameters.context.createTexture(colorRamp, gfx::TextureChannelDataType::UnsignedByte);
}
- parameters.context.clear(Color{ 0.0f, 0.0f, 0.0f, 1.0f }, {}, {});
+ glContext.clear(Color{ 0.0f, 0.0f, 0.0f, 1.0f }, {}, {});
for (const RenderTile& tile : renderTiles) {
auto bucket_ = tile.tile.getBucket<HeatmapBucket>(*baseImpl);
@@ -99,13 +102,13 @@ void RenderHeatmapLayer::render(PaintParameters& parameters, RenderSource*) {
const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID());
- auto& programInstance = parameters.programs.getHeatmapLayerPrograms().heatmap.get(evaluated);
+ auto& programInstance = parameters.programs.getHeatmapLayerPrograms().heatmap;
const auto allUniformValues = programInstance.computeAllUniformValues(
HeatmapProgram::LayoutUniformValues {
- uniforms::u_intensity::Value( evaluated.get<style::HeatmapIntensity>() ),
- uniforms::u_matrix::Value( tile.matrix ),
- uniforms::heatmap::u_extrude_scale::Value( extrudeScale )
+ uniforms::intensity::Value( evaluated.get<style::HeatmapIntensity>() ),
+ uniforms::matrix::Value( tile.matrix ),
+ uniforms::heatmap::extrude_scale::Value( extrudeScale )
},
paintPropertyBinders,
evaluated,
@@ -148,9 +151,9 @@ void RenderHeatmapLayer::render(PaintParameters& parameters, RenderSource*) {
const auto allUniformValues = programInstance.computeAllUniformValues(
HeatmapTextureProgram::LayoutUniformValues{
- uniforms::u_matrix::Value( viewportMat ),
- uniforms::u_world::Value( size ),
- uniforms::u_opacity::Value( evaluated.get<HeatmapOpacity>() )
+ uniforms::matrix::Value( viewportMat ),
+ uniforms::world::Value( size ),
+ uniforms::opacity::Value( evaluated.get<HeatmapOpacity>() )
},
paintAttributeData,
properties,
@@ -176,8 +179,8 @@ void RenderHeatmapLayer::render(PaintParameters& parameters, RenderSource*) {
allUniformValues,
allAttributeBindings,
HeatmapTextureProgram::TextureBindings{
- textures::u_image::Value{ *renderTexture->getTexture().resource, gfx::TextureFilterType::Linear },
- textures::u_color_ramp::Value{ *colorRampTexture->resource, gfx::TextureFilterType::Linear },
+ textures::image::Value{ *renderTexture->getTexture().resource, gfx::TextureFilterType::Linear },
+ textures::color_ramp::Value{ *colorRampTexture->resource, gfx::TextureFilterType::Linear },
},
getID()
);
diff --git a/src/mbgl/renderer/layers/render_hillshade_layer.cpp b/src/mbgl/renderer/layers/render_hillshade_layer.cpp
index 00ecad444c..1d030f5946 100644
--- a/src/mbgl/renderer/layers/render_hillshade_layer.cpp
+++ b/src/mbgl/renderer/layers/render_hillshade_layer.cpp
@@ -10,7 +10,6 @@
#include <mbgl/tile/tile.hpp>
#include <mbgl/style/layers/hillshade_layer_impl.hpp>
#include <mbgl/gfx/cull_face_mode.hpp>
-#include <mbgl/gl/context.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/util/offscreen_texture.hpp>
@@ -77,12 +76,12 @@ void RenderHillshadeLayer::render(PaintParameters& parameters, RenderSource* src
const auto allUniformValues = programInstance.computeAllUniformValues(
HillshadeProgram::LayoutUniformValues {
- uniforms::u_matrix::Value( matrix ),
- uniforms::u_highlight::Value( evaluated.get<HillshadeHighlightColor>() ),
- uniforms::u_shadow::Value( evaluated.get<HillshadeShadowColor>() ),
- uniforms::u_accent::Value( evaluated.get<HillshadeAccentColor>() ),
- uniforms::u_light::Value( getLight(parameters) ),
- uniforms::u_latrange::Value( getLatRange(id) ),
+ uniforms::matrix::Value( matrix ),
+ uniforms::highlight::Value( evaluated.get<HillshadeHighlightColor>() ),
+ uniforms::shadow::Value( evaluated.get<HillshadeShadowColor>() ),
+ uniforms::accent::Value( evaluated.get<HillshadeAccentColor>() ),
+ uniforms::light::Value( getLight(parameters) ),
+ uniforms::latrange::Value( getLatRange(id) ),
},
paintAttributeData,
evaluated,
@@ -141,10 +140,10 @@ void RenderHillshadeLayer::render(PaintParameters& parameters, RenderSource* src
const auto allUniformValues = programInstance.computeAllUniformValues(
HillshadePrepareProgram::LayoutUniformValues {
- uniforms::u_matrix::Value( mat ),
- uniforms::u_dimension::Value( {{stride, stride}} ),
- uniforms::u_zoom::Value( float(tile.id.canonical.z) ),
- uniforms::u_maxzoom::Value( float(maxzoom) ),
+ uniforms::matrix::Value( mat ),
+ uniforms::dimension::Value( {{stride, stride}} ),
+ uniforms::zoom::Value( float(tile.id.canonical.z) ),
+ uniforms::maxzoom::Value( float(maxzoom) ),
},
paintAttributeData,
properties,
@@ -170,7 +169,7 @@ void RenderHillshadeLayer::render(PaintParameters& parameters, RenderSource* src
allUniformValues,
allAttributeBindings,
HillshadePrepareProgram::TextureBindings{
- textures::u_image::Value{ *bucket.dem->resource },
+ textures::image::Value{ *bucket.dem->resource },
},
getID()
);
@@ -187,7 +186,7 @@ void RenderHillshadeLayer::render(PaintParameters& parameters, RenderSource* src
bucket.segments,
tile.id,
HillshadeProgram::TextureBindings{
- textures::u_image::Value{ *bucket.texture->resource, gfx::TextureFilterType::Linear },
+ textures::image::Value{ *bucket.texture->resource, gfx::TextureFilterType::Linear },
});
} else {
// Draw the full tile.
@@ -197,7 +196,7 @@ void RenderHillshadeLayer::render(PaintParameters& parameters, RenderSource* src
parameters.staticData.rasterSegments,
tile.id,
HillshadeProgram::TextureBindings{
- textures::u_image::Value{ *bucket.texture->resource, gfx::TextureFilterType::Linear },
+ textures::image::Value{ *bucket.texture->resource, gfx::TextureFilterType::Linear },
});
}
}
diff --git a/src/mbgl/renderer/layers/render_line_layer.cpp b/src/mbgl/renderer/layers/render_line_layer.cpp
index eee151ccaa..2d246df7f4 100644
--- a/src/mbgl/renderer/layers/render_line_layer.cpp
+++ b/src/mbgl/renderer/layers/render_line_layer.cpp
@@ -9,7 +9,6 @@
#include <mbgl/tile/tile.hpp>
#include <mbgl/style/layers/line_layer_impl.hpp>
#include <mbgl/gfx/cull_face_mode.hpp>
-#include <mbgl/gl/context.hpp>
#include <mbgl/geometry/feature_index.hpp>
#include <mbgl/util/math.hpp>
#include <mbgl/util/intersection_tests.hpp>
@@ -34,10 +33,7 @@ void RenderLineLayer::transition(const TransitionParameters& parameters) {
}
void RenderLineLayer::evaluate(const PropertyEvaluationParameters& parameters) {
- style::Properties<LineFloorwidth>::Unevaluated extra(unevaluated.get<style::LineWidth>());
- evaluated = RenderLinePaintProperties::PossiblyEvaluated(
- unevaluated.evaluate(parameters).concat(extra.evaluate(parameters)));
-
+ evaluated = unevaluated.evaluate(parameters);
crossfade = parameters.getCrossfadeParameters();
passes = (evaluated.get<style::LineOpacity>().constantOr(1.0) > 0
@@ -66,11 +62,10 @@ void RenderLineLayer::render(PaintParameters& parameters, RenderSource*) {
}
LineBucket& bucket = *bucket_;
- auto draw = [&](auto& program, auto&& uniformValues,
+ auto draw = [&](auto& programInstance,
+ auto&& uniformValues,
const optional<ImagePosition>& patternPositionA,
const optional<ImagePosition>& patternPositionB, auto&& textureBindings) {
- auto& programInstance = program.get(evaluated);
-
const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID());
paintPropertyBinders.setPatternParameters(patternPositionA, patternPositionB, crossfade);
@@ -145,10 +140,10 @@ void RenderLineLayer::render(PaintParameters& parameters, RenderSource*) {
texsize,
crossfade,
parameters.pixelRatio),
- *posA,
- *posB,
+ posA,
+ posB,
LinePatternProgram::TextureBindings{
- textures::u_image::Value{ *geometryTile.iconAtlasTexture->resource, gfx::TextureFilterType::Linear },
+ textures::image::Value{ *geometryTile.iconAtlasTexture->resource, gfx::TextureFilterType::Linear },
});
} else if (!unevaluated.get<LineGradient>().getValue().isUndefined()) {
if (!colorRampTexture) {
@@ -164,7 +159,7 @@ void RenderLineLayer::render(PaintParameters& parameters, RenderSource*) {
{},
{},
LineGradientProgram::TextureBindings{
- textures::u_image::Value{ *colorRampTexture->resource, gfx::TextureFilterType::Linear },
+ textures::image::Value{ *colorRampTexture->resource, gfx::TextureFilterType::Linear },
});
} else {
draw(parameters.programs.getLineLayerPrograms().line,
diff --git a/src/mbgl/renderer/layers/render_line_layer.hpp b/src/mbgl/renderer/layers/render_line_layer.hpp
index 186b740234..cb4492ebc3 100644
--- a/src/mbgl/renderer/layers/render_line_layer.hpp
+++ b/src/mbgl/renderer/layers/render_line_layer.hpp
@@ -10,15 +10,6 @@
namespace mbgl {
-struct LineFloorwidth : style::DataDrivenPaintProperty<float, attributes::a_floorwidth, uniforms::u_floorwidth> {
- using EvaluatorType = DataDrivenPropertyEvaluator<float, true>;
- static float defaultValue() { return 1.0; }
-};
-
-class RenderLinePaintProperties : public style::ConcatenateProperties<
- style::LinePaintProperties,
- style::Properties<LineFloorwidth>> {};
-
class RenderLineLayer: public RenderLayer {
public:
using StyleLayerImpl = style::LineLayer::Impl;
@@ -44,7 +35,7 @@ public:
// Paint properties
style::LinePaintProperties::Unevaluated unevaluated;
- RenderLinePaintProperties::PossiblyEvaluated evaluated;
+ style::LinePaintProperties::PossiblyEvaluated evaluated;
const style::LineLayer::Impl& impl() const;
diff --git a/src/mbgl/renderer/layers/render_raster_layer.cpp b/src/mbgl/renderer/layers/render_raster_layer.cpp
index c8f00eb1fd..94c4a8dc42 100644
--- a/src/mbgl/renderer/layers/render_raster_layer.cpp
+++ b/src/mbgl/renderer/layers/render_raster_layer.cpp
@@ -8,7 +8,6 @@
#include <mbgl/programs/raster_program.hpp>
#include <mbgl/tile/tile.hpp>
#include <mbgl/gfx/cull_face_mode.hpp>
-#include <mbgl/gl/context.hpp>
#include <mbgl/style/layers/raster_layer_impl.hpp>
namespace mbgl {
@@ -85,17 +84,17 @@ void RenderRasterLayer::render(PaintParameters& parameters, RenderSource* source
const auto allUniformValues = programInstance.computeAllUniformValues(
RasterProgram::LayoutUniformValues {
- uniforms::u_matrix::Value( matrix ),
- uniforms::u_opacity::Value( evaluated.get<RasterOpacity>() ),
- uniforms::u_fade_t::Value( 1 ),
- uniforms::u_brightness_low::Value( evaluated.get<RasterBrightnessMin>() ),
- uniforms::u_brightness_high::Value( evaluated.get<RasterBrightnessMax>() ),
- uniforms::u_saturation_factor::Value( saturationFactor(evaluated.get<RasterSaturation>()) ),
- uniforms::u_contrast_factor::Value( contrastFactor(evaluated.get<RasterContrast>()) ),
- uniforms::u_spin_weights::Value( spinWeights(evaluated.get<RasterHueRotate>()) ),
- uniforms::u_buffer_scale::Value( 1.0f ),
- uniforms::u_scale_parent::Value( 1.0f ),
- uniforms::u_tl_parent::Value( std::array<float, 2> {{ 0.0f, 0.0f }} ),
+ uniforms::matrix::Value( matrix ),
+ uniforms::opacity::Value( evaluated.get<RasterOpacity>() ),
+ uniforms::fade_t::Value( 1 ),
+ uniforms::brightness_low::Value( evaluated.get<RasterBrightnessMin>() ),
+ uniforms::brightness_high::Value( evaluated.get<RasterBrightnessMax>() ),
+ uniforms::saturation_factor::Value( saturationFactor(evaluated.get<RasterSaturation>()) ),
+ uniforms::contrast_factor::Value( contrastFactor(evaluated.get<RasterContrast>()) ),
+ uniforms::spin_weights::Value( spinWeights(evaluated.get<RasterHueRotate>()) ),
+ uniforms::buffer_scale::Value( 1.0f ),
+ uniforms::scale_parent::Value( 1.0f ),
+ uniforms::tl_parent::Value( std::array<float, 2> {{ 0.0f, 0.0f }} ),
},
paintAttributeData,
evaluated,
@@ -138,8 +137,8 @@ void RenderRasterLayer::render(PaintParameters& parameters, RenderSource* source
*bucket.indexBuffer,
bucket.segments,
RasterProgram::TextureBindings{
- textures::u_image0::Value{ *bucket.texture->resource, filter },
- textures::u_image1::Value{ *bucket.texture->resource, filter },
+ textures::image0::Value{ *bucket.texture->resource, filter },
+ textures::image1::Value{ *bucket.texture->resource, filter },
});
}
}
@@ -162,8 +161,8 @@ void RenderRasterLayer::render(PaintParameters& parameters, RenderSource* source
*bucket.indexBuffer,
bucket.segments,
RasterProgram::TextureBindings{
- textures::u_image0::Value{ *bucket.texture->resource, filter },
- textures::u_image1::Value{ *bucket.texture->resource, filter },
+ textures::image0::Value{ *bucket.texture->resource, filter },
+ textures::image1::Value{ *bucket.texture->resource, filter },
});
} else {
// Draw the full tile.
@@ -172,8 +171,8 @@ void RenderRasterLayer::render(PaintParameters& parameters, RenderSource* source
parameters.staticData.quadTriangleIndexBuffer,
parameters.staticData.rasterSegments,
RasterProgram::TextureBindings{
- textures::u_image0::Value{ *bucket.texture->resource, filter },
- textures::u_image1::Value{ *bucket.texture->resource, filter },
+ textures::image0::Value{ *bucket.texture->resource, filter },
+ textures::image1::Value{ *bucket.texture->resource, filter },
});
}
}
diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp
index 31d92dd414..d7951c647a 100644
--- a/src/mbgl/renderer/layers/render_symbol_layer.cpp
+++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp
@@ -5,6 +5,7 @@
#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/text/glyph_atlas.hpp>
+#include <mbgl/text/shaping.hpp>
#include <mbgl/programs/programs.hpp>
#include <mbgl/programs/symbol_program.hpp>
#include <mbgl/programs/collision_box_program.hpp>
@@ -13,8 +14,8 @@
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/style/layers/symbol_layer_impl.hpp>
#include <mbgl/gfx/cull_face_mode.hpp>
-#include <mbgl/gl/context.hpp>
#include <mbgl/layout/symbol_projection.hpp>
+#include <mbgl/layout/symbol_layout.hpp>
#include <mbgl/util/math.hpp>
#include <cmath>
@@ -23,6 +24,19 @@ namespace mbgl {
using namespace style;
+namespace {
+Point<float> calculateVariableRenderShift(style::SymbolAnchorType anchor, float width, float height, float radialOffset, float textBoxScale, float renderTextSize) {
+ AnchorAlignment alignment = AnchorAlignment::getAnchorAlignment(anchor);
+ float shiftX = -(alignment.horizontalAlign - 0.5f) * width;
+ float shiftY = -(alignment.verticalAlign - 0.5f) * height;
+ Point<float> offset = SymbolLayout::evaluateRadialOffset(anchor, radialOffset);
+ return Point<float>(
+ (shiftX / textBoxScale + offset.x) * renderTextSize,
+ (shiftY / textBoxScale + offset.y) * renderTextSize
+ );
+}
+} // namespace
+
RenderSymbolLayer::RenderSymbolLayer(Immutable<style::SymbolLayer::Impl> _impl)
: RenderLayer(std::move(_impl)),
unevaluated(impl().paint.untransitioned()) {
@@ -89,17 +103,14 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) {
const auto& evaluated_ = bucketPaintProperties.evaluated;
const auto& layout = bucket.layout;
- auto draw = [&] (auto& program,
+ auto draw = [&] (auto& programInstance,
auto&& uniformValues,
const auto& buffers,
const auto& symbolSizeBinder,
const SymbolPropertyValues& values_,
const auto& binders,
const auto& paintProperties,
- auto&& textureBindings)
- {
- auto& programInstance = program.get(paintProperties);
-
+ auto&& textureBindings) {
const auto allUniformValues = programInstance.computeAllUniformValues(
std::move(uniformValues),
*symbolSizeBinder,
@@ -172,7 +183,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) {
if (bucket.sdfIcons) {
if (values.hasHalo) {
draw(parameters.programs.getSymbolLayerPrograms().symbolIconSDF,
- SymbolSDFIconProgram::layoutUniformValues(false, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Halo),
+ SymbolSDFIconProgram::layoutUniformValues(false, false, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Halo),
bucket.icon,
bucket.iconSizeBinder,
values,
@@ -185,7 +196,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) {
if (values.hasFill) {
draw(parameters.programs.getSymbolLayerPrograms().symbolIconSDF,
- SymbolSDFIconProgram::layoutUniformValues(false, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Fill),
+ SymbolSDFIconProgram::layoutUniformValues(false, false, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Fill),
bucket.icon,
bucket.iconSizeBinder,
values,
@@ -197,7 +208,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) {
}
} else {
draw(parameters.programs.getSymbolLayerPrograms().symbolIcon,
- SymbolIconProgram::layoutUniformValues(false, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange),
+ SymbolIconProgram::layoutUniformValues(false, false, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange),
bucket.icon,
bucket.iconSizeBinder,
values,
@@ -215,6 +226,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) {
auto values = textPropertyValues(evaluated_, layout);
const auto& paintPropertyValues = textPaintProperties(evaluated_);
+ bool hasVariablePacement = false;
const bool alongLine = layout.get<SymbolPlacement>() != SymbolPlacementType::Point &&
layout.get<TextRotationAlignment>() == AlignmentType::Map;
@@ -229,13 +241,79 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) {
parameters.state);
parameters.context.updateVertexBuffer(*bucket.text.dynamicVertexBuffer, std::move(bucket.text.dynamicVertices));
+ } else if (!layout.get<TextVariableAnchor>().empty()) {
+ bucket.text.dynamicVertices.clear();
+
+ const auto partiallyEvaluatedSize = bucket.textSizeBinder->evaluateForZoom(parameters.state.getZoom());
+ const float tileScale = std::pow(2, parameters.state.getZoom() - tile.tile.id.overscaledZ);
+ const bool rotateWithMap = layout.get<TextRotationAlignment>() == AlignmentType::Map;
+ const bool pitchWithMap = layout.get<TextPitchAlignment>() == AlignmentType::Map;
+ const float pixelsToTileUnits = tile.id.pixelsToTileUnits(1.0, parameters.state.getZoom());
+ const auto labelPlaneMatrix = getLabelPlaneMatrix(tile.matrix, pitchWithMap, rotateWithMap, parameters.state, pixelsToTileUnits);
+
+ for (const PlacedSymbol& symbol : bucket.text.placedSymbols) {
+ optional<VariableOffset> variableOffset;
+ if (!symbol.hidden && symbol.crossTileID != 0u) {
+ auto it = parameters.variableOffsets.get().find(symbol.crossTileID);
+ if (it != parameters.variableOffsets.get().end()) {
+ variableOffset = it->second;
+ hasVariablePacement |= true;
+ }
+ }
+
+ if (!variableOffset) {
+ // These symbols are from a justification that is not being used, or a label that wasn't placed
+ // so we don't need to do the extra math to figure out what incremental shift to apply.
+ hideGlyphs(symbol.glyphOffsets.size(), bucket.text.dynamicVertices);
+ } else {
+ const Point<float> tileAnchor = symbol.anchorPoint;
+ const auto projectedAnchor = project(tileAnchor, pitchWithMap ? tile.matrix : labelPlaneMatrix);
+ const float perspectiveRatio = 0.5f + 0.5f * (parameters.state.getCameraToCenterDistance() / projectedAnchor.second);
+ float renderTextSize = evaluateSizeForFeature(partiallyEvaluatedSize, symbol) * perspectiveRatio / util::ONE_EM;
+ if (pitchWithMap) {
+ // Go from size in pixels to equivalent size in tile units
+ renderTextSize *= bucket.tilePixelRatio / tileScale;
+ }
+
+ auto shift = calculateVariableRenderShift(
+ (*variableOffset).anchor,
+ (*variableOffset).width,
+ (*variableOffset).height,
+ (*variableOffset).radialOffset,
+ (*variableOffset).textBoxScale,
+ renderTextSize);
+
+ // Usual case is that we take the projected anchor and add the pixel-based shift
+ // calculated above. In the (somewhat weird) case of pitch-aligned text, we add an equivalent
+ // tile-unit based shift to the anchor before projecting to the label plane.
+ Point<float> shiftedAnchor;
+ if (pitchWithMap) {
+ shiftedAnchor = project(Point<float>(tileAnchor.x + shift.x, tileAnchor.y + shift.y),
+ labelPlaneMatrix).first;
+ } else {
+ if (rotateWithMap) {
+ auto rotated = util::rotate(shift, -parameters.state.getPitch());
+ shiftedAnchor = Point<float>(projectedAnchor.first.x + rotated.x,
+ projectedAnchor.first.y + rotated.y);
+ } else {
+ shiftedAnchor = Point<float>(projectedAnchor.first.x + shift.x,
+ projectedAnchor.first.y + shift.y);
+ }
+ }
+
+ for (std::size_t i = 0; i < symbol.glyphOffsets.size(); i++) {
+ addDynamicAttributes(shiftedAnchor, 0, bucket.text.dynamicVertices);
+ }
+ }
+ }
+ parameters.context.updateVertexBuffer(*bucket.text.dynamicVertexBuffer, std::move(bucket.text.dynamicVertices));
}
const Size texsize = geometryTile.glyphAtlasTexture->size;
if (values.hasHalo) {
draw(parameters.programs.getSymbolLayerPrograms().symbolGlyph,
- SymbolSDFTextProgram::layoutUniformValues(true, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Halo),
+ SymbolSDFTextProgram::layoutUniformValues(true, hasVariablePacement, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Halo),
bucket.text,
bucket.textSizeBinder,
values,
@@ -248,7 +326,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) {
if (values.hasFill) {
draw(parameters.programs.getSymbolLayerPrograms().symbolGlyph,
- SymbolSDFTextProgram::layoutUniformValues(true, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Fill),
+ SymbolSDFTextProgram::layoutUniformValues(true, hasVariablePacement, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Fill),
bucket.text,
bucket.textSizeBinder,
values,
@@ -280,9 +358,9 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) {
parameters.colorModeForRenderPass(),
gfx::CullFaceMode::disabled(),
CollisionBoxProgram::LayoutUniformValues {
- uniforms::u_matrix::Value( tile.matrix ),
- uniforms::u_extrude_scale::Value( extrudeScale ),
- uniforms::u_camera_to_center_distance::Value( parameters.state.getCameraToCenterDistance() )
+ uniforms::matrix::Value( tile.matrix ),
+ uniforms::extrude_scale::Value( extrudeScale ),
+ uniforms::camera_to_center_distance::Value( parameters.state.getCameraToCenterDistance() )
},
*bucket.collisionBox.vertexBuffer,
*bucket.collisionBox.dynamicVertexBuffer,
@@ -316,10 +394,10 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) {
parameters.colorModeForRenderPass(),
gfx::CullFaceMode::disabled(),
CollisionCircleProgram::LayoutUniformValues {
- uniforms::u_matrix::Value( tile.matrix ),
- uniforms::u_extrude_scale::Value( extrudeScale ),
- uniforms::u_overscale_factor::Value( float(tile.tile.id.overscaleFactor()) ),
- uniforms::u_camera_to_center_distance::Value( parameters.state.getCameraToCenterDistance() )
+ uniforms::matrix::Value( tile.matrix ),
+ uniforms::extrude_scale::Value( extrudeScale ),
+ uniforms::overscale_factor::Value( float(tile.tile.id.overscaleFactor()) ),
+ uniforms::camera_to_center_distance::Value( parameters.state.getCameraToCenterDistance() )
},
*bucket.collisionCircle.vertexBuffer,
*bucket.collisionCircle.dynamicVertexBuffer,
@@ -392,12 +470,9 @@ style::SymbolPropertyValues RenderSymbolLayer::textPropertyValues(const style::S
};
}
-RenderLayer::RenderTiles RenderSymbolLayer::filterRenderTiles(RenderTiles tiles) const {
+void RenderSymbolLayer::setRenderTiles(RenderTiles tiles, const TransformState& state) {
auto filterFn = [](auto& tile){ return !tile.tile.isRenderable(); };
- return RenderLayer::filterRenderTiles(std::move(tiles), filterFn);
-}
-
-void RenderSymbolLayer::sortRenderTiles(const TransformState& state) {
+ renderTiles = RenderLayer::filterRenderTiles(std::move(tiles), filterFn);
// Sort symbol tiles in opposite y position, so tiles with overlapping symbols are drawn
// on top of each other, with lower symbols being drawn on top of higher symbols.
std::sort(renderTiles.begin(), renderTiles.end(), [&state](const auto& a, const auto& b) {
diff --git a/src/mbgl/renderer/layers/render_symbol_layer.hpp b/src/mbgl/renderer/layers/render_symbol_layer.hpp
index e44ad398f4..4de5c8538a 100644
--- a/src/mbgl/renderer/layers/render_symbol_layer.hpp
+++ b/src/mbgl/renderer/layers/render_symbol_layer.hpp
@@ -57,7 +57,7 @@ class BucketParameters;
class SymbolLayout;
class GeometryTileLayer;
-class RenderSymbolLayer: public RenderLayer, public RenderLayerSymbolInterface {
+class RenderSymbolLayer final: public RenderLayer, public RenderLayerSymbolInterface {
public:
RenderSymbolLayer(Immutable<style::SymbolLayer::Impl>);
~RenderSymbolLayer() final = default;
@@ -67,6 +67,7 @@ public:
bool hasTransition() const override;
bool hasCrossfade() const override;
void render(PaintParameters&, RenderSource*) override;
+ void setRenderTiles(RenderTiles, const TransformState&) override;
static style::IconPaintProperties::PossiblyEvaluated iconPaintProperties(const style::SymbolPaintProperties::PossiblyEvaluated&);
static style::TextPaintProperties::PossiblyEvaluated textPaintProperties(const style::SymbolPaintProperties::PossiblyEvaluated&);
@@ -91,8 +92,6 @@ protected:
const style::SymbolLayoutProperties::PossiblyEvaluated&);
static style::SymbolPropertyValues textPropertyValues(const style::SymbolPaintProperties::PossiblyEvaluated&,
const style::SymbolLayoutProperties::PossiblyEvaluated&);
- RenderTiles filterRenderTiles(RenderTiles) const final;
- void sortRenderTiles(const TransformState&) final;
void updateBucketPaintProperties(Bucket*) const final;
};
diff --git a/src/mbgl/renderer/paint_parameters.cpp b/src/mbgl/renderer/paint_parameters.cpp
index 2237b016d2..55dbf70472 100644
--- a/src/mbgl/renderer/paint_parameters.cpp
+++ b/src/mbgl/renderer/paint_parameters.cpp
@@ -5,7 +5,7 @@
namespace mbgl {
-PaintParameters::PaintParameters(gl::Context& context_,
+PaintParameters::PaintParameters(gfx::Context& context_,
float pixelRatio_,
GLContextMode contextMode_,
RendererBackend& backend_,
@@ -13,7 +13,8 @@ PaintParameters::PaintParameters(gl::Context& context_,
const EvaluatedLight& evaluatedLight_,
RenderStaticData& staticData_,
ImageManager& imageManager_,
- LineAtlas& lineAtlas_)
+ LineAtlas& lineAtlas_,
+ Placement::VariableOffsets variableOffsets_)
: context(context_),
backend(backend_),
state(updateParameters.transformState),
@@ -26,6 +27,7 @@ PaintParameters::PaintParameters(gl::Context& context_,
contextMode(contextMode_),
timePoint(updateParameters.timePoint),
pixelRatio(pixelRatio_),
+ variableOffsets(variableOffsets_),
#ifndef NDEBUG
programs((debugOptions & MapDebugOptions::Overdraw) ? staticData_.overdrawPrograms : staticData_.programs)
#else
diff --git a/src/mbgl/renderer/paint_parameters.hpp b/src/mbgl/renderer/paint_parameters.hpp
index ea3b41adfe..537158a68e 100644
--- a/src/mbgl/renderer/paint_parameters.hpp
+++ b/src/mbgl/renderer/paint_parameters.hpp
@@ -9,6 +9,7 @@
#include <mbgl/gfx/color_mode.hpp>
#include <mbgl/util/mat4.hpp>
#include <mbgl/algorithm/generate_clip_ids.hpp>
+#include <mbgl/text/placement.hpp>
#include <array>
@@ -23,13 +24,13 @@ class ImageManager;
class LineAtlas;
class UnwrappedTileID;
-namespace gl {
+namespace gfx {
class Context;
-} // namespace gl
+} // namespace gfx
class PaintParameters {
public:
- PaintParameters(gl::Context&,
+ PaintParameters(gfx::Context&,
float pixelRatio,
GLContextMode,
RendererBackend&,
@@ -37,9 +38,10 @@ public:
const EvaluatedLight&,
RenderStaticData&,
ImageManager&,
- LineAtlas&);
+ LineAtlas&,
+ Placement::VariableOffsets);
- gl::Context& context;
+ gfx::Context& context;
RendererBackend& backend;
const TransformState& state;
@@ -56,6 +58,7 @@ public:
TimePoint timePoint;
float pixelRatio;
+ Placement::VariableOffsets variableOffsets;
std::array<float, 2> pixelsToGLUnits;
algorithm::ClipIDGenerator clipIDGenerator;
diff --git a/src/mbgl/renderer/paint_property_binder.hpp b/src/mbgl/renderer/paint_property_binder.hpp
index a014b36ece..dd56afb2e8 100644
--- a/src/mbgl/renderer/paint_property_binder.hpp
+++ b/src/mbgl/renderer/paint_property_binder.hpp
@@ -4,6 +4,7 @@
#include <mbgl/gfx/uniform.hpp>
#include <mbgl/gfx/attribute.hpp>
#include <mbgl/programs/attributes.hpp>
+#include <mbgl/util/literal.hpp>
#include <mbgl/util/type_list.hpp>
#include <mbgl/renderer/possibly_evaluated_property_value.hpp>
#include <mbgl/renderer/paint_property_statistics.hpp>
@@ -147,7 +148,7 @@ public:
void upload(gfx::Context&) override {}
void setPatternParameters(const optional<ImagePosition>& posA, const optional<ImagePosition>& posB, CrossfadeParameters&) override {
- if (!posA && !posB) {
+ if (!posA || !posB) {
return;
} else {
constantPatternPositions = std::tuple<std::array<uint16_t, 4>, std::array<uint16_t, 4>> { posB->tlbr(), posA->tlbr() };
@@ -431,17 +432,15 @@ PaintPropertyBinder<T, UniformValueType, PossiblyEvaluatedType, As...>::create(c
}
template <class Attr>
-struct ZoomInterpolatedAttribute {
- static auto name() { return Attr::name(); }
+struct ZoomInterpolatedAttribute : public Attr {
using Type = ZoomInterpolatedAttributeType<typename Attr::Type>;
};
template <class Attr>
struct InterpolationUniform {
using Value = float;
- static auto name() {
- static const std::string name = Attr::name() + std::string("_t");
- return name.c_str();
+ static constexpr auto name() {
+ return concat_literals<&Attr::name, &string_literal<'_', 't'>::value>::value();
}
};
@@ -546,29 +545,6 @@ public:
return result;
}
- template <class>
- struct UniformDefines;
-
- template <class... Us>
- struct UniformDefines<TypeList<Us...>> {
- static void appendDefines(std::vector<std::string>& defines) {
- util::ignore({
- (defines.push_back(std::string("#define HAS_UNIFORM_") + Us::name()), 0)...
- });
- }
- };
-
- template <class EvaluatedProperties>
- static std::vector<std::string> defines(const EvaluatedProperties& currentProperties) {
- std::vector<std::string> result;
- util::ignore({
- (currentProperties.template get<Ps>().isConstant()
- ? UniformDefines<typename Ps::UniformList>::appendDefines(result)
- : (void) 0, 0)...
- });
- return result;
- }
-
private:
Binders binders;
};
diff --git a/src/mbgl/renderer/render_layer.cpp b/src/mbgl/renderer/render_layer.cpp
index 32236d0f24..24a45b9146 100644
--- a/src/mbgl/renderer/render_layer.cpp
+++ b/src/mbgl/renderer/render_layer.cpp
@@ -3,7 +3,7 @@
#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/style/types.hpp>
#include <mbgl/tile/tile.hpp>
-#include <mbgl/gl/context.hpp>
+#include <mbgl/gfx/context.hpp>
#include <mbgl/util/logging.hpp>
namespace mbgl {
@@ -33,18 +33,9 @@ bool RenderLayer::needsRendering(float zoom) const {
&& baseImpl->maxZoom >= zoom;
}
-void RenderLayer::setRenderTiles(RenderTiles tiles, const TransformState& state) {
- renderTiles = filterRenderTiles(std::move(tiles));
- sortRenderTiles(state);
-}
-
-RenderLayer::RenderTiles RenderLayer::filterRenderTiles(RenderTiles tiles) const {
+void RenderLayer::setRenderTiles(RenderTiles tiles, const TransformState&) {
auto filterFn = [](auto& tile){ return !tile.tile.isRenderable() || tile.tile.holdForFade(); };
- return filterRenderTiles(std::move(tiles), filterFn);
-}
-
-void RenderLayer::sortRenderTiles(const TransformState&) {
- // no-op
+ renderTiles = filterRenderTiles(std::move(tiles), filterFn);
}
const RenderLayerSymbolInterface* RenderLayer::getSymbolInterface() const {
diff --git a/src/mbgl/renderer/render_layer.hpp b/src/mbgl/renderer/render_layer.hpp
index ec4c71b08c..98e151435a 100644
--- a/src/mbgl/renderer/render_layer.hpp
+++ b/src/mbgl/renderer/render_layer.hpp
@@ -63,7 +63,7 @@ public:
const mat4&) const { return false; };
using RenderTiles = std::vector<std::reference_wrapper<RenderTile>>;
- void setRenderTiles(RenderTiles, const TransformState&);
+ virtual void setRenderTiles(RenderTiles, const TransformState&);
// Private implementation
Immutable<style::Layer::Impl> baseImpl;
@@ -84,9 +84,6 @@ protected:
// in the console to inform the developer.
void checkRenderability(const PaintParameters&, uint32_t activeBindingCount);
- // Code specific to RenderTiles sorting / filtering
- virtual RenderTiles filterRenderTiles(RenderTiles) const;
- virtual void sortRenderTiles(const TransformState&);
// For some layers, we want Buckets to cache their corresponding paint properties, so that outdated buckets (and
// the cached paint properties) can be still in use while the tile is loading new buckets (which will
// correpond to the current paint properties of the layer).
diff --git a/src/mbgl/renderer/render_static_data.cpp b/src/mbgl/renderer/render_static_data.cpp
index 16d0d64a33..24eed0326c 100644
--- a/src/mbgl/renderer/render_static_data.cpp
+++ b/src/mbgl/renderer/render_static_data.cpp
@@ -1,5 +1,5 @@
#include <mbgl/renderer/render_static_data.hpp>
-#include <mbgl/gl/context.hpp>
+#include <mbgl/gfx/context.hpp>
#include <mbgl/programs/program_parameters.hpp>
namespace mbgl {
@@ -48,7 +48,7 @@ static gfx::VertexVector<ExtrusionTextureLayoutVertex> extrusionTextureVertices(
return result;
}
-RenderStaticData::RenderStaticData(gl::Context& context, float pixelRatio, const optional<std::string>& programCacheDir)
+RenderStaticData::RenderStaticData(gfx::Context& context, float pixelRatio, const optional<std::string>& programCacheDir)
: tileVertexBuffer(context.createVertexBuffer(tileVertices())),
rasterVertexBuffer(context.createVertexBuffer(rasterVertices())),
extrusionTextureVertexBuffer(context.createVertexBuffer(extrusionTextureVertices())),
diff --git a/src/mbgl/renderer/render_static_data.hpp b/src/mbgl/renderer/render_static_data.hpp
index b9b52b09ca..23f632bc12 100644
--- a/src/mbgl/renderer/render_static_data.hpp
+++ b/src/mbgl/renderer/render_static_data.hpp
@@ -12,10 +12,13 @@
#include <string>
namespace mbgl {
+namespace gfx {
+class Context;
+} // namespace gfx
class RenderStaticData {
public:
- RenderStaticData(gl::Context&, float pixelRatio, const optional<std::string>& programCacheDir);
+ RenderStaticData(gfx::Context&, float pixelRatio, const optional<std::string>& programCacheDir);
gfx::VertexBuffer<gfx::Vertex<PositionOnlyLayoutAttributes>> tileVertexBuffer;
gfx::VertexBuffer<RasterLayoutVertex> rasterVertexBuffer;
diff --git a/src/mbgl/renderer/render_tile.cpp b/src/mbgl/renderer/render_tile.cpp
index 24826bfd78..745a577683 100644
--- a/src/mbgl/renderer/render_tile.cpp
+++ b/src/mbgl/renderer/render_tile.cpp
@@ -4,7 +4,7 @@
#include <mbgl/renderer/render_static_data.hpp>
#include <mbgl/programs/programs.hpp>
#include <mbgl/map/transform_state.hpp>
-#include <mbgl/gl/context.hpp>
+#include <mbgl/gfx/cull_face_mode.hpp>
#include <mbgl/tile/tile.hpp>
#include <mbgl/util/math.hpp>
@@ -105,8 +105,8 @@ void RenderTile::finishRender(PaintParameters& parameters) {
tile.debugBucket->segments,
program.computeAllUniformValues(
DebugProgram::LayoutUniformValues {
- uniforms::u_matrix::Value( matrix ),
- uniforms::u_color::Value( Color::white() )
+ uniforms::matrix::Value( matrix ),
+ uniforms::color::Value( Color::white() )
},
paintAttributeData,
properties,
@@ -128,8 +128,8 @@ void RenderTile::finishRender(PaintParameters& parameters) {
tile.debugBucket->segments,
program.computeAllUniformValues(
DebugProgram::LayoutUniformValues {
- uniforms::u_matrix::Value( matrix ),
- uniforms::u_color::Value( Color::black() )
+ uniforms::matrix::Value( matrix ),
+ uniforms::color::Value( Color::black() )
},
paintAttributeData,
properties,
@@ -153,8 +153,8 @@ void RenderTile::finishRender(PaintParameters& parameters) {
parameters.staticData.tileBorderSegments,
program.computeAllUniformValues(
DebugProgram::LayoutUniformValues {
- uniforms::u_matrix::Value( matrix ),
- uniforms::u_color::Value( Color::red() )
+ uniforms::matrix::Value( matrix ),
+ uniforms::color::Value( Color::red() )
},
paintAttributeData,
properties,
diff --git a/src/mbgl/renderer/renderer.cpp b/src/mbgl/renderer/renderer.cpp
index fbd9049207..4da7b78374 100644
--- a/src/mbgl/renderer/renderer.cpp
+++ b/src/mbgl/renderer/renderer.cpp
@@ -34,6 +34,10 @@ void Renderer::render(const UpdateParameters& updateParameters) {
impl->render(updateParameters);
}
+void Renderer::flush() {
+ impl->flush();
+}
+
std::vector<Feature> Renderer::queryRenderedFeatures(const ScreenLineString& geometry, const RenderedQueryOptions& options) const {
return impl->queryRenderedFeatures(geometry, options);
}
diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp
index 471536cf40..7144a2dcee 100644
--- a/src/mbgl/renderer/renderer_impl.cpp
+++ b/src/mbgl/renderer/renderer_impl.cpp
@@ -16,6 +16,7 @@
#include <mbgl/renderer/query.hpp>
#include <mbgl/renderer/backend_scope.hpp>
#include <mbgl/renderer/image_manager.hpp>
+#include <mbgl/gl/context.hpp>
#include <mbgl/gl/debugging.hpp>
#include <mbgl/geometry/line_atlas.hpp>
#include <mbgl/style/source_impl.hpp>
@@ -82,6 +83,7 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
if (!imageManager) {
imageManager = std::make_unique<ImageManager>();
+ imageManager->setObserver(this);
}
if (updateParameters.mode != MapMode::Continuous) {
@@ -142,6 +144,9 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
const ImageDifference imageDiff = diffImages(imageImpls, updateParameters.images);
imageImpls = updateParameters.images;
+ // Only trigger tile reparse for changed images. Changed images only need a relayout when they have a different size.
+ bool hasImageDiff = !imageDiff.removed.empty();
+
// Remove removed images from sprite atlas.
for (const auto& entry : imageDiff.removed) {
imageManager->removeImage(entry.first);
@@ -154,9 +159,10 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
// Update changed images.
for (const auto& entry : imageDiff.changed) {
- imageManager->updateImage(entry.second.after);
+ hasImageDiff = imageManager->updateImage(entry.second.after) || hasImageDiff;
}
+ imageManager->notifyIfMissingImageAdded();
imageManager->setLoaded(updateParameters.spriteLoaded);
@@ -214,8 +220,6 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
renderSources.emplace(entry.first, std::move(renderSource));
}
- const bool hasImageDiff = !(imageDiff.added.empty() && imageDiff.removed.empty() && imageDiff.changed.empty());
-
// Update all sources.
for (const auto& source : *sourceImpls) {
std::vector<Immutable<Layer::Impl>> filteredLayers;
@@ -262,7 +266,8 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
renderLight.getEvaluated(),
*staticData,
*imageManager,
- *lineAtlas
+ *lineAtlas,
+ placement->getVariableOffsets()
};
bool loaded = updateParameters.styleLoaded && isLoaded();
@@ -278,8 +283,11 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
backend.updateAssumedState();
+ // TODO: remove cast
+ gl::Context& glContext = reinterpret_cast<gl::Context&>(parameters.context);
+
if (parameters.contextMode == GLContextMode::Shared) {
- parameters.context.setDirtyState();
+ glContext.setDirtyState();
}
Color backgroundColor;
@@ -292,6 +300,7 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
};
std::vector<RenderItem> order;
+ std::vector<const RenderLayerSymbolInterface*> renderItemsWithSymbols;
for (auto& layerImpl : *layerImpls) {
RenderLayer* layer = getRenderLayer(layerImpl->id);
@@ -326,6 +335,10 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
layer->setRenderTiles(source->getRenderTiles(), parameters.state);
order.emplace_back(*layer, source);
+
+ if (const RenderLayerSymbolInterface* symbolLayer = layer->getSymbolInterface()) {
+ renderItemsWithSymbols.push_back(symbolLayer);
+ }
}
{
@@ -334,32 +347,28 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
crossTileSymbolIndex.reset();
}
- std::vector<RenderItem> renderItemsWithSymbols;
- std::copy_if(order.rbegin(), order.rend(), std::back_inserter(renderItemsWithSymbols),
- [](const auto& item) { return item.layer.getSymbolInterface() != nullptr; });
-
bool symbolBucketsChanged = false;
const bool placementChanged = !placement->stillRecent(parameters.timePoint);
- std::unique_ptr<Placement> newPlacement;
std::set<std::string> usedSymbolLayers;
if (placementChanged) {
- newPlacement = std::make_unique<Placement>(parameters.state, parameters.mapMode, updateParameters.transitionOptions, updateParameters.crossSourceCollisions);
+ placement = std::make_unique<Placement>(parameters.state, parameters.mapMode, updateParameters.transitionOptions, updateParameters.crossSourceCollisions, std::move(placement));
}
- for (const auto& item : renderItemsWithSymbols) {
- if (crossTileSymbolIndex.addLayer(*item.layer.getSymbolInterface(), parameters.state.getLatLng().longitude())) symbolBucketsChanged = true;
+ for (auto it = renderItemsWithSymbols.rbegin(); it != renderItemsWithSymbols.rend(); ++it) {
+ const RenderLayerSymbolInterface *symbolLayer = *it;
+ if (crossTileSymbolIndex.addLayer(*symbolLayer, parameters.state.getLatLng().longitude())) symbolBucketsChanged = true;
- if (newPlacement) {
- usedSymbolLayers.insert(item.layer.getID());
- newPlacement->placeLayer(*item.layer.getSymbolInterface(), parameters.projMatrix, parameters.debugOptions & MapDebugOptions::Collision);
+ if (placementChanged) {
+ usedSymbolLayers.insert(symbolLayer->layerID());
+ placement->placeLayer(*symbolLayer, parameters.projMatrix, parameters.debugOptions & MapDebugOptions::Collision);
}
}
- if (newPlacement) {
- newPlacement->commit(*placement, parameters.timePoint);
+ if (placementChanged) {
+ placement->commit(parameters.timePoint);
crossTileSymbolIndex.pruneUnusedLayers(usedSymbolLayers);
- placement = std::move(newPlacement);
+ parameters.variableOffsets = placement->getVariableOffsets();
updateFadingTiles();
} else {
placement->setStale();
@@ -368,8 +377,9 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
parameters.symbolFadeChange = placement->symbolFadeChange(parameters.timePoint);
if (placementChanged || symbolBucketsChanged) {
- for (const auto& item : renderItemsWithSymbols) {
- placement->updateLayerOpacities(*item.layer.getSymbolInterface());
+ for (auto it = renderItemsWithSymbols.rbegin(); it != renderItemsWithSymbols.rend(); ++it) {
+ const RenderLayerSymbolInterface *symbolLayer = *it;
+ placement->updateLayerOpacities(*symbolLayer);
}
}
}
@@ -402,7 +412,7 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
if (!parameters.staticData.depthRenderbuffer ||
parameters.staticData.depthRenderbuffer->size != parameters.staticData.backendSize) {
parameters.staticData.depthRenderbuffer =
- parameters.context.createRenderbuffer<gl::RenderbufferType::DepthComponent>(parameters.staticData.backendSize);
+ glContext.createRenderbuffer<gl::RenderbufferType::DepthComponent>(parameters.staticData.backendSize);
}
parameters.staticData.depthRenderbuffer->shouldClear(true);
@@ -425,11 +435,11 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
MBGL_DEBUG_GROUP(parameters.context, "clear");
parameters.backend.bind();
if (parameters.debugOptions & MapDebugOptions::Overdraw) {
- parameters.context.clear(Color::black(), ClearDepth::Default, ClearStencil::Default);
+ glContext.clear(Color::black(), ClearDepth::Default, ClearStencil::Default);
} else if (parameters.contextMode == GLContextMode::Shared) {
- parameters.context.clear({}, ClearDepth::Default, ClearStencil::Default);
+ glContext.clear({}, ClearDepth::Default, ClearStencil::Default);
} else {
- parameters.context.clear(backgroundColor, ClearDepth::Default, ClearStencil::Default);
+ glContext.clear(backgroundColor, ClearDepth::Default, ClearStencil::Default);
}
}
@@ -462,7 +472,7 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
parameters.staticData.tileTriangleSegments,
program.computeAllUniformValues(
ClippingMaskProgram::LayoutUniformValues {
- uniforms::u_matrix::Value( parameters.matrixForTile(clipID.first) ),
+ uniforms::matrix::Value( parameters.matrixForTile(clipID.first) ),
},
paintAttributeData,
properties,
@@ -482,17 +492,17 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
#if not MBGL_USE_GLES2 and not defined(NDEBUG)
// Render tile clip boundaries, using stencil buffer to calculate fill color.
if (parameters.debugOptions & MapDebugOptions::StencilClip) {
- parameters.context.setStencilMode(gfx::StencilMode::disabled());
- parameters.context.setDepthMode(gfx::DepthMode::disabled());
- parameters.context.setColorMode(gfx::ColorMode::unblended());
- parameters.context.program = 0;
+ glContext.setStencilMode(gfx::StencilMode::disabled());
+ glContext.setDepthMode(gfx::DepthMode::disabled());
+ glContext.setColorMode(gfx::ColorMode::unblended());
+ glContext.program = 0;
// Reset the value in case someone else changed it, or it's dirty.
- parameters.context.pixelTransferStencil = gl::value::PixelTransferStencil::Default;
+ glContext.pixelTransferStencil = gl::value::PixelTransferStencil::Default;
// Read the stencil buffer
- const auto viewport = parameters.context.viewport.getCurrentValue();
- auto image = parameters.context.readFramebuffer<AlphaImage, gfx::TexturePixelType::Stencil>(viewport.size, false);
+ const auto viewport = glContext.viewport.getCurrentValue();
+ auto image = glContext.readFramebuffer<AlphaImage, gfx::TexturePixelType::Stencil>(viewport.size, false);
// Scale the Stencil buffer to cover the entire color space.
auto it = image.data.get();
@@ -502,9 +512,9 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
*it *= factor;
}
- parameters.context.pixelZoom = { 1, 1 };
- parameters.context.rasterPos = { -1, -1, 0, 1 };
- parameters.context.drawPixels(image);
+ glContext.pixelZoom = { 1, 1 };
+ glContext.rasterPos = { -1, -1, 0, 1 };
+ glContext.drawPixels(image);
return;
}
@@ -565,39 +575,26 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
#if not MBGL_USE_GLES2 and not defined(NDEBUG)
// Render the depth buffer.
if (parameters.debugOptions & MapDebugOptions::DepthBuffer) {
- parameters.context.setStencilMode(gfx::StencilMode::disabled());
- parameters.context.setDepthMode(gfx::DepthMode::disabled());
- parameters.context.setColorMode(gfx::ColorMode::unblended());
- parameters.context.program = 0;
+ glContext.setStencilMode(gfx::StencilMode::disabled());
+ glContext.setDepthMode(gfx::DepthMode::disabled());
+ glContext.setColorMode(gfx::ColorMode::unblended());
+ glContext.program = 0;
// Scales the values in the depth buffer so that they cover the entire grayscale range. This
// makes it easier to spot tiny differences.
const float base = 1.0f / (1.0f - parameters.depthRangeSize);
- parameters.context.pixelTransferDepth = { base, 1.0f - base };
+ glContext.pixelTransferDepth = { base, 1.0f - base };
// Read the stencil buffer
- auto viewport = parameters.context.viewport.getCurrentValue();
- auto image = parameters.context.readFramebuffer<AlphaImage, gfx::TexturePixelType::Depth>(viewport.size, false);
+ auto viewport = glContext.viewport.getCurrentValue();
+ auto image = glContext.readFramebuffer<AlphaImage, gfx::TexturePixelType::Depth>(viewport.size, false);
- parameters.context.pixelZoom = { 1, 1 };
- parameters.context.rasterPos = { -1, -1, 0, 1 };
- parameters.context.drawPixels(image);
+ glContext.pixelZoom = { 1, 1 };
+ glContext.rasterPos = { -1, -1, 0, 1 };
+ glContext.drawPixels(image);
}
#endif
- // TODO: Find a better way to unbind VAOs after we're done with them without introducing
- // unnecessary bind(0)/bind(N) sequences.
- {
- MBGL_DEBUG_GROUP(parameters.context, "cleanup");
-
- parameters.context.activeTextureUnit = 1;
- parameters.context.texture[1] = 0;
- parameters.context.activeTextureUnit = 0;
- parameters.context.texture[0] = 0;
-
- parameters.context.bindVertexArray = 0;
- }
-
observer->onDidFinishRenderingFrame(
loaded ? RendererObserver::RenderMode::Full : RendererObserver::RenderMode::Partial,
updateParameters.mode == MapMode::Continuous && hasTransitions(parameters.timePoint)
@@ -614,6 +611,12 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
parameters.context.performCleanup();
}
+void Renderer::Impl::flush() {
+ assert(BackendScope::exists());
+
+ backend.getContext().flush();
+}
+
std::vector<Feature> Renderer::Impl::queryRenderedFeatures(const ScreenLineString& geometry, const RenderedQueryOptions& options) const {
std::vector<const RenderLayer*> layers;
if (options.layerIDs) {
@@ -837,4 +840,8 @@ void Renderer::Impl::onTileChanged(RenderSource&, const OverscaledTileID&) {
observer->onInvalidate();
}
+void Renderer::Impl::onStyleImageMissing(const std::string& id, std::function<void()> done) {
+ observer->onStyleImageMissing(id, std::move(done));
+}
+
} // namespace mbgl
diff --git a/src/mbgl/renderer/renderer_impl.hpp b/src/mbgl/renderer/renderer_impl.hpp
index 05bf2e9b2b..624b4c273c 100644
--- a/src/mbgl/renderer/renderer_impl.hpp
+++ b/src/mbgl/renderer/renderer_impl.hpp
@@ -11,6 +11,7 @@
#include <mbgl/map/zoom_history.hpp>
#include <mbgl/text/cross_tile_symbol_index.hpp>
#include <mbgl/text/glyph_manager_observer.hpp>
+#include <mbgl/renderer/image_manager_observer.hpp>
#include <mbgl/text/placement.hpp>
#include <memory>
@@ -34,6 +35,7 @@ class LineAtlas;
class CrossTileSymbolIndex;
class Renderer::Impl : public GlyphManagerObserver,
+ public ImageManagerObserver,
public RenderSourceObserver{
public:
Impl(RendererBackend&, float pixelRatio_, Scheduler&, GLContextMode,
@@ -48,6 +50,8 @@ public:
void render(const UpdateParameters&);
+ void flush();
+
std::vector<Feature> queryRenderedFeatures(const ScreenLineString&, const RenderedQueryOptions&) const;
std::vector<Feature> querySourceFeatures(const std::string& sourceID, const SourceQueryOptions&) const;
std::vector<Feature> queryShapeAnnotations(const ScreenLineString&) const;
@@ -84,6 +88,9 @@ private:
void onTileChanged(RenderSource&, const OverscaledTileID&) override;
void onTileError(RenderSource&, const OverscaledTileID&, std::exception_ptr) override;
+ // ImageManagerObserver implementation
+ void onStyleImageMissing(const std::string&, std::function<void()>) override;
+
void updateFadingTiles();
friend class Renderer;
diff --git a/src/mbgl/renderer/sources/render_image_source.cpp b/src/mbgl/renderer/sources/render_image_source.cpp
index 1b135a2838..dee3eab750 100644
--- a/src/mbgl/renderer/sources/render_image_source.cpp
+++ b/src/mbgl/renderer/sources/render_image_source.cpp
@@ -7,7 +7,7 @@
#include <mbgl/renderer/tile_parameters.hpp>
#include <mbgl/renderer/render_static_data.hpp>
#include <mbgl/programs/programs.hpp>
-#include <mbgl/gl/context.hpp>
+#include <mbgl/gfx/cull_face_mode.hpp>
#include <mbgl/util/tile_coordinate.hpp>
#include <mbgl/util/tile_cover.hpp>
#include <mbgl/util/logging.hpp>
@@ -73,8 +73,8 @@ void RenderImageSource::finishRender(PaintParameters& parameters) {
parameters.staticData.tileBorderSegments,
programInstance.computeAllUniformValues(
DebugProgram::LayoutUniformValues {
- uniforms::u_matrix::Value( matrix ),
- uniforms::u_color::Value( Color::red() )
+ uniforms::matrix::Value( matrix ),
+ uniforms::color::Value( Color::red() )
},
paintAttributeData,
properties,
diff --git a/src/mbgl/storage/asset_file_source.hpp b/src/mbgl/storage/asset_file_source.hpp
index 5d98b4e69e..cc15dbb60b 100644
--- a/src/mbgl/storage/asset_file_source.hpp
+++ b/src/mbgl/storage/asset_file_source.hpp
@@ -10,7 +10,7 @@ template <typename T> class Thread;
class AssetFileSource : public FileSource {
public:
- AssetFileSource(const std::string& assetRoot);
+ AssetFileSource(const std::string& assetPath);
~AssetFileSource() override;
std::unique_ptr<AsyncRequest> request(const Resource&, Callback) override;
diff --git a/src/mbgl/storage/file_source.cpp b/src/mbgl/storage/file_source.cpp
new file mode 100644
index 0000000000..5854682771
--- /dev/null
+++ b/src/mbgl/storage/file_source.cpp
@@ -0,0 +1,37 @@
+#include <mbgl/storage/file_source.hpp>
+#include <mbgl/storage/resource_options.hpp>
+#include <mbgl/util/string.hpp>
+
+#include <mutex>
+#include <map>
+
+namespace mbgl {
+
+std::shared_ptr<FileSource> FileSource::getSharedFileSource(const ResourceOptions& options) {
+ static std::mutex mutex;
+ static std::map<std::string, std::weak_ptr<mbgl::FileSource>> fileSources;
+
+ std::lock_guard<std::mutex> lock(mutex);
+
+ // Purge entries no longer in use.
+ for (auto it = fileSources.begin(); it != fileSources.end();) {
+ it = it->second.expired() ? fileSources.erase(it) : ++it;
+ }
+
+ const uint64_t context = reinterpret_cast<uint64_t>(options.platformContext());
+ const std::string key = options.baseURL() + '|' + options.accessToken() + '|' + options.cachePath() + '|' + util::toString(context);
+
+ std::shared_ptr<mbgl::FileSource> fileSource;
+ auto tuple = fileSources.find(key);
+ if (tuple != fileSources.end()) {
+ fileSource = tuple->second.lock();
+ }
+
+ if (!fileSource) {
+ fileSources[key] = fileSource = createPlatformFileSource(options);
+ }
+
+ return fileSource;
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/storage/resource_options.cpp b/src/mbgl/storage/resource_options.cpp
new file mode 100644
index 0000000000..c56a22540b
--- /dev/null
+++ b/src/mbgl/storage/resource_options.cpp
@@ -0,0 +1,80 @@
+#include <mbgl/storage/resource_options.hpp>
+#include <mbgl/util/constants.hpp>
+
+namespace mbgl {
+
+class ResourceOptions::Impl {
+public:
+ std::string accessToken;
+ std::string baseURL = mbgl::util::API_BASE_URL;
+ std::string cachePath = ":memory:";
+ std::string assetPath = ".";
+ uint64_t maximumSize = mbgl::util::DEFAULT_MAX_CACHE_SIZE;
+ void* platformContext = nullptr;
+};
+
+// These requires the complete type of Impl.
+ResourceOptions::ResourceOptions() : impl_(std::make_unique<Impl>()) {}
+ResourceOptions::~ResourceOptions() = default;
+ResourceOptions::ResourceOptions(ResourceOptions&&) noexcept = default;
+ResourceOptions::ResourceOptions(const ResourceOptions& other) : impl_(std::make_unique<Impl>(*other.impl_)) {}
+
+ResourceOptions ResourceOptions::clone() const {
+ return ResourceOptions(*this);
+}
+
+ResourceOptions& ResourceOptions::withAccessToken(std::string token) {
+ impl_->accessToken = std::move(token);
+ return *this;
+}
+
+const std::string& ResourceOptions::accessToken() const {
+ return impl_->accessToken;
+}
+
+ResourceOptions& ResourceOptions::withBaseURL(std::string url) {
+ impl_->baseURL = std::move(url);
+ return *this;
+}
+
+const std::string& ResourceOptions::baseURL() const {
+ return impl_->baseURL;
+}
+
+ResourceOptions& ResourceOptions::withCachePath(std::string path) {
+ impl_->cachePath = std::move(path);
+ return *this;
+}
+
+const std::string& ResourceOptions::cachePath() const {
+ return impl_->cachePath;
+}
+
+ResourceOptions& ResourceOptions::withAssetPath(std::string path) {
+ impl_->assetPath = std::move(path);
+ return *this;
+}
+
+const std::string& ResourceOptions::assetPath() const {
+ return impl_->assetPath;
+}
+
+ResourceOptions& ResourceOptions::withMaximumCacheSize(uint64_t size) {
+ impl_->maximumSize = size;
+ return *this;
+}
+
+uint64_t ResourceOptions::maximumCacheSize() const {
+ return impl_->maximumSize;
+}
+
+ResourceOptions& ResourceOptions::withPlatformContext(void* context) {
+ impl_->platformContext = context;
+ return *this;
+}
+
+void* ResourceOptions::platformContext() const {
+ return impl_->platformContext;
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/style/conversion/constant.cpp b/src/mbgl/style/conversion/constant.cpp
index bdc6371722..0fcaab433b 100644
--- a/src/mbgl/style/conversion/constant.cpp
+++ b/src/mbgl/style/conversion/constant.cpp
@@ -49,6 +49,27 @@ optional<T> Converter<T, typename std::enable_if_t<std::is_enum<T>::value>>::ope
return *result;
}
+template <class T>
+auto Converter<std::vector<T>, typename std::enable_if_t<std::is_enum<T>::value>>::operator()(const Convertible& value, Error& error) const -> optional<std::vector<T>> {
+ if (!isArray(value)) {
+ error.message = "value must be an array";
+ return nullopt;
+ }
+
+ std::vector<T> result;
+ result.reserve(arrayLength(value));
+
+ for (std::size_t i = 0; i < arrayLength(value); ++i) {
+ optional<T> enumItem = Converter<T>{}(arrayMember(value, i), error);
+ if (!enumItem) {
+ return nullopt;
+ }
+ result.push_back(*enumItem);
+ }
+
+ return result;
+}
+
template optional<AlignmentType> Converter<AlignmentType>::operator()(const Convertible&, Error&) const;
template optional<CirclePitchScaleType> Converter<CirclePitchScaleType>::operator()(const Convertible&, Error&) const;
template optional<HillshadeIlluminationAnchorType> Converter<HillshadeIlluminationAnchorType>::operator()(const Convertible&, Error&) const;
@@ -64,6 +85,7 @@ template optional<TextJustifyType> Converter<TextJustifyType>::operator()(const
template optional<TextTransformType> Converter<TextTransformType>::operator()(const Convertible&, Error&) const;
template optional<TranslateAnchorType> Converter<TranslateAnchorType>::operator()(const Convertible&, Error&) const;
template optional<VisibilityType> Converter<VisibilityType>::operator()(const Convertible&, Error&) const;
+template optional<std::vector<TextVariableAnchorType>> Converter<std::vector<TextVariableAnchorType>>::operator()(const Convertible&, Error&) const;
optional<Color> Converter<Color>::operator()(const Convertible& value, Error& error) const {
optional<std::string> string = toString(value);
diff --git a/src/mbgl/style/conversion/function.cpp b/src/mbgl/style/conversion/function.cpp
index 79ad2fc7d8..df4decc73e 100644
--- a/src/mbgl/style/conversion/function.cpp
+++ b/src/mbgl/style/conversion/function.cpp
@@ -136,6 +136,8 @@ template optional<PropertyExpression<std::vector<std::string>>>
convertFunctionToExpression<std::vector<std::string>>(const Convertible&, Error&, bool);
template optional<PropertyExpression<SymbolAnchorType>>
convertFunctionToExpression<SymbolAnchorType>(const Convertible&, Error&, bool);
+template optional<PropertyExpression<std::vector<TextVariableAnchorType>>>
+ convertFunctionToExpression<std::vector<TextVariableAnchorType>>(const Convertible&, Error&, bool);
template optional<PropertyExpression<SymbolPlacementType>>
convertFunctionToExpression<SymbolPlacementType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<SymbolZOrderType>>
diff --git a/src/mbgl/style/conversion/property_value.cpp b/src/mbgl/style/conversion/property_value.cpp
index ff038908b6..6e1d747324 100644
--- a/src/mbgl/style/conversion/property_value.cpp
+++ b/src/mbgl/style/conversion/property_value.cpp
@@ -73,6 +73,7 @@ template optional<PropertyValue<LineJoinType>> Converter<PropertyValue<LineJoinT
template optional<PropertyValue<Position>> Converter<PropertyValue<Position>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<RasterResamplingType>> Converter<PropertyValue<RasterResamplingType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<SymbolAnchorType>> Converter<PropertyValue<SymbolAnchorType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
+template optional<PropertyValue<std::vector<TextVariableAnchorType>>> Converter<PropertyValue<std::vector<TextVariableAnchorType>>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<SymbolPlacementType>> Converter<PropertyValue<SymbolPlacementType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<SymbolZOrderType>> Converter<PropertyValue<SymbolZOrderType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<TextJustifyType>> Converter<PropertyValue<TextJustifyType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
diff --git a/src/mbgl/style/expression/value.cpp b/src/mbgl/style/expression/value.cpp
index 436ed83ecd..e826a8a3cc 100644
--- a/src/mbgl/style/expression/value.cpp
+++ b/src/mbgl/style/expression/value.cpp
@@ -166,6 +166,11 @@ mbgl::Value ValueConverter<mbgl::Value>::fromExpressionValue(const Value& value)
}
options.emplace("text-font", std::vector<mbgl::Value>{ std::string("literal"), fontStack });
}
+
+ if (section.textColor) {
+ options.emplace("text-color", fromExpressionValue(*section.textColor));
+ }
+
serialized.push_back(options);
}
return serialized;
@@ -324,6 +329,9 @@ template struct ValueConverter<std::vector<float>>;
template type::Type valueTypeToExpressionType<std::vector<std::string>>();
template struct ValueConverter<std::vector<std::string>>;
+template type::Type valueTypeToExpressionType<std::vector<TextVariableAnchorType>>();
+template struct ValueConverter<std::vector<TextVariableAnchorType>>;
+
template type::Type valueTypeToExpressionType<AlignmentType>();
template struct ValueConverter<AlignmentType>;
diff --git a/src/mbgl/style/image_impl.hpp b/src/mbgl/style/image_impl.hpp
index 54b5e6487b..b2decbf781 100644
--- a/src/mbgl/style/image_impl.hpp
+++ b/src/mbgl/style/image_impl.hpp
@@ -34,5 +34,6 @@ enum class ImageType : bool {
using ImageMap = std::unordered_map<std::string, Immutable<style::Image::Impl>>;
using ImageDependencies = std::unordered_map<std::string, ImageType>;
using ImageRequestPair = std::pair<ImageDependencies, uint64_t>;
+using ImageVersionMap = std::unordered_map<std::string, uint32_t>;
} // namespace mbgl
diff --git a/src/mbgl/style/layers/circle_layer_properties.hpp b/src/mbgl/style/layers/circle_layer_properties.hpp
index bc0c961e75..57caba9e3a 100644
--- a/src/mbgl/style/layers/circle_layer_properties.hpp
+++ b/src/mbgl/style/layers/circle_layer_properties.hpp
@@ -12,19 +12,19 @@
namespace mbgl {
namespace style {
-struct CircleRadius : DataDrivenPaintProperty<float, attributes::a_radius, uniforms::u_radius> {
+struct CircleRadius : DataDrivenPaintProperty<float, attributes::radius, uniforms::radius> {
static float defaultValue() { return 5; }
};
-struct CircleColor : DataDrivenPaintProperty<Color, attributes::a_color, uniforms::u_color> {
+struct CircleColor : DataDrivenPaintProperty<Color, attributes::color, uniforms::color> {
static Color defaultValue() { return Color::black(); }
};
-struct CircleBlur : DataDrivenPaintProperty<float, attributes::a_blur, uniforms::u_blur> {
+struct CircleBlur : DataDrivenPaintProperty<float, attributes::blur, uniforms::blur> {
static float defaultValue() { return 0; }
};
-struct CircleOpacity : DataDrivenPaintProperty<float, attributes::a_opacity, uniforms::u_opacity> {
+struct CircleOpacity : DataDrivenPaintProperty<float, attributes::opacity, uniforms::opacity> {
static float defaultValue() { return 1; }
};
@@ -44,15 +44,15 @@ struct CirclePitchAlignment : PaintProperty<AlignmentType> {
static AlignmentType defaultValue() { return AlignmentType::Viewport; }
};
-struct CircleStrokeWidth : DataDrivenPaintProperty<float, attributes::a_stroke_width, uniforms::u_stroke_width> {
+struct CircleStrokeWidth : DataDrivenPaintProperty<float, attributes::stroke_width, uniforms::stroke_width> {
static float defaultValue() { return 0; }
};
-struct CircleStrokeColor : DataDrivenPaintProperty<Color, attributes::a_stroke_color, uniforms::u_stroke_color> {
+struct CircleStrokeColor : DataDrivenPaintProperty<Color, attributes::stroke_color, uniforms::stroke_color> {
static Color defaultValue() { return Color::black(); }
};
-struct CircleStrokeOpacity : DataDrivenPaintProperty<float, attributes::a_stroke_opacity, uniforms::u_stroke_opacity> {
+struct CircleStrokeOpacity : DataDrivenPaintProperty<float, attributes::stroke_opacity, uniforms::stroke_opacity> {
static float defaultValue() { return 1; }
};
diff --git a/src/mbgl/style/layers/fill_extrusion_layer_properties.hpp b/src/mbgl/style/layers/fill_extrusion_layer_properties.hpp
index 20cba699fe..a7799eee22 100644
--- a/src/mbgl/style/layers/fill_extrusion_layer_properties.hpp
+++ b/src/mbgl/style/layers/fill_extrusion_layer_properties.hpp
@@ -16,7 +16,7 @@ struct FillExtrusionOpacity : PaintProperty<float> {
static float defaultValue() { return 1; }
};
-struct FillExtrusionColor : DataDrivenPaintProperty<Color, attributes::a_color, uniforms::u_color> {
+struct FillExtrusionColor : DataDrivenPaintProperty<Color, attributes::color, uniforms::color> {
static Color defaultValue() { return Color::black(); }
};
@@ -28,15 +28,15 @@ struct FillExtrusionTranslateAnchor : PaintProperty<TranslateAnchorType> {
static TranslateAnchorType defaultValue() { return TranslateAnchorType::Map; }
};
-struct FillExtrusionPattern : CrossFadedDataDrivenPaintProperty<std::string, attributes::a_pattern_to, uniforms::u_pattern_to, attributes::a_pattern_from, uniforms::u_pattern_from> {
+struct FillExtrusionPattern : CrossFadedDataDrivenPaintProperty<std::string, attributes::pattern_to, uniforms::pattern_to, attributes::pattern_from, uniforms::pattern_from> {
static std::string defaultValue() { return ""; }
};
-struct FillExtrusionHeight : DataDrivenPaintProperty<float, attributes::a_height, uniforms::u_height> {
+struct FillExtrusionHeight : DataDrivenPaintProperty<float, attributes::height, uniforms::height> {
static float defaultValue() { return 0; }
};
-struct FillExtrusionBase : DataDrivenPaintProperty<float, attributes::a_base, uniforms::u_base> {
+struct FillExtrusionBase : DataDrivenPaintProperty<float, attributes::base, uniforms::base> {
static float defaultValue() { return 0; }
};
diff --git a/src/mbgl/style/layers/fill_layer_properties.hpp b/src/mbgl/style/layers/fill_layer_properties.hpp
index a20089ff2e..942733f2e1 100644
--- a/src/mbgl/style/layers/fill_layer_properties.hpp
+++ b/src/mbgl/style/layers/fill_layer_properties.hpp
@@ -16,15 +16,15 @@ struct FillAntialias : PaintProperty<bool> {
static bool defaultValue() { return true; }
};
-struct FillOpacity : DataDrivenPaintProperty<float, attributes::a_opacity, uniforms::u_opacity> {
+struct FillOpacity : DataDrivenPaintProperty<float, attributes::opacity, uniforms::opacity> {
static float defaultValue() { return 1; }
};
-struct FillColor : DataDrivenPaintProperty<Color, attributes::a_color, uniforms::u_color> {
+struct FillColor : DataDrivenPaintProperty<Color, attributes::color, uniforms::color> {
static Color defaultValue() { return Color::black(); }
};
-struct FillOutlineColor : DataDrivenPaintProperty<Color, attributes::a_outline_color, uniforms::u_outline_color> {
+struct FillOutlineColor : DataDrivenPaintProperty<Color, attributes::outline_color, uniforms::outline_color> {
static Color defaultValue() { return {}; }
};
@@ -36,7 +36,7 @@ struct FillTranslateAnchor : PaintProperty<TranslateAnchorType> {
static TranslateAnchorType defaultValue() { return TranslateAnchorType::Map; }
};
-struct FillPattern : CrossFadedDataDrivenPaintProperty<std::string, attributes::a_pattern_to, uniforms::u_pattern_to, attributes::a_pattern_from, uniforms::u_pattern_from> {
+struct FillPattern : CrossFadedDataDrivenPaintProperty<std::string, attributes::pattern_to, uniforms::pattern_to, attributes::pattern_from, uniforms::pattern_from> {
static std::string defaultValue() { return ""; }
};
diff --git a/src/mbgl/style/layers/heatmap_layer_properties.hpp b/src/mbgl/style/layers/heatmap_layer_properties.hpp
index 4d49a52c72..ce00217b2e 100644
--- a/src/mbgl/style/layers/heatmap_layer_properties.hpp
+++ b/src/mbgl/style/layers/heatmap_layer_properties.hpp
@@ -12,11 +12,11 @@
namespace mbgl {
namespace style {
-struct HeatmapRadius : DataDrivenPaintProperty<float, attributes::a_radius, uniforms::u_radius> {
+struct HeatmapRadius : DataDrivenPaintProperty<float, attributes::radius, uniforms::radius> {
static float defaultValue() { return 30; }
};
-struct HeatmapWeight : DataDrivenPaintProperty<float, attributes::a_weight, uniforms::u_weight> {
+struct HeatmapWeight : DataDrivenPaintProperty<float, attributes::weight, uniforms::weight> {
static float defaultValue() { return 1; }
};
diff --git a/src/mbgl/style/layers/layer.cpp.ejs b/src/mbgl/style/layers/layer.cpp.ejs
index fcae615fe0..201189c849 100644
--- a/src/mbgl/style/layers/layer.cpp.ejs
+++ b/src/mbgl/style/layers/layer.cpp.ejs
@@ -153,6 +153,9 @@ void <%- camelize(type) %>Layer::set<%- camelize(property.name) %>(<%- propertyV
return;
auto impl_ = mutableImpl();
impl_->paint.template get<<%- camelize(property.name) %>>().value = value;
+<% if (property.name === 'line-width') { -%>
+ impl_->paint.template get<LineFloorWidth>().value = value;
+<% } -%>
baseImpl = std::move(impl_);
observer->onLayerChanged(*this);
}
diff --git a/src/mbgl/style/layers/layer_properties.hpp.ejs b/src/mbgl/style/layers/layer_properties.hpp.ejs
index 89dffdcd42..de647fbc07 100644
--- a/src/mbgl/style/layers/layer_properties.hpp.ejs
+++ b/src/mbgl/style/layers/layer_properties.hpp.ejs
@@ -37,6 +37,13 @@ struct <%- camelize(property.name) %> : <%- paintPropertyType(property, type) %>
template<typename T> static bool hasOverride(const T& t) { return !!t.<%- camelizeWithLeadingLowercase(property.name) %>; };
<% } -%>
};
+<% if (property.name === 'line-width') { -%>
+
+struct LineFloorWidth : DataDrivenPaintProperty<float, attributes::floorwidth, uniforms::floorwidth> {
+ using EvaluatorType = DataDrivenPropertyEvaluator<float, true>;
+ static float defaultValue() { return 1.0f; }
+};
+<% } -%>
<% } -%>
<% } -%>
@@ -52,6 +59,9 @@ class <%- camelize(type) %>LayoutProperties : public Properties<
class <%- camelize(type) %>PaintProperties : public Properties<
<% for (const property of paintProperties.slice(0, -1)) { -%>
<%- camelize(property.name) %>,
+<% if (property.name === 'line-width') { -%>
+ LineFloorWidth,
+<% } -%>
<% } -%>
<%- camelize(paintProperties.slice(-1)[0].name) %>
> {};
diff --git a/src/mbgl/style/layers/line_layer.cpp b/src/mbgl/style/layers/line_layer.cpp
index 643c294edf..0a20762697 100644
--- a/src/mbgl/style/layers/line_layer.cpp
+++ b/src/mbgl/style/layers/line_layer.cpp
@@ -248,6 +248,7 @@ void LineLayer::setLineWidth(PropertyValue<float> value) {
return;
auto impl_ = mutableImpl();
impl_->paint.template get<LineWidth>().value = value;
+ impl_->paint.template get<LineFloorWidth>().value = value;
baseImpl = std::move(impl_);
observer->onLayerChanged(*this);
}
diff --git a/src/mbgl/style/layers/line_layer_properties.hpp b/src/mbgl/style/layers/line_layer_properties.hpp
index bab6e77ce5..33d7eddbe8 100644
--- a/src/mbgl/style/layers/line_layer_properties.hpp
+++ b/src/mbgl/style/layers/line_layer_properties.hpp
@@ -32,11 +32,11 @@ struct LineRoundLimit : LayoutProperty<float> {
static float defaultValue() { return 1; }
};
-struct LineOpacity : DataDrivenPaintProperty<float, attributes::a_opacity, uniforms::u_opacity> {
+struct LineOpacity : DataDrivenPaintProperty<float, attributes::opacity, uniforms::opacity> {
static float defaultValue() { return 1; }
};
-struct LineColor : DataDrivenPaintProperty<Color, attributes::a_color, uniforms::u_color> {
+struct LineColor : DataDrivenPaintProperty<Color, attributes::color, uniforms::color> {
static Color defaultValue() { return Color::black(); }
};
@@ -48,19 +48,24 @@ struct LineTranslateAnchor : PaintProperty<TranslateAnchorType> {
static TranslateAnchorType defaultValue() { return TranslateAnchorType::Map; }
};
-struct LineWidth : DataDrivenPaintProperty<float, attributes::a_width, uniforms::u_width> {
+struct LineWidth : DataDrivenPaintProperty<float, attributes::width, uniforms::width> {
static float defaultValue() { return 1; }
};
-struct LineGapWidth : DataDrivenPaintProperty<float, attributes::a_gapwidth, uniforms::u_gapwidth> {
+struct LineFloorWidth : DataDrivenPaintProperty<float, attributes::floorwidth, uniforms::floorwidth> {
+ using EvaluatorType = DataDrivenPropertyEvaluator<float, true>;
+ static float defaultValue() { return 1.0f; }
+};
+
+struct LineGapWidth : DataDrivenPaintProperty<float, attributes::gapwidth, uniforms::gapwidth> {
static float defaultValue() { return 0; }
};
-struct LineOffset : DataDrivenPaintProperty<float, attributes::a_offset, uniforms::u_offset> {
+struct LineOffset : DataDrivenPaintProperty<float, attributes::offset, uniforms::offset> {
static float defaultValue() { return 0; }
};
-struct LineBlur : DataDrivenPaintProperty<float, attributes::a_blur, uniforms::u_blur> {
+struct LineBlur : DataDrivenPaintProperty<float, attributes::blur, uniforms::blur> {
static float defaultValue() { return 0; }
};
@@ -68,7 +73,7 @@ struct LineDasharray : CrossFadedPaintProperty<std::vector<float>> {
static std::vector<float> defaultValue() { return { }; }
};
-struct LinePattern : CrossFadedDataDrivenPaintProperty<std::string, attributes::a_pattern_to, uniforms::u_pattern_to, attributes::a_pattern_from, uniforms::u_pattern_from> {
+struct LinePattern : CrossFadedDataDrivenPaintProperty<std::string, attributes::pattern_to, uniforms::pattern_to, attributes::pattern_from, uniforms::pattern_from> {
static std::string defaultValue() { return ""; }
};
@@ -88,6 +93,7 @@ class LinePaintProperties : public Properties<
LineTranslate,
LineTranslateAnchor,
LineWidth,
+ LineFloorWidth,
LineGapWidth,
LineOffset,
LineBlur,
diff --git a/src/mbgl/style/layers/symbol_layer.cpp b/src/mbgl/style/layers/symbol_layer.cpp
index 75ed881058..1c56888f73 100644
--- a/src/mbgl/style/layers/symbol_layer.cpp
+++ b/src/mbgl/style/layers/symbol_layer.cpp
@@ -492,6 +492,38 @@ void SymbolLayer::setTextJustify(PropertyValue<TextJustifyType> value) {
baseImpl = std::move(impl_);
observer->onLayerChanged(*this);
}
+PropertyValue<float> SymbolLayer::getDefaultTextRadialOffset() {
+ return TextRadialOffset::defaultValue();
+}
+
+PropertyValue<float> SymbolLayer::getTextRadialOffset() const {
+ return impl().layout.get<TextRadialOffset>();
+}
+
+void SymbolLayer::setTextRadialOffset(PropertyValue<float> value) {
+ if (value == getTextRadialOffset())
+ return;
+ auto impl_ = mutableImpl();
+ impl_->layout.get<TextRadialOffset>() = value;
+ baseImpl = std::move(impl_);
+ observer->onLayerChanged(*this);
+}
+PropertyValue<std::vector<TextVariableAnchorType>> SymbolLayer::getDefaultTextVariableAnchor() {
+ return TextVariableAnchor::defaultValue();
+}
+
+PropertyValue<std::vector<TextVariableAnchorType>> SymbolLayer::getTextVariableAnchor() const {
+ return impl().layout.get<TextVariableAnchor>();
+}
+
+void SymbolLayer::setTextVariableAnchor(PropertyValue<std::vector<TextVariableAnchorType>> value) {
+ if (value == getTextVariableAnchor())
+ return;
+ auto impl_ = mutableImpl();
+ impl_->layout.get<TextVariableAnchor>() = value;
+ baseImpl = std::move(impl_);
+ observer->onLayerChanged(*this);
+}
PropertyValue<SymbolAnchorType> SymbolLayer::getDefaultTextAnchor() {
return TextAnchor::defaultValue();
}
@@ -1325,6 +1357,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
TextLineHeight,
TextLetterSpacing,
TextJustify,
+ TextRadialOffset,
+ TextVariableAnchor,
TextAnchor,
TextMaxAngle,
TextRotate,
@@ -1364,6 +1398,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
{ "text-line-height", static_cast<uint8_t>(Property::TextLineHeight) },
{ "text-letter-spacing", static_cast<uint8_t>(Property::TextLetterSpacing) },
{ "text-justify", static_cast<uint8_t>(Property::TextJustify) },
+ { "text-radial-offset", static_cast<uint8_t>(Property::TextRadialOffset) },
+ { "text-variable-anchor", static_cast<uint8_t>(Property::TextVariableAnchor) },
{ "text-anchor", static_cast<uint8_t>(Property::TextAnchor) },
{ "text-max-angle", static_cast<uint8_t>(Property::TextMaxAngle) },
{ "text-rotate", static_cast<uint8_t>(Property::TextRotate) },
@@ -1525,7 +1561,7 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
}
- if (property == Property::IconSize || property == Property::IconRotate || property == Property::TextSize || property == Property::TextMaxWidth || property == Property::TextLetterSpacing || property == Property::TextRotate) {
+ if (property == Property::IconSize || property == Property::IconRotate || property == Property::TextSize || property == Property::TextMaxWidth || property == Property::TextLetterSpacing || property == Property::TextRadialOffset || property == Property::TextRotate) {
Error error;
optional<PropertyValue<float>> typedValue = convert<PropertyValue<float>>(value, error, true, false);
if (!typedValue) {
@@ -1557,6 +1593,11 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
return nullopt;
}
+ if (property == Property::TextRadialOffset) {
+ setTextRadialOffset(*typedValue);
+ return nullopt;
+ }
+
if (property == Property::TextRotate) {
setTextRotate(*typedValue);
return nullopt;
@@ -1674,6 +1715,18 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
}
+ if (property == Property::TextVariableAnchor) {
+ Error error;
+ optional<PropertyValue<std::vector<TextVariableAnchorType>>> typedValue = convert<PropertyValue<std::vector<TextVariableAnchorType>>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setTextVariableAnchor(*typedValue);
+ return nullopt;
+
+ }
+
if (property == Property::TextTransform) {
Error error;
optional<PropertyValue<TextTransformType>> typedValue = convert<PropertyValue<TextTransformType>>(value, error, true, false);
diff --git a/src/mbgl/style/layers/symbol_layer_impl.hpp b/src/mbgl/style/layers/symbol_layer_impl.hpp
index f937fccaa8..9b63e0e8d6 100644
--- a/src/mbgl/style/layers/symbol_layer_impl.hpp
+++ b/src/mbgl/style/layers/symbol_layer_impl.hpp
@@ -3,9 +3,11 @@
#include <mbgl/style/layer_impl.hpp>
#include <mbgl/style/layers/symbol_layer.hpp>
#include <mbgl/style/layers/symbol_layer_properties.hpp>
+#include <mbgl/style/expression/literal.hpp>
#include <mbgl/style/expression/format_expression.hpp>
#include <mbgl/style/expression/formatted.hpp>
#include <mbgl/style/expression/format_section_override.hpp>
+#include <mbgl/style/expression/value.hpp>
namespace mbgl {
namespace style {
@@ -56,25 +58,57 @@ struct FormatSectionOverrides<TypeList<PaintProperty...>> {
template<typename Property, typename FormattedProperty>
static bool hasOverride(const FormattedProperty& formatted) {
+
+ const auto checkLiteral = [] (const TextField::Type& literal) {
+ for (const auto& section : literal.sections) {
+ if (Property::hasOverride(section)) {
+ return true;
+ }
+ }
+ return false;
+ };
+
return formatted.match(
- [] (const TextField::Type& t) {
- for (const auto& section : t.sections) {
- if (Property::hasOverride(section)) {
- return true;
- }
- }
- return false;
+ [&checkLiteral] (const TextField::Type& literal) {
+ return checkLiteral(literal);
},
- [] (const PropertyExpression<TextField::Type>& t) {
- if (t.getExpression().getKind() == expression::Kind::FormatExpression) {
- const auto* e = static_cast<const expression::FormatExpression*>(&t.getExpression());
- for (const auto& section : e->getSections()) {
- if (Property::hasOverride(section)) {
- return true;
+ [&checkLiteral] (const PropertyExpression<TextField::Type>& property) {
+ bool expressionHasOverrides = false;
+ const auto checkExpression = [&](const expression::Expression& e) {
+ if (expressionHasOverrides) {
+ return;
+ }
+
+ if (e.getKind() == expression::Kind::Literal &&
+ e.getType() == expression::type::Formatted) {
+ const auto* literalExpr = static_cast<const expression::Literal*>(&e);
+ const auto formattedValue = expression::fromExpressionValue<expression::Formatted>(literalExpr->getValue());
+ if (formattedValue && checkLiteral(*formattedValue)) {
+ expressionHasOverrides = true;
+ }
+ return;
+ }
+
+ if (e.getKind() == expression::Kind::FormatExpression) {
+ const auto* formatExpr = static_cast<const expression::FormatExpression*>(&e);
+ for (const auto& section : formatExpr->getSections()) {
+ if (Property::hasOverride(section)) {
+ expressionHasOverrides = true;
+ break;
+ }
}
}
+ };
+
+ // Check root property expression and return early.
+ checkExpression(property.getExpression());
+ if (expressionHasOverrides) {
+ return true;
}
- return false;
+
+ // Traverse thru children and check whether any of them have overrides.
+ property.getExpression().eachChild(checkExpression);
+ return expressionHasOverrides;
},
[] (const auto&) {
return false;
diff --git a/src/mbgl/style/layers/symbol_layer_properties.hpp b/src/mbgl/style/layers/symbol_layer_properties.hpp
index c352ab8e77..cf8a9ab0d0 100644
--- a/src/mbgl/style/layers/symbol_layer_properties.hpp
+++ b/src/mbgl/style/layers/symbol_layer_properties.hpp
@@ -147,6 +147,16 @@ struct TextJustify : DataDrivenLayoutProperty<TextJustifyType> {
static TextJustifyType defaultValue() { return TextJustifyType::Center; }
};
+struct TextRadialOffset : DataDrivenLayoutProperty<float> {
+ static constexpr const char *name() { return "text-radial-offset"; }
+ static float defaultValue() { return 0; }
+};
+
+struct TextVariableAnchor : LayoutProperty<std::vector<TextVariableAnchorType>> {
+ static constexpr const char *name() { return "text-variable-anchor"; }
+ static std::vector<TextVariableAnchorType> defaultValue() { return { }; }
+};
+
struct TextAnchor : DataDrivenLayoutProperty<SymbolAnchorType> {
static constexpr const char *name() { return "text-anchor"; }
static SymbolAnchorType defaultValue() { return SymbolAnchorType::Center; }
@@ -197,23 +207,23 @@ struct TextOptional : LayoutProperty<bool> {
static bool defaultValue() { return false; }
};
-struct IconOpacity : DataDrivenPaintProperty<float, attributes::a_opacity, uniforms::u_opacity> {
+struct IconOpacity : DataDrivenPaintProperty<float, attributes::opacity, uniforms::opacity> {
static float defaultValue() { return 1; }
};
-struct IconColor : DataDrivenPaintProperty<Color, attributes::a_fill_color, uniforms::u_fill_color> {
+struct IconColor : DataDrivenPaintProperty<Color, attributes::fill_color, uniforms::fill_color> {
static Color defaultValue() { return Color::black(); }
};
-struct IconHaloColor : DataDrivenPaintProperty<Color, attributes::a_halo_color, uniforms::u_halo_color> {
+struct IconHaloColor : DataDrivenPaintProperty<Color, attributes::halo_color, uniforms::halo_color> {
static Color defaultValue() { return {}; }
};
-struct IconHaloWidth : DataDrivenPaintProperty<float, attributes::a_halo_width, uniforms::u_halo_width> {
+struct IconHaloWidth : DataDrivenPaintProperty<float, attributes::halo_width, uniforms::halo_width> {
static float defaultValue() { return 0; }
};
-struct IconHaloBlur : DataDrivenPaintProperty<float, attributes::a_halo_blur, uniforms::u_halo_blur> {
+struct IconHaloBlur : DataDrivenPaintProperty<float, attributes::halo_blur, uniforms::halo_blur> {
static float defaultValue() { return 0; }
};
@@ -225,26 +235,26 @@ struct IconTranslateAnchor : PaintProperty<TranslateAnchorType> {
static TranslateAnchorType defaultValue() { return TranslateAnchorType::Map; }
};
-struct TextOpacity : DataDrivenPaintProperty<float, attributes::a_opacity, uniforms::u_opacity> {
+struct TextOpacity : DataDrivenPaintProperty<float, attributes::opacity, uniforms::opacity> {
static float defaultValue() { return 1; }
};
-struct TextColor : DataDrivenPaintProperty<Color, attributes::a_fill_color, uniforms::u_fill_color, true> {
+struct TextColor : DataDrivenPaintProperty<Color, attributes::fill_color, uniforms::fill_color, true> {
static Color defaultValue() { return Color::black(); }
static constexpr const char *name() { return "text-color"; }
static constexpr auto expressionType() { return expression::type::ColorType{}; };
template<typename T> static bool hasOverride(const T& t) { return !!t.textColor; };
};
-struct TextHaloColor : DataDrivenPaintProperty<Color, attributes::a_halo_color, uniforms::u_halo_color> {
+struct TextHaloColor : DataDrivenPaintProperty<Color, attributes::halo_color, uniforms::halo_color> {
static Color defaultValue() { return {}; }
};
-struct TextHaloWidth : DataDrivenPaintProperty<float, attributes::a_halo_width, uniforms::u_halo_width> {
+struct TextHaloWidth : DataDrivenPaintProperty<float, attributes::halo_width, uniforms::halo_width> {
static float defaultValue() { return 0; }
};
-struct TextHaloBlur : DataDrivenPaintProperty<float, attributes::a_halo_blur, uniforms::u_halo_blur> {
+struct TextHaloBlur : DataDrivenPaintProperty<float, attributes::halo_blur, uniforms::halo_blur> {
static float defaultValue() { return 0; }
};
@@ -284,6 +294,8 @@ class SymbolLayoutProperties : public Properties<
TextLineHeight,
TextLetterSpacing,
TextJustify,
+ TextRadialOffset,
+ TextVariableAnchor,
TextAnchor,
TextMaxAngle,
TextRotate,
diff --git a/src/mbgl/style/sources/raster_dem_source.cpp b/src/mbgl/style/sources/raster_dem_source.cpp
index dc9feb8eeb..bb745561b1 100644
--- a/src/mbgl/style/sources/raster_dem_source.cpp
+++ b/src/mbgl/style/sources/raster_dem_source.cpp
@@ -3,7 +3,6 @@
#include <mbgl/style/source_observer.hpp>
#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion/tileset.hpp>
-#include <mbgl/storage/file_source.hpp>
#include <mbgl/util/mapbox.hpp>
namespace mbgl {
@@ -13,7 +12,5 @@ RasterDEMSource::RasterDEMSource(std::string id, variant<std::string, Tileset> u
: RasterSource(std::move(id), urlOrTileset_, tileSize, SourceType::RasterDEM){
}
-
-
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/style_impl.cpp b/src/mbgl/style/style_impl.cpp
index d65e9c9de2..fde5aa632d 100644
--- a/src/mbgl/style/style_impl.cpp
+++ b/src/mbgl/style/style_impl.cpp
@@ -254,6 +254,7 @@ bool Style::Impl::isLoaded() const {
void Style::Impl::addImage(std::unique_ptr<style::Image> image) {
images.remove(image->getID()); // We permit using addImage to update.
images.add(std::move(image));
+ observer->onUpdate();
}
void Style::Impl::removeImage(const std::string& id) {
diff --git a/src/mbgl/style/types.cpp b/src/mbgl/style/types.cpp
index 51174cf152..889f6029e2 100644
--- a/src/mbgl/style/types.cpp
+++ b/src/mbgl/style/types.cpp
@@ -76,13 +76,14 @@ MBGL_DEFINE_ENUM(SymbolAnchorType, {
{ SymbolAnchorType::BottomLeft, "bottom-left" },
{ SymbolAnchorType::BottomRight, "bottom-right" }
});
-
+
MBGL_DEFINE_ENUM(SymbolZOrderType, {
{ SymbolZOrderType::ViewportY, "viewport-y" },
{ SymbolZOrderType::Source, "source" }
});
MBGL_DEFINE_ENUM(TextJustifyType, {
+ { TextJustifyType::Auto, "auto" },
{ TextJustifyType::Center, "center" },
{ TextJustifyType::Left, "left" },
{ TextJustifyType::Right, "right" },
diff --git a/src/mbgl/text/collision_index.cpp b/src/mbgl/text/collision_index.cpp
index 90acb2b441..88e59bf51c 100644
--- a/src/mbgl/text/collision_index.cpp
+++ b/src/mbgl/text/collision_index.cpp
@@ -80,6 +80,7 @@ bool CollisionIndex::isInsideTile(const CollisionBox& box, const CollisionTileBo
std::pair<bool,bool> CollisionIndex::placeFeature(CollisionFeature& feature,
+ Point<float> shift,
const mat4& posMatrix,
const mat4& labelPlaneMatrix,
const float textPixelRatio,
@@ -95,10 +96,10 @@ std::pair<bool,bool> CollisionIndex::placeFeature(CollisionFeature& feature,
CollisionBox& box = feature.boxes.front();
const auto projectedPoint = projectAndGetPerspectiveRatio(posMatrix, box.anchor);
const float tileToViewport = textPixelRatio * projectedPoint.second;
- box.px1 = box.x1 * tileToViewport + projectedPoint.first.x;
- box.py1 = box.y1 * tileToViewport + projectedPoint.first.y;
- box.px2 = box.x2 * tileToViewport + projectedPoint.first.x;
- box.py2 = box.y2 * tileToViewport + projectedPoint.first.y;
+ box.px1 = (box.x1 + shift.x) * tileToViewport + projectedPoint.first.x;
+ box.py1 = (box.y1 + shift.y) * tileToViewport + projectedPoint.first.y;
+ box.px2 = (box.x2 + shift.x) * tileToViewport + projectedPoint.first.x;
+ box.py2 = (box.y2 + shift.y) * tileToViewport + projectedPoint.first.y;
if ((avoidEdges && !isInsideTile(box, *avoidEdges)) ||
diff --git a/src/mbgl/text/collision_index.hpp b/src/mbgl/text/collision_index.hpp
index dac0aa0bf7..dd160c945c 100644
--- a/src/mbgl/text/collision_index.hpp
+++ b/src/mbgl/text/collision_index.hpp
@@ -23,6 +23,7 @@ public:
explicit CollisionIndex(const TransformState&);
std::pair<bool,bool> placeFeature(CollisionFeature& feature,
+ Point<float> shift,
const mat4& posMatrix,
const mat4& labelPlaneMatrix,
const float textPixelRatio,
diff --git a/src/mbgl/text/glyph.hpp b/src/mbgl/text/glyph.hpp
index c97b242c10..7d6415c057 100644
--- a/src/mbgl/text/glyph.hpp
+++ b/src/mbgl/text/glyph.hpp
@@ -78,15 +78,17 @@ enum class WritingModeType : uint8_t;
class Shaping {
public:
- explicit Shaping() = default;
- explicit Shaping(float x, float y, WritingModeType writingMode_)
- : top(y), bottom(y), left(x), right(x), writingMode(writingMode_) {}
+ Shaping() = default;
+ explicit Shaping(float x, float y, WritingModeType writingMode_, std::size_t lineCount_)
+ : top(y), bottom(y), left(x), right(x), writingMode(writingMode_), lineCount(lineCount_) {}
std::vector<PositionedGlyph> positionedGlyphs;
float top = 0;
float bottom = 0;
float left = 0;
float right = 0;
WritingModeType writingMode;
+ std::size_t lineCount = 0u;
+ std::string text = {};
explicit operator bool() const { return !positionedGlyphs.empty(); }
};
diff --git a/src/mbgl/text/placement.cpp b/src/mbgl/text/placement.cpp
index 4cc12b0980..f6c4ac1eb6 100644
--- a/src/mbgl/text/placement.cpp
+++ b/src/mbgl/text/placement.cpp
@@ -1,10 +1,13 @@
#include <mbgl/text/placement.hpp>
+
+#include <mbgl/layout/symbol_layout.hpp>
#include <mbgl/renderer/render_layer.hpp>
#include <mbgl/renderer/layers/render_layer_symbol_interface.hpp>
#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/tile/geometry_tile.hpp>
#include <mbgl/renderer/buckets/symbol_bucket.hpp>
#include <mbgl/renderer/bucket.hpp>
+#include <mbgl/util/math.hpp>
namespace mbgl {
@@ -55,13 +58,18 @@ const CollisionGroups::CollisionGroup& CollisionGroups::get(const std::string& s
}
}
-Placement::Placement(const TransformState& state_, MapMode mapMode_, style::TransitionOptions transitionOptions_, const bool crossSourceCollisions)
+Placement::Placement(const TransformState& state_, MapMode mapMode_, style::TransitionOptions transitionOptions_, const bool crossSourceCollisions, std::unique_ptr<Placement> prevPlacement_)
: collisionIndex(state_)
, state(state_)
, mapMode(mapMode_)
, transitionOptions(transitionOptions_)
, collisionGroups(crossSourceCollisions)
-{}
+ , prevPlacement(std::move(prevPlacement_))
+{
+ if (prevPlacement) {
+ prevPlacement->prevPlacement.reset(); // Only hold on to one placement back
+ }
+}
void Placement::placeLayer(const RenderLayerSymbolInterface& symbolInterface, const mat4& projMatrix, bool showCollisionBoxes) {
@@ -121,6 +129,19 @@ void Placement::placeLayer(const RenderLayerSymbolInterface& symbolInterface, co
}
}
+namespace {
+Point<float> calculateVariableLayoutOffset(style::SymbolAnchorType anchor, float width, float height, float radialOffset, float textBoxScale) {
+ AnchorAlignment alignment = AnchorAlignment::getAnchorAlignment(anchor);
+ float shiftX = -(alignment.horizontalAlign - 0.5f) * width;
+ float shiftY = -(alignment.verticalAlign - 0.5f) * height;
+ Point<float> offset = SymbolLayout::evaluateRadialOffset(anchor, radialOffset);
+ return Point<float>(
+ shiftX + offset.x * textBoxScale,
+ shiftY + offset.y * textBoxScale
+ );
+}
+} // namespace
+
void Placement::placeLayerBucket(
SymbolBucket& bucket,
const mat4& posMatrix,
@@ -161,8 +182,11 @@ void Placement::placeLayerBucket(
// See https://github.com/mapbox/mapbox-gl-native/issues/12683
const bool alwaysShowText = textAllowOverlap && (iconAllowOverlap || !bucket.hasIconData() || bucket.layout.get<style::IconOptional>());
const bool alwaysShowIcon = iconAllowOverlap && (textAllowOverlap || !bucket.hasTextData() || bucket.layout.get<style::TextOptional>());
+ std::vector<style::TextVariableAnchorType> variableTextAnchors = bucket.layout.get<style::TextVariableAnchor>();
+ const bool rotateWithMap = bucket.layout.get<style::TextRotationAlignment>() == style::AlignmentType::Map;
+ const bool pitchWithMap = bucket.layout.get<style::TextPitchAlignment>() == style::AlignmentType::Map;
- for (auto& symbolInstance : bucket.symbolInstances) {
+ for (SymbolInstance& symbolInstance : bucket.symbolInstances) {
if (seenCrossTileIDs.count(symbolInstance.crossTileID) == 0) {
if (holdingForFade) {
@@ -175,30 +199,111 @@ void Placement::placeLayerBucket(
bool placeText = false;
bool placeIcon = false;
bool offscreen = true;
-
- if (symbolInstance.placedTextIndex) {
- PlacedSymbol& placedSymbol = bucket.text.placedSymbols.at(*symbolInstance.placedTextIndex);
+ optional<size_t> horizontalTextIndex = symbolInstance.getDefaultHorizontalPlacedTextIndex();
+ if (horizontalTextIndex) {
+ CollisionFeature& textCollisionFeature = symbolInstance.textCollisionFeature;
+ PlacedSymbol& placedSymbol = bucket.text.placedSymbols.at(*horizontalTextIndex);
const float fontSize = evaluateSizeForFeature(partiallyEvaluatedTextSize, placedSymbol);
-
- auto placed = collisionIndex.placeFeature(symbolInstance.textCollisionFeature,
- posMatrix, textLabelPlaneMatrix, textPixelRatio,
- placedSymbol, scale, fontSize,
- bucket.layout.get<style::TextAllowOverlap>(),
- bucket.layout.get<style::TextPitchAlignment>() == style::AlignmentType::Map,
- showCollisionBoxes, avoidEdges, collisionGroup.second);
- placeText = placed.first;
- offscreen &= placed.second;
+ if (variableTextAnchors.empty()) {
+ auto placed = collisionIndex.placeFeature(textCollisionFeature, {},
+ posMatrix, textLabelPlaneMatrix, textPixelRatio,
+ placedSymbol, scale, fontSize,
+ bucket.layout.get<style::TextAllowOverlap>(),
+ pitchWithMap,
+ showCollisionBoxes, avoidEdges, collisionGroup.second);
+ placeText = placed.first;
+ offscreen &= placed.second;
+ } else if (!textCollisionFeature.alongLine && !textCollisionFeature.boxes.empty()) {
+ const CollisionBox& textBox = symbolInstance.textCollisionFeature.boxes[0];
+ const float width = textBox.x2 - textBox.x1;
+ const float height = textBox.y2 - textBox.y1;
+ const float textBoxScale = symbolInstance.textBoxScale;
+
+ // If this symbol was in the last placement, shift the previously used
+ // anchor to the front of the anchor list.
+ if (prevPlacement) {
+ auto prevOffset = prevPlacement->variableOffsets.find(symbolInstance.crossTileID);
+ if (prevOffset != prevPlacement->variableOffsets.end() &&
+ variableTextAnchors.front() != prevOffset->second.anchor) {
+ std::vector<style::TextVariableAnchorType> filtered;
+ filtered.reserve(variableTextAnchors.size());
+ filtered.push_back(prevOffset->second.anchor);
+ for (auto anchor : variableTextAnchors) {
+ if (anchor != prevOffset->second.anchor) {
+ filtered.push_back(anchor);
+ }
+ }
+ variableTextAnchors = std::move(filtered);
+ }
+ }
+
+ for (auto anchor : variableTextAnchors) {
+ Point<float> shift = calculateVariableLayoutOffset(anchor, width, height, symbolInstance.radialTextOffset, textBoxScale);
+ if (rotateWithMap) {
+ float angle = pitchWithMap ? state.getBearing() : -state.getBearing();
+ shift = util::rotate(shift, angle);
+ }
+
+ auto placed = collisionIndex.placeFeature(textCollisionFeature, shift,
+ posMatrix, mat4(), textPixelRatio,
+ placedSymbol, scale, fontSize,
+ bucket.layout.get<style::TextAllowOverlap>(),
+ pitchWithMap,
+ showCollisionBoxes, avoidEdges, collisionGroup.second);
+
+ if (placed.first) {
+ assert(symbolInstance.crossTileID != 0u);
+ optional<style::TextVariableAnchorType> prevAnchor;
+
+ // If this label was placed in the previous placement, record the anchor position
+ // to allow us to animate the transition
+ if (prevPlacement) {
+ auto prevOffset = prevPlacement->variableOffsets.find(symbolInstance.crossTileID);
+ auto prevPlacements = prevPlacement->placements.find(symbolInstance.crossTileID);
+ if (prevOffset != prevPlacement->variableOffsets.end() &&
+ prevPlacements != prevPlacement->placements.end() &&
+ prevPlacements->second.text) {
+ prevAnchor = prevOffset->second.anchor;
+ }
+ }
+
+ variableOffsets.insert(std::make_pair(symbolInstance.crossTileID, VariableOffset{
+ symbolInstance.radialTextOffset,
+ width,
+ height,
+ anchor,
+ textBoxScale,
+ prevAnchor
+ }));
+ markUsedJustification(bucket, anchor, symbolInstance);
+
+ placeText = placed.first;
+ offscreen &= placed.second;
+ break;
+ }
+ }
+
+ // If we didn't get placed, we still need to copy our position from the last placement for
+ // fade animations
+ if (prevPlacement && variableOffsets.find(symbolInstance.crossTileID) == variableOffsets.end()) {
+ auto prevOffset = prevPlacement->variableOffsets.find(symbolInstance.crossTileID);
+ if (prevOffset != prevPlacement->variableOffsets.end()) {
+ variableOffsets[symbolInstance.crossTileID] = prevOffset->second;
+ markUsedJustification(bucket, prevOffset->second.anchor, symbolInstance);
+ }
+ }
+ }
}
if (symbolInstance.placedIconIndex) {
PlacedSymbol& placedSymbol = bucket.icon.placedSymbols.at(*symbolInstance.placedIconIndex);
const float fontSize = evaluateSizeForFeature(partiallyEvaluatedIconSize, placedSymbol);
- auto placed = collisionIndex.placeFeature(symbolInstance.iconCollisionFeature,
+ auto placed = collisionIndex.placeFeature(symbolInstance.iconCollisionFeature, {},
posMatrix, iconLabelPlaneMatrix, textPixelRatio,
placedSymbol, scale, fontSize,
bucket.layout.get<style::IconAllowOverlap>(),
- bucket.layout.get<style::IconPitchAlignment>() == style::AlignmentType::Map,
+ pitchWithMap,
showCollisionBoxes, avoidEdges, collisionGroup.second);
placeIcon = placed.first;
offscreen &= placed.second;
@@ -240,7 +345,8 @@ void Placement::placeLayerBucket(
bucket.justReloaded = false;
}
-void Placement::commit(const Placement& prevPlacement, TimePoint now) {
+void Placement::commit(TimePoint now) {
+ assert(prevPlacement);
commitTime = now;
bool placementChanged = false;
@@ -248,13 +354,13 @@ void Placement::commit(const Placement& prevPlacement, TimePoint now) {
float increment = mapMode == MapMode::Continuous &&
transitionOptions.enablePlacementTransitions &&
transitionOptions.duration.value_or(util::DEFAULT_TRANSITION_DURATION) > Milliseconds(0) ?
- std::chrono::duration<float>(commitTime - prevPlacement.commitTime) / transitionOptions.duration.value_or(util::DEFAULT_TRANSITION_DURATION) :
+ std::chrono::duration<float>(commitTime - prevPlacement->commitTime) / transitionOptions.duration.value_or(util::DEFAULT_TRANSITION_DURATION) :
1.0;
// add the opacities from the current placement, and copy their current values from the previous placement
for (auto& jointPlacement : placements) {
- auto prevOpacity = prevPlacement.opacities.find(jointPlacement.first);
- if (prevOpacity != prevPlacement.opacities.end()) {
+ auto prevOpacity = prevPlacement->opacities.find(jointPlacement.first);
+ if (prevOpacity != prevPlacement->opacities.end()) {
opacities.emplace(jointPlacement.first, JointOpacityState(prevOpacity->second, increment, jointPlacement.second.text, jointPlacement.second.icon));
placementChanged = placementChanged ||
jointPlacement.second.icon != prevOpacity->second.icon.placed ||
@@ -266,7 +372,7 @@ void Placement::commit(const Placement& prevPlacement, TimePoint now) {
}
// copy and update values from the previous placement that aren't in the current placement but haven't finished fading
- for (auto& prevOpacity : prevPlacement.opacities) {
+ for (auto& prevOpacity : prevPlacement->opacities) {
if (opacities.find(prevOpacity.first) == opacities.end()) {
JointOpacityState jointOpacity(prevOpacity.second, increment, false, false);
if (!jointOpacity.isHidden()) {
@@ -276,7 +382,16 @@ void Placement::commit(const Placement& prevPlacement, TimePoint now) {
}
}
- fadeStartTime = placementChanged ? commitTime : prevPlacement.fadeStartTime;
+ for (auto& prevOffset : prevPlacement->variableOffsets) {
+ const uint32_t crossTileID = prevOffset.first;
+ auto foundOffset = variableOffsets.find(crossTileID);
+ auto foundOpacity = opacities.find(crossTileID);
+ if (foundOffset == variableOffsets.end() && foundOpacity != opacities.end() && !foundOpacity->second.isHidden()) {
+ variableOffsets[prevOffset.first] = prevOffset.second;
+ }
+ }
+
+ fadeStartTime = placementChanged ? commitTime : prevPlacement->fadeStartTime;
}
void Placement::updateLayerOpacities(const RenderLayerSymbolInterface& symbolInterface) {
@@ -310,7 +425,10 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, std::set<uint32_t>&
const bool textAllowOverlap = bucket.layout.get<style::TextAllowOverlap>();
const bool iconAllowOverlap = bucket.layout.get<style::IconAllowOverlap>();
-
+ const bool variablePlacement = !bucket.layout.get<style::TextVariableAnchor>().empty();
+ const bool rotateWithMap = bucket.layout.get<style::TextRotationAlignment>() == style::AlignmentType::Map;
+ const bool pitchWithMap = bucket.layout.get<style::TextPitchAlignment>() == style::AlignmentType::Map;
+
// If allow-overlap is true, we can show symbols before placement runs on them
// But we have to wait for placement if we potentially depend on a paired icon/text
// with allow-overlap: false.
@@ -339,18 +457,38 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, std::set<uint32_t>&
if (symbolInstance.hasText) {
auto opacityVertex = SymbolSDFTextProgram::opacityVertex(opacityState.text.placed, opacityState.text.opacity);
- for (size_t i = 0; i < symbolInstance.horizontalGlyphQuads.size() * 4; i++) {
- bucket.text.opacityVertices.emplace_back(opacityVertex);
+ if (symbolInstance.placedRightTextIndex) {
+ for (size_t i = 0; i < symbolInstance.rightJustifiedGlyphQuads.size() * 4; i++) {
+ bucket.text.opacityVertices.emplace_back(opacityVertex);
+ }
+ PlacedSymbol& placed = bucket.text.placedSymbols[*symbolInstance.placedRightTextIndex];
+ placed.hidden = opacityState.isHidden();
}
- for (size_t i = 0; i < symbolInstance.verticalGlyphQuads.size() * 4; i++) {
- bucket.text.opacityVertices.emplace_back(opacityVertex);
+ if (symbolInstance.placedCenterTextIndex && !symbolInstance.singleLine) {
+ for (size_t i = 0; i < symbolInstance.centerJustifiedGlyphQuads.size() * 4; i++) {
+ bucket.text.opacityVertices.emplace_back(opacityVertex);
+ }
+ PlacedSymbol& placed = bucket.text.placedSymbols[*symbolInstance.placedCenterTextIndex];
+ placed.hidden = opacityState.isHidden();
}
- if (symbolInstance.placedTextIndex) {
- bucket.text.placedSymbols[*symbolInstance.placedTextIndex].hidden = opacityState.isHidden();
+ if (symbolInstance.placedLeftTextIndex && !symbolInstance.singleLine) {
+ for (size_t i = 0; i < symbolInstance.leftJustifiedGlyphQuads.size() * 4; i++) {
+ bucket.text.opacityVertices.emplace_back(opacityVertex);
+ }
+ PlacedSymbol& placed = bucket.text.placedSymbols[*symbolInstance.placedLeftTextIndex];
+ placed.hidden = opacityState.isHidden();
}
if (symbolInstance.placedVerticalTextIndex) {
+ for (size_t i = 0; i < symbolInstance.verticalGlyphQuads.size() * 4; i++) {
+ bucket.text.opacityVertices.emplace_back(opacityVertex);
+ }
bucket.text.placedSymbols[*symbolInstance.placedVerticalTextIndex].hidden = opacityState.isHidden();
}
+
+ auto prevOffset = variableOffsets.find(symbolInstance.crossTileID);
+ if (prevOffset != variableOffsets.end()) {
+ markUsedJustification(bucket, prevOffset->second.anchor, symbolInstance);
+ }
}
if (symbolInstance.hasIcon) {
auto opacityVertex = SymbolIconProgram::opacityVertex(opacityState.icon.placed, opacityState.icon.opacity);
@@ -369,7 +507,42 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, std::set<uint32_t>&
if (feature.alongLine) {
return;
}
- auto dynamicVertex = CollisionBoxProgram::dynamicVertex(placed, false);
+ auto dynamicVertex = CollisionBoxProgram::dynamicVertex(placed, false, {});
+ for (size_t i = 0; i < feature.boxes.size() * 4; i++) {
+ bucket.collisionBox.dynamicVertices.emplace_back(dynamicVertex);
+ }
+ };
+
+ auto updateCollisionTextBox = [this, &bucket, &symbolInstance, variablePlacement, rotateWithMap, pitchWithMap](const auto& feature, const bool placed) {
+ if (feature.alongLine) {
+ return;
+ }
+ Point<float> shift;
+ bool used = true;
+ if (variablePlacement) {
+ auto foundOffset = variableOffsets.find(symbolInstance.crossTileID);
+ if (foundOffset != variableOffsets.end()) {
+ const VariableOffset& variableOffset = foundOffset->second;
+ // This will show either the currently placed position or the last
+ // successfully placed position (so you can visualize what collision
+ // just made the symbol disappear, and the most likely place for the
+ // symbol to come back)
+ shift = calculateVariableLayoutOffset(variableOffset.anchor,
+ variableOffset.width,
+ variableOffset.height,
+ variableOffset.radialOffset,
+ variableOffset.textBoxScale);
+ if (rotateWithMap) {
+ shift = util::rotate(shift, pitchWithMap ? state.getBearing() : -state.getBearing());
+ }
+ } else {
+ // No offset -> this symbol hasn't been placed since coming on-screen
+ // No single box is particularly meaningful and all of them would be too noisy
+ // Use the center box just to show something's there, but mark it "not used"
+ used = false;
+ }
+ }
+ auto dynamicVertex = CollisionBoxProgram::dynamicVertex(placed, !used, shift);
for (size_t i = 0; i < feature.boxes.size() * 4; i++) {
bucket.collisionBox.dynamicVertices.emplace_back(dynamicVertex);
}
@@ -380,7 +553,7 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, std::set<uint32_t>&
return;
}
for (const CollisionBox& box : feature.boxes) {
- auto dynamicVertex = CollisionBoxProgram::dynamicVertex(placed, !box.used);
+ auto dynamicVertex = CollisionBoxProgram::dynamicVertex(placed, !box.used, {});
bucket.collisionCircle.dynamicVertices.emplace_back(dynamicVertex);
bucket.collisionCircle.dynamicVertices.emplace_back(dynamicVertex);
bucket.collisionCircle.dynamicVertices.emplace_back(dynamicVertex);
@@ -389,7 +562,7 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, std::set<uint32_t>&
};
if (bucket.hasCollisionBoxData()) {
- updateCollisionBox(symbolInstance.textCollisionFeature, opacityState.text.placed);
+ updateCollisionTextBox(symbolInstance.textCollisionFeature, opacityState.text.placed);
updateCollisionBox(symbolInstance.iconCollisionFeature, opacityState.icon.placed);
}
if (bucket.hasCollisionCircleData()) {
@@ -406,6 +579,31 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, std::set<uint32_t>&
}
}
+void Placement::markUsedJustification(SymbolBucket& bucket, style::TextVariableAnchorType placedAnchor, SymbolInstance& symbolInstance) {
+ std::map<style::TextJustifyType, optional<size_t>> justificationToIndex {
+ {style::TextJustifyType::Right, symbolInstance.placedRightTextIndex},
+ {style::TextJustifyType::Center, symbolInstance.placedCenterTextIndex},
+ {style::TextJustifyType::Left, symbolInstance.placedLeftTextIndex},
+ };
+ style::TextJustifyType justify = getAnchorJustification(placedAnchor);
+ assert(justify == style::TextJustifyType::Right || justify == style::TextJustifyType::Center || justify == style::TextJustifyType::Left);
+ const optional<size_t> autoIndex = justificationToIndex[justify];
+
+ for (auto& pair : justificationToIndex) {
+ const optional<size_t> index = pair.second;
+ if (index) {
+ assert(bucket.text.placedSymbols.size() > *index);
+ if (autoIndex && *index != *autoIndex) {
+ // There are multiple justifications and this one isn't it: shift offscreen
+ bucket.text.placedSymbols.at(*index).crossTileID = 0u;
+ } else {
+ // Either this is the chosen justification or the justification is hardwired: use this one
+ bucket.text.placedSymbols.at(*index).crossTileID = symbolInstance.crossTileID;
+ }
+ }
+ }
+}
+
float Placement::symbolFadeChange(TimePoint now) const {
if (mapMode == MapMode::Continuous && transitionOptions.enablePlacementTransitions &&
transitionOptions.duration.value_or(util::DEFAULT_TRANSITION_DURATION) > Milliseconds(0)) {
diff --git a/src/mbgl/text/placement.hpp b/src/mbgl/text/placement.hpp
index cc23110e54..3f2a7b8a03 100644
--- a/src/mbgl/text/placement.hpp
+++ b/src/mbgl/text/placement.hpp
@@ -12,6 +12,7 @@ namespace mbgl {
class RenderLayerSymbolInterface;
class SymbolBucket;
+class SymbolInstance;
class OpacityState {
public:
@@ -31,6 +32,16 @@ public:
OpacityState text;
};
+class VariableOffset {
+public:
+ float radialOffset;
+ float width;
+ float height;
+ style::TextVariableAnchorType anchor;
+ float textBoxScale;
+ optional<style::TextVariableAnchorType> prevAnchor;
+};
+
class JointPlacement {
public:
JointPlacement(bool text_, bool icon_, bool skipFade_)
@@ -45,7 +56,7 @@ public:
// visible right away.
const bool skipFade;
};
-
+
struct RetainedQueryData {
uint32_t bucketInstanceId;
std::shared_ptr<FeatureIndex> featureIndex;
@@ -80,9 +91,9 @@ private:
class Placement {
public:
- Placement(const TransformState&, MapMode, style::TransitionOptions, const bool crossSourceCollisions);
+ Placement(const TransformState&, MapMode, style::TransitionOptions, const bool crossSourceCollisions, std::unique_ptr<Placement> prevPlacementOrNull = nullptr);
void placeLayer(const RenderLayerSymbolInterface&, const mat4&, bool showCollisionBoxes);
- void commit(const Placement& prevPlacement, TimePoint);
+ void commit(TimePoint);
void updateLayerOpacities(const RenderLayerSymbolInterface&);
float symbolFadeChange(TimePoint now) const;
bool hasTransitions(TimePoint now) const;
@@ -94,8 +105,10 @@ public:
void setStale();
const RetainedQueryData& getQueryData(uint32_t bucketInstanceId) const;
-private:
+ using VariableOffsets = std::reference_wrapper<const std::unordered_map<uint32_t, VariableOffset>>;
+ VariableOffsets getVariableOffsets() const { return std::cref(variableOffsets); }
+private:
void placeLayerBucket(
SymbolBucket&,
const mat4& posMatrix,
@@ -109,6 +122,7 @@ private:
const CollisionGroups::CollisionGroup& collisionGroup);
void updateBucketOpacities(SymbolBucket&, std::set<uint32_t>&);
+ void markUsedJustification(SymbolBucket&, style::TextVariableAnchorType, SymbolInstance&);
CollisionIndex collisionIndex;
@@ -121,11 +135,13 @@ private:
std::unordered_map<uint32_t, JointPlacement> placements;
std::unordered_map<uint32_t, JointOpacityState> opacities;
+ std::unordered_map<uint32_t, VariableOffset> variableOffsets;
bool stale = false;
std::unordered_map<uint32_t, RetainedQueryData> retainedQueryData;
CollisionGroups collisionGroups;
+ std::unique_ptr<Placement> prevPlacement;
};
} // namespace mbgl
diff --git a/src/mbgl/text/quads.cpp b/src/mbgl/text/quads.cpp
index ec0045caad..6be5d8c01e 100644
--- a/src/mbgl/text/quads.cpp
+++ b/src/mbgl/text/quads.cpp
@@ -92,16 +92,12 @@ SymbolQuad getIconQuad(const PositionedIcon& shapedIcon,
}
SymbolQuads getGlyphQuads(const Shaping& shapedText,
+ const std::array<float, 2> textOffset,
const SymbolLayoutProperties::Evaluated& layout,
const style::SymbolPlacementType placement,
const GlyphPositions& positions) {
const float textRotate = layout.get<TextRotate>() * util::DEG2RAD;
- const float oneEm = 24.0;
- std::array<float, 2> textOffset = layout.get<TextOffset>();
- textOffset[0] *= oneEm;
- textOffset[1] *= oneEm;
-
SymbolQuads quads;
for (const PositionedGlyph &positionedGlyph: shapedText.positionedGlyphs) {
diff --git a/src/mbgl/text/quads.hpp b/src/mbgl/text/quads.hpp
index f41a4fec66..0bb892e4d1 100644
--- a/src/mbgl/text/quads.hpp
+++ b/src/mbgl/text/quads.hpp
@@ -49,6 +49,7 @@ SymbolQuad getIconQuad(const PositionedIcon& shapedIcon,
const Shaping& shapedText);
SymbolQuads getGlyphQuads(const Shaping& shapedText,
+ const std::array<float, 2> textOffset,
const style::SymbolLayoutProperties::Evaluated&,
style::SymbolPlacementType placement,
const GlyphPositions& positions);
diff --git a/src/mbgl/text/shaping.cpp b/src/mbgl/text/shaping.cpp
index 02dbf146e1..ba21b97389 100644
--- a/src/mbgl/text/shaping.cpp
+++ b/src/mbgl/text/shaping.cpp
@@ -1,4 +1,5 @@
#include <mbgl/text/shaping.hpp>
+#include <mbgl/util/constants.hpp>
#include <mbgl/util/i18n.hpp>
#include <mbgl/layout/symbol_feature.hpp>
#include <mbgl/math/minmax.hpp>
@@ -10,58 +11,61 @@
namespace mbgl {
-struct AnchorAlignment {
- AnchorAlignment(float horizontal_, float vertical_)
- : horizontalAlign(horizontal_), verticalAlign(vertical_) {
- }
-
- float horizontalAlign;
- float verticalAlign;
-};
-AnchorAlignment getAnchorAlignment(style::SymbolAnchorType anchor) {
- float horizontalAlign = 0.5;
- float verticalAlign = 0.5;
+// static
+AnchorAlignment AnchorAlignment::getAnchorAlignment(style::SymbolAnchorType anchor) {
+ AnchorAlignment result(0.5f, 0.5f);
switch (anchor) {
- case style::SymbolAnchorType::Top:
- case style::SymbolAnchorType::Bottom:
- case style::SymbolAnchorType::Center:
- break;
case style::SymbolAnchorType::Right:
case style::SymbolAnchorType::TopRight:
case style::SymbolAnchorType::BottomRight:
- horizontalAlign = 1;
+ result.horizontalAlign = 1.0f;
break;
case style::SymbolAnchorType::Left:
case style::SymbolAnchorType::TopLeft:
case style::SymbolAnchorType::BottomLeft:
- horizontalAlign = 0;
+ result.horizontalAlign = 0.0f;
break;
+ default:
+ break;
}
switch (anchor) {
- case style::SymbolAnchorType::Left:
- case style::SymbolAnchorType::Right:
- case style::SymbolAnchorType::Center:
- break;
case style::SymbolAnchorType::Bottom:
case style::SymbolAnchorType::BottomLeft:
case style::SymbolAnchorType::BottomRight:
- verticalAlign = 1;
+ result.verticalAlign = 1.0f;
break;
case style::SymbolAnchorType::Top:
case style::SymbolAnchorType::TopLeft:
case style::SymbolAnchorType::TopRight:
- verticalAlign = 0;
+ result.verticalAlign = 0.0f;
+ break;
+ default:
break;
}
- return AnchorAlignment(horizontalAlign, verticalAlign);
+ return result;
+}
+
+style::TextJustifyType getAnchorJustification(style::SymbolAnchorType anchor) {
+ switch (anchor) {
+ case style::SymbolAnchorType::Right:
+ case style::SymbolAnchorType::TopRight:
+ case style::SymbolAnchorType::BottomRight:
+ return style::TextJustifyType::Right;
+ case style::SymbolAnchorType::Left:
+ case style::SymbolAnchorType::TopLeft:
+ case style::SymbolAnchorType::BottomLeft:
+ return style::TextJustifyType::Left;
+ default:
+ return style::TextJustifyType::Center;
+ }
}
PositionedIcon PositionedIcon::shapeIcon(const ImagePosition& image, const std::array<float, 2>& iconOffset, style::SymbolAnchorType iconAnchor, const float iconRotation) {
- AnchorAlignment anchorAlign = getAnchorAlignment(iconAnchor);
+ AnchorAlignment anchorAlign = AnchorAlignment::getAnchorAlignment(iconAnchor);
float dx = iconOffset[0];
float dy = iconOffset[1];
float x1 = dx - image.displaySize()[0] * anchorAlign.horizontalAlign;
@@ -269,7 +273,6 @@ void shapeLines(Shaping& shaping,
const float lineHeight,
const style::SymbolAnchorType textAnchor,
const style::TextJustifyType textJustify,
- const float verticalHeight,
const WritingModeType writingMode,
const GlyphMap& glyphMap) {
@@ -314,7 +317,7 @@ void shapeLines(Shaping& shaping,
// We don't know the baseline, but since we're laying out
// at 24 points, we can calculate how much it will move when
// we scale up or down.
- const double baselineOffset = (lineMaxScale - section.scale) * 24;
+ const double baselineOffset = (lineMaxScale - section.scale) * util::ONE_EM;
const Glyph& glyph = **it->second;
@@ -323,7 +326,7 @@ void shapeLines(Shaping& shaping,
x += glyph.metrics.advance * section.scale + spacing;
} else {
shaping.positionedGlyphs.emplace_back(codePoint, x, baselineOffset, true, section.fontStackHash, section.scale, sectionIndex);
- x += verticalHeight * section.scale + spacing;
+ x += util::ONE_EM * section.scale + spacing;
}
}
@@ -340,7 +343,7 @@ void shapeLines(Shaping& shaping,
y += lineHeight * lineMaxScale;
}
- auto anchorAlign = getAnchorAlignment(textAnchor);
+ auto anchorAlign = AnchorAlignment::getAnchorAlignment(textAnchor);
align(shaping, justify, anchorAlign.horizontalAlign, anchorAlign.verticalAlign, maxLineLength,
lineHeight, lines.size());
@@ -360,12 +363,9 @@ const Shaping getShaping(const TaggedString& formattedString,
const style::TextJustifyType textJustify,
const float spacing,
const Point<float>& translate,
- const float verticalHeight,
const WritingModeType writingMode,
BiDi& bidi,
- const GlyphMap& glyphs) {
- Shaping shaping(translate.x, translate.y, writingMode);
-
+ const GlyphMap& glyphs) {
std::vector<TaggedString> reorderedLines;
if (formattedString.sectionCount() == 1) {
auto untaggedLines = bidi.processText(formattedString.rawText(),
@@ -380,9 +380,9 @@ const Shaping getShaping(const TaggedString& formattedString,
reorderedLines.emplace_back(line, formattedString.getSections());
}
}
-
+ Shaping shaping(translate.x, translate.y, writingMode, reorderedLines.size());
shapeLines(shaping, reorderedLines, spacing, lineHeight, textAnchor,
- textJustify, verticalHeight, writingMode, glyphs);
+ textJustify, writingMode, glyphs);
return shaping;
}
diff --git a/src/mbgl/text/shaping.hpp b/src/mbgl/text/shaping.hpp
index 50ac893098..766b1ce233 100644
--- a/src/mbgl/text/shaping.hpp
+++ b/src/mbgl/text/shaping.hpp
@@ -7,6 +7,20 @@
namespace mbgl {
+struct AnchorAlignment {
+ AnchorAlignment(float horizontal, float vertical)
+ : horizontalAlign(horizontal), verticalAlign(vertical) {
+ }
+
+ static AnchorAlignment getAnchorAlignment(style::SymbolAnchorType anchor);
+
+ float horizontalAlign;
+ float verticalAlign;
+};
+
+// Choose the justification that matches the direction of the TextAnchor
+style::TextJustifyType getAnchorJustification(style::SymbolAnchorType anchor);
+
class SymbolFeature;
class BiDi;
@@ -53,7 +67,6 @@ const Shaping getShaping(const TaggedString& string,
style::TextJustifyType textJustify,
float spacing,
const Point<float>& translate,
- float verticalHeight,
const WritingModeType,
BiDi& bidi,
const GlyphMap& glyphs);
diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp
index c8498976b8..9165c03267 100644
--- a/src/mbgl/tile/geometry_tile.cpp
+++ b/src/mbgl/tile/geometry_tile.cpp
@@ -13,7 +13,6 @@
#include <mbgl/renderer/query.hpp>
#include <mbgl/text/glyph_atlas.hpp>
#include <mbgl/renderer/image_atlas.hpp>
-#include <mbgl/storage/file_source.hpp>
#include <mbgl/geometry/feature_index.hpp>
#include <mbgl/map/transform_state.hpp>
#include <mbgl/util/logging.hpp>
@@ -157,8 +156,8 @@ void GeometryTile::getGlyphs(GlyphDependencies glyphDependencies) {
glyphManager.getGlyphs(*this, std::move(glyphDependencies));
}
-void GeometryTile::onImagesAvailable(ImageMap images, ImageMap patterns, uint64_t imageCorrelationID) {
- worker.self().invoke(&GeometryTileWorker::onImagesAvailable, std::move(images), std::move(patterns), imageCorrelationID);
+void GeometryTile::onImagesAvailable(ImageMap images, ImageMap patterns, ImageVersionMap versionMap, uint64_t imageCorrelationID) {
+ worker.self().invoke(&GeometryTileWorker::onImagesAvailable, std::move(images), std::move(patterns), std::move(versionMap), imageCorrelationID);
}
void GeometryTile::getImages(ImageRequestPair pair) {
@@ -193,6 +192,10 @@ void GeometryTile::upload(gfx::Context& context) {
iconAtlasTexture = context.createTexture(iconAtlas.image);
iconAtlas.image = {};
}
+
+ if (iconAtlasTexture) {
+ iconAtlas.patchUpdatedImages(context, *iconAtlasTexture, imageManager);
+ }
}
Bucket* GeometryTile::getBucket(const Layer::Impl& layer) const {
diff --git a/src/mbgl/tile/geometry_tile.hpp b/src/mbgl/tile/geometry_tile.hpp
index b652e7ba5d..53a8910c27 100644
--- a/src/mbgl/tile/geometry_tile.hpp
+++ b/src/mbgl/tile/geometry_tile.hpp
@@ -37,7 +37,7 @@ public:
void setShowCollisionBoxes(const bool showCollisionBoxes) override;
void onGlyphsAvailable(GlyphMap) override;
- void onImagesAvailable(ImageMap, ImageMap, uint64_t imageCorrelationID) override;
+ void onImagesAvailable(ImageMap, ImageMap, ImageVersionMap versionMap, uint64_t imageCorrelationID) override;
void getGlyphs(GlyphDependencies);
void getImages(ImageRequestPair);
diff --git a/src/mbgl/tile/geometry_tile_worker.cpp b/src/mbgl/tile/geometry_tile_worker.cpp
index 943e782af1..0b703cd68b 100644
--- a/src/mbgl/tile/geometry_tile_worker.cpp
+++ b/src/mbgl/tile/geometry_tile_worker.cpp
@@ -278,12 +278,13 @@ void GeometryTileWorker::onGlyphsAvailable(GlyphMap newGlyphMap) {
symbolDependenciesChanged();
}
-void GeometryTileWorker::onImagesAvailable(ImageMap newIconMap, ImageMap newPatternMap, uint64_t imageCorrelationID_) {
+void GeometryTileWorker::onImagesAvailable(ImageMap newIconMap, ImageMap newPatternMap, ImageVersionMap newVersionMap, uint64_t imageCorrelationID_) {
if (imageCorrelationID != imageCorrelationID_) {
return; // Ignore outdated image request replies.
}
imageMap = std::move(newIconMap);
patternMap = std::move(newPatternMap);
+ versionMap = std::move(newVersionMap);
pendingImageDependencies.clear();
symbolDependenciesChanged();
}
@@ -441,7 +442,7 @@ void GeometryTileWorker::finalizeLayout() {
MBGL_TIMING_START(watch)
optional<AlphaImage> glyphAtlasImage;
- ImageAtlas iconAtlas = makeImageAtlas(imageMap, patternMap);
+ ImageAtlas iconAtlas = makeImageAtlas(imageMap, patternMap, versionMap);
if (!layouts.empty()) {
GlyphAtlas glyphAtlas = makeGlyphAtlas(glyphMap);
glyphAtlasImage = std::move(glyphAtlas.image);
diff --git a/src/mbgl/tile/geometry_tile_worker.hpp b/src/mbgl/tile/geometry_tile_worker.hpp
index 485d1315a6..706bac0154 100644
--- a/src/mbgl/tile/geometry_tile_worker.hpp
+++ b/src/mbgl/tile/geometry_tile_worker.hpp
@@ -44,7 +44,7 @@ public:
void setShowCollisionBoxes(bool showCollisionBoxes_, uint64_t correlationID_);
void onGlyphsAvailable(GlyphMap glyphs);
- void onImagesAvailable(ImageMap icons, ImageMap patterns, uint64_t imageCorrelationID);
+ void onImagesAvailable(ImageMap icons, ImageMap patterns, ImageVersionMap versionMap, uint64_t imageCorrelationID);
private:
void coalesced();
@@ -96,6 +96,7 @@ private:
GlyphMap glyphMap;
ImageMap imageMap;
ImageMap patternMap;
+ ImageVersionMap versionMap;
bool showCollisionBoxes;
bool firstLoad = true;
diff --git a/src/mbgl/tile/raster_dem_tile.cpp b/src/mbgl/tile/raster_dem_tile.cpp
index ba961853d0..224c5c9062 100644
--- a/src/mbgl/tile/raster_dem_tile.cpp
+++ b/src/mbgl/tile/raster_dem_tile.cpp
@@ -5,7 +5,6 @@
#include <mbgl/style/source.hpp>
#include <mbgl/storage/resource.hpp>
#include <mbgl/storage/response.hpp>
-#include <mbgl/storage/file_source.hpp>
#include <mbgl/renderer/tile_parameters.hpp>
#include <mbgl/renderer/buckets/hillshade_bucket.hpp>
#include <mbgl/actor/scheduler.hpp>
diff --git a/src/mbgl/tile/raster_tile.cpp b/src/mbgl/tile/raster_tile.cpp
index 22561ec11d..ff02301021 100644
--- a/src/mbgl/tile/raster_tile.cpp
+++ b/src/mbgl/tile/raster_tile.cpp
@@ -5,7 +5,6 @@
#include <mbgl/style/source.hpp>
#include <mbgl/storage/resource.hpp>
#include <mbgl/storage/response.hpp>
-#include <mbgl/storage/file_source.hpp>
#include <mbgl/renderer/tile_parameters.hpp>
#include <mbgl/renderer/buckets/raster_bucket.hpp>
#include <mbgl/actor/scheduler.hpp>
diff --git a/src/mbgl/util/literal.hpp b/src/mbgl/util/literal.hpp
new file mode 100644
index 0000000000..d4fec49b35
--- /dev/null
+++ b/src/mbgl/util/literal.hpp
@@ -0,0 +1,67 @@
+#pragma once
+
+#include <utility>
+#include <cstddef>
+
+namespace mbgl {
+
+// Using structs instead of constexpr templates because GCC 4.9 doesn't support these yet.
+
+template <char... Cs>
+struct string_literal {
+ static constexpr const char chars[] = { Cs..., 0 };
+
+ static constexpr const char* value() {
+ return chars;
+ }
+};
+
+template <char... Cs>
+constexpr const char string_literal<Cs...>::chars[];
+
+namespace detail {
+
+using string_fn = const char* (*)();
+
+template <string_fn name, std::size_t... Is>
+string_literal<name()[Is]...> to_string_literal(std::index_sequence<Is...>);
+
+constexpr std::size_t string_length(const char* const str, std::size_t len = 0) {
+ return str[0] ? string_length(str + 1, len + 1) : len;
+}
+
+template <class...>
+struct concat_literals;
+
+template <>
+struct concat_literals<> {
+ static constexpr auto value() {
+ return "";
+ }
+};
+
+template <char... As, char... Bs, class... Rest>
+struct concat_literals<string_literal<As...>, string_literal<Bs...>, Rest...> {
+ static constexpr auto value() {
+ return concat_literals<string_literal<As..., Bs...>, Rest...>::value();
+ }
+};
+
+template <char... Cs>
+struct concat_literals<string_literal<Cs...>> {
+ static constexpr auto value() {
+ return string_literal<Cs...>::value();
+ }
+};
+
+} // namespace detail
+
+template <detail::string_fn... str>
+struct concat_literals {
+ static constexpr auto value() {
+ return detail::concat_literals<decltype(detail::to_string_literal<str>(
+ std::make_index_sequence<detail::string_length(str())>()))...>::value();
+ }
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/util/offscreen_texture.cpp b/src/mbgl/util/offscreen_texture.cpp
index 2a58ff86a3..6bc09c7b16 100644
--- a/src/mbgl/util/offscreen_texture.cpp
+++ b/src/mbgl/util/offscreen_texture.cpp
@@ -62,18 +62,20 @@ private:
const gfx::TextureChannelDataType type;
};
-OffscreenTexture::OffscreenTexture(gl::Context& context,
+OffscreenTexture::OffscreenTexture(gfx::Context& context,
const Size size,
const gfx::TextureChannelDataType type)
- : impl(std::make_unique<Impl>(context, std::move(size), type)) {
+ // TODO: remove cast
+ : impl(std::make_unique<Impl>(reinterpret_cast<gl::Context&>(context), std::move(size), type)) {
assert(!size.isEmpty());
}
-OffscreenTexture::OffscreenTexture(gl::Context& context,
+OffscreenTexture::OffscreenTexture(gfx::Context& context,
const Size size,
gl::Renderbuffer<gl::RenderbufferType::DepthComponent>& renderbuffer,
const gfx::TextureChannelDataType type)
- : impl(std::make_unique<Impl>(context, std::move(size), renderbuffer, type)) {
+ // TODO: remove cast
+ : impl(std::make_unique<Impl>(reinterpret_cast<gl::Context&>(context), std::move(size), renderbuffer, type)) {
assert(!size.isEmpty());
}
diff --git a/src/mbgl/util/offscreen_texture.hpp b/src/mbgl/util/offscreen_texture.hpp
index 9446fabecf..f4459556b8 100644
--- a/src/mbgl/util/offscreen_texture.hpp
+++ b/src/mbgl/util/offscreen_texture.hpp
@@ -6,20 +6,17 @@
namespace mbgl {
-namespace gl {
-class Context;
-} // namespace gl
-
namespace gfx {
+class Context;
class Texture;
} // namespace gfx
class OffscreenTexture {
public:
- OffscreenTexture(gl::Context&,
+ OffscreenTexture(gfx::Context&,
Size size = { 256, 256 },
gfx::TextureChannelDataType type = gfx::TextureChannelDataType::UnsignedByte);
- OffscreenTexture(gl::Context&,
+ OffscreenTexture(gfx::Context&,
Size size,
gl::Renderbuffer<gl::RenderbufferType::DepthComponent>&,
gfx::TextureChannelDataType type = gfx::TextureChannelDataType::UnsignedByte);
diff --git a/test/api/annotations.test.cpp b/test/api/annotations.test.cpp
index aad85f8d57..11920d1624 100644
--- a/test/api/annotations.test.cpp
+++ b/test/api/annotations.test.cpp
@@ -1,11 +1,11 @@
#include <mbgl/test/util.hpp>
#include <mbgl/test/stub_file_source.hpp>
+#include <mbgl/test/map_adapter.hpp>
#include <mbgl/util/default_thread_pool.hpp>
#include <mbgl/annotation/annotation.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/image.hpp>
-#include <mbgl/map/map.hpp>
#include <mbgl/map/map_options.hpp>
#include <mbgl/util/io.hpp>
#include <mbgl/util/run_loop.hpp>
@@ -28,13 +28,11 @@ std::unique_ptr<style::Image> namedMarker(const std::string& name) {
class AnnotationTest {
public:
util::RunLoop loop;
- StubFileSource fileSource;
ThreadPool threadPool { 4 };
- float pixelRatio { 1 };
- HeadlessFrontend frontend { pixelRatio, threadPool };
+ HeadlessFrontend frontend { 1, threadPool };
- Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, fileSource,
- threadPool, MapOptions().withMapMode(MapMode::Static)};
+ MapAdapter map { frontend, MapObserver::nullObserver(), std::make_shared<StubFileSource>(), threadPool,
+ MapOptions().withMapMode(MapMode::Static).withSize(frontend.getSize())};
void checkRendering(const char * name) {
test::checkImage(std::string("test/fixtures/annotations/") + name,
diff --git a/test/api/api_misuse.test.cpp b/test/api/api_misuse.test.cpp
index 2ccfb0a7ff..cca47de69c 100644
--- a/test/api/api_misuse.test.cpp
+++ b/test/api/api_misuse.test.cpp
@@ -1,12 +1,11 @@
#include <mbgl/test/util.hpp>
#include <mbgl/test/stub_file_source.hpp>
#include <mbgl/test/fixture_log_observer.hpp>
+#include <mbgl/test/map_adapter.hpp>
-#include <mbgl/map/map.hpp>
#include <mbgl/map/map_options.hpp>
#include <mbgl/renderer/backend_scope.hpp>
#include <mbgl/gl/headless_frontend.hpp>
-#include <mbgl/storage/online_file_source.hpp>
#include <mbgl/util/default_thread_pool.hpp>
#include <mbgl/util/exception.hpp>
#include <mbgl/util/run_loop.hpp>
@@ -22,14 +21,12 @@ TEST(API, RenderWithoutCallback) {
util::RunLoop loop;
- StubFileSource fileSource;
ThreadPool threadPool(4);
- float pixelRatio { 1 };
- HeadlessFrontend frontend { pixelRatio, threadPool };
+ HeadlessFrontend frontend { 1, threadPool };
- auto map = std::make_unique<Map>(frontend, MapObserver::nullObserver(), frontend.getSize(),
- pixelRatio, fileSource, threadPool,
- MapOptions().withMapMode(MapMode::Static));
+ auto map = std::make_unique<MapAdapter>(frontend, MapObserver::nullObserver(),
+ std::make_shared<StubFileSource>(), threadPool,
+ MapOptions().withMapMode(MapMode::Static).withSize(frontend.getSize()));
map->renderStill(nullptr);
// Force Map thread to join.
diff --git a/test/api/custom_geometry_source.test.cpp b/test/api/custom_geometry_source.test.cpp
index 6959a36f15..f796e3086b 100644
--- a/test/api/custom_geometry_source.test.cpp
+++ b/test/api/custom_geometry_source.test.cpp
@@ -3,8 +3,8 @@
#include <mbgl/map/map.hpp>
#include <mbgl/map/map_options.hpp>
#include <mbgl/util/shared_thread_pool.hpp>
-#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/gl/headless_frontend.hpp>
+#include <mbgl/storage/resource_options.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/sources/custom_geometry_source.hpp>
#include <mbgl/style/layers/fill_layer.hpp>
@@ -20,12 +20,11 @@ using namespace mbgl::style;
TEST(CustomGeometrySource, Grid) {
util::RunLoop loop;
- DefaultFileSource fileSource(":memory:", "test/fixtures/api/assets");
auto threadPool = sharedThreadPool();
- float pixelRatio { 1 };
- HeadlessFrontend frontend { pixelRatio, *threadPool };
- Map map(frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, fileSource,
- *threadPool, MapOptions().withMapMode(MapMode::Static));
+ HeadlessFrontend frontend { 1, *threadPool };
+ Map map(frontend, MapObserver::nullObserver(), *threadPool,
+ MapOptions().withMapMode(MapMode::Static).withSize(frontend.getSize()),
+ ResourceOptions().withCachePath(":memory:").withAssetPath("test/fixtures/api/assets"));
map.getStyle().loadJSON(util::read_file("test/fixtures/api/water.json"));
map.jumpTo(CameraOptions().withCenter(LatLng { 37.8, -122.5 }).withZoom(10.0));
diff --git a/test/api/custom_layer.test.cpp b/test/api/custom_layer.test.cpp
index 18c6dc1692..c836ab81ac 100644
--- a/test/api/custom_layer.test.cpp
+++ b/test/api/custom_layer.test.cpp
@@ -4,9 +4,9 @@
#include <mbgl/map/map.hpp>
#include <mbgl/map/map_options.hpp>
#include <mbgl/util/default_thread_pool.hpp>
-#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/gl/defines.hpp>
#include <mbgl/gl/headless_frontend.hpp>
+#include <mbgl/storage/resource_options.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/layers/custom_layer.hpp>
#include <mbgl/style/layers/fill_layer.hpp>
@@ -90,12 +90,11 @@ public:
TEST(CustomLayer, Basic) {
util::RunLoop loop;
- DefaultFileSource fileSource(":memory:", "test/fixtures/api/assets");
ThreadPool threadPool(4);
- float pixelRatio { 1 };
- HeadlessFrontend frontend { pixelRatio, threadPool };
- Map map(frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, fileSource,
- threadPool, MapOptions().withMapMode(MapMode::Static));
+ HeadlessFrontend frontend { 1, threadPool };
+ Map map(frontend, MapObserver::nullObserver(), threadPool,
+ MapOptions().withMapMode(MapMode::Static).withSize(frontend.getSize()),
+ ResourceOptions().withCachePath(":memory:").withAssetPath("test/fixtures/api/assets"));
map.getStyle().loadJSON(util::read_file("test/fixtures/api/water.json"));
map.jumpTo(CameraOptions().withCenter(LatLng { 37.8, -122.5 }).withZoom(10.0));
map.getStyle().addLayer(std::make_unique<CustomLayer>(
diff --git a/test/api/query.test.cpp b/test/api/query.test.cpp
index 5567eabc73..ddf5df6aab 100644
--- a/test/api/query.test.cpp
+++ b/test/api/query.test.cpp
@@ -1,4 +1,5 @@
-#include <mbgl/map/map.hpp>
+#include <mbgl/test/map_adapter.hpp>
+
#include <mbgl/map/map_options.hpp>
#include <mbgl/util/default_thread_pool.hpp>
#include <mbgl/test/stub_file_source.hpp>
@@ -33,16 +34,15 @@ public:
}
util::RunLoop loop;
- StubFileSource fileSource;
+ std::shared_ptr<StubFileSource> fileSource = std::make_shared<StubFileSource>();
ThreadPool threadPool { 4 };
- float pixelRatio { 1 };
- HeadlessFrontend frontend { pixelRatio, threadPool };
- Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, fileSource,
- threadPool, MapOptions().withMapMode(MapMode::Static)};
+ HeadlessFrontend frontend { 1, threadPool };
+ MapAdapter map { frontend, MapObserver::nullObserver(), fileSource, threadPool,
+ MapOptions().withMapMode(MapMode::Static).withSize(frontend.getSize())};
};
std::vector<Feature> getTopClusterFeature(QueryTest& test) {
- test.fileSource.sourceResponse = [&] (const Resource& resource) {
+ test.fileSource->sourceResponse = [&] (const Resource& resource) {
EXPECT_EQ("http://url"s, resource.url);
Response response;
response.data = std::make_unique<std::string>(util::read_file("test/fixtures/supercluster/places.json"s));
@@ -54,7 +54,7 @@ std::vector<Feature> getTopClusterFeature(QueryTest& test) {
options.cluster = true;
auto source = std::make_unique<GeoJSONSource>("cluster_source"s, options);
source->setURL("http://url"s);
- source->loadDescription(test.fileSource);
+ source->loadDescription(*test.fileSource);
auto clusterLayer = std::make_unique<SymbolLayer>("cluster_layer"s, "cluster_source"s);
clusterLayer->setIconImage("test-icon"s);
diff --git a/test/api/recycle_map.cpp b/test/api/recycle_map.cpp
index db576b4cf6..ac9de9b230 100644
--- a/test/api/recycle_map.cpp
+++ b/test/api/recycle_map.cpp
@@ -1,11 +1,10 @@
#include <mbgl/test/util.hpp>
#include <mbgl/test/stub_file_source.hpp>
+#include <mbgl/test/map_adapter.hpp>
#include <mbgl/gl/headless_frontend.hpp>
-#include <mbgl/map/map.hpp>
#include <mbgl/map/map_options.hpp>
#include <mbgl/renderer/backend_scope.hpp>
-#include <mbgl/storage/online_file_source.hpp>
#include <mbgl/style/layers/symbol_layer.hpp>
#include <mbgl/style/sources/geojson_source.hpp>
#include <mbgl/style/image.hpp>
@@ -24,14 +23,12 @@ using namespace mbgl::style;
TEST(API, RecycleMapUpdateImages) {
util::RunLoop loop;
- StubFileSource fileSource;
ThreadPool threadPool(4);
- float pixelRatio { 1 };
- HeadlessFrontend frontend { pixelRatio, threadPool };
- auto map = std::make_unique<Map>(frontend, MapObserver::nullObserver(), frontend.getSize(),
- pixelRatio, fileSource, threadPool,
- MapOptions().withMapMode(MapMode::Static));
+ HeadlessFrontend frontend { 1, threadPool };
+ auto map = std::make_unique<MapAdapter>(frontend, MapObserver::nullObserver(),
+ std::make_shared<StubFileSource>(), threadPool,
+ MapOptions().withMapMode(MapMode::Static).withSize(frontend.getSize()));
EXPECT_TRUE(map);
diff --git a/test/gl/bucket.test.cpp b/test/gl/bucket.test.cpp
index bc9f6aac5a..2be224382a 100644
--- a/test/gl/bucket.test.cpp
+++ b/test/gl/bucket.test.cpp
@@ -116,7 +116,7 @@ TEST(Buckets, SymbolBucket) {
std::vector<SymbolInstance> symbolInstances;
gl::Context context;
- SymbolBucket bucket { layout, {}, 16.0f, 1.0f, 0, sdfIcons, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(symbolInstances) };
+ SymbolBucket bucket { layout, {}, 16.0f, 1.0f, 0, sdfIcons, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(symbolInstances), 1.0f };
ASSERT_FALSE(bucket.hasIconData());
ASSERT_FALSE(bucket.hasTextData());
ASSERT_FALSE(bucket.hasCollisionBoxData());
diff --git a/test/gl/context.test.cpp b/test/gl/context.test.cpp
index 3c055c2ce0..291813bd9a 100644
--- a/test/gl/context.test.cpp
+++ b/test/gl/context.test.cpp
@@ -5,9 +5,9 @@
#include <mbgl/map/map.hpp>
#include <mbgl/map/map_options.hpp>
#include <mbgl/util/default_thread_pool.hpp>
-#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/gl/defines.hpp>
#include <mbgl/gl/headless_frontend.hpp>
+#include <mbgl/storage/resource_options.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/layers/custom_layer.hpp>
#include <mbgl/style/layers/fill_layer.hpp>
@@ -86,14 +86,13 @@ struct Buffer {
TEST(GLContextMode, Shared) {
util::RunLoop loop;
- DefaultFileSource fileSource(":memory:", "test/fixtures/api/assets");
ThreadPool threadPool(4);
- float pixelRatio { 1 };
- HeadlessFrontend frontend { pixelRatio, threadPool, {}, GLContextMode::Shared };
+ HeadlessFrontend frontend { 1, threadPool, {}, GLContextMode::Shared };
- Map map(frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio,
- fileSource, threadPool, MapOptions().withMapMode(MapMode::Static));
+ Map map(frontend, MapObserver::nullObserver(), threadPool,
+ MapOptions().withMapMode(MapMode::Static).withSize(frontend.getSize()),
+ ResourceOptions().withCachePath(":memory:").withAssetPath("test/fixtures/api/assets"));
map.getStyle().loadJSON(util::read_file("test/fixtures/api/water.json"));
map.jumpTo(CameraOptions().withCenter(LatLng { 37.8, -122.5 }).withZoom(10.0));
diff --git a/test/map/map.test.cpp b/test/map/map.test.cpp
index 410a7e76af..be92890b07 100644
--- a/test/map/map.test.cpp
+++ b/test/map/map.test.cpp
@@ -3,12 +3,13 @@
#include <mbgl/test/stub_map_observer.hpp>
#include <mbgl/test/fake_file_source.hpp>
#include <mbgl/test/fixture_log_observer.hpp>
+#include <mbgl/test/map_adapter.hpp>
-#include <mbgl/map/map.hpp>
#include <mbgl/map/map_options.hpp>
#include <mbgl/gl/context.hpp>
#include <mbgl/gl/headless_frontend.hpp>
#include <mbgl/util/default_thread_pool.hpp>
+#include <mbgl/storage/resource_options.hpp>
#include <mbgl/storage/network_status.hpp>
#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/storage/online_file_source.hpp>
@@ -31,27 +32,26 @@ template <class FileSource = StubFileSource>
class MapTest {
public:
util::RunLoop runLoop;
- FileSource fileSource;
+ std::shared_ptr<FileSource> fileSource;
ThreadPool threadPool { 4 };
StubMapObserver observer;
HeadlessFrontend frontend;
- Map map;
+ MapAdapter map;
MapTest(float pixelRatio = 1, MapMode mode = MapMode::Static)
- : frontend(pixelRatio, threadPool)
- , map(frontend, observer, frontend.getSize(), pixelRatio,
- fileSource, threadPool, MapOptions().withMapMode(mode)) {
- }
+ : fileSource(std::make_shared<FileSource>())
+ , frontend(pixelRatio, threadPool)
+ , map(frontend, observer, fileSource, threadPool,
+ MapOptions().withMapMode(mode).withSize(frontend.getSize()).withPixelRatio(pixelRatio)) {}
template <typename T = FileSource>
- MapTest(const std::string& cachePath, const std::string& assetRoot,
+ MapTest(const std::string& cachePath, const std::string& assetPath,
float pixelRatio = 1, MapMode mode = MapMode::Static,
typename std::enable_if<std::is_same<T, DefaultFileSource>::value>::type* = 0)
- : fileSource { cachePath, assetRoot }
+ : fileSource(std::make_shared<T>(cachePath, assetPath))
, frontend(pixelRatio, threadPool)
- , map(frontend, observer, frontend.getSize(), pixelRatio,
- fileSource, threadPool, MapOptions().withMapMode(mode)) {
- }
+ , map(frontend, observer, fileSource, threadPool,
+ MapOptions().withMapMode(mode).withSize(frontend.getSize()).withPixelRatio(pixelRatio)) {}
};
TEST(Map, RendererState) {
@@ -85,7 +85,7 @@ TEST(Map, RendererState) {
const ScreenCoordinate& point = test.frontend.pixelForLatLng(coordinate);
EXPECT_NEAR(coordinate.latitude(), latLng.latitude(), 1e-1);
EXPECT_NEAR(coordinate.longitude(), latLng.longitude(), 1e-1);
- const Size size = test.map.getSize();
+ const Size size = test.map.getMapOptions().size();
EXPECT_NEAR(point.x, size.width / 2.0, 1e-7);
EXPECT_NEAR(point.y, size.height / 2.0, 1e-7);
}
@@ -151,6 +151,18 @@ TEST(Map, LatLngBoundsToCamera) {
EXPECT_NEAR(*virtualCamera.zoom, 1.55467, 1e-5);
}
+TEST(Map, LatLngBoundsToCameraWithExcessivePadding) {
+ MapTest<> test;
+
+ test.map.jumpTo(CameraOptions().withCenter(LatLng { 40.712730, -74.005953 }).withZoom(16.0));
+
+ LatLngBounds bounds = LatLngBounds::hull({15.68169,73.499857}, {53.560711, 134.77281});
+
+ CameraOptions virtualCamera = test.map.cameraForLatLngBounds(bounds, {500, 0, 1200, 0});
+ ASSERT_TRUE(bounds.contains(*virtualCamera.center));
+ EXPECT_NEAR(*virtualCamera.zoom, 16.0, 1e-5);
+}
+
TEST(Map, LatLngBoundsToCameraWithBearing) {
MapTest<> test;
@@ -209,9 +221,10 @@ TEST(Map, CameraToLatLngBounds) {
test.map.jumpTo(CameraOptions().withCenter(LatLng { 45, 90 }).withZoom(16.0));
+ const Size size = test.map.getMapOptions().size();
LatLngBounds bounds = LatLngBounds::hull(
test.map.latLngForPixel({}),
- test.map.latLngForPixel({ double(test.map.getSize().width), double(test.map.getSize().height) }));
+ test.map.latLngForPixel({ double(size.width), double(size.height) }));
CameraOptions camera = test.map.getCameraOptions();
@@ -235,12 +248,12 @@ TEST(Map, Offline) {
};
const std::string prefix = "http://127.0.0.1:3000/";
- test.fileSource.put(Resource::style(prefix + "style.json"), expiredItem("style.json"));
- test.fileSource.put(Resource::source(prefix + "streets.json"), expiredItem("streets.json"));
- test.fileSource.put(Resource::spriteJSON(prefix + "sprite", 1.0), expiredItem("sprite.json"));
- test.fileSource.put(Resource::spriteImage(prefix + "sprite", 1.0), expiredItem("sprite.png"));
- test.fileSource.put(Resource::tile(prefix + "{z}-{x}-{y}.vector.pbf", 1.0, 0, 0, 0, Tileset::Scheme::XYZ), expiredItem("0-0-0.vector.pbf"));
- test.fileSource.put(Resource::glyphs(prefix + "{fontstack}/{range}.pbf", {{"Helvetica"}}, {0, 255}), expiredItem("glyph.pbf"));
+ test.fileSource->put(Resource::style(prefix + "style.json"), expiredItem("style.json"));
+ test.fileSource->put(Resource::source(prefix + "streets.json"), expiredItem("streets.json"));
+ test.fileSource->put(Resource::spriteJSON(prefix + "sprite", 1.0), expiredItem("sprite.json"));
+ test.fileSource->put(Resource::spriteImage(prefix + "sprite", 1.0), expiredItem("sprite.png"));
+ test.fileSource->put(Resource::tile(prefix + "{z}-{x}-{y}.vector.pbf", 1.0, 0, 0, 0, Tileset::Scheme::XYZ), expiredItem("0-0-0.vector.pbf"));
+ test.fileSource->put(Resource::glyphs(prefix + "{fontstack}/{range}.pbf", {{"Helvetica"}}, {0, 255}), expiredItem("glyph.pbf"));
NetworkStatus::Set(NetworkStatus::Status::Offline);
test.map.getStyle().loadURL(prefix + "style.json");
@@ -308,6 +321,39 @@ TEST(Map, DefaultBoundOptions) {
EXPECT_EQ(*bounds.bounds, LatLngBounds::unbounded());
}
+TEST(Map, MapOptions) {
+ float pixelRatio { 2 };
+ MapTest<> test { pixelRatio, MapMode::Continuous };
+
+ test.map.setNorthOrientation(NorthOrientation::Rightwards);
+ test.map.setConstrainMode(ConstrainMode::None);
+ test.map.setViewportMode(ViewportMode::FlippedY);
+ Size size = { 512, 512 };
+ test.map.setSize(size);
+
+ auto options = test.map.getMapOptions();
+ EXPECT_EQ(options.mapMode(), MapMode::Continuous);
+ EXPECT_EQ(options.viewportMode(), ViewportMode::FlippedY);
+ EXPECT_EQ(options.constrainMode(), ConstrainMode::None);
+ EXPECT_EQ(options.northOrientation(), NorthOrientation::Rightwards);
+ EXPECT_EQ(options.size(), size);
+ EXPECT_EQ(options.pixelRatio(), pixelRatio);
+}
+
+TEST(Map, DefaultMapOptions) {
+ MapTest<> test;
+
+ auto options = test.map.getMapOptions();
+ EXPECT_EQ(options.mapMode(), MapMode::Static);
+ EXPECT_EQ(options.viewportMode(), ViewportMode::Default);
+ EXPECT_EQ(options.constrainMode(), ConstrainMode::HeightOnly);
+ EXPECT_EQ(options.northOrientation(), NorthOrientation::Upwards);
+ EXPECT_TRUE(options.crossSourceCollisions());
+ EXPECT_EQ(options.size().width, 256);
+ EXPECT_EQ(options.size().height, 256);
+ EXPECT_EQ(options.pixelRatio(), 1);
+}
+
TEST(Map, SetStyleInvalidJSON) {
Log::setObserver(std::make_unique<FixtureLogObserver>());
@@ -334,7 +380,7 @@ TEST(Map, SetStyleInvalidJSON) {
TEST(Map, SetStyleInvalidURL) {
MapTest<> test;
- test.fileSource.styleResponse = [] (const Resource&) {
+ test.fileSource->styleResponse = [] (const Resource&) {
Response response;
response.error = std::make_unique<Response::Error>(
Response::Error::Reason::Other,
@@ -364,14 +410,14 @@ TEST(Map, StyleFresh) {
MapTest<FakeFileSource> test;
test.map.getStyle().loadURL("mapbox://styles/test");
- EXPECT_EQ(1u, test.fileSource.requests.size());
+ EXPECT_EQ(1u, test.fileSource->requests.size());
Response response;
response.data = std::make_shared<std::string>(util::read_file("test/fixtures/api/empty.json"));
response.expires = Timestamp::max();
- test.fileSource.respond(Resource::Style, response);
- EXPECT_EQ(1u, test.fileSource.requests.size());
+ test.fileSource->respond(Resource::Style, response);
+ EXPECT_EQ(1u, test.fileSource->requests.size());
}
TEST(Map, StyleExpired) {
@@ -382,31 +428,31 @@ TEST(Map, StyleExpired) {
MapTest<FakeFileSource> test;
test.map.getStyle().loadURL("mapbox://styles/test");
- EXPECT_EQ(1u, test.fileSource.requests.size());
+ EXPECT_EQ(1u, test.fileSource->requests.size());
Response response;
response.data = std::make_shared<std::string>(util::read_file("test/fixtures/api/empty.json"));
response.expires = util::now() - 1h;
- test.fileSource.respond(Resource::Style, response);
- EXPECT_EQ(1u, test.fileSource.requests.size());
+ test.fileSource->respond(Resource::Style, response);
+ EXPECT_EQ(1u, test.fileSource->requests.size());
// Mutate layer. From now on, sending a response to the style won't overwrite it anymore, but
// we should continue to wait for a fresh response.
test.map.getStyle().addLayer(std::make_unique<style::BackgroundLayer>("bg"));
- EXPECT_EQ(1u, test.fileSource.requests.size());
+ EXPECT_EQ(1u, test.fileSource->requests.size());
// Send another expired response, and confirm that we didn't overwrite the style, but continue
// to wait for a fresh response.
- test.fileSource.respond(Resource::Style, response);
- EXPECT_EQ(1u, test.fileSource.requests.size());
+ test.fileSource->respond(Resource::Style, response);
+ EXPECT_EQ(1u, test.fileSource->requests.size());
EXPECT_NE(nullptr, test.map.getStyle().getLayer("bg"));
// Send a fresh response, and confirm that we didn't overwrite the style, but continue to wait
// for a fresh response.
response.expires = util::now() + 1h;
- test.fileSource.respond(Resource::Style, response);
- EXPECT_EQ(1u, test.fileSource.requests.size());
+ test.fileSource->respond(Resource::Style, response);
+ EXPECT_EQ(1u, test.fileSource->requests.size());
EXPECT_NE(nullptr, test.map.getStyle().getLayer("bg"));
}
@@ -418,20 +464,20 @@ TEST(Map, StyleExpiredWithAnnotations) {
MapTest<FakeFileSource> test;
test.map.getStyle().loadURL("mapbox://styles/test");
- EXPECT_EQ(1u, test.fileSource.requests.size());
+ EXPECT_EQ(1u, test.fileSource->requests.size());
Response response;
response.data = std::make_shared<std::string>(util::read_file("test/fixtures/api/empty.json"));
response.expires = util::now() - 1h;
- test.fileSource.respond(Resource::Style, response);
- EXPECT_EQ(1u, test.fileSource.requests.size());
+ test.fileSource->respond(Resource::Style, response);
+ EXPECT_EQ(1u, test.fileSource->requests.size());
test.map.addAnnotation(LineAnnotation { LineString<double> {{ { 0, 0 }, { 10, 10 } }} });
- EXPECT_EQ(1u, test.fileSource.requests.size());
+ EXPECT_EQ(1u, test.fileSource->requests.size());
- test.fileSource.respond(Resource::Style, response);
- EXPECT_EQ(1u, test.fileSource.requests.size());
+ test.fileSource->respond(Resource::Style, response);
+ EXPECT_EQ(1u, test.fileSource->requests.size());
}
TEST(Map, StyleExpiredWithRender) {
@@ -442,20 +488,20 @@ TEST(Map, StyleExpiredWithRender) {
MapTest<FakeFileSource> test;
test.map.getStyle().loadURL("mapbox://styles/test");
- EXPECT_EQ(1u, test.fileSource.requests.size());
+ EXPECT_EQ(1u, test.fileSource->requests.size());
Response response;
response.data = std::make_shared<std::string>(util::read_file("test/fixtures/api/empty.json"));
response.expires = util::now() - 1h;
- test.fileSource.respond(Resource::Style, response);
- EXPECT_EQ(1u, test.fileSource.requests.size());
+ test.fileSource->respond(Resource::Style, response);
+ EXPECT_EQ(1u, test.fileSource->requests.size());
test.frontend.render(test.map);
- EXPECT_EQ(1u, test.fileSource.requests.size());
+ EXPECT_EQ(1u, test.fileSource->requests.size());
- test.fileSource.respond(Resource::Style, response);
- EXPECT_EQ(1u, test.fileSource.requests.size());
+ test.fileSource->respond(Resource::Style, response);
+ EXPECT_EQ(1u, test.fileSource->requests.size());
}
TEST(Map, StyleEarlyMutation) {
@@ -468,9 +514,9 @@ TEST(Map, StyleEarlyMutation) {
Response response;
response.data = std::make_shared<std::string>(util::read_file("test/fixtures/api/water.json"));
- test.fileSource.respond(Resource::Style, response);
+ test.fileSource->respond(Resource::Style, response);
- EXPECT_EQ(1u, test.fileSource.requests.size());
+ EXPECT_EQ(1u, test.fileSource->requests.size());
EXPECT_NE(nullptr, test.map.getStyle().getLayer("water"));
}
@@ -592,7 +638,7 @@ TEST(Map, DisabledSources) {
MapTest<> test;
// Always load the same image tile for raster layers.
- test.fileSource.response = [] (const Resource& res) -> optional<Response> {
+ test.fileSource->response = [] (const Resource& res) -> optional<Response> {
if (res.url == "asset://tile.png") {
Response response;
response.data = std::make_shared<std::string>(
@@ -668,7 +714,7 @@ TEST(Map, DontLoadUnneededTiles) {
using Tiles = std::unordered_set<std::string>;
Tiles tiles;
- test.fileSource.tileResponse = [&](const Resource& rsc) {
+ test.fileSource->tileResponse = [&](const Resource& rsc) {
tiles.emplace(rsc.url);
Response res;
res.noContent = true;
@@ -698,8 +744,6 @@ TEST(Map, DontLoadUnneededTiles) {
TEST(Map, TEST_DISABLED_ON_CI(ContinuousRendering)) {
util::RunLoop runLoop;
ThreadPool threadPool { 4 };
- DefaultFileSource fileSource(":memory:", "test/fixtures/api/assets");
- float pixelRatio { 1 };
using namespace std::chrono_literals;
@@ -711,7 +755,7 @@ TEST(Map, TEST_DISABLED_ON_CI(ContinuousRendering)) {
util::Timer timer;
- HeadlessFrontend frontend(pixelRatio, threadPool);
+ HeadlessFrontend frontend(1, threadPool);
StubMapObserver observer;
observer.didFinishRenderingFrameCallback = [&] (MapObserver::RenderMode) {
@@ -723,8 +767,9 @@ TEST(Map, TEST_DISABLED_ON_CI(ContinuousRendering)) {
});
};
- Map map(frontend, observer, frontend.getSize(), pixelRatio, fileSource,
- threadPool, MapOptions().withMapMode(MapMode::Continuous));
+ Map map(frontend, observer, threadPool,
+ MapOptions().withMapMode(MapMode::Continuous).withSize(frontend.getSize()),
+ ResourceOptions().withCachePath(":memory:").withAssetPath("test/fixtures/api/assets"));
map.getStyle().loadJSON(util::read_file("test/fixtures/api/water.json"));
runLoop.run();
@@ -739,7 +784,7 @@ TEST(Map, NoContentTiles) {
Response response;
response.noContent = true;
response.expires = util::now() + 1h;
- test.fileSource.put(Resource::tile("http://example.com/{z}-{x}-{y}.vector.pbf", 1.0, 0, 0, 0,
+ test.fileSource->put(Resource::tile("http://example.com/{z}-{x}-{y}.vector.pbf", 1.0, 0, 0, 0,
Tileset::Scheme::XYZ),
response);
@@ -776,7 +821,7 @@ TEST(Map, NoContentTiles) {
TEST(Map, Issue12432) {
MapTest<> test { 1, MapMode::Continuous };
- test.fileSource.tileResponse = [&](const Resource&) {
+ test.fileSource->tileResponse = [&](const Resource&) {
Response result;
result.data = std::make_shared<std::string>(util::read_file("test/fixtures/map/issue12432/0-0-0.mvt"));
return result;
diff --git a/test/map/prefetch.test.cpp b/test/map/prefetch.test.cpp
index dfde3a779b..3232c99a22 100644
--- a/test/map/prefetch.test.cpp
+++ b/test/map/prefetch.test.cpp
@@ -1,11 +1,10 @@
#include <mbgl/test/util.hpp>
#include <mbgl/test/stub_file_source.hpp>
#include <mbgl/test/stub_map_observer.hpp>
+#include <mbgl/test/map_adapter.hpp>
-#include <mbgl/map/map.hpp>
#include <mbgl/map/map_options.hpp>
#include <mbgl/gl/headless_frontend.hpp>
-#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/util/default_thread_pool.hpp>
#include <mbgl/util/image.hpp>
@@ -24,7 +23,7 @@ using namespace std::chrono_literals;
TEST(Map, PrefetchTiles) {
util::RunLoop runLoop;
ThreadPool threadPool(4);
- StubFileSource fileSource;
+ std::shared_ptr<StubFileSource> fileSource = std::make_shared<StubFileSource>();
util::Timer emergencyShutoff;
emergencyShutoff.start(10s, 0s, [&] {
@@ -38,12 +37,12 @@ TEST(Map, PrefetchTiles) {
};
HeadlessFrontend frontend { { 512, 512 }, 1, threadPool };
- Map map(frontend, observer, frontend.getSize(), 1, fileSource, threadPool,
- MapOptions().withMapMode(MapMode::Continuous));
+ MapAdapter map(frontend, observer, fileSource, threadPool,
+ MapOptions().withMapMode(MapMode::Continuous).withSize(frontend.getSize()));
std::vector<int> tiles;
- fileSource.response = [&] (const Resource& res) -> optional<Response> {
+ fileSource->response = [&] (const Resource& res) -> optional<Response> {
static std::string tile = util::read_file("test/fixtures/map/prefetch/tile.png");
auto zoom = std::stoi(res.url);
diff --git a/test/programs/symbol_program.test.cpp b/test/programs/symbol_program.test.cpp
index 4d30e5dc3d..28d734c21a 100644
--- a/test/programs/symbol_program.test.cpp
+++ b/test/programs/symbol_program.test.cpp
@@ -9,9 +9,9 @@ using namespace mbgl::style::expression::dsl;
TEST(SymbolProgram, SymbolSizeBinder) {
auto binder = SymbolSizeBinder::create(5.0f, 12.0f, 0.0f);
auto uniformValues = binder->uniformValues(5.5f);
- EXPECT_EQ(uniformValues.get<uniforms::u_is_size_zoom_constant>(), true);
- EXPECT_EQ(uniformValues.get<uniforms::u_is_size_feature_constant>(), true);
- EXPECT_EQ(uniformValues.get<uniforms::u_size>(), 12.0f);
+ EXPECT_EQ(uniformValues.get<uniforms::is_size_zoom_constant>(), true);
+ EXPECT_EQ(uniformValues.get<uniforms::is_size_feature_constant>(), true);
+ EXPECT_EQ(uniformValues.get<uniforms::size>(), 12.0f);
binder = SymbolSizeBinder::create(1.0f, style::PropertyExpression<float>(
interpolate(
@@ -20,9 +20,9 @@ TEST(SymbolProgram, SymbolSizeBinder) {
0., literal(8.),
10., literal(18.))), 0.0f);
uniformValues = binder->uniformValues(1.5f);
- EXPECT_EQ(uniformValues.get<uniforms::u_is_size_zoom_constant>(), false);
- EXPECT_EQ(uniformValues.get<uniforms::u_is_size_feature_constant>(), true);
- EXPECT_EQ(uniformValues.get<uniforms::u_size>(), 9.5f);
+ EXPECT_EQ(uniformValues.get<uniforms::is_size_zoom_constant>(), false);
+ EXPECT_EQ(uniformValues.get<uniforms::is_size_feature_constant>(), true);
+ EXPECT_EQ(uniformValues.get<uniforms::size>(), 9.5f);
binder = SymbolSizeBinder::create(0.0f, style::PropertyExpression<float>(
interpolate(
@@ -31,9 +31,9 @@ TEST(SymbolProgram, SymbolSizeBinder) {
1., literal(8.),
11., literal(18.))), 0.0f);
uniformValues = binder->uniformValues(0.5f);
- EXPECT_EQ(uniformValues.get<uniforms::u_is_size_zoom_constant>(), false);
- EXPECT_EQ(uniformValues.get<uniforms::u_is_size_feature_constant>(), true);
- EXPECT_EQ(uniformValues.get<uniforms::u_size>(), 8.0f);
+ EXPECT_EQ(uniformValues.get<uniforms::is_size_zoom_constant>(), false);
+ EXPECT_EQ(uniformValues.get<uniforms::is_size_feature_constant>(), true);
+ EXPECT_EQ(uniformValues.get<uniforms::size>(), 8.0f);
binder = SymbolSizeBinder::create(12.0f, style::PropertyExpression<float>(
interpolate(
@@ -42,9 +42,9 @@ TEST(SymbolProgram, SymbolSizeBinder) {
1., literal(8.),
11., literal(18.))), 0.0f);
uniformValues = binder->uniformValues(12.5f);
- EXPECT_EQ(uniformValues.get<uniforms::u_is_size_zoom_constant>(), false);
- EXPECT_EQ(uniformValues.get<uniforms::u_is_size_feature_constant>(), true);
- EXPECT_EQ(uniformValues.get<uniforms::u_size>(), 18.0f);
+ EXPECT_EQ(uniformValues.get<uniforms::is_size_zoom_constant>(), false);
+ EXPECT_EQ(uniformValues.get<uniforms::is_size_feature_constant>(), true);
+ EXPECT_EQ(uniformValues.get<uniforms::size>(), 18.0f);
binder = SymbolSizeBinder::create(0.0f, style::PropertyExpression<float>(
interpolate(
@@ -53,8 +53,8 @@ TEST(SymbolProgram, SymbolSizeBinder) {
1., literal(8.),
11., literal(18.))), 0.0f);
uniformValues = binder->uniformValues(12.5f);
- EXPECT_EQ(uniformValues.get<uniforms::u_is_size_zoom_constant>(), true);
- EXPECT_EQ(uniformValues.get<uniforms::u_is_size_feature_constant>(), false);
+ EXPECT_EQ(uniformValues.get<uniforms::is_size_zoom_constant>(), true);
+ EXPECT_EQ(uniformValues.get<uniforms::is_size_feature_constant>(), false);
binder = SymbolSizeBinder::create(5.0f, style::PropertyExpression<float>(
interpolate(
@@ -63,7 +63,7 @@ TEST(SymbolProgram, SymbolSizeBinder) {
1., interpolate(linear(), number(get("x")), 0., literal(8.), 100., literal(18.)),
11., interpolate(linear(), number(get("x")), 0., literal(12.), 100., literal(24.9)))), 0.0f);
uniformValues = binder->uniformValues(5.5f);
- EXPECT_EQ(uniformValues.get<uniforms::u_is_size_zoom_constant>(), false);
- EXPECT_EQ(uniformValues.get<uniforms::u_is_size_feature_constant>(), false);
- EXPECT_EQ(uniformValues.get<uniforms::u_size_t>(), 0.45f);
+ EXPECT_EQ(uniformValues.get<uniforms::is_size_zoom_constant>(), false);
+ EXPECT_EQ(uniformValues.get<uniforms::is_size_feature_constant>(), false);
+ EXPECT_EQ(uniformValues.get<uniforms::size_t>(), 0.45f);
}
diff --git a/test/renderer/image_manager.test.cpp b/test/renderer/image_manager.test.cpp
index 4a838d0f9c..b73d9b5c7a 100644
--- a/test/renderer/image_manager.test.cpp
+++ b/test/renderer/image_manager.test.cpp
@@ -1,9 +1,9 @@
#include <mbgl/test/util.hpp>
#include <mbgl/test/fixture_log_observer.hpp>
-#include <mbgl/test/stub_file_source.hpp>
#include <mbgl/test/stub_style_observer.hpp>
#include <mbgl/renderer/image_manager.hpp>
+#include <mbgl/renderer/image_manager_observer.hpp>
#include <mbgl/sprite/sprite_parser.hpp>
#include <mbgl/style/image_impl.hpp>
#include <mbgl/util/io.hpp>
@@ -108,11 +108,11 @@ TEST(ImageManager, RemoveReleasesBinPackRect) {
class StubImageRequestor : public ImageRequestor {
public:
- void onImagesAvailable(ImageMap icons, ImageMap patterns, uint64_t imageCorrelationID_) final {
- if (imagesAvailable && imageCorrelationID == imageCorrelationID_) imagesAvailable(icons, patterns);
+ void onImagesAvailable(ImageMap icons, ImageMap patterns, std::unordered_map<std::string, uint32_t> versionMap, uint64_t imageCorrelationID_) final {
+ if (imagesAvailable && imageCorrelationID == imageCorrelationID_) imagesAvailable(icons, patterns, versionMap);
}
- std::function<void (ImageMap, ImageMap)> imagesAvailable;
+ std::function<void (ImageMap, ImageMap, std::unordered_map<std::string, uint32_t>)> imagesAvailable;
uint64_t imageCorrelationID = 0;
};
@@ -121,7 +121,10 @@ TEST(ImageManager, NotifiesRequestorWhenSpriteIsLoaded) {
StubImageRequestor requestor;
bool notified = false;
- requestor.imagesAvailable = [&] (ImageMap, ImageMap) {
+ ImageManagerObserver observer;
+ imageManager.setObserver(&observer);
+
+ requestor.imagesAvailable = [&] (ImageMap, ImageMap, std::unordered_map<std::string, uint32_t>) {
notified = true;
};
@@ -132,6 +135,8 @@ TEST(ImageManager, NotifiesRequestorWhenSpriteIsLoaded) {
ASSERT_FALSE(notified);
imageManager.setLoaded(true);
+ ASSERT_FALSE(notified);
+ imageManager.notifyIfMissingImageAdded();
ASSERT_TRUE(notified);
}
@@ -140,7 +145,7 @@ TEST(ImageManager, NotifiesRequestorImmediatelyIfDependenciesAreSatisfied) {
StubImageRequestor requestor;
bool notified = false;
- requestor.imagesAvailable = [&] (ImageMap, ImageMap) {
+ requestor.imagesAvailable = [&] (ImageMap, ImageMap, std::unordered_map<std::string, uint32_t>) {
notified = true;
};
diff --git a/test/src/mbgl/test/map_adapter.hpp b/test/src/mbgl/test/map_adapter.hpp
new file mode 100644
index 0000000000..5bdab1d164
--- /dev/null
+++ b/test/src/mbgl/test/map_adapter.hpp
@@ -0,0 +1,21 @@
+#pragma once
+
+#include <mbgl/map/map.hpp>
+#include <mbgl/map/map_impl.hpp>
+
+namespace mbgl {
+
+class FileSource;
+
+// Non-public version of mbgl::Map that accepts a file source as parameter.
+class MapAdapter : public Map {
+public:
+ explicit MapAdapter(RendererFrontend& frontend,
+ MapObserver& observer,
+ std::shared_ptr<FileSource> fileSource,
+ Scheduler& scheduler,
+ const MapOptions& options)
+ : Map(std::make_unique<Map::Impl>(frontend, observer, scheduler, std::move(fileSource), options)) {}
+};
+
+} // namespace mbgl
diff --git a/test/style/style_layer.test.cpp b/test/style/style_layer.test.cpp
index e58a5fe5d0..7598d888e9 100644
--- a/test/style/style_layer.test.cpp
+++ b/test/style/style_layer.test.cpp
@@ -1,4 +1,5 @@
#include <mbgl/style/expression/dsl.hpp>
+#include <mbgl/style/expression/match.hpp>
#include <mbgl/style/expression/format_expression.hpp>
#include <mbgl/style/style_impl.hpp>
#include <mbgl/style/layers/background_layer.hpp>
@@ -330,6 +331,17 @@ void testHasOverrides(LayoutType& layout) {
PropertyExpression<Formatted> propExprOverride(std::move(formatExprOverride));
layout.template get<TextField>() = PropertyValueType<Formatted>(std::move(propExprOverride));
EXPECT_TRUE(MockOverrides::hasOverrides(layout.template get<TextField>()));
+
+ // Nested expressions, overridden text-color.
+ auto formattedExpr1 = format("first paragraph");
+ std::vector<FormatExpressionSection> sections{ { literal("second paragraph"), nullopt, nullopt, toColor(literal("blue")) } };
+ auto formattedExpr2 = std::make_unique<FormatExpression>(std::move(sections));
+ std::unordered_map<std::string, std::shared_ptr<Expression>> branches{ { "1st", std::move(formattedExpr1) },
+ { "2nd", std::move(formattedExpr2) } };
+ auto match = std::make_unique<Match<std::string>>(type::Formatted, literal("input"), std::move(branches), format("otherwise"));
+ PropertyExpression<Formatted> nestedPropExpr(std::move(match));
+ layout.template get<TextField>() = PropertyValueType<Formatted>(std::move(nestedPropExpr));
+ EXPECT_TRUE(MockOverrides::hasOverrides(layout.template get<TextField>()));
}
} // namespace
diff --git a/test/test-files.json b/test/test-files.json
index 498237e072..58970689be 100644
--- a/test/test-files.json
+++ b/test/test-files.json
@@ -114,6 +114,7 @@
"mbgl/test/fake_file_source.hpp": "test/src/mbgl/test/fake_file_source.hpp",
"mbgl/test/fixture_log_observer.hpp": "test/src/mbgl/test/fixture_log_observer.hpp",
"mbgl/test/getrss.hpp": "test/src/mbgl/test/getrss.hpp",
+ "mbgl/test/map_adapter.hpp": "test/src/mbgl/test/map_adapter.hpp",
"mbgl/test/mock.hpp": "test/src/mbgl/test/mock.hpp",
"mbgl/test/sqlite3_test_fs.hpp": "test/src/mbgl/test/sqlite3_test_fs.hpp",
"mbgl/test/stub_file_source.hpp": "test/src/mbgl/test/stub_file_source.hpp",
diff --git a/test/text/cross_tile_symbol_index.test.cpp b/test/text/cross_tile_symbol_index.test.cpp
index 67f82413b2..f121781766 100644
--- a/test/text/cross_tile_symbol_index.test.cpp
+++ b/test/text/cross_tile_symbol_index.test.cpp
@@ -7,11 +7,11 @@ using namespace mbgl;
SymbolInstance makeSymbolInstance(float x, float y, std::u16string key) {
GeometryCoordinates line;
GlyphPositions positions;
- const std::pair<Shaping, Shaping> shaping(Shaping{}, Shaping{});
+ const ShapedTextOrientations shaping{};
style::SymbolLayoutProperties::Evaluated layout_;
IndexedSubfeature subfeature(0, "", "", 0);
Anchor anchor(x, y, 0, 0);
- return {anchor, line, shaping, {}, layout_, 0, 0, 0, style::SymbolPlacementType::Point, {{0, 0}}, 0, 0, {{0, 0}}, positions, subfeature, 0, 0, key, 0, 0};
+ return SymbolInstance(anchor, line, shaping, {}, layout_, 0, 0, 0, style::SymbolPlacementType::Point, {{0, 0}}, 0, 0, {{0, 0}}, positions, subfeature, 0, 0, key, 0, 0, 0.0f);
}
@@ -31,7 +31,7 @@ TEST(CrossTileSymbolLayerIndex, addBucket) {
std::vector<SymbolInstance> mainInstances;
mainInstances.push_back(makeSymbolInstance(1000, 1000, u"Detroit"));
mainInstances.push_back(makeSymbolInstance(2000, 2000, u"Toronto"));
- SymbolBucket mainBucket { layout, {}, 16.0f, 1.0f, 0, sdfIcons, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(mainInstances) };
+ SymbolBucket mainBucket { layout, {}, 16.0f, 1.0f, 0, sdfIcons, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(mainInstances), 1.0f };
mainBucket.bucketInstanceId = ++maxBucketInstanceId;
index.addBucket(mainID, mainBucket, maxCrossTileID);
@@ -46,7 +46,7 @@ TEST(CrossTileSymbolLayerIndex, addBucket) {
childInstances.push_back(makeSymbolInstance(2000, 2000, u"Windsor"));
childInstances.push_back(makeSymbolInstance(3000, 3000, u"Toronto"));
childInstances.push_back(makeSymbolInstance(4001, 4001, u"Toronto"));
- SymbolBucket childBucket { layout, {}, 16.0f, 1.0f, 0, sdfIcons, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(childInstances) };
+ SymbolBucket childBucket { layout, {}, 16.0f, 1.0f, 0, sdfIcons, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(childInstances), 1.0f };
childBucket.bucketInstanceId = ++maxBucketInstanceId;
index.addBucket(childID, childBucket, maxCrossTileID);
@@ -62,7 +62,7 @@ TEST(CrossTileSymbolLayerIndex, addBucket) {
OverscaledTileID parentID(5, 0, 5, 4, 4);
std::vector<SymbolInstance> parentInstances;
parentInstances.push_back(makeSymbolInstance(500, 500, u"Detroit"));
- SymbolBucket parentBucket { layout, {}, 16.0f, 1.0f, 0, sdfIcons, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(parentInstances) };
+ SymbolBucket parentBucket { layout, {}, 16.0f, 1.0f, 0, sdfIcons, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(parentInstances), 1.0f };
parentBucket.bucketInstanceId = ++maxBucketInstanceId;
index.addBucket(parentID, parentBucket, maxCrossTileID);
@@ -78,7 +78,7 @@ TEST(CrossTileSymbolLayerIndex, addBucket) {
std::vector<SymbolInstance> grandchildInstances;
grandchildInstances.push_back(makeSymbolInstance(4000, 4000, u"Detroit"));
grandchildInstances.push_back(makeSymbolInstance(4000, 4000, u"Windsor"));
- SymbolBucket grandchildBucket { layout, {}, 16.0f, 1.0f, 0, sdfIcons, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(grandchildInstances) };
+ SymbolBucket grandchildBucket { layout, {}, 16.0f, 1.0f, 0, sdfIcons, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(grandchildInstances), 1.0f };
grandchildBucket.bucketInstanceId = ++maxBucketInstanceId;
index.addBucket(grandchildID, grandchildBucket, maxCrossTileID);
@@ -104,13 +104,13 @@ TEST(CrossTileSymbolLayerIndex, resetIDs) {
OverscaledTileID mainID(6, 0, 6, 8, 8);
std::vector<SymbolInstance> mainInstances;
mainInstances.push_back(makeSymbolInstance(1000, 1000, u"Detroit"));
- SymbolBucket mainBucket { layout, {}, 16.0f, 1.0f, 0, sdfIcons, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(mainInstances) };
+ SymbolBucket mainBucket { layout, {}, 16.0f, 1.0f, 0, sdfIcons, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(mainInstances), 1.0f };
mainBucket.bucketInstanceId = ++maxBucketInstanceId;
OverscaledTileID childID(7, 0, 7, 16, 16);
std::vector<SymbolInstance> childInstances;
childInstances.push_back(makeSymbolInstance(2000, 2000, u"Detroit"));
- SymbolBucket childBucket { layout, {}, 16.0f, 1.0f, 0, sdfIcons, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(childInstances) };
+ SymbolBucket childBucket { layout, {}, 16.0f, 1.0f, 0, sdfIcons, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(childInstances), 1.0f };
childBucket.bucketInstanceId = ++maxBucketInstanceId;
// assigns a new id
@@ -145,7 +145,7 @@ TEST(CrossTileSymbolLayerIndex, noDuplicatesWithinZoomLevel) {
std::vector<SymbolInstance> mainInstances;
mainInstances.push_back(makeSymbolInstance(1000, 1000, u"")); // A
mainInstances.push_back(makeSymbolInstance(1000, 1000, u"")); // B
- SymbolBucket mainBucket { layout, {}, 16.0f, 1.0f, 0, sdfIcons, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(mainInstances) };
+ SymbolBucket mainBucket { layout, {}, 16.0f, 1.0f, 0, sdfIcons, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(mainInstances), 1.0f };
mainBucket.bucketInstanceId = ++maxBucketInstanceId;
OverscaledTileID childID(7, 0, 7, 16, 16);
@@ -153,7 +153,7 @@ TEST(CrossTileSymbolLayerIndex, noDuplicatesWithinZoomLevel) {
childInstances.push_back(makeSymbolInstance(2000, 2000, u"")); // A'
childInstances.push_back(makeSymbolInstance(2000, 2000, u"")); // B'
childInstances.push_back(makeSymbolInstance(2000, 2000, u"")); // C'
- SymbolBucket childBucket { layout, {}, 16.0f, 1.0f, 0, sdfIcons, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(childInstances) };
+ SymbolBucket childBucket { layout, {}, 16.0f, 1.0f, 0, sdfIcons, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(childInstances), 1.0f };
childBucket.bucketInstanceId = ++maxBucketInstanceId;
// assigns new ids
@@ -183,14 +183,14 @@ TEST(CrossTileSymbolLayerIndex, bucketReplacement) {
std::vector<SymbolInstance> firstInstances;
firstInstances.push_back(makeSymbolInstance(1000, 1000, u"")); // A
firstInstances.push_back(makeSymbolInstance(1000, 1000, u"")); // B
- SymbolBucket firstBucket { layout, {}, 16.0f, 1.0f, 0, sdfIcons, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(firstInstances) };
+ SymbolBucket firstBucket { layout, {}, 16.0f, 1.0f, 0, sdfIcons, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(firstInstances), 1.0f };
firstBucket.bucketInstanceId = ++maxBucketInstanceId;
std::vector<SymbolInstance> secondInstances;
secondInstances.push_back(makeSymbolInstance(1000, 1000, u"")); // A'
secondInstances.push_back(makeSymbolInstance(1000, 1000, u"")); // B'
secondInstances.push_back(makeSymbolInstance(1000, 1000, u"")); // C'
- SymbolBucket secondBucket { layout, {}, 16.0f, 1.0f, 0, sdfIcons, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(secondInstances) };
+ SymbolBucket secondBucket { layout, {}, 16.0f, 1.0f, 0, sdfIcons, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(secondInstances), 1.0f };
secondBucket.bucketInstanceId = ++maxBucketInstanceId;
// assigns new ids
diff --git a/test/text/local_glyph_rasterizer.test.cpp b/test/text/local_glyph_rasterizer.test.cpp
index d0fdb5ee57..26e4a2eb1d 100644
--- a/test/text/local_glyph_rasterizer.test.cpp
+++ b/test/text/local_glyph_rasterizer.test.cpp
@@ -1,6 +1,7 @@
#include <mbgl/test/util.hpp>
#include <mbgl/test/stub_file_source.hpp>
-#include <mbgl/map/map.hpp>
+#include <mbgl/test/map_adapter.hpp>
+
#include <mbgl/map/map_options.hpp>
#include <mbgl/util/io.hpp>
#include <mbgl/util/run_loop.hpp>
@@ -33,17 +34,16 @@ namespace {
class LocalGlyphRasterizerTest {
public:
LocalGlyphRasterizerTest(const optional<std::string> fontFamily)
- : frontend(pixelRatio, threadPool, optional<std::string>(), GLContextMode::Unique, fontFamily)
+ : frontend(1, threadPool, optional<std::string>(), GLContextMode::Unique, fontFamily)
{
}
util::RunLoop loop;
- StubFileSource fileSource;
+ std::shared_ptr<StubFileSource> fileSource = std::make_shared<StubFileSource>();
ThreadPool threadPool { 4 };
- float pixelRatio { 1 };
HeadlessFrontend frontend;
- Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, fileSource,
- threadPool, MapOptions().withMapMode(MapMode::Static)};
+ MapAdapter map { frontend, MapObserver::nullObserver(), fileSource, threadPool,
+ MapOptions().withMapMode(MapMode::Static).withSize(frontend.getSize())};
void checkRendering(const char * name) {
test::checkImage(std::string("test/fixtures/local_glyphs/") + name,
@@ -59,7 +59,7 @@ public:
TEST(LocalGlyphRasterizer, PingFang) {
LocalGlyphRasterizerTest test(std::string("PingFang"));
- test.fileSource.glyphsResponse = [&] (const Resource& resource) {
+ test.fileSource->glyphsResponse = [&] (const Resource& resource) {
EXPECT_EQ(Resource::Kind::Glyphs, resource.kind);
Response response;
response.data = std::make_shared<std::string>(util::read_file("test/fixtures/resources/glyphs.pbf"));
@@ -80,7 +80,7 @@ TEST(LocalGlyphRasterizer, NoLocal) {
// the output should just contain basic latin characters.
LocalGlyphRasterizerTest test({});
- test.fileSource.glyphsResponse = [&] (const Resource& resource) {
+ test.fileSource->glyphsResponse = [&] (const Resource& resource) {
EXPECT_EQ(Resource::Kind::Glyphs, resource.kind);
Response response;
response.data = std::make_shared<std::string>(util::read_file("test/fixtures/resources/glyphs.pbf"));
diff --git a/test/util/memory.test.cpp b/test/util/memory.test.cpp
index 36bed57ab5..e3ad976432 100644
--- a/test/util/memory.test.cpp
+++ b/test/util/memory.test.cpp
@@ -1,8 +1,8 @@
#include <mbgl/test/stub_file_source.hpp>
#include <mbgl/test/getrss.hpp>
#include <mbgl/test/util.hpp>
+#include <mbgl/test/map_adapter.hpp>
-#include <mbgl/map/map.hpp>
#include <mbgl/map/map_options.hpp>
#include <mbgl/gl/headless_frontend.hpp>
#include <mbgl/util/default_thread_pool.hpp>
@@ -16,6 +16,7 @@
#include <string>
#include <unordered_map>
#include <utility>
+#include <memory>
#include <cstdlib>
#include <unistd.h>
@@ -26,16 +27,16 @@ using namespace std::literals::string_literals;
class MemoryTest {
public:
MemoryTest() {
- fileSource.styleResponse = [&](const Resource& res) { return response("style_" + getType(res) + ".json");};
- fileSource.tileResponse = [&](const Resource& res) { return response(getType(res) + ".tile"); };
- fileSource.sourceResponse = [&](const Resource& res) { return response("source_" + getType(res) + ".json"); };
- fileSource.glyphsResponse = [&](const Resource&) { return response("glyphs.pbf"); };
- fileSource.spriteJSONResponse = [&](const Resource&) { return response("sprite.json"); };
- fileSource.spriteImageResponse = [&](const Resource&) { return response("sprite.png"); };
+ fileSource->styleResponse = [&](const Resource& res) { return response("style_" + getType(res) + ".json");};
+ fileSource->tileResponse = [&](const Resource& res) { return response(getType(res) + ".tile"); };
+ fileSource->sourceResponse = [&](const Resource& res) { return response("source_" + getType(res) + ".json"); };
+ fileSource->glyphsResponse = [&](const Resource&) { return response("glyphs.pbf"); };
+ fileSource->spriteJSONResponse = [&](const Resource&) { return response("sprite.json"); };
+ fileSource->spriteImageResponse = [&](const Resource&) { return response("sprite.png"); };
}
util::RunLoop runLoop;
- StubFileSource fileSource;
+ std::shared_ptr<StubFileSource> fileSource = std::make_shared<StubFileSource>();
ThreadPool threadPool { 4 };
private:
@@ -72,8 +73,8 @@ TEST(Memory, Vector) {
float ratio { 2 };
HeadlessFrontend frontend { { 256, 256 }, ratio, test.threadPool };
- Map map(frontend, MapObserver::nullObserver(), frontend.getSize(), ratio, test.fileSource,
- test.threadPool, MapOptions().withMapMode(MapMode::Static));
+ MapAdapter map(frontend, MapObserver::nullObserver(), test.fileSource, test.threadPool,
+ MapOptions().withMapMode(MapMode::Static).withSize(frontend.getSize()).withPixelRatio(ratio));
map.jumpTo(CameraOptions().withZoom(16));
map.getStyle().loadURL("mapbox://streets");
@@ -85,8 +86,8 @@ TEST(Memory, Raster) {
float ratio { 2 };
HeadlessFrontend frontend { { 256, 256 }, ratio, test.threadPool };
- Map map(frontend, MapObserver::nullObserver(), frontend.getSize(), ratio, test.fileSource,
- test.threadPool, MapOptions().withMapMode(MapMode::Static));
+ MapAdapter map(frontend, MapObserver::nullObserver(), test.fileSource, test.threadPool,
+ MapOptions().withMapMode(MapMode::Static).withSize(frontend.getSize()).withPixelRatio(ratio));
map.getStyle().loadURL("mapbox://satellite");
frontend.render(map);
@@ -123,15 +124,15 @@ TEST(Memory, Footprint) {
public:
FrontendAndMap(MemoryTest& test_, const char* style)
: frontend(Size{ 256, 256 }, 2, test_.threadPool)
- , map(frontend, MapObserver::nullObserver(), frontend.getSize(), 2, test_.fileSource
- , test_.threadPool, MapOptions().withMapMode(MapMode::Static)) {
+ , map(frontend, MapObserver::nullObserver(), test_.fileSource, test_.threadPool,
+ MapOptions().withMapMode(MapMode::Static).withSize(frontend.getSize()).withPixelRatio(2)) {
map.jumpTo(CameraOptions().withZoom(16));
map.getStyle().loadURL(style);
frontend.render(map);
}
HeadlessFrontend frontend;
- Map map;
+ MapAdapter map;
};
// Warm up buffers and cache.
diff --git a/vendor/args b/vendor/args
new file mode 160000
+Subproject f68b7e186cd2a020cbddfe3194c1d8ddfeeb101
diff --git a/vendor/args-files.json b/vendor/args-files.json
new file mode 100644
index 0000000000..c3c9bb64c6
--- /dev/null
+++ b/vendor/args-files.json
@@ -0,0 +1,8 @@
+{
+ "//": "This file is generated. Do not edit. Regenerate it with scripts/generate-file-lists.js",
+ "sources": [],
+ "public_headers": {
+ "args.hxx": "vendor/args/args.hxx"
+ },
+ "private_headers": {}
+}
diff --git a/vendor/args.cmake b/vendor/args.cmake
new file mode 100644
index 0000000000..b5839943c2
--- /dev/null
+++ b/vendor/args.cmake
@@ -0,0 +1,5 @@
+add_library(args INTERFACE)
+
+target_include_directories(args SYSTEM INTERFACE
+ ${CMAKE_SOURCE_DIR}/vendor/args
+)
diff --git a/vendor/optional.cmake b/vendor/optional.cmake
index fa299da6a6..ed7bfe8a38 100644
--- a/vendor/optional.cmake
+++ b/vendor/optional.cmake
@@ -1,9 +1,5 @@
add_library(optional INTERFACE)
-# This polyfill is needed for Windows and Android since these standard libraries don't ship with
-# usable versions of <experimental/optional>
-if(WIN32 OR MBGL_PLATFORM STREQUAL "android")
- target_include_directories(optional SYSTEM INTERFACE
- ${CMAKE_SOURCE_DIR}/vendor/optional/include
- )
-endif()
+target_include_directories(optional SYSTEM INTERFACE
+ ${CMAKE_SOURCE_DIR}/vendor/optional/include
+)