From 1ccaa1dc718c2b1d66014a9c3b0b8c725d4565f1 Mon Sep 17 00:00:00 2001 From: Fabian Guerra Soto Date: Tue, 21 Mar 2017 12:54:29 -0400 Subject: [ios] podspec update to 3.5.0 (#8487) --- platform/ios/Mapbox-iOS-SDK-symbols.podspec | 2 +- platform/ios/Mapbox-iOS-SDK.podspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/ios/Mapbox-iOS-SDK-symbols.podspec b/platform/ios/Mapbox-iOS-SDK-symbols.podspec index aa9a6cf7e5..cc0fb07e27 100644 --- a/platform/ios/Mapbox-iOS-SDK-symbols.podspec +++ b/platform/ios/Mapbox-iOS-SDK-symbols.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |m| - version = '3.5.0-rc.2' + version = '3.5.0' m.name = 'Mapbox-iOS-SDK-symbols' m.version = "#{version}-symbols" diff --git a/platform/ios/Mapbox-iOS-SDK.podspec b/platform/ios/Mapbox-iOS-SDK.podspec index 296015da11..987e9fed15 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 = '3.5.0-rc.2' + version = '3.5.0' m.name = 'Mapbox-iOS-SDK' m.version = version -- cgit v1.2.1 From 60717822e6a5f4b9262241cb4f4504d723b3a82b Mon Sep 17 00:00:00 2001 From: Anand Thakker Date: Wed, 22 Mar 2017 14:32:22 -0400 Subject: Use highp for color attributes (#8496) Addresses #8385 Updates shaders to reflect https://github.com/mapbox/mapbox-gl-js/pull/4476 --- mapbox-gl-js | 2 +- src/mbgl/shaders/circle.cpp | 12 ++++++------ src/mbgl/shaders/debug.cpp | 2 +- src/mbgl/shaders/fill.cpp | 6 +++--- src/mbgl/shaders/fill_outline.cpp | 6 +++--- src/mbgl/shaders/line.cpp | 6 +++--- src/mbgl/shaders/line_sdf.cpp | 6 +++--- src/mbgl/shaders/symbol_sdf.cpp | 12 ++++++------ 8 files changed, 26 insertions(+), 26 deletions(-) diff --git a/mapbox-gl-js b/mapbox-gl-js index 69bb05cef2..dc426c2122 160000 --- a/mapbox-gl-js +++ b/mapbox-gl-js @@ -1 +1 @@ -Subproject commit 69bb05cef27c99722f6616867032d64b5f12ee57 +Subproject commit dc426c212208bf06300b7412983c62c689e7a796 diff --git a/src/mbgl/shaders/circle.cpp b/src/mbgl/shaders/circle.cpp index b479f1d40c..1c977d2bce 100644 --- a/src/mbgl/shaders/circle.cpp +++ b/src/mbgl/shaders/circle.cpp @@ -14,8 +14,8 @@ uniform vec2 u_extrude_scale; attribute vec2 a_pos; uniform lowp float a_color_t; -attribute lowp vec4 a_color; -varying lowp vec4 color; +attribute highp vec4 a_color; +varying highp vec4 color; uniform lowp float a_radius_t; attribute mediump vec2 a_radius; varying mediump float radius; @@ -26,8 +26,8 @@ uniform lowp float a_opacity_t; attribute lowp vec2 a_opacity; varying lowp float opacity; uniform lowp float a_stroke_color_t; -attribute lowp vec4 a_stroke_color; -varying lowp vec4 stroke_color; +attribute highp vec4 a_stroke_color; +varying highp vec4 stroke_color; uniform lowp float a_stroke_width_t; attribute mediump vec2 a_stroke_width; varying mediump float stroke_width; @@ -69,11 +69,11 @@ void main(void) { )MBGL_SHADER"; const char* circle::fragmentSource = R"MBGL_SHADER( -varying lowp vec4 color; +varying highp vec4 color; varying mediump float radius; varying lowp float blur; varying lowp float opacity; -varying lowp vec4 stroke_color; +varying highp vec4 stroke_color; varying mediump float stroke_width; varying lowp float stroke_opacity; diff --git a/src/mbgl/shaders/debug.cpp b/src/mbgl/shaders/debug.cpp index 27a15698d4..d39dcf25be 100644 --- a/src/mbgl/shaders/debug.cpp +++ b/src/mbgl/shaders/debug.cpp @@ -17,7 +17,7 @@ void main() { )MBGL_SHADER"; const char* debug::fragmentSource = R"MBGL_SHADER( -uniform lowp vec4 u_color; +uniform highp vec4 u_color; void main() { gl_FragColor = u_color; diff --git a/src/mbgl/shaders/fill.cpp b/src/mbgl/shaders/fill.cpp index a1fba4d749..0b775273d2 100644 --- a/src/mbgl/shaders/fill.cpp +++ b/src/mbgl/shaders/fill.cpp @@ -12,8 +12,8 @@ attribute vec2 a_pos; uniform mat4 u_matrix; uniform lowp float a_color_t; -attribute lowp vec4 a_color; -varying lowp vec4 color; +attribute highp vec4 a_color; +varying highp vec4 color; uniform lowp float a_opacity_t; attribute lowp vec2 a_opacity; varying lowp float opacity; @@ -27,7 +27,7 @@ void main() { )MBGL_SHADER"; const char* fill::fragmentSource = R"MBGL_SHADER( -varying lowp vec4 color; +varying highp vec4 color; varying lowp float opacity; void main() { diff --git a/src/mbgl/shaders/fill_outline.cpp b/src/mbgl/shaders/fill_outline.cpp index 74201b518d..3e160ac6c2 100644 --- a/src/mbgl/shaders/fill_outline.cpp +++ b/src/mbgl/shaders/fill_outline.cpp @@ -15,8 +15,8 @@ uniform vec2 u_world; varying vec2 v_pos; uniform lowp float a_outline_color_t; -attribute lowp vec4 a_outline_color; -varying lowp vec4 outline_color; +attribute highp vec4 a_outline_color; +varying highp vec4 outline_color; uniform lowp float a_opacity_t; attribute lowp vec2 a_opacity; varying lowp float opacity; @@ -31,7 +31,7 @@ void main() { )MBGL_SHADER"; const char* fill_outline::fragmentSource = R"MBGL_SHADER( -varying lowp vec4 outline_color; +varying highp vec4 outline_color; varying lowp float opacity; varying vec2 v_pos; diff --git a/src/mbgl/shaders/line.cpp b/src/mbgl/shaders/line.cpp index dc4aa774dc..4392bd051f 100644 --- a/src/mbgl/shaders/line.cpp +++ b/src/mbgl/shaders/line.cpp @@ -34,8 +34,8 @@ varying vec2 v_width2; varying float v_gamma_scale; uniform lowp float a_color_t; -attribute lowp vec4 a_color; -varying lowp vec4 color; +attribute highp vec4 a_color; +varying highp vec4 color; uniform lowp float a_blur_t; attribute lowp vec2 a_blur; varying lowp float blur; @@ -105,7 +105,7 @@ void main() { )MBGL_SHADER"; const char* line::fragmentSource = R"MBGL_SHADER( -varying lowp vec4 color; +varying highp vec4 color; varying lowp float blur; varying lowp float opacity; diff --git a/src/mbgl/shaders/line_sdf.cpp b/src/mbgl/shaders/line_sdf.cpp index cd0d4ac318..17a6a19739 100644 --- a/src/mbgl/shaders/line_sdf.cpp +++ b/src/mbgl/shaders/line_sdf.cpp @@ -42,8 +42,8 @@ varying vec2 v_tex_b; varying float v_gamma_scale; uniform lowp float a_color_t; -attribute lowp vec4 a_color; -varying lowp vec4 color; +attribute highp vec4 a_color; +varying highp vec4 color; uniform lowp float a_blur_t; attribute lowp vec2 a_blur; varying lowp float blur; @@ -127,7 +127,7 @@ varying vec2 v_tex_a; varying vec2 v_tex_b; varying float v_gamma_scale; -varying lowp vec4 color; +varying highp vec4 color; varying lowp float blur; varying lowp float opacity; diff --git a/src/mbgl/shaders/symbol_sdf.cpp b/src/mbgl/shaders/symbol_sdf.cpp index e0ee57b6d4..7cbc9babf5 100644 --- a/src/mbgl/shaders/symbol_sdf.cpp +++ b/src/mbgl/shaders/symbol_sdf.cpp @@ -14,11 +14,11 @@ attribute vec2 a_texture_pos; attribute vec4 a_data; uniform lowp float a_fill_color_t; -attribute lowp vec4 a_fill_color; -varying lowp vec4 fill_color; +attribute highp vec4 a_fill_color; +varying highp vec4 fill_color; uniform lowp float a_halo_color_t; -attribute lowp vec4 a_halo_color; -varying lowp vec4 halo_color; +attribute highp vec4 a_halo_color; +varying highp vec4 halo_color; uniform lowp float a_opacity_t; attribute lowp vec2 a_opacity; varying lowp float opacity; @@ -119,8 +119,8 @@ const char* symbol_sdf::fragmentSource = R"MBGL_SHADER( #define EDGE_GAMMA 0.105/DEVICE_PIXEL_RATIO uniform bool u_is_halo; -varying lowp vec4 fill_color; -varying lowp vec4 halo_color; +varying highp vec4 fill_color; +varying highp vec4 halo_color; varying lowp float opacity; varying lowp float halo_width; varying lowp float halo_blur; -- cgit v1.2.1 From 3a6d748bc4feb629271c6047afa0c4a3e364a751 Mon Sep 17 00:00:00 2001 From: Antonio Zugaldia Date: Wed, 22 Mar 2017 17:03:34 -0400 Subject: [android] [auto] Update properties to version 5.0.1 in preparation for build. --- platform/android/MapboxGLAndroidSDK/gradle.properties | 2 +- .../resources/fabric/com.mapbox.mapboxsdk.mapbox-android-sdk.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/android/MapboxGLAndroidSDK/gradle.properties b/platform/android/MapboxGLAndroidSDK/gradle.properties index 7a6f777a3b..9872478d9a 100644 --- a/platform/android/MapboxGLAndroidSDK/gradle.properties +++ b/platform/android/MapboxGLAndroidSDK/gradle.properties @@ -1,5 +1,5 @@ GROUP=com.mapbox.mapboxsdk -VERSION_NAME=5.1.0-SNAPSHOT +VERSION_NAME=5.0.1 POM_DESCRIPTION=Mapbox GL Android SDK POM_URL=https://github.com/mapbox/mapbox-gl-native diff --git a/platform/android/MapboxGLAndroidSDK/src/main/resources/fabric/com.mapbox.mapboxsdk.mapbox-android-sdk.properties b/platform/android/MapboxGLAndroidSDK/src/main/resources/fabric/com.mapbox.mapboxsdk.mapbox-android-sdk.properties index 1d436f1291..bc0350fe1f 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/resources/fabric/com.mapbox.mapboxsdk.mapbox-android-sdk.properties +++ b/platform/android/MapboxGLAndroidSDK/src/main/resources/fabric/com.mapbox.mapboxsdk.mapbox-android-sdk.properties @@ -1,3 +1,3 @@ fabric-identifier=com.mapbox.mapboxsdk.mapbox-android-sdk -fabric-version=5.0.0 +fabric-version=5.0.1 fabric-build-type=binary -- cgit v1.2.1 From 81650240c420907493cfc656e401d1f027cfb873 Mon Sep 17 00:00:00 2001 From: Antonio Zugaldia Date: Thu, 23 Mar 2017 09:06:34 -0400 Subject: [android] update CHANGELOG.md with 5.0.1 information --- platform/android/CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index d8338347c2..5c6b8d57b0 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -2,6 +2,12 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to do so please see the [`Contributing Guide`](https://github.com/mapbox/mapbox-gl-native/blob/master/CONTRIBUTING.md) first to get started. +## 5.0.1 - March 22nd, 2017 + +5.0.1 is a patch release that addresses a shader precision issue that created a rendering problem on some devices. + +* Use `highp` for color attributes [#8385](https://github.com/mapbox/mapbox-gl-native/issues/8385) + ## 5.0.0 - March 17th, 2017 5.0.0 final release contains: -- cgit v1.2.1 From f169577aab74c9c4f23ed9d1c93b8a1fa605ce33 Mon Sep 17 00:00:00 2001 From: Antonio Zugaldia Date: Thu, 23 Mar 2017 09:07:51 -0400 Subject: [android] revert version name to snapshot --- platform/android/MapboxGLAndroidSDK/gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/android/MapboxGLAndroidSDK/gradle.properties b/platform/android/MapboxGLAndroidSDK/gradle.properties index 9872478d9a..7a6f777a3b 100644 --- a/platform/android/MapboxGLAndroidSDK/gradle.properties +++ b/platform/android/MapboxGLAndroidSDK/gradle.properties @@ -1,5 +1,5 @@ GROUP=com.mapbox.mapboxsdk -VERSION_NAME=5.0.1 +VERSION_NAME=5.1.0-SNAPSHOT POM_DESCRIPTION=Mapbox GL Android SDK POM_URL=https://github.com/mapbox/mapbox-gl-native -- cgit v1.2.1 From 348cffa1195e605d8012c2339a2b480727b59fba Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 9 Mar 2017 15:10:24 -0800 Subject: [core] Avoid -Wundefined-var-template warnings with clang 3.9+ --- include/mbgl/util/enum.hpp | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/include/mbgl/util/enum.hpp b/include/mbgl/util/enum.hpp index 48ffda463e..369ca86bfd 100644 --- a/include/mbgl/util/enum.hpp +++ b/include/mbgl/util/enum.hpp @@ -11,26 +11,26 @@ namespace mbgl { template class Enum { public: - using Value = std::pair; - - static const char * toString(T t) { - auto it = std::find_if(begin, end, [&] (const auto& v) { return t == v.first; }); - assert(it != end); return it->second; - } - - static optional toEnum(const std::string& s) { - auto it = std::find_if(begin, end, [&] (const auto& v) { return s == v.second; }); - return it == end ? optional() : it->first; - } - -private: - static const Value* begin; - static const Value* end; + static const char * toString(T); + static optional toEnum(const std::string&); }; -#define MBGL_DEFINE_ENUM(type, strings...) \ -const constexpr Enum::Value type##_names[] = strings; \ -template <> const Enum::Value* Enum::begin = std::begin(type##_names); \ -template <> const Enum::Value* Enum::end = std::end(type##_names) +#define MBGL_DEFINE_ENUM(T, values...) \ + \ +static const constexpr std::pair T##_names[] = values; \ + \ +template <> \ +const char * Enum::toString(T t) { \ + auto it = std::find_if(std::begin(T##_names), std::end(T##_names), \ + [&] (const auto& v) { return t == v.first; }); \ + assert(it != std::end(T##_names)); return it->second; \ +} \ + \ +template <> \ +optional Enum::toEnum(const std::string& s) { \ + auto it = std::find_if(std::begin(T##_names), std::end(T##_names), \ + [&] (const auto& v) { return s == v.second; }); \ + return it == std::end(T##_names) ? optional() : it->first; \ +} } // namespace mbgl -- cgit v1.2.1 From cfb26c0a7951e773ca3d01d692e988a2f060b244 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 12 Jan 2017 14:44:29 -0800 Subject: [test] Fix polygon construction to compile with clang 3.9.x --- test/api/annotations.test.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/api/annotations.test.cpp b/test/api/annotations.test.cpp index 30027d8610..87d64d53de 100644 --- a/test/api/annotations.test.cpp +++ b/test/api/annotations.test.cpp @@ -73,7 +73,7 @@ TEST(Annotations, LineAnnotation) { TEST(Annotations, FillAnnotation) { AnnotationTest test; - Polygon polygon = {{ {{ { 0, 0 }, { 0, 45 }, { 45, 45 }, { 45, 0 } }} }}; + Polygon polygon = { {{ { 0, 0 }, { 0, 45 }, { 45, 45 }, { 45, 0 } }} }; FillAnnotation annotation { polygon }; annotation.color = Color::red(); @@ -98,7 +98,7 @@ TEST(Annotations, AntimeridianAnnotationSmall) { lineAnnotation.width = { 2 }; test.map.addAnnotation(lineAnnotation); - Polygon polygon = {{ {{ { antimeridian+10, 0 }, { antimeridian - 10, 10 }, { antimeridian-10, -10 } }} }}; + Polygon polygon = { {{ { antimeridian+10, 0 }, { antimeridian - 10, 10 }, { antimeridian-10, -10 } }} }; FillAnnotation polygonAnnotation { polygon }; polygonAnnotation.color = Color::blue(); test.map.addAnnotation(polygonAnnotation); @@ -119,7 +119,7 @@ TEST(Annotations, AntimeridianAnnotationLarge) { lineAnnotation.width = { 2 }; test.map.addAnnotation(lineAnnotation); - Polygon polygon = {{ {{ { antimeridian-10, 0 }, { -antimeridian+10, 10 }, { -antimeridian+10, -10 } }} }}; + Polygon polygon = { {{ { antimeridian-10, 0 }, { -antimeridian+10, 10 }, { -antimeridian+10, -10 } }} }; FillAnnotation polygonAnnotation { polygon }; polygonAnnotation.color = Color::blue(); test.map.addAnnotation(polygonAnnotation); @@ -130,7 +130,7 @@ TEST(Annotations, AntimeridianAnnotationLarge) { TEST(Annotations, OverlappingFillAnnotation) { AnnotationTest test; - Polygon polygon = {{ {{ { 0, 0 }, { 0, 45 }, { 45, 45 }, { 45, 0 } }} }}; + Polygon polygon = { {{ { 0, 0 }, { 0, 45 }, { 45, 45 }, { 45, 0 } }} }; FillAnnotation underlaidAnnotation { polygon }; underlaidAnnotation.color = Color::green(); FillAnnotation overlaidAnnotation { polygon }; @@ -145,7 +145,7 @@ TEST(Annotations, OverlappingFillAnnotation) { TEST(Annotations, StyleSourcedShapeAnnotation) { AnnotationTest test; - Polygon polygon = {{ {{ { 0, 0 }, { 0, 45 }, { 45, 45 }, { 45, 0 } }} }}; + Polygon polygon = { {{ { 0, 0 }, { 0, 45 }, { 45, 45 }, { 45, 0 } }} }; test.map.setStyleJSON(util::read_file("test/fixtures/api/annotation.json")); test.map.addAnnotation(StyleSourcedAnnotation { polygon, "annotation" }); @@ -171,7 +171,7 @@ TEST(Annotations, NonImmediateAdd) { test.map.setStyleJSON(util::read_file("test/fixtures/api/empty.json")); test::render(test.map, test.view); - Polygon polygon = {{ {{ { 0, 0 }, { 0, 45 }, { 45, 45 }, { 45, 0 } }} }}; + Polygon polygon = { {{ { 0, 0 }, { 0, 45 }, { 45, 45 }, { 45, 0 } }} }; FillAnnotation annotation { polygon }; annotation.color = Color::red(); @@ -245,7 +245,7 @@ TEST(Annotations, UpdateLineAnnotationStyle) { TEST(Annotations, UpdateFillAnnotationGeometry) { AnnotationTest test; - FillAnnotation annotation { Polygon {{ {{ { 0, 0 }, { 0, 45 }, { 45, 45 }, { 45, 0 } }} }} }; + FillAnnotation annotation { Polygon { {{ { 0, 0 }, { 0, 45 }, { 45, 45 }, { 45, 0 } }} } }; annotation.color = Color::red(); test.map.setStyleJSON(util::read_file("test/fixtures/api/empty.json")); @@ -253,7 +253,7 @@ TEST(Annotations, UpdateFillAnnotationGeometry) { test::render(test.map, test.view); - annotation.geometry = Polygon {{ {{ { 0, 0 }, { 0, 45 }, { 45, 0 } }} }}; + annotation.geometry = Polygon { {{ { 0, 0 }, { 0, 45 }, { 45, 0 } }} }; test.map.updateAnnotation(fill, annotation); test.checkRendering("update_fill_geometry"); } @@ -261,7 +261,7 @@ TEST(Annotations, UpdateFillAnnotationGeometry) { TEST(Annotations, UpdateFillAnnotationStyle) { AnnotationTest test; - Polygon polygon = {{ {{ { 0, 0 }, { 0, 45 }, { 45, 45 }, { 45, 0 } }} }}; + Polygon polygon = { {{ { 0, 0 }, { 0, 45 }, { 45, 45 }, { 45, 0 } }} }; FillAnnotation annotation { polygon }; annotation.color = Color::red(); -- cgit v1.2.1 From 8c34a5081c883eb7f4871b8e2c26f32b786ee8e4 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Wed, 8 Mar 2017 15:42:16 -0800 Subject: [linux, node] Build with clang 3.9 --- .travis.yml | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/.travis.yml b/.travis.yml index 391520319f..256e6a2aaa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,20 +5,20 @@ git: addons: apt: sources: - - &common_sources [ 'ubuntu-toolchain-r-test', 'george-edison55-precise-backports' ] + - &common_sources [ 'ubuntu-toolchain-r-test', 'george-edison55-precise-backports', 'llvm-toolchain-trusty-3.9' ] packages: - &common_packages [ 'libllvm3.8v4', 'cmake', 'cmake-data' ] - - &clang38_packages [ 'clang-3.8', 'libstdc++-5-dev', 'libstdc++6' ] + - &clang39_packages [ 'clang-3.9', 'libstdc++-5-dev', 'libstdc++6' ] - &gcc5_packages [ 'gcc-5', 'g++-5' ] - &glfw_packages [ 'libxrandr-dev', 'libxcursor-dev', 'libxinerama-dev' ] addons_shortcuts: - addons_clang38: &clang38 + addons_clang39: &clang39 apt: sources: *common_sources packages: - *common_packages - - *clang38_packages + - *clang39_packages - *glfw_packages addons_gcc5: &gcc5 apt: @@ -81,14 +81,14 @@ matrix: - git fetch origin master:refs/remotes/origin/master - make check - # EGL - Node - Clang 3.8 - Debug + # EGL - Node - Clang 3.9 - Debug - os: linux sudo: required dist: trusty language: node - compiler: "egl-node4-clang38-debug" - env: BUILDTYPE=Debug _CXX=clang++-3.8 _CC=clang-3.8 WITH_EGL=1 - addons: *clang38 + compiler: "egl-node4-clang39-debug" + env: BUILDTYPE=Debug _CXX=clang++-3.9 _CC=clang-3.9 WITH_EGL=1 + addons: *clang39 before_script: - mapbox_install_logbt - mapbox_start_xvfb @@ -104,14 +104,14 @@ matrix: after_failure: - aws s3 cp . s3://mapbox/mapbox-gl-native/render-tests/$TRAVIS_JOB_NUMBER --recursive --exclude "*" --include "*.trace" - # EGL - Node - Clang 3.8 - Release + # EGL - Node - Clang 3.9 - Release - os: linux sudo: required dist: trusty language: node - compiler: "egl-node4-clang38-release" - env: BUILDTYPE=Release _CXX=clang++-3.8 _CC=clang-3.8 WITH_EGL=1 - addons: *clang38 + compiler: "egl-node4-clang39-release" + env: BUILDTYPE=Release _CXX=clang++-3.9 _CC=clang-3.9 WITH_EGL=1 + addons: *clang39 before_script: # fglrx causes the GLX extension to be unavailable - sudo apt-get purge -qq fglrx @@ -148,14 +148,14 @@ matrix: - ccache --show-stats - ./platform/linux/scripts/coveralls.sh - # EGL - Clang 3.8 - Debug + # EGL - Clang 3.9 - Debug - os: linux sudo: required dist: trusty language: cpp - compiler: "egl-clang38-debug" - env: BUILDTYPE=Debug _CXX=clang++-3.8 _CC=clang-3.8 WITH_EGL=1 - addons: *clang38 + compiler: "egl-clang39-debug" + env: BUILDTYPE=Debug _CXX=clang++-3.9 _CC=clang-3.9 WITH_EGL=1 + addons: *clang39 before_script: - mapbox_start_xvfb - mapbox_export_mesa_library_path -- cgit v1.2.1 From c5c69102c5ca1aabb0efda1fe64224256a56bbb1 Mon Sep 17 00:00:00 2001 From: Fabian Guerra Soto Date: Tue, 28 Mar 2017 16:06:16 -0400 Subject: [ios] nil check in visibleAnnotationsInRect to avoid crash (#8513) --- platform/ios/src/MGLMapView.mm | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 1baebf60bc..6ce41d6fb4 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -3044,7 +3044,10 @@ public: continue; } MGLAnnotationContext annotationContext = _annotationContextsByAnnotationTag.at(annotationTag); - [annotations addObject:annotationContext.annotation]; + if (annotationContext.annotation) + { + [annotations addObject:annotationContext.annotation]; + } } return [annotations copy]; -- cgit v1.2.1 From 1edbb0f24b3b405bfc203803fffb1fa1ed68f142 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Tue, 28 Mar 2017 16:02:48 -0700 Subject: [core] check null data in query source features (#8553) * [core] check null data in query source features * Include what you use --- src/mbgl/tile/geometry_tile.cpp | 5 +++++ test/tile/vector_tile.test.cpp | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp index 5f1fc5de66..5ccc037ce0 100644 --- a/src/mbgl/tile/geometry_tile.cpp +++ b/src/mbgl/tile/geometry_tile.cpp @@ -165,6 +165,11 @@ void GeometryTile::queryRenderedFeatures( void GeometryTile::querySourceFeatures( std::vector& result, const style::SourceQueryOptions& options) { + + // Data not yet available + if (!data) { + return; + } // No source layers, specified, nothing to do if (!options.sourceLayers) { diff --git a/test/tile/vector_tile.test.cpp b/test/tile/vector_tile.test.cpp index 49fdcbd9f8..f9bdafa5d2 100644 --- a/test/tile/vector_tile.test.cpp +++ b/test/tile/vector_tile.test.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -86,3 +87,12 @@ TEST(VectorTile, Issue7615) { EXPECT_EQ(symbolBucket.get(), tile.getBucket(symbolLayer)); } + +TEST(VectorTile, Issue8542) { + VectorTileTest test; + VectorTile tile(OverscaledTileID(0, 0, 0), "source", test.updateParameters, test.tileset); + + // Query before data is set + std::vector result; + tile.querySourceFeatures(result, { { {"layer"} }, {} }); +} -- cgit v1.2.1 From dcb14f98ee534b22cae8a0f829302a0b2b2459b2 Mon Sep 17 00:00:00 2001 From: Jesse Bounds Date: Mon, 27 Mar 2017 14:26:59 -0700 Subject: [ios] Modify return type so callout bridges with protocol in Swift `- (nullable UIView *)mapView:(MGLMapView *)mapView calloutViewForAnnotation:(id )annotation;` bridges with a `UIView?` return type in Swift. This changes replaces the `UIView` type in the method signature so that, when bridged to Swift, the returned object is defined as `MGLCalloutView?`. --- platform/ios/CHANGELOG.md | 6 ++++++ platform/ios/src/MGLMapViewDelegate.h | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index 40795a2aef..027689696e 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -2,6 +2,12 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONTRIBUTING.md](../../CONTRIBUTING.md) to get started. +## 3.5.1 + +### Other changes + +* Fixed an issue that caused the return type of a map view delegate method to bridge incorrectly to applications written in Swift. ([#8541](https://github.com/mapbox/mapbox-gl-native/pull/8541)) + ## 3.5.0 ### Packaging diff --git a/platform/ios/src/MGLMapViewDelegate.h b/platform/ios/src/MGLMapViewDelegate.h index c1faaa3d07..096711fcbb 100644 --- a/platform/ios/src/MGLMapViewDelegate.h +++ b/platform/ios/src/MGLMapViewDelegate.h @@ -456,7 +456,7 @@ NS_ASSUME_NONNULL_BEGIN @return A view conforming to the `MGLCalloutView` protocol, or `nil` to use the default callout view. */ -- (nullable UIView *)mapView:(MGLMapView *)mapView calloutViewForAnnotation:(id )annotation; +- (nullable id )mapView:(MGLMapView *)mapView calloutViewForAnnotation:(id )annotation; /** Returns the view to display on the left side of the standard callout bubble. -- cgit v1.2.1 From a46d91f7c5cbcdd9343d1a3dfba17e375a466e2a Mon Sep 17 00:00:00 2001 From: Tobrun Date: Thu, 30 Mar 2017 17:30:47 +0200 Subject: Revert 5.x touch changes (#8585) * Revert "[android] - only dispatch events if not handled by MarkerView (#8447)" This reverts commit 09d76854ab15b2a6f473c270da9d46e903e426da. * Revert "[android] - move touch handling of MarkerViews back to View#setOnClickListener. Workaround panning issue by dispatching touch events to the parent ViewGroup. (#8272)" This reverts commit 1693b389d7d17315b8a2a9bdd862207ace053f77. --- .../mapboxsdk/annotations/MarkerViewContainer.java | 34 --------------- .../mapboxsdk/annotations/MarkerViewManager.java | 49 ++++++++++++---------- .../mapbox/mapboxsdk/maps/AnnotationManager.java | 17 ++++---- .../com/mapbox/mapboxsdk/maps/IconManager.java | 21 ++++++++++ .../main/res/layout/mapbox_mapview_internal.xml | 2 +- .../activity/annotation/MarkerViewActivity.java | 7 ---- 6 files changed, 60 insertions(+), 70 deletions(-) delete mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewContainer.java diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewContainer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewContainer.java deleted file mode 100644 index d590582f09..0000000000 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewContainer.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.mapbox.mapboxsdk.annotations; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.ViewGroup; -import android.widget.FrameLayout; - -/** - * ViewGroup that dispatches TouchEvents to the parent ViewGroup. - *

- * This allows to dispatch touch events that occur on MarkerView to MapView. - * https://github.com/mapbox/mapbox-gl-native/issues/5388 - *

- */ -public class MarkerViewContainer extends FrameLayout { - - public MarkerViewContainer(Context context, AttributeSet attrs) { - super(context, attrs); - setTag(false); - } - - @Override - public boolean dispatchTouchEvent(MotionEvent ev) { - super.dispatchTouchEvent(ev); - boolean actionUp = (boolean) getTag(); - if (!actionUp) { - ((ViewGroup) getParent()).onTouchEvent(ev); - } else { - setTag(false); - } - return true; - } -} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java index 0f1298eeaf..315e12d280 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java @@ -8,7 +8,6 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.util.LongSparseArray; import android.view.LayoutInflater; -import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; @@ -504,26 +503,6 @@ public class MarkerViewManager implements MapView.OnMapChangedListener { } } - adaptedView.setOnTouchListener(new View.OnTouchListener() { - - @Override - public boolean onTouch(View v, MotionEvent event) { - if (event.getAction() == MotionEvent.ACTION_UP) { - boolean clickHandled = false; - if (onMarkerViewClickListener != null) { - clickHandled = onMarkerViewClickListener.onMarkerClick(marker, v, adapter); - markerViewContainer.setTag(true); - } - - if (!clickHandled) { - ensureInfoWindowOffset(marker); - select(marker, v, adapter); - } - } - return true; - } - }); - marker.setMapboxMap(mapboxMap); markerViewMap.put(marker, adaptedView); if (convertView == null) { @@ -551,6 +530,34 @@ public class MarkerViewManager implements MapView.OnMapChangedListener { updateMarkerViewsPosition(); } + /** + * When the provided {@link MarkerView} is clicked on by a user, we check if a custom click + * event has been created and if not, display a {@link InfoWindow}. + * + * @param markerView that the click event occurred. + */ + public boolean onClickMarkerView(MarkerView markerView) { + boolean clickHandled = false; + + MapboxMap.MarkerViewAdapter adapter = getViewAdapter(markerView); + View view = getView(markerView); + if (adapter == null || view == null) { + // not a valid state + return true; + } + + if (onMarkerViewClickListener != null) { + clickHandled = onMarkerViewClickListener.onMarkerClick(markerView, view, adapter); + } + + if (!clickHandled) { + ensureInfoWindowOffset(markerView); + select(markerView, view, adapter); + } + + return clickHandled; + } + /** * Handles the {@link MarkerView}'s info window offset. * diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java index e91779dfd1..0c77723354 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java @@ -10,7 +10,6 @@ import com.mapbox.mapboxsdk.annotations.Annotation; import com.mapbox.mapboxsdk.annotations.BaseMarkerOptions; import com.mapbox.mapboxsdk.annotations.BaseMarkerViewOptions; import com.mapbox.mapboxsdk.annotations.Icon; -import com.mapbox.mapboxsdk.annotations.IconFactory; import com.mapbox.mapboxsdk.annotations.Marker; import com.mapbox.mapboxsdk.annotations.MarkerView; import com.mapbox.mapboxsdk.annotations.MarkerViewManager; @@ -257,11 +256,7 @@ class AnnotationManager { private MarkerView prepareViewMarker(BaseMarkerViewOptions markerViewOptions) { MarkerView marker = markerViewOptions.getMarker(); - Icon icon = markerViewOptions.getIcon(); - if (icon == null) { - icon = IconFactory.getInstance(mapView.getContext()).defaultMarkerView(); - } - marker.setIcon(icon); + iconManager.loadIconForMarkerView(marker); return marker; } @@ -665,16 +660,24 @@ class AnnotationManager { if (annotation.getId() == newSelectedMarkerId) { Marker marker = (Marker) annotation; - if (!(marker instanceof MarkerView)) { + if (marker instanceof MarkerView) { + handledDefaultClick = markerViewManager.onClickMarkerView((MarkerView) marker); + } else { if (onMarkerClickListener != null) { // end developer has provided a custom click listener handledDefaultClick = onMarkerClickListener.onMarkerClick(marker); } + } + + if (annotation instanceof MarkerView) { + markerViewManager.onClickMarkerView((MarkerView) annotation); + } else { if (!handledDefaultClick) { // only select marker if user didn't handle the click event themselves selectMarker(marker); } } + return true; } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/IconManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/IconManager.java index c152630278..c9d81a88bc 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/IconManager.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/IconManager.java @@ -71,6 +71,27 @@ class IconManager { return icon; } + Icon loadIconForMarkerView(MarkerView marker) { + Icon icon = marker.getIcon(); + int iconSize = icons.size() + 1; + if (icon == null) { + icon = IconFactory.getInstance(nativeMapView.getContext()).defaultMarkerView(); + marker.setIcon(icon); + } + Bitmap bitmap = icon.getBitmap(); + averageIconHeight = averageIconHeight + (bitmap.getHeight() - averageIconHeight) / iconSize; + averageIconWidth = averageIconWidth + (bitmap.getWidth() - averageIconWidth) / iconSize; + if (!icons.contains(icon)) { + icons.add(icon); + } else { + Icon oldIcon = icons.get(icons.indexOf(icon)); + if (!oldIcon.getBitmap().sameAs(icon.getBitmap())) { + throw new IconBitmapChangedException(); + } + } + return icon; + } + int getTopOffsetPixelsForIcon(Icon icon) { return (int) (nativeMapView.getTopOffsetPixelsForAnnotationSymbol(icon.getId()) * nativeMapView.getPixelRatio()); } 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 7a38437fee..e6a2677785 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 @@ -8,7 +8,7 @@ android:contentDescription="@null" android:visibility="gone"/> - Date: Fri, 31 Mar 2017 13:48:47 +0200 Subject: Cherry pick v5.0.2 changes (#8586) * [android] execute resource transform callback on the right thread * [android] allow resetting of resource transform callback * update CHANGELOG for v5.0.2 * [android] - correct anchoring when Icon is updated (#8519) --- platform/android/CHANGELOG.md | 8 ++++++++ .../main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java | 9 +++++++++ .../java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java | 1 + .../src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java | 4 ++-- platform/android/src/file_source.cpp | 6 +++--- 5 files changed, 23 insertions(+), 5 deletions(-) diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index 5c6b8d57b0..01d7b1ab5b 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -2,6 +2,14 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to do so please see the [`Contributing Guide`](https://github.com/mapbox/mapbox-gl-native/blob/master/CONTRIBUTING.md) first to get started. +## 5.0.2 - April 3, 2017 + +5.0.2 is a patch release that contains the following changes: + +* Fix resource transform callback [#8582](https://github.com/mapbox/mapbox-gl-native/pull/8582) +* Restore onTouch behaviour to 4.x version [#8585](https://github.com/mapbox/mapbox-gl-native/pull/8585) +* Restore anchoring after updating MarkerView Icon [#8519](https://github.com/mapbox/mapbox-gl-native/pull/8519) + ## 5.0.1 - March 22nd, 2017 5.0.1 is a patch release that addresses a shader precision issue that created a rendering problem on some devices. diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java index 220d3322cb..30336d4ebd 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java @@ -389,6 +389,15 @@ public class MarkerView extends Marker { } } + /** + * Invalidates the MarkerView resulting in remeasuring the View. + */ + void invalidate() { + width = height = 0; + offsetX = offsetY = MapboxConstants.UNMEASURED; + markerViewManager.invalidateViewMarkersInVisibleRegion(); + } + /** * Get the String representation of a MarkerView. * diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java index 315e12d280..bb51f3bfc2 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java @@ -232,6 +232,7 @@ public class MarkerViewManager implements MapView.OnMapChangedListener { View convertView = markerViewMap.get(markerView); if (convertView != null && convertView instanceof ImageView) { ((ImageView) convertView).setImageBitmap(markerView.getIcon().getBitmap()); + markerView.invalidate(); } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java index 8681777023..a12d8f9954 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java @@ -123,9 +123,9 @@ public class FileSource { * The callback will be executed on the main thread once for every requested URL. *

* - * @param callback the callback to be invoked + * @param callback the callback to be invoked or null to reset */ - public native void setResourceTransform(@NonNull final ResourceTransformCallback callback); + public native void setResourceTransform(final ResourceTransformCallback callback); private native void initialize(String accessToken, String cachePath, String apkPath); diff --git a/platform/android/src/file_source.cpp b/platform/android/src/file_source.cpp index 30e1ff50fe..20715bf920 100644 --- a/platform/android/src/file_source.cpp +++ b/platform/android/src/file_source.cpp @@ -46,10 +46,10 @@ void FileSource::setResourceTransform(jni::JNIEnv& env, jni::Object(transformCallback.NewGlobalRef(env).release()->Get(), GenericGlobalRefDeleter()), - env + callback = std::shared_ptr(transformCallback.NewGlobalRef(env).release()->Get(), GenericGlobalRefDeleter()) ](mbgl::Resource::Kind kind, std::string&& url_) { - return FileSource::ResourceTransformCallback::onURL(const_cast(env), jni::Object(*callback), int(kind), url_); + android::UniqueEnv _env = android::AttachEnv(); + return FileSource::ResourceTransformCallback::onURL(*_env, jni::Object(*callback), int(kind), url_); }); } else { // Reset the callback -- cgit v1.2.1 From aa3db60300eecc52b21e4b38c70bd89566daa95f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Sun, 26 Mar 2017 01:21:12 -0700 Subject: [ios, macos] Copyedited data-driven styling guides Cursorily copy-edited the data-driven styling guide, removing a stray class reference, replacing a redundant h1, and making stops examples platform-agnostic and less redundant. Fixed an issue in the style authors guide where style function tables appeared under each style layer type table. --- .../darwin/docs/guides/Data-Driven Styling.md.ejs | 59 ++++---- .../darwin/docs/guides/For Style Authors.md.ejs | 62 ++++---- platform/ios/docs/guides/Data-Driven Styling.md | 59 ++++---- platform/ios/docs/guides/For Style Authors.md | 158 +++++---------------- platform/macos/docs/guides/Data-Driven Styling.md | 59 ++++---- platform/macos/docs/guides/For Style Authors.md | 158 +++++---------------- 6 files changed, 198 insertions(+), 357 deletions(-) diff --git a/platform/darwin/docs/guides/Data-Driven Styling.md.ejs b/platform/darwin/docs/guides/Data-Driven Styling.md.ejs index 820f71f594..7b597c6737 100644 --- a/platform/darwin/docs/guides/Data-Driven Styling.md.ejs +++ b/platform/darwin/docs/guides/Data-Driven Styling.md.ejs @@ -12,44 +12,43 @@ # Data-Driven Styling -Mapbox’s data-driven styling features allow you to use data properties to style your maps. You can style map features automatically based on their individual attributes. +Mapbox’s data-driven styling features allow you to use attributes in the data to style your maps. You can style map features automatically based on their individual attributes. Vary POI icons, transit route line colors, city polygon opacity, and more based on any attribute in your data. Need to visualize hotel data by price? You can have your map’s point radii and colors change automatically with your data. ![available bikes](img/data-driven-styling/citibikes.png) ![subway lines](img/data-driven-styling/polylineExample.png) -# How to use Data-Driven Styling This guide uses earthquake data from the [U.S. Geological Survey](https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php) to style a map based on attributes. For more information about how to work with GeoJSON data in our iOS SDK, please see our [working with GeoJSON data](working-with-geojson-data.html) guide. -`MGLStyleFunction` +## Style functions There are three subclasses of `MGLStyleFunction`: -* `MGLCameraStyleFunction` - For a style value that changes with zoom level. For example, you can make the radius of a circle increase according to zoom level. -* `MGLSourceStyleFunction` - For a style value that changes with the attributes of a feature. For example, you can adjust the radius of a circle based on the magnitude of an earthquake. -* `MGLCompositeStyleFunction` - For a style value that changes with both zoom level and attribute values. For example, you can add a circle layer where each circle has a radius based on both zoom level and the magnitude of an earthquake. +* `MGLCameraStyleFunction` is a style value that changes with zoom level. For example, you can make the radius of a circle increase according to zoom level. +* `MGLSourceStyleFunction` is a style value that changes with the attributes of a feature. For example, you can adjust the radius of a circle based on the magnitude of an earthquake. +* `MGLCompositeStyleFunction` is a style value that changes with both zoom level and attribute values. For example, you can add a circle layer where each circle has a radius based on both zoom level and the magnitude of an earthquake. -The documentation for individual style properties will note which style functions are enabled for that property. +The documentation for each individual style layer property notes which style functions are enabled for that property. ## Stops Stops are key-value pairs that that determine a style value. With a `MGLCameraSourceFunction` stop, you can use a dictionary with a zoom level for a key and a `MGLStyleValue` for the value. For example, you can use a stops dictionary with zoom levels 0, 10, and 20 as keys, and yellow, orange, and red as the values. A `MGLSourceStyleFunction` uses the relevant attribute value as the key. ```swift -let stops = [0: MGLStyleValue(rawValue: UIColor.yellow), - 2.5: MGLStyleValue(rawValue: UIColor.orange), - 5: MGLStyleValue(rawValue: UIColor.red), - 7.5: MGLStyleValue(rawValue: UIColor.blue), - 10: MGLStyleValue(rawValue: UIColor.white)] +let stops = [0: MGLStyleValue<<%- cocoaPrefix %>Color>(rawValue: .yellow), + 2.5: MGLStyleValue(rawValue: .orange), + 5: MGLStyleValue(rawValue: .red), + 7.5: MGLStyleValue(rawValue: .blue), + 10: MGLStyleValue(rawValue: .white)] ``` -## Interpolation Mode +## Interpolation mode The effect a key has on the style value is determined by the interpolation mode. There are four interpolation modes that can be used with a source style function: exponential, interval, categorical, and identity. You can also use exponential and interval interpolation modes with a camera style function. ### Linear -`MGLInterpolationModelExponential` interpolates linearly or exponentially between style function stop values. By default, the `MGLStyleFunction` options parameter `MGLStyleFunctionOptionInterpolationBase` equals `1`, which represents linear interpolation, and doesn’t need to be included in the options dictionary. +`MGLInterpolationModeExponential` interpolates linearly or exponentially between style function stop values. By default, the `MGLStyleFunction` options parameter `MGLStyleFunctionOptionInterpolationBase` equals `1`, which represents linear interpolation and doesn’t need to be included in the options dictionary. The stops dictionary below, for example, shows colors that continuously shift from yellow to orange to red to blue to white based on the attribute value. @@ -61,11 +60,11 @@ let symbolLayer = MGLSymbolStyleLayer(identifier: "place-city-sm", source: symbo let source = MGLShapeSource(identifier: "earthquakes", url: url, options: nil) style.addSource(source) -let stops = [0: MGLStyleValue(rawValue: <%- cocoaPrefix %>Color.yellow), - 2.5: MGLStyleValue(rawValue: <%- cocoaPrefix %>Color.orange), - 5: MGLStyleValue(rawValue: <%- cocoaPrefix %>Color.red), - 7.5: MGLStyleValue(rawValue: <%- cocoaPrefix %>Color.blue), - 10: MGLStyleValue(rawValue: <%- cocoaPrefix %>Color.white)] +let stops = [0: MGLStyleValue<<%- cocoaPrefix %>Color>(rawValue: .yellow), + 2.5: MGLStyleValue(rawValue: .orange), + 5: MGLStyleValue(rawValue: .red), + 7.5: MGLStyleValue(rawValue: .blue), + 10: MGLStyleValue(rawValue: .white)] let layer = MGLCircleStyleLayer(identifier: "circles", source: source) layer.circleColor = MGLStyleValue(interpolationMode: .exponential, @@ -80,7 +79,7 @@ style.insertLayer(layer, below: symbolLayer) ### Exponential -`MGLInterpolationModelExponential` combined with any `MGLStyleFunctionOptionInterpolationBase` greater than `0`, you can interpolate between values exponentially, create an accelerated ramp effect. +By combining `MGLInterpolationModeExponential` with an `MGLStyleFunctionOptionInterpolationBase` greater than `0` (other than `1`), you can interpolate between values exponentially, create an accelerated ramp effect. Here’s a visualization from Mapbox Studio (see [Working with Mapbox Studio](working-with-mapbox-studio.html)) comparing interpolation base values of `1.5` and `0.5` based on zoom. @@ -106,11 +105,11 @@ layer.circleRadius = MGLStyleValue(interpolationMode: .exponential, When we use the stops dictionary given above with an interval interpolation mode, we create ranges where earthquakes with a magnitude of 0 to just less than 2.5 would be yellow, 2.5 to just less than 5 would be orange, and so on. ``` swift -let stops = [0: MGLStyleValue(rawValue: <%- cocoaPrefix %>Color.yellow), - 2.5: MGLStyleValue(rawValue: <%- cocoaPrefix %>Color.orange), - 5: MGLStyleValue(rawValue: <%- cocoaPrefix %>Color.red), - 7.5: MGLStyleValue(rawValue: <%- cocoaPrefix %>Color.blue), - 10: MGLStyleValue(rawValue: <%- cocoaPrefix %>Color.white)] +let stops = [0: MGLStyleValue<<%- cocoaPrefix %>Color>(rawValue: .yellow), + 2.5: MGLStyleValue(rawValue: .orange), + 5: MGLStyleValue(rawValue: .red), + 7.5: MGLStyleValue(rawValue: .blue), + 10: MGLStyleValue(rawValue: .white)] layer.circleColor = MGLStyleValue(interpolationMode: .interval, sourceStops: stops, @@ -122,19 +121,19 @@ layer.circleColor = MGLStyleValue(interpolationMode: .interval, ### Categorical -Returns the output value that is equal to the stop for the function input. We’re going to use a different stops dictionary than we did for the previous two modes. +At each stop, `MGLInterpolationModeCategorical` produces an output value equal to the function input. We’re going to use a different stops dictionary than we did for the previous two modes. There are three main types of events in the dataset: earthquakes, explosions, and quarry blasts. In this case, the color of the circle layer will be determined by the type of event, with a default value of green to catch any events that do not fall into any of those categories. ``` swift -let categoricalStops = ["earthquake": MGLStyleValue(rawValue: <%- cocoaPrefix %>Color.orange), - "explosion": MGLStyleValue(rawValue: <%- cocoaPrefix %>Color.red), - "quarry blast": MGLStyleValue(rawValue: <%- cocoaPrefix %>Color.yellow)] +let categoricalStops = ["earthquake": MGLStyleValue<<%- cocoaPrefix %>Color>(rawValue: .orange), + "explosion": MGLStyleValue(rawValue: .red), + "quarry blast": MGLStyleValue(rawValue: .yellow)] layer.circleColor = MGLStyleValue(interpolationMode: .categorical, sourceStops: categoricalStops, attributeName: "type", - options: [.defaultValue: MGLStyleValue(rawValue: <%- cocoaPrefix %>Color.blue)]) + options: [.defaultValue: MGLStyleValue<<%- cocoaPrefix %>Color>(rawValue: .blue)]) ``` diff --git a/platform/darwin/docs/guides/For Style Authors.md.ejs b/platform/darwin/docs/guides/For Style Authors.md.ejs index 92ce4c1594..93ca7014a3 100644 --- a/platform/darwin/docs/guides/For Style Authors.md.ejs +++ b/platform/darwin/docs/guides/For Style Authors.md.ejs @@ -240,30 +240,6 @@ whose names differ from the style specification are listed below: <% for (const type in renamedProperties) { -%> <% if (renamedProperties.hasOwnProperty(type)) { -%> -### <%- camelize(type) %> style functions - -The runtime styling API introduces `MGLStyleFunction` to the <%- os %> SDK. -[Data-driven styling](data-driven-styling.html) expands `MGLStyleFunction`. -Individual style property documentation includes which subclasses of -`MGLStyleFunction` are enabled for that property. You can use `MGLStyleValue` -methods to create a `MGLStyleFunction`. - -In style specification | In the SDK | [MGLStyleValue valueWithInterpolationMode:...] ------------------------|-------------------------------|------------- -`zoom function` | `MGLCameraStyleFunction` | `cameraStops:options:` -`property function` | `MGLSourceStyleFunction` | `sourceStops:attributeName:options:` -`zoom-and-property functions`| `MGLCompositeStyleFunction` | `compositeStops:attributeName:options:` - -Data-driven styling also introduces interpolation mode, which defines the -relationship between style values and attributes or zoom levels. - -In style specification | In the SDK ------------------------------|----------- -`exponential` | `MGLInterpolationModeExponential` -`interval` | `MGLInterpolationModeInterval` -`categorical` | `MGLInterpolationModeCategorical` -`identity` | `MGLInterpolationModeIdentity` - ### <%- camelize(type) %> style layers In style JSON | In Objective-C | In Swift @@ -280,10 +256,12 @@ In style JSON | In Objective-C | In Swift Each property representing a layout or paint attribute is set to an `MGLStyleValue` object, which is either an `MGLConstantStyleValue` object (for -constant values) or an `MGLStyleFunction` object (for zoom level functions). The +constant values) or an `MGLStyleFunction` object (for style functions). The style value object is a container for the raw value or function parameters that you want the attribute to be set to. +### Constant style values + In contrast to the JSON type that the style specification defines for each layout or paint property, the style value object often contains a more specific Foundation or Cocoa type. General rules for attribute types are listed below. @@ -326,6 +304,40 @@ translation downward. This is the reverse of how `CGVector` is interpreted on iOS. <% } -%> +### Style functions + +A _style function_ allows you to vary the value of a layout or paint attribute +based on the zoom level, data provided by content sources, or both. For more +information about style functions that incorporate data from sources, see +“[Data-Driven Styling](data-driven-styling.html)”. + +Each kind of style function is represented by a distinct class, but you +typically create style functions as you create any other style value, using +class methods on `MGLStyleValue`: + +In style specification | SDK class | SDK factory method +---------------------------|-----------------------------|------------------- +zoom function | `MGLCameraStyleFunction` | `+[MGLStyleValue valueWithInterpolationMode:cameraStops:options:]` +property function | `MGLSourceStyleFunction` | `+[MGLStyleValue valueWithInterpolationMode:sourceStops:attributeName:options:]` +zoom-and-property function | `MGLCompositeStyleFunction` | `+[MGLStyleValue valueWithInterpolationMode:compositeStops:attributeName:options:]` + +The documentation for each individual style layer property indicates the kinds +of style functions that are enabled for that property. + +When you create a style function, you specify an _interpolation mode_ and a +series of _stops_. Each stop determines the effective value displayed at a +particular zoom level (for camera functions) or the effective value on features +with a particular attribute value in the content source (for source functions). +The interpolation mode tells the SDK how to calculate the effective value +between any two stops: + +In style specification | In the SDK +-----------------------------|----------- +`exponential` | `MGLInterpolationModeExponential` +`interval` | `MGLInterpolationModeInterval` +`categorical` | `MGLInterpolationModeCategorical` +`identity` | `MGLInterpolationModeIdentity` + ## Filtering sources You can filter a shape or vector source by setting the diff --git a/platform/ios/docs/guides/Data-Driven Styling.md b/platform/ios/docs/guides/Data-Driven Styling.md index 0b685512b4..a5ed874b5d 100644 --- a/platform/ios/docs/guides/Data-Driven Styling.md +++ b/platform/ios/docs/guides/Data-Driven Styling.md @@ -6,44 +6,43 @@ # Data-Driven Styling -Mapbox’s data-driven styling features allow you to use data properties to style your maps. You can style map features automatically based on their individual attributes. +Mapbox’s data-driven styling features allow you to use attributes in the data to style your maps. You can style map features automatically based on their individual attributes. Vary POI icons, transit route line colors, city polygon opacity, and more based on any attribute in your data. Need to visualize hotel data by price? You can have your map’s point radii and colors change automatically with your data. ![available bikes](img/data-driven-styling/citibikes.png) ![subway lines](img/data-driven-styling/polylineExample.png) -# How to use Data-Driven Styling This guide uses earthquake data from the [U.S. Geological Survey](https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php) to style a map based on attributes. For more information about how to work with GeoJSON data in our iOS SDK, please see our [working with GeoJSON data](working-with-geojson-data.html) guide. -`MGLStyleFunction` +## Style functions There are three subclasses of `MGLStyleFunction`: -* `MGLCameraStyleFunction` - For a style value that changes with zoom level. For example, you can make the radius of a circle increase according to zoom level. -* `MGLSourceStyleFunction` - For a style value that changes with the attributes of a feature. For example, you can adjust the radius of a circle based on the magnitude of an earthquake. -* `MGLCompositeStyleFunction` - For a style value that changes with both zoom level and attribute values. For example, you can add a circle layer where each circle has a radius based on both zoom level and the magnitude of an earthquake. +* `MGLCameraStyleFunction` is a style value that changes with zoom level. For example, you can make the radius of a circle increase according to zoom level. +* `MGLSourceStyleFunction` is a style value that changes with the attributes of a feature. For example, you can adjust the radius of a circle based on the magnitude of an earthquake. +* `MGLCompositeStyleFunction` is a style value that changes with both zoom level and attribute values. For example, you can add a circle layer where each circle has a radius based on both zoom level and the magnitude of an earthquake. -The documentation for individual style properties will note which style functions are enabled for that property. +The documentation for each individual style layer property notes which style functions are enabled for that property. ## Stops Stops are key-value pairs that that determine a style value. With a `MGLCameraSourceFunction` stop, you can use a dictionary with a zoom level for a key and a `MGLStyleValue` for the value. For example, you can use a stops dictionary with zoom levels 0, 10, and 20 as keys, and yellow, orange, and red as the values. A `MGLSourceStyleFunction` uses the relevant attribute value as the key. ```swift -let stops = [0: MGLStyleValue(rawValue: UIColor.yellow), - 2.5: MGLStyleValue(rawValue: UIColor.orange), - 5: MGLStyleValue(rawValue: UIColor.red), - 7.5: MGLStyleValue(rawValue: UIColor.blue), - 10: MGLStyleValue(rawValue: UIColor.white)] +let stops = [0: MGLStyleValue(rawValue: .yellow), + 2.5: MGLStyleValue(rawValue: .orange), + 5: MGLStyleValue(rawValue: .red), + 7.5: MGLStyleValue(rawValue: .blue), + 10: MGLStyleValue(rawValue: .white)] ``` -## Interpolation Mode +## Interpolation mode The effect a key has on the style value is determined by the interpolation mode. There are four interpolation modes that can be used with a source style function: exponential, interval, categorical, and identity. You can also use exponential and interval interpolation modes with a camera style function. ### Linear -`MGLInterpolationModelExponential` interpolates linearly or exponentially between style function stop values. By default, the `MGLStyleFunction` options parameter `MGLStyleFunctionOptionInterpolationBase` equals `1`, which represents linear interpolation, and doesn’t need to be included in the options dictionary. +`MGLInterpolationModeExponential` interpolates linearly or exponentially between style function stop values. By default, the `MGLStyleFunction` options parameter `MGLStyleFunctionOptionInterpolationBase` equals `1`, which represents linear interpolation and doesn’t need to be included in the options dictionary. The stops dictionary below, for example, shows colors that continuously shift from yellow to orange to red to blue to white based on the attribute value. @@ -55,11 +54,11 @@ let symbolLayer = MGLSymbolStyleLayer(identifier: "place-city-sm", source: symbo let source = MGLShapeSource(identifier: "earthquakes", url: url, options: nil) style.addSource(source) -let stops = [0: MGLStyleValue(rawValue: UIColor.yellow), - 2.5: MGLStyleValue(rawValue: UIColor.orange), - 5: MGLStyleValue(rawValue: UIColor.red), - 7.5: MGLStyleValue(rawValue: UIColor.blue), - 10: MGLStyleValue(rawValue: UIColor.white)] +let stops = [0: MGLStyleValue(rawValue: .yellow), + 2.5: MGLStyleValue(rawValue: .orange), + 5: MGLStyleValue(rawValue: .red), + 7.5: MGLStyleValue(rawValue: .blue), + 10: MGLStyleValue(rawValue: .white)] let layer = MGLCircleStyleLayer(identifier: "circles", source: source) layer.circleColor = MGLStyleValue(interpolationMode: .exponential, @@ -74,7 +73,7 @@ style.insertLayer(layer, below: symbolLayer) ### Exponential -`MGLInterpolationModelExponential` combined with any `MGLStyleFunctionOptionInterpolationBase` greater than `0`, you can interpolate between values exponentially, create an accelerated ramp effect. +By combining `MGLInterpolationModeExponential` with an `MGLStyleFunctionOptionInterpolationBase` greater than `0` (other than `1`), you can interpolate between values exponentially, create an accelerated ramp effect. Here’s a visualization from Mapbox Studio (see [Working with Mapbox Studio](working-with-mapbox-studio.html)) comparing interpolation base values of `1.5` and `0.5` based on zoom. @@ -100,11 +99,11 @@ layer.circleRadius = MGLStyleValue(interpolationMode: .exponential, When we use the stops dictionary given above with an interval interpolation mode, we create ranges where earthquakes with a magnitude of 0 to just less than 2.5 would be yellow, 2.5 to just less than 5 would be orange, and so on. ``` swift -let stops = [0: MGLStyleValue(rawValue: UIColor.yellow), - 2.5: MGLStyleValue(rawValue: UIColor.orange), - 5: MGLStyleValue(rawValue: UIColor.red), - 7.5: MGLStyleValue(rawValue: UIColor.blue), - 10: MGLStyleValue(rawValue: UIColor.white)] +let stops = [0: MGLStyleValue(rawValue: .yellow), + 2.5: MGLStyleValue(rawValue: .orange), + 5: MGLStyleValue(rawValue: .red), + 7.5: MGLStyleValue(rawValue: .blue), + 10: MGLStyleValue(rawValue: .white)] layer.circleColor = MGLStyleValue(interpolationMode: .interval, sourceStops: stops, @@ -116,19 +115,19 @@ layer.circleColor = MGLStyleValue(interpolationMode: .interval, ### Categorical -Returns the output value that is equal to the stop for the function input. We’re going to use a different stops dictionary than we did for the previous two modes. +At each stop, `MGLInterpolationModeCategorical` produces an output value equal to the function input. We’re going to use a different stops dictionary than we did for the previous two modes. There are three main types of events in the dataset: earthquakes, explosions, and quarry blasts. In this case, the color of the circle layer will be determined by the type of event, with a default value of green to catch any events that do not fall into any of those categories. ``` swift -let categoricalStops = ["earthquake": MGLStyleValue(rawValue: UIColor.orange), - "explosion": MGLStyleValue(rawValue: UIColor.red), - "quarry blast": MGLStyleValue(rawValue: UIColor.yellow)] +let categoricalStops = ["earthquake": MGLStyleValue(rawValue: .orange), + "explosion": MGLStyleValue(rawValue: .red), + "quarry blast": MGLStyleValue(rawValue: .yellow)] layer.circleColor = MGLStyleValue(interpolationMode: .categorical, sourceStops: categoricalStops, attributeName: "type", - options: [.defaultValue: MGLStyleValue(rawValue: UIColor.blue)]) + options: [.defaultValue: MGLStyleValue(rawValue: .blue)]) ``` diff --git a/platform/ios/docs/guides/For Style Authors.md b/platform/ios/docs/guides/For Style Authors.md index 952be6bec7..d3ba331e09 100644 --- a/platform/ios/docs/guides/For Style Authors.md +++ b/platform/ios/docs/guides/For Style Authors.md @@ -190,30 +190,6 @@ layer objects. The property names generally correspond to the style JSON properties, except for the use of camelCase instead of kebab-case. Properties whose names differ from the style specification are listed below: -### Circle style functions - -The runtime styling API introduces `MGLStyleFunction` to the iOS SDK. -[Data-driven styling](data-driven-styling.html) expands `MGLStyleFunction`. -Individual style property documentation includes which subclasses of -`MGLStyleFunction` are enabled for that property. You can use `MGLStyleValue` -methods to create a `MGLStyleFunction`. - -In style specification | In the SDK | [MGLStyleValue valueWithInterpolationMode:...] ------------------------|-------------------------------|------------- -`zoom function` | `MGLCameraStyleFunction` | `cameraStops:options:` -`property function` | `MGLSourceStyleFunction` | `sourceStops:attributeName:options:` -`zoom-and-property functions`| `MGLCompositeStyleFunction` | `compositeStops:attributeName:options:` - -Data-driven styling also introduces interpolation mode, which defines the -relationship between style values and attributes or zoom levels. - -In style specification | In the SDK ------------------------------|----------- -`exponential` | `MGLInterpolationModeExponential` -`interval` | `MGLInterpolationModeInterval` -`categorical` | `MGLInterpolationModeCategorical` -`identity` | `MGLInterpolationModeIdentity` - ### Circle style layers In style JSON | In Objective-C | In Swift @@ -222,30 +198,6 @@ In style JSON | In Objective-C | In Swift `circle-translate` | `MGLCircleStyleLayer.circleTranslation` | `MGLCircleStyleLayer.circleTranslation` `circle-translate-anchor` | `MGLCircleStyleLayer.circleTranslationAnchor` | `MGLCircleStyleLayer.circleTranslationAnchor` -### Fill style functions - -The runtime styling API introduces `MGLStyleFunction` to the iOS SDK. -[Data-driven styling](data-driven-styling.html) expands `MGLStyleFunction`. -Individual style property documentation includes which subclasses of -`MGLStyleFunction` are enabled for that property. You can use `MGLStyleValue` -methods to create a `MGLStyleFunction`. - -In style specification | In the SDK | [MGLStyleValue valueWithInterpolationMode:...] ------------------------|-------------------------------|------------- -`zoom function` | `MGLCameraStyleFunction` | `cameraStops:options:` -`property function` | `MGLSourceStyleFunction` | `sourceStops:attributeName:options:` -`zoom-and-property functions`| `MGLCompositeStyleFunction` | `compositeStops:attributeName:options:` - -Data-driven styling also introduces interpolation mode, which defines the -relationship between style values and attributes or zoom levels. - -In style specification | In the SDK ------------------------------|----------- -`exponential` | `MGLInterpolationModeExponential` -`interval` | `MGLInterpolationModeInterval` -`categorical` | `MGLInterpolationModeCategorical` -`identity` | `MGLInterpolationModeIdentity` - ### Fill style layers In style JSON | In Objective-C | In Swift @@ -254,30 +206,6 @@ In style JSON | In Objective-C | In Swift `fill-translate` | `MGLFillStyleLayer.fillTranslation` | `MGLFillStyleLayer.fillTranslation` `fill-translate-anchor` | `MGLFillStyleLayer.fillTranslationAnchor` | `MGLFillStyleLayer.fillTranslationAnchor` -### Line style functions - -The runtime styling API introduces `MGLStyleFunction` to the iOS SDK. -[Data-driven styling](data-driven-styling.html) expands `MGLStyleFunction`. -Individual style property documentation includes which subclasses of -`MGLStyleFunction` are enabled for that property. You can use `MGLStyleValue` -methods to create a `MGLStyleFunction`. - -In style specification | In the SDK | [MGLStyleValue valueWithInterpolationMode:...] ------------------------|-------------------------------|------------- -`zoom function` | `MGLCameraStyleFunction` | `cameraStops:options:` -`property function` | `MGLSourceStyleFunction` | `sourceStops:attributeName:options:` -`zoom-and-property functions`| `MGLCompositeStyleFunction` | `compositeStops:attributeName:options:` - -Data-driven styling also introduces interpolation mode, which defines the -relationship between style values and attributes or zoom levels. - -In style specification | In the SDK ------------------------------|----------- -`exponential` | `MGLInterpolationModeExponential` -`interval` | `MGLInterpolationModeInterval` -`categorical` | `MGLInterpolationModeCategorical` -`identity` | `MGLInterpolationModeIdentity` - ### Line style layers In style JSON | In Objective-C | In Swift @@ -286,30 +214,6 @@ In style JSON | In Objective-C | In Swift `line-translate` | `MGLLineStyleLayer.lineTranslation` | `MGLLineStyleLayer.lineTranslation` `line-translate-anchor` | `MGLLineStyleLayer.lineTranslationAnchor` | `MGLLineStyleLayer.lineTranslationAnchor` -### Raster style functions - -The runtime styling API introduces `MGLStyleFunction` to the iOS SDK. -[Data-driven styling](data-driven-styling.html) expands `MGLStyleFunction`. -Individual style property documentation includes which subclasses of -`MGLStyleFunction` are enabled for that property. You can use `MGLStyleValue` -methods to create a `MGLStyleFunction`. - -In style specification | In the SDK | [MGLStyleValue valueWithInterpolationMode:...] ------------------------|-------------------------------|------------- -`zoom function` | `MGLCameraStyleFunction` | `cameraStops:options:` -`property function` | `MGLSourceStyleFunction` | `sourceStops:attributeName:options:` -`zoom-and-property functions`| `MGLCompositeStyleFunction` | `compositeStops:attributeName:options:` - -Data-driven styling also introduces interpolation mode, which defines the -relationship between style values and attributes or zoom levels. - -In style specification | In the SDK ------------------------------|----------- -`exponential` | `MGLInterpolationModeExponential` -`interval` | `MGLInterpolationModeInterval` -`categorical` | `MGLInterpolationModeCategorical` -`identity` | `MGLInterpolationModeIdentity` - ### Raster style layers In style JSON | In Objective-C | In Swift @@ -318,30 +222,6 @@ In style JSON | In Objective-C | In Swift `raster-brightness-min` | `MGLRasterStyleLayer.minimumRasterBrightness` | `MGLRasterStyleLayer.minimumRasterBrightness` `raster-hue-rotate` | `MGLRasterStyleLayer.rasterHueRotation` | `MGLRasterStyleLayer.rasterHueRotation` -### Symbol style functions - -The runtime styling API introduces `MGLStyleFunction` to the iOS SDK. -[Data-driven styling](data-driven-styling.html) expands `MGLStyleFunction`. -Individual style property documentation includes which subclasses of -`MGLStyleFunction` are enabled for that property. You can use `MGLStyleValue` -methods to create a `MGLStyleFunction`. - -In style specification | In the SDK | [MGLStyleValue valueWithInterpolationMode:...] ------------------------|-------------------------------|------------- -`zoom function` | `MGLCameraStyleFunction` | `cameraStops:options:` -`property function` | `MGLSourceStyleFunction` | `sourceStops:attributeName:options:` -`zoom-and-property functions`| `MGLCompositeStyleFunction` | `compositeStops:attributeName:options:` - -Data-driven styling also introduces interpolation mode, which defines the -relationship between style values and attributes or zoom levels. - -In style specification | In the SDK ------------------------------|----------- -`exponential` | `MGLInterpolationModeExponential` -`interval` | `MGLInterpolationModeInterval` -`categorical` | `MGLInterpolationModeCategorical` -`identity` | `MGLInterpolationModeIdentity` - ### Symbol style layers In style JSON | In Objective-C | In Swift @@ -374,10 +254,12 @@ In style JSON | In Objective-C | In Swift Each property representing a layout or paint attribute is set to an `MGLStyleValue` object, which is either an `MGLConstantStyleValue` object (for -constant values) or an `MGLStyleFunction` object (for zoom level functions). The +constant values) or an `MGLStyleFunction` object (for style functions). The style value object is a container for the raw value or function parameters that you want the attribute to be set to. +### Constant style values + In contrast to the JSON type that the style specification defines for each layout or paint property, the style value object often contains a more specific Foundation or Cocoa type. General rules for attribute types are listed below. @@ -402,6 +284,40 @@ in Swift are specified in counterclockwise order, in contrast to the clockwise order defined by the style specification. +### Style functions + +A _style function_ allows you to vary the value of a layout or paint attribute +based on the zoom level, data provided by content sources, or both. For more +information about style functions that incorporate data from sources, see +“[Data-Driven Styling](data-driven-styling.html)”. + +Each kind of style function is represented by a distinct class, but you +typically create style functions as you create any other style value, using +class methods on `MGLStyleValue`: + +In style specification | SDK class | SDK factory method +---------------------------|-----------------------------|------------------- +zoom function | `MGLCameraStyleFunction` | `+[MGLStyleValue valueWithInterpolationMode:cameraStops:options:]` +property function | `MGLSourceStyleFunction` | `+[MGLStyleValue valueWithInterpolationMode:sourceStops:attributeName:options:]` +zoom-and-property function | `MGLCompositeStyleFunction` | `+[MGLStyleValue valueWithInterpolationMode:compositeStops:attributeName:options:]` + +The documentation for each individual style layer property indicates the kinds +of style functions that are enabled for that property. + +When you create a style function, you specify an _interpolation mode_ and a +series of _stops_. Each stop determines the effective value displayed at a +particular zoom level (for camera functions) or the effective value on features +with a particular attribute value in the content source (for source functions). +The interpolation mode tells the SDK how to calculate the effective value +between any two stops: + +In style specification | In the SDK +-----------------------------|----------- +`exponential` | `MGLInterpolationModeExponential` +`interval` | `MGLInterpolationModeInterval` +`categorical` | `MGLInterpolationModeCategorical` +`identity` | `MGLInterpolationModeIdentity` + ## Filtering sources You can filter a shape or vector source by setting the diff --git a/platform/macos/docs/guides/Data-Driven Styling.md b/platform/macos/docs/guides/Data-Driven Styling.md index 9e38e71318..2adb0197d1 100644 --- a/platform/macos/docs/guides/Data-Driven Styling.md +++ b/platform/macos/docs/guides/Data-Driven Styling.md @@ -6,44 +6,43 @@ # Data-Driven Styling -Mapbox’s data-driven styling features allow you to use data properties to style your maps. You can style map features automatically based on their individual attributes. +Mapbox’s data-driven styling features allow you to use attributes in the data to style your maps. You can style map features automatically based on their individual attributes. Vary POI icons, transit route line colors, city polygon opacity, and more based on any attribute in your data. Need to visualize hotel data by price? You can have your map’s point radii and colors change automatically with your data. ![available bikes](img/data-driven-styling/citibikes.png) ![subway lines](img/data-driven-styling/polylineExample.png) -# How to use Data-Driven Styling This guide uses earthquake data from the [U.S. Geological Survey](https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php) to style a map based on attributes. For more information about how to work with GeoJSON data in our iOS SDK, please see our [working with GeoJSON data](working-with-geojson-data.html) guide. -`MGLStyleFunction` +## Style functions There are three subclasses of `MGLStyleFunction`: -* `MGLCameraStyleFunction` - For a style value that changes with zoom level. For example, you can make the radius of a circle increase according to zoom level. -* `MGLSourceStyleFunction` - For a style value that changes with the attributes of a feature. For example, you can adjust the radius of a circle based on the magnitude of an earthquake. -* `MGLCompositeStyleFunction` - For a style value that changes with both zoom level and attribute values. For example, you can add a circle layer where each circle has a radius based on both zoom level and the magnitude of an earthquake. +* `MGLCameraStyleFunction` is a style value that changes with zoom level. For example, you can make the radius of a circle increase according to zoom level. +* `MGLSourceStyleFunction` is a style value that changes with the attributes of a feature. For example, you can adjust the radius of a circle based on the magnitude of an earthquake. +* `MGLCompositeStyleFunction` is a style value that changes with both zoom level and attribute values. For example, you can add a circle layer where each circle has a radius based on both zoom level and the magnitude of an earthquake. -The documentation for individual style properties will note which style functions are enabled for that property. +The documentation for each individual style layer property notes which style functions are enabled for that property. ## Stops Stops are key-value pairs that that determine a style value. With a `MGLCameraSourceFunction` stop, you can use a dictionary with a zoom level for a key and a `MGLStyleValue` for the value. For example, you can use a stops dictionary with zoom levels 0, 10, and 20 as keys, and yellow, orange, and red as the values. A `MGLSourceStyleFunction` uses the relevant attribute value as the key. ```swift -let stops = [0: MGLStyleValue(rawValue: UIColor.yellow), - 2.5: MGLStyleValue(rawValue: UIColor.orange), - 5: MGLStyleValue(rawValue: UIColor.red), - 7.5: MGLStyleValue(rawValue: UIColor.blue), - 10: MGLStyleValue(rawValue: UIColor.white)] +let stops = [0: MGLStyleValue(rawValue: .yellow), + 2.5: MGLStyleValue(rawValue: .orange), + 5: MGLStyleValue(rawValue: .red), + 7.5: MGLStyleValue(rawValue: .blue), + 10: MGLStyleValue(rawValue: .white)] ``` -## Interpolation Mode +## Interpolation mode The effect a key has on the style value is determined by the interpolation mode. There are four interpolation modes that can be used with a source style function: exponential, interval, categorical, and identity. You can also use exponential and interval interpolation modes with a camera style function. ### Linear -`MGLInterpolationModelExponential` interpolates linearly or exponentially between style function stop values. By default, the `MGLStyleFunction` options parameter `MGLStyleFunctionOptionInterpolationBase` equals `1`, which represents linear interpolation, and doesn’t need to be included in the options dictionary. +`MGLInterpolationModeExponential` interpolates linearly or exponentially between style function stop values. By default, the `MGLStyleFunction` options parameter `MGLStyleFunctionOptionInterpolationBase` equals `1`, which represents linear interpolation and doesn’t need to be included in the options dictionary. The stops dictionary below, for example, shows colors that continuously shift from yellow to orange to red to blue to white based on the attribute value. @@ -55,11 +54,11 @@ let symbolLayer = MGLSymbolStyleLayer(identifier: "place-city-sm", source: symbo let source = MGLShapeSource(identifier: "earthquakes", url: url, options: nil) style.addSource(source) -let stops = [0: MGLStyleValue(rawValue: NSColor.yellow), - 2.5: MGLStyleValue(rawValue: NSColor.orange), - 5: MGLStyleValue(rawValue: NSColor.red), - 7.5: MGLStyleValue(rawValue: NSColor.blue), - 10: MGLStyleValue(rawValue: NSColor.white)] +let stops = [0: MGLStyleValue(rawValue: .yellow), + 2.5: MGLStyleValue(rawValue: .orange), + 5: MGLStyleValue(rawValue: .red), + 7.5: MGLStyleValue(rawValue: .blue), + 10: MGLStyleValue(rawValue: .white)] let layer = MGLCircleStyleLayer(identifier: "circles", source: source) layer.circleColor = MGLStyleValue(interpolationMode: .exponential, @@ -74,7 +73,7 @@ style.insertLayer(layer, below: symbolLayer) ### Exponential -`MGLInterpolationModelExponential` combined with any `MGLStyleFunctionOptionInterpolationBase` greater than `0`, you can interpolate between values exponentially, create an accelerated ramp effect. +By combining `MGLInterpolationModeExponential` with an `MGLStyleFunctionOptionInterpolationBase` greater than `0` (other than `1`), you can interpolate between values exponentially, create an accelerated ramp effect. Here’s a visualization from Mapbox Studio (see [Working with Mapbox Studio](working-with-mapbox-studio.html)) comparing interpolation base values of `1.5` and `0.5` based on zoom. @@ -100,11 +99,11 @@ layer.circleRadius = MGLStyleValue(interpolationMode: .exponential, When we use the stops dictionary given above with an interval interpolation mode, we create ranges where earthquakes with a magnitude of 0 to just less than 2.5 would be yellow, 2.5 to just less than 5 would be orange, and so on. ``` swift -let stops = [0: MGLStyleValue(rawValue: NSColor.yellow), - 2.5: MGLStyleValue(rawValue: NSColor.orange), - 5: MGLStyleValue(rawValue: NSColor.red), - 7.5: MGLStyleValue(rawValue: NSColor.blue), - 10: MGLStyleValue(rawValue: NSColor.white)] +let stops = [0: MGLStyleValue(rawValue: .yellow), + 2.5: MGLStyleValue(rawValue: .orange), + 5: MGLStyleValue(rawValue: .red), + 7.5: MGLStyleValue(rawValue: .blue), + 10: MGLStyleValue(rawValue: .white)] layer.circleColor = MGLStyleValue(interpolationMode: .interval, sourceStops: stops, @@ -116,19 +115,19 @@ layer.circleColor = MGLStyleValue(interpolationMode: .interval, ### Categorical -Returns the output value that is equal to the stop for the function input. We’re going to use a different stops dictionary than we did for the previous two modes. +At each stop, `MGLInterpolationModeCategorical` produces an output value equal to the function input. We’re going to use a different stops dictionary than we did for the previous two modes. There are three main types of events in the dataset: earthquakes, explosions, and quarry blasts. In this case, the color of the circle layer will be determined by the type of event, with a default value of green to catch any events that do not fall into any of those categories. ``` swift -let categoricalStops = ["earthquake": MGLStyleValue(rawValue: NSColor.orange), - "explosion": MGLStyleValue(rawValue: NSColor.red), - "quarry blast": MGLStyleValue(rawValue: NSColor.yellow)] +let categoricalStops = ["earthquake": MGLStyleValue(rawValue: .orange), + "explosion": MGLStyleValue(rawValue: .red), + "quarry blast": MGLStyleValue(rawValue: .yellow)] layer.circleColor = MGLStyleValue(interpolationMode: .categorical, sourceStops: categoricalStops, attributeName: "type", - options: [.defaultValue: MGLStyleValue(rawValue: NSColor.blue)]) + options: [.defaultValue: MGLStyleValue(rawValue: .blue)]) ``` diff --git a/platform/macos/docs/guides/For Style Authors.md b/platform/macos/docs/guides/For Style Authors.md index 9c3665d816..f576921857 100644 --- a/platform/macos/docs/guides/For Style Authors.md +++ b/platform/macos/docs/guides/For Style Authors.md @@ -179,30 +179,6 @@ layer objects. The property names generally correspond to the style JSON properties, except for the use of camelCase instead of kebab-case. Properties whose names differ from the style specification are listed below: -### Circle style functions - -The runtime styling API introduces `MGLStyleFunction` to the macOS SDK. -[Data-driven styling](data-driven-styling.html) expands `MGLStyleFunction`. -Individual style property documentation includes which subclasses of -`MGLStyleFunction` are enabled for that property. You can use `MGLStyleValue` -methods to create a `MGLStyleFunction`. - -In style specification | In the SDK | [MGLStyleValue valueWithInterpolationMode:...] ------------------------|-------------------------------|------------- -`zoom function` | `MGLCameraStyleFunction` | `cameraStops:options:` -`property function` | `MGLSourceStyleFunction` | `sourceStops:attributeName:options:` -`zoom-and-property functions`| `MGLCompositeStyleFunction` | `compositeStops:attributeName:options:` - -Data-driven styling also introduces interpolation mode, which defines the -relationship between style values and attributes or zoom levels. - -In style specification | In the SDK ------------------------------|----------- -`exponential` | `MGLInterpolationModeExponential` -`interval` | `MGLInterpolationModeInterval` -`categorical` | `MGLInterpolationModeCategorical` -`identity` | `MGLInterpolationModeIdentity` - ### Circle style layers In style JSON | In Objective-C | In Swift @@ -211,30 +187,6 @@ In style JSON | In Objective-C | In Swift `circle-translate` | `MGLCircleStyleLayer.circleTranslation` | `MGLCircleStyleLayer.circleTranslation` `circle-translate-anchor` | `MGLCircleStyleLayer.circleTranslationAnchor` | `MGLCircleStyleLayer.circleTranslationAnchor` -### Fill style functions - -The runtime styling API introduces `MGLStyleFunction` to the macOS SDK. -[Data-driven styling](data-driven-styling.html) expands `MGLStyleFunction`. -Individual style property documentation includes which subclasses of -`MGLStyleFunction` are enabled for that property. You can use `MGLStyleValue` -methods to create a `MGLStyleFunction`. - -In style specification | In the SDK | [MGLStyleValue valueWithInterpolationMode:...] ------------------------|-------------------------------|------------- -`zoom function` | `MGLCameraStyleFunction` | `cameraStops:options:` -`property function` | `MGLSourceStyleFunction` | `sourceStops:attributeName:options:` -`zoom-and-property functions`| `MGLCompositeStyleFunction` | `compositeStops:attributeName:options:` - -Data-driven styling also introduces interpolation mode, which defines the -relationship between style values and attributes or zoom levels. - -In style specification | In the SDK ------------------------------|----------- -`exponential` | `MGLInterpolationModeExponential` -`interval` | `MGLInterpolationModeInterval` -`categorical` | `MGLInterpolationModeCategorical` -`identity` | `MGLInterpolationModeIdentity` - ### Fill style layers In style JSON | In Objective-C | In Swift @@ -243,30 +195,6 @@ In style JSON | In Objective-C | In Swift `fill-translate` | `MGLFillStyleLayer.fillTranslation` | `MGLFillStyleLayer.fillTranslation` `fill-translate-anchor` | `MGLFillStyleLayer.fillTranslationAnchor` | `MGLFillStyleLayer.fillTranslationAnchor` -### Line style functions - -The runtime styling API introduces `MGLStyleFunction` to the macOS SDK. -[Data-driven styling](data-driven-styling.html) expands `MGLStyleFunction`. -Individual style property documentation includes which subclasses of -`MGLStyleFunction` are enabled for that property. You can use `MGLStyleValue` -methods to create a `MGLStyleFunction`. - -In style specification | In the SDK | [MGLStyleValue valueWithInterpolationMode:...] ------------------------|-------------------------------|------------- -`zoom function` | `MGLCameraStyleFunction` | `cameraStops:options:` -`property function` | `MGLSourceStyleFunction` | `sourceStops:attributeName:options:` -`zoom-and-property functions`| `MGLCompositeStyleFunction` | `compositeStops:attributeName:options:` - -Data-driven styling also introduces interpolation mode, which defines the -relationship between style values and attributes or zoom levels. - -In style specification | In the SDK ------------------------------|----------- -`exponential` | `MGLInterpolationModeExponential` -`interval` | `MGLInterpolationModeInterval` -`categorical` | `MGLInterpolationModeCategorical` -`identity` | `MGLInterpolationModeIdentity` - ### Line style layers In style JSON | In Objective-C | In Swift @@ -275,30 +203,6 @@ In style JSON | In Objective-C | In Swift `line-translate` | `MGLLineStyleLayer.lineTranslation` | `MGLLineStyleLayer.lineTranslation` `line-translate-anchor` | `MGLLineStyleLayer.lineTranslationAnchor` | `MGLLineStyleLayer.lineTranslationAnchor` -### Raster style functions - -The runtime styling API introduces `MGLStyleFunction` to the macOS SDK. -[Data-driven styling](data-driven-styling.html) expands `MGLStyleFunction`. -Individual style property documentation includes which subclasses of -`MGLStyleFunction` are enabled for that property. You can use `MGLStyleValue` -methods to create a `MGLStyleFunction`. - -In style specification | In the SDK | [MGLStyleValue valueWithInterpolationMode:...] ------------------------|-------------------------------|------------- -`zoom function` | `MGLCameraStyleFunction` | `cameraStops:options:` -`property function` | `MGLSourceStyleFunction` | `sourceStops:attributeName:options:` -`zoom-and-property functions`| `MGLCompositeStyleFunction` | `compositeStops:attributeName:options:` - -Data-driven styling also introduces interpolation mode, which defines the -relationship between style values and attributes or zoom levels. - -In style specification | In the SDK ------------------------------|----------- -`exponential` | `MGLInterpolationModeExponential` -`interval` | `MGLInterpolationModeInterval` -`categorical` | `MGLInterpolationModeCategorical` -`identity` | `MGLInterpolationModeIdentity` - ### Raster style layers In style JSON | In Objective-C | In Swift @@ -307,30 +211,6 @@ In style JSON | In Objective-C | In Swift `raster-brightness-min` | `MGLRasterStyleLayer.minimumRasterBrightness` | `MGLRasterStyleLayer.minimumRasterBrightness` `raster-hue-rotate` | `MGLRasterStyleLayer.rasterHueRotation` | `MGLRasterStyleLayer.rasterHueRotation` -### Symbol style functions - -The runtime styling API introduces `MGLStyleFunction` to the macOS SDK. -[Data-driven styling](data-driven-styling.html) expands `MGLStyleFunction`. -Individual style property documentation includes which subclasses of -`MGLStyleFunction` are enabled for that property. You can use `MGLStyleValue` -methods to create a `MGLStyleFunction`. - -In style specification | In the SDK | [MGLStyleValue valueWithInterpolationMode:...] ------------------------|-------------------------------|------------- -`zoom function` | `MGLCameraStyleFunction` | `cameraStops:options:` -`property function` | `MGLSourceStyleFunction` | `sourceStops:attributeName:options:` -`zoom-and-property functions`| `MGLCompositeStyleFunction` | `compositeStops:attributeName:options:` - -Data-driven styling also introduces interpolation mode, which defines the -relationship between style values and attributes or zoom levels. - -In style specification | In the SDK ------------------------------|----------- -`exponential` | `MGLInterpolationModeExponential` -`interval` | `MGLInterpolationModeInterval` -`categorical` | `MGLInterpolationModeCategorical` -`identity` | `MGLInterpolationModeIdentity` - ### Symbol style layers In style JSON | In Objective-C | In Swift @@ -363,10 +243,12 @@ In style JSON | In Objective-C | In Swift Each property representing a layout or paint attribute is set to an `MGLStyleValue` object, which is either an `MGLConstantStyleValue` object (for -constant values) or an `MGLStyleFunction` object (for zoom level functions). The +constant values) or an `MGLStyleFunction` object (for style functions). The style value object is a container for the raw value or function parameters that you want the attribute to be set to. +### Constant style values + In contrast to the JSON type that the style specification defines for each layout or paint property, the style value object often contains a more specific Foundation or Cocoa type. General rules for attribute types are listed below. @@ -397,6 +279,40 @@ offset or translation upward, while a negative `CGVector.dy` means an offset or translation downward. This is the reverse of how `CGVector` is interpreted on iOS. +### Style functions + +A _style function_ allows you to vary the value of a layout or paint attribute +based on the zoom level, data provided by content sources, or both. For more +information about style functions that incorporate data from sources, see +“[Data-Driven Styling](data-driven-styling.html)”. + +Each kind of style function is represented by a distinct class, but you +typically create style functions as you create any other style value, using +class methods on `MGLStyleValue`: + +In style specification | SDK class | SDK factory method +---------------------------|-----------------------------|------------------- +zoom function | `MGLCameraStyleFunction` | `+[MGLStyleValue valueWithInterpolationMode:cameraStops:options:]` +property function | `MGLSourceStyleFunction` | `+[MGLStyleValue valueWithInterpolationMode:sourceStops:attributeName:options:]` +zoom-and-property function | `MGLCompositeStyleFunction` | `+[MGLStyleValue valueWithInterpolationMode:compositeStops:attributeName:options:]` + +The documentation for each individual style layer property indicates the kinds +of style functions that are enabled for that property. + +When you create a style function, you specify an _interpolation mode_ and a +series of _stops_. Each stop determines the effective value displayed at a +particular zoom level (for camera functions) or the effective value on features +with a particular attribute value in the content source (for source functions). +The interpolation mode tells the SDK how to calculate the effective value +between any two stops: + +In style specification | In the SDK +-----------------------------|----------- +`exponential` | `MGLInterpolationModeExponential` +`interval` | `MGLInterpolationModeInterval` +`categorical` | `MGLInterpolationModeCategorical` +`identity` | `MGLInterpolationModeIdentity` + ## Filtering sources You can filter a shape or vector source by setting the -- cgit v1.2.1 From 228bff76020c48299a393fb324ff1fead06aeefb Mon Sep 17 00:00:00 2001 From: Jason Wray Date: Sun, 10 May 2015 22:49:58 -0700 Subject: [ios] Replaced UIActionSheet, UIAlertView with UIAlertController --- platform/ios/src/MGLMapView.mm | 160 ++++++++++++++++++++++------------------- 1 file changed, 88 insertions(+), 72 deletions(-) diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 6ce41d6fb4..79467a065f 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -220,10 +220,8 @@ public: @interface MGLMapView () @@ -236,7 +234,6 @@ public: @property (nonatomic) NS_MUTABLE_ARRAY_OF(NSLayoutConstraint *) *logoViewConstraints; @property (nonatomic, readwrite) UIButton *attributionButton; @property (nonatomic) NS_MUTABLE_ARRAY_OF(NSLayoutConstraint *) *attributionButtonConstraints; -@property (nonatomic) UIActionSheet *attributionSheet; @property (nonatomic, readwrite) MGLStyle *style; @property (nonatomic) UITapGestureRecognizer *singleTapGestureRecognizer; @property (nonatomic) UIPanGestureRecognizer *pan; @@ -312,8 +309,6 @@ public: MGLCompassDirectionFormatter *_accessibilityCompassFormatter; - NS_ARRAY_OF(MGLAttributionInfo *) *_attributionInfos; - MGLReachability *_reachability; } @@ -897,11 +892,6 @@ public: _mbglMap->setSize([self size]); } - if (self.attributionSheet.visible) - { - [self.attributionSheet dismissWithClickedButtonIndex:self.attributionSheet.cancelButtonIndex animated:YES]; - } - if (self.compassView.alpha) { [self updateHeadingForDeviceOrientation]; @@ -1881,82 +1871,108 @@ public: - (void)showAttribution { - self.attributionSheet = [[UIActionSheet alloc] initWithTitle:NSLocalizedStringWithDefaultValue(@"SDK_NAME", nil, nil, @"Mapbox iOS SDK", @"Action sheet title") - delegate:self - cancelButtonTitle:NSLocalizedStringWithDefaultValue(@"CANCEL", nil, nil, @"Cancel", @"") - destructiveButtonTitle:nil - otherButtonTitles:nil]; - - _attributionInfos = [self.style attributionInfosWithFontSize:[UIFont buttonFontSize] linkColor:nil]; - for (MGLAttributionInfo *info in _attributionInfos) + NSString *title = NSLocalizedStringWithDefaultValue(@"SDK_NAME", nil, nil, @"Mapbox iOS SDK", @"Action sheet title"); + UIAlertController *attributionController = [UIAlertController alertControllerWithTitle:title + message:nil + preferredStyle:UIAlertControllerStyleActionSheet]; + + NSArray *attributionInfos = [self.style attributionInfosWithFontSize:[UIFont buttonFontSize] + linkColor:nil]; + for (MGLAttributionInfo *info in attributionInfos) { NSString *title = [info.title.string mgl_titleCasedStringWithLocale:[NSLocale currentLocale]]; - [self.attributionSheet addButtonWithTitle:title]; - } - - [self.attributionSheet addButtonWithTitle:NSLocalizedStringWithDefaultValue(@"TELEMETRY_NAME", nil, nil, @"Mapbox Telemetry", @"Action in attribution sheet")]; - - [self.attributionSheet showFromRect:self.attributionButton.frame inView:self animated:YES]; -} - -- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex -{ - if (buttonIndex == actionSheet.numberOfButtons - 1) - { - NSString *message; - NSString *participate; - NSString *optOut; - - if ([[NSUserDefaults standardUserDefaults] boolForKey:@"MGLMapboxMetricsEnabled"]) - { - message = NSLocalizedStringWithDefaultValue(@"TELEMETRY_ENABLED_MSG", nil, nil, @"You are helping to make OpenStreetMap and Mapbox maps better by contributing anonymous usage data.", @"Telemetry prompt message"); - participate = NSLocalizedStringWithDefaultValue(@"TELEMETRY_ENABLED_ON", nil, nil, @"Keep Participating", @"Telemetry prompt button"); - optOut = NSLocalizedStringWithDefaultValue(@"TELEMETRY_ENABLED_OFF", nil, nil, @"Stop Participating", @"Telemetry prompt button"); - } - else - { - message = NSLocalizedStringWithDefaultValue(@"TELEMETRY_DISABLED_MSG", nil, nil, @"You can help make OpenStreetMap and Mapbox maps better by contributing anonymous usage data.", @"Telemetry prompt message"); - participate = NSLocalizedStringWithDefaultValue(@"TELEMETRY_DISABLED_ON", nil, nil, @"Participate", @"Telemetry prompt button"); - optOut = NSLocalizedStringWithDefaultValue(@"TELEMETRY_DISABLED_OFF", nil, nil, @"Don’t Participate", @"Telemetry prompt button"); - } - - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedStringWithDefaultValue(@"TELEMETRY_TITLE", nil, nil, @"Make Mapbox Maps Better", @"Telemetry prompt title") - message:message - delegate:self - cancelButtonTitle:participate - otherButtonTitles:NSLocalizedStringWithDefaultValue(@"TELEMETRY_MORE", nil, nil, @"Tell Me More", @"Telemetry prompt button"), optOut, nil]; - [alert show]; - } - else if (buttonIndex > 0) - { - MGLAttributionInfo *info = _attributionInfos[buttonIndex + actionSheet.firstOtherButtonIndex]; - NSURL *url = info.URL; - if (url) - { - if (info.feedbackLink) + UIAlertAction *action = [UIAlertAction actionWithTitle:title + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * _Nonnull action) { + NSURL *url = info.URL; + if (url) { - url = [info feedbackURLAtCenterCoordinate:self.centerCoordinate zoomLevel:self.zoomLevel]; + if (info.feedbackLink) + { + url = [info feedbackURLAtCenterCoordinate:self.centerCoordinate + zoomLevel:self.zoomLevel]; + } + [[UIApplication sharedApplication] openURL:url]; } - [[UIApplication sharedApplication] openURL:url]; - } + }]; + [attributionController addAction:action]; + } + + NSString *telemetryTitle = NSLocalizedStringWithDefaultValue(@"TELEMETRY_NAME", nil, nil, @"Mapbox Telemetry", @"Action in attribution sheet"); + UIAlertAction *telemetryAction = [UIAlertAction actionWithTitle:telemetryTitle + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * _Nonnull action) { + [self presentTelemetryAlertController]; + }]; + [attributionController addAction:telemetryAction]; + + NSString *cancelTitle = NSLocalizedStringWithDefaultValue(@"CANCEL", nil, nil, @"Cancel", @""); + UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:cancelTitle + style:UIAlertActionStyleCancel + handler:NULL]; + [attributionController addAction:cancelAction]; + + attributionController.popoverPresentationController.sourceView = self; + attributionController.popoverPresentationController.sourceRect = self.attributionButton.frame; + + UIViewController *viewController = self.window.rootViewController; + if ([viewController isKindOfClass:[UINavigationController class]]) { + viewController = [(UINavigationController *)viewController viewControllers].firstObject; } + [viewController presentViewController:attributionController + animated:YES + completion:NULL]; } -- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex +- (void)presentTelemetryAlertController { - if (buttonIndex == alertView.cancelButtonIndex) + NSString *title = NSLocalizedStringWithDefaultValue(@"TELEMETRY_TITLE", nil, nil, @"Make Mapbox Maps Better", @"Telemetry prompt title"); + NSString *message; + NSString *participateTitle; + NSString *declineTitle; + if ([[NSUserDefaults standardUserDefaults] boolForKey:@"MGLMapboxMetricsEnabled"]) { - [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"MGLMapboxMetricsEnabled"]; + message = NSLocalizedStringWithDefaultValue(@"TELEMETRY_ENABLED_MSG", nil, nil, @"You are helping to make OpenStreetMap and Mapbox maps better by contributing anonymous usage data.", @"Telemetry prompt message"); + participateTitle = NSLocalizedStringWithDefaultValue(@"TELEMETRY_ENABLED_ON", nil, nil, @"Keep Participating", @"Telemetry prompt button"); + declineTitle = NSLocalizedStringWithDefaultValue(@"TELEMETRY_ENABLED_OFF", nil, nil, @"Stop Participating", @"Telemetry prompt button"); } - else if (buttonIndex == alertView.firstOtherButtonIndex) + else { + message = NSLocalizedStringWithDefaultValue(@"TELEMETRY_DISABLED_MSG", nil, nil, @"You can help make OpenStreetMap and Mapbox maps better by contributing anonymous usage data.", @"Telemetry prompt message"); + participateTitle = NSLocalizedStringWithDefaultValue(@"TELEMETRY_DISABLED_ON", nil, nil, @"Participate", @"Telemetry prompt button"); + declineTitle = NSLocalizedStringWithDefaultValue(@"TELEMETRY_DISABLED_OFF", nil, nil, @"Don’t Participate", @"Telemetry prompt button"); + } + + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title + message:message + preferredStyle:UIAlertControllerStyleAlert]; + + NSString *moreTitle = NSLocalizedStringWithDefaultValue(@"TELEMETRY_MORE", nil, nil, @"Tell Me More", @"Telemetry prompt button"); + UIAlertAction *moreAction = [UIAlertAction actionWithTitle:moreTitle + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * _Nonnull action) { [[UIApplication sharedApplication] openURL: [NSURL URLWithString:@"https://www.mapbox.com/telemetry/"]]; - } - else if (buttonIndex == alertView.firstOtherButtonIndex + 1) - { + }]; + [alertController addAction:moreAction]; + + UIAlertAction *declineAction = [UIAlertAction actionWithTitle:declineTitle + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * _Nonnull action) { [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"MGLMapboxMetricsEnabled"]; - } + }]; + [alertController addAction:declineAction]; + + UIAlertAction *participateAction = [UIAlertAction actionWithTitle:participateTitle + style:UIAlertActionStyleCancel + handler:^(UIAlertAction * _Nonnull action) { + [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"MGLMapboxMetricsEnabled"]; + }]; + [alertController addAction:participateAction]; + + [self.window.rootViewController presentViewController:alertController + animated:YES + completion:NULL]; } #pragma mark - Properties - -- cgit v1.2.1 From b10bbecf34a39ef6b60d95a358866570087e8679 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Fri, 10 Mar 2017 17:58:56 -0800 Subject: [ios, macos] Updated changelogs --- platform/ios/CHANGELOG.md | 7 +++---- platform/macos/CHANGELOG.md | 5 +++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index 027689696e..8b1d6219a3 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -4,9 +4,9 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT ## 3.5.1 -### Other changes - * Fixed an issue that caused the return type of a map view delegate method to bridge incorrectly to applications written in Swift. ([#8541](https://github.com/mapbox/mapbox-gl-native/pull/8541)) +* Fixed a crash that could occur when calling `-[MGLShapeSource featuresMatchingPredicate:]` or `-[MGLVectorSource featuresInSourceLayersWithIdentifiers:predicate:]`. ([#8553](https://github.com/mapbox/mapbox-gl-native/pull/8553)) +* Fixed a crash that could occur after adding view-backed annotations to the map. ([#8513](https://github.com/mapbox/mapbox-gl-native/pull/8513)) ## 3.5.0 @@ -21,8 +21,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT * Added support for right-to-left text and Arabic ligatures in labels. ([#6984](https://github.com/mapbox/mapbox-gl-native/pull/6984), [#7123](https://github.com/mapbox/mapbox-gl-native/pull/7123)) * Improved the line wrapping behavior of point-placed labels, especially labels written in Chinese and Japanese. ([#6828](https://github.com/mapbox/mapbox-gl-native/pull/6828), [#7446](https://github.com/mapbox/mapbox-gl-native/pull/7446)) * CJK characters now remain upright in vertically oriented labels that have line placement, such as road labels. ([#7114](https://github.com/mapbox/mapbox-gl-native/issues/7114)) -* Added Catalan, Chinese (Simplified and Traditional), Dutch, Finnish, French, German, Japanese, Lithuanian, Polish, Portuguese (Brazilian), Russian, Spanish, Swedish, Ukrainian, and Vietnamese localizations. ([#7316](https://github.com/mapbox/mapbox-gl-native/pull/7316), [#7899](https://github.com/mapbox/mapbox-gl-native/pull/7899), [#7999](https://github.com/mapbox/mapbox-gl-native/pull/7999), -[#8113](https://github.com/mapbox/mapbox-gl-native/pull/8113), [#8256](https://github.com/mapbox/mapbox-gl-native/pull/8256)) +* Added Catalan, Chinese (Simplified and Traditional), Dutch, Finnish, French, German, Japanese, Lithuanian, Polish, Portuguese (Brazilian), Russian, Spanish, Swedish, Ukrainian, and Vietnamese localizations. ([#7316](https://github.com/mapbox/mapbox-gl-native/pull/7316), [#7899](https://github.com/mapbox/mapbox-gl-native/pull/7899), [#7999](https://github.com/mapbox/mapbox-gl-native/pull/7999), [#8113](https://github.com/mapbox/mapbox-gl-native/pull/8113), [#8256](https://github.com/mapbox/mapbox-gl-native/pull/8256)) ### Styles diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md index 7e3eac9877..fa5822863f 100644 --- a/platform/macos/CHANGELOG.md +++ b/platform/macos/CHANGELOG.md @@ -2,13 +2,14 @@ ## 0.4.0 +This version of the Mapbox macOS SDK corresponds to version 3.5.1 of the Mapbox iOS SDK. + ### Internationalization * Added support for right-to-left text and Arabic ligatures in labels. ([#6984](https://github.com/mapbox/mapbox-gl-native/pull/6984), [#7123](https://github.com/mapbox/mapbox-gl-native/pull/7123)) * Improved the line wrapping behavior of point-placed labels, especially labels written in Chinese and Japanese. ([#6828](https://github.com/mapbox/mapbox-gl-native/pull/6828), [#7446](https://github.com/mapbox/mapbox-gl-native/pull/7446)) * CJK characters now remain upright in vertically oriented labels that have line placement, such as road labels. ([#7114](https://github.com/mapbox/mapbox-gl-native/issues/7114)) -* Added Catalan, Chinese (Simplified and Traditional), Dutch, Finnish, French, German, Japanese, Lithuanian, Polish, Portuguese (Brazilian), Spanish, Swedish, Ukrainian, and Vietnamese localizations. ([#7316](https://github.com/mapbox/mapbox-gl-native/pull/7316), [#7503](https://github.com/mapbox/mapbox-gl-native/pull/7503), [#7899](https://github.com/mapbox/mapbox-gl-native/pull/7899), [#7999](https://github.com/mapbox/mapbox-gl-native/pull/7999), -[#8113](https://github.com/mapbox/mapbox-gl-native/pull/8113), [#8256](https://github.com/mapbox/mapbox-gl-native/pull/8256)) +* Added Catalan, Chinese (Simplified and Traditional), Dutch, Finnish, French, German, Japanese, Lithuanian, Polish, Portuguese (Brazilian), Spanish, Swedish, Ukrainian, and Vietnamese localizations. ([#7316](https://github.com/mapbox/mapbox-gl-native/pull/7316), [#7503](https://github.com/mapbox/mapbox-gl-native/pull/7503), [#7899](https://github.com/mapbox/mapbox-gl-native/pull/7899), [#7999](https://github.com/mapbox/mapbox-gl-native/pull/7999), [#8113](https://github.com/mapbox/mapbox-gl-native/pull/8113), [#8256](https://github.com/mapbox/mapbox-gl-native/pull/8256)) ### Styles -- cgit v1.2.1 From 8af81ec88cf4b2dbb32256440ca16b8e9b67101f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Sun, 2 Apr 2017 00:40:35 -0700 Subject: macos-v0.4.0 --- platform/macos/Mapbox-macOS-SDK-symbols.podspec | 2 +- platform/macos/Mapbox-macOS-SDK.podspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/macos/Mapbox-macOS-SDK-symbols.podspec b/platform/macos/Mapbox-macOS-SDK-symbols.podspec index c17e665512..4bac6dff2d 100644 --- a/platform/macos/Mapbox-macOS-SDK-symbols.podspec +++ b/platform/macos/Mapbox-macOS-SDK-symbols.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |m| - version = '0.3.1' + version = '0.4.0' m.name = 'Mapbox-macOS-SDK-symbols' m.version = "#{version}-symbols" diff --git a/platform/macos/Mapbox-macOS-SDK.podspec b/platform/macos/Mapbox-macOS-SDK.podspec index a6f2d2838b..a7ecb7423e 100644 --- a/platform/macos/Mapbox-macOS-SDK.podspec +++ b/platform/macos/Mapbox-macOS-SDK.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |m| - version = '0.3.1' + version = '0.4.0' m.name = 'Mapbox-macOS-SDK' m.version = version -- cgit v1.2.1 From c1cd6759b4a87ef58442e864a192317284cf20ae Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 9 Mar 2017 07:53:02 -0800 Subject: [core] Extract and de-templatize several Program static methods --- cmake/core-files.cmake | 2 ++ src/mbgl/programs/program.hpp | 31 ++++--------------------------- src/mbgl/shaders/shaders.cpp | 33 +++++++++++++++++++++++++++++++++ src/mbgl/shaders/shaders.hpp | 15 +++++++++++++++ 4 files changed, 54 insertions(+), 27 deletions(-) create mode 100644 src/mbgl/shaders/shaders.cpp create mode 100644 src/mbgl/shaders/shaders.hpp diff --git a/cmake/core-files.cmake b/cmake/core-files.cmake index d2a77aa3aa..afc45a24cc 100644 --- a/cmake/core-files.cmake +++ b/cmake/core-files.cmake @@ -209,6 +209,8 @@ set(MBGL_CORE_FILES src/mbgl/shaders/preludes.hpp src/mbgl/shaders/raster.cpp src/mbgl/shaders/raster.hpp + src/mbgl/shaders/shaders.cpp + src/mbgl/shaders/shaders.hpp src/mbgl/shaders/symbol_icon.cpp src/mbgl/shaders/symbol_icon.hpp src/mbgl/shaders/symbol_sdf.cpp diff --git a/src/mbgl/programs/program.hpp b/src/mbgl/programs/program.hpp index ffad767c3a..8437e3a651 100644 --- a/src/mbgl/programs/program.hpp +++ b/src/mbgl/programs/program.hpp @@ -1,13 +1,9 @@ #pragma once #include -#include #include #include -#include - -#include -#include +#include namespace mbgl { @@ -34,30 +30,11 @@ public: ProgramType program; Program(gl::Context& context, const ProgramParameters& programParameters) - : program(context, vertexSource(programParameters), fragmentSource(programParameters)) + : program(context, + shaders::vertexSource(programParameters, Shaders::vertexSource), + shaders::fragmentSource(programParameters, Shaders::fragmentSource)) {} - static std::string pixelRatioDefine(const ProgramParameters& parameters) { - std::ostringstream pixelRatioSS; - pixelRatioSS.imbue(std::locale("C")); - pixelRatioSS.setf(std::ios_base::showpoint); - pixelRatioSS << parameters.pixelRatio; - return std::string("#define DEVICE_PIXEL_RATIO ") + pixelRatioSS.str() + "\n"; - } - - static std::string fragmentSource(const ProgramParameters& parameters) { - std::string source = pixelRatioDefine(parameters) + shaders::fragmentPrelude + Shaders::fragmentSource; - if (parameters.overdraw) { - assert(source.find("#ifdef OVERDRAW_INSPECTOR") != std::string::npos); - source.replace(source.find_first_of('\n'), 1, "\n#define OVERDRAW_INSPECTOR\n"); - } - return source; - } - - static std::string vertexSource(const ProgramParameters& parameters) { - return pixelRatioDefine(parameters) + shaders::vertexPrelude + Shaders::vertexSource; - } - template void draw(gl::Context& context, DrawMode drawMode, diff --git a/src/mbgl/shaders/shaders.cpp b/src/mbgl/shaders/shaders.cpp new file mode 100644 index 0000000000..f7f5b4d44f --- /dev/null +++ b/src/mbgl/shaders/shaders.cpp @@ -0,0 +1,33 @@ +#include +#include +#include + +#include +#include + +namespace mbgl { +namespace shaders { + +static std::string pixelRatioDefine(const ProgramParameters& parameters) { + std::ostringstream pixelRatioSS; + pixelRatioSS.imbue(std::locale("C")); + pixelRatioSS.setf(std::ios_base::showpoint); + pixelRatioSS << parameters.pixelRatio; + return std::string("#define DEVICE_PIXEL_RATIO ") + pixelRatioSS.str() + "\n"; +} + +std::string fragmentSource(const ProgramParameters& parameters, const char* fragmentSource) { + std::string source = pixelRatioDefine(parameters) + fragmentPrelude + fragmentSource; + if (parameters.overdraw) { + assert(source.find("#ifdef OVERDRAW_INSPECTOR") != std::string::npos); + source.replace(source.find_first_of('\n'), 1, "\n#define OVERDRAW_INSPECTOR\n"); + } + return source; +} + +std::string vertexSource(const ProgramParameters& parameters, const char* vertexSource) { + return pixelRatioDefine(parameters) + vertexPrelude + vertexSource; +} + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/shaders.hpp b/src/mbgl/shaders/shaders.hpp new file mode 100644 index 0000000000..e2912c5688 --- /dev/null +++ b/src/mbgl/shaders/shaders.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include + +namespace mbgl { + +class ProgramParameters; + +namespace shaders { + +std::string fragmentSource(const ProgramParameters&, const char* fragmentSource); +std::string vertexSource(const ProgramParameters&, const char* vertexSource); + +} // namespace shaders +} // namespace mbgl -- cgit v1.2.1 From f86333961eeacb9f2dd83a4c3680d30e06f947a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=A4fer?= Date: Wed, 15 Mar 2017 18:43:58 +0100 Subject: [core] cache binary shaders on Android --- cmake/core-files.cmake | 5 + cmake/test-files.cmake | 3 + include/mbgl/map/map.hpp | 3 +- .../com/mapbox/mapboxsdk/maps/NativeMapView.java | 11 +- platform/android/src/native_map_view.cpp | 26 +++-- platform/android/src/native_map_view.hpp | 8 +- proto/binary_program.proto | 18 ++++ src/mbgl/gl/attribute.hpp | 13 ++- src/mbgl/gl/context.cpp | 49 +++++++++ src/mbgl/gl/context.hpp | 10 ++ src/mbgl/gl/features.hpp | 7 ++ src/mbgl/gl/program.hpp | 30 ++++-- src/mbgl/gl/program_binary.cpp | 24 +++++ src/mbgl/gl/program_binary.hpp | 27 +++++ src/mbgl/gl/types.hpp | 2 + src/mbgl/gl/uniform.hpp | 13 ++- src/mbgl/map/map.cpp | 16 ++- src/mbgl/programs/binary_program.cpp | 117 +++++++++++++++++++++ src/mbgl/programs/binary_program.hpp | 43 ++++++++ src/mbgl/programs/program.hpp | 58 +++++++++- src/mbgl/programs/program_parameters.hpp | 15 ++- src/mbgl/programs/programs.hpp | 4 +- src/mbgl/renderer/painter.cpp | 16 +-- src/mbgl/renderer/painter.hpp | 2 +- src/mbgl/shaders/shaders.cpp | 14 +++ src/mbgl/shaders/shaders.hpp | 2 + src/mbgl/util/io.cpp | 10 ++ src/mbgl/util/io.hpp | 3 + test/programs/binary_program.test.cpp | 39 +++++++ 29 files changed, 541 insertions(+), 47 deletions(-) create mode 100644 proto/binary_program.proto create mode 100644 src/mbgl/gl/features.hpp create mode 100644 src/mbgl/gl/program_binary.cpp create mode 100644 src/mbgl/gl/program_binary.hpp create mode 100644 src/mbgl/programs/binary_program.cpp create mode 100644 src/mbgl/programs/binary_program.hpp create mode 100644 test/programs/binary_program.test.cpp diff --git a/cmake/core-files.cmake b/cmake/core-files.cmake index afc45a24cc..61bc79c334 100644 --- a/cmake/core-files.cmake +++ b/cmake/core-files.cmake @@ -67,6 +67,7 @@ set(MBGL_CORE_FILES src/mbgl/gl/draw_mode.hpp src/mbgl/gl/extension.cpp src/mbgl/gl/extension.hpp + src/mbgl/gl/features.hpp src/mbgl/gl/framebuffer.hpp src/mbgl/gl/gl.cpp src/mbgl/gl/index_buffer.hpp @@ -75,6 +76,8 @@ set(MBGL_CORE_FILES src/mbgl/gl/object.hpp src/mbgl/gl/primitives.hpp src/mbgl/gl/program.hpp + src/mbgl/gl/program_binary.cpp + src/mbgl/gl/program_binary.hpp src/mbgl/gl/renderbuffer.hpp src/mbgl/gl/segment.cpp src/mbgl/gl/segment.hpp @@ -134,6 +137,8 @@ set(MBGL_CORE_FILES # programs src/mbgl/programs/attributes.hpp + src/mbgl/programs/binary_program.cpp + src/mbgl/programs/binary_program.hpp src/mbgl/programs/circle_program.cpp src/mbgl/programs/circle_program.hpp src/mbgl/programs/collision_box_program.cpp diff --git a/cmake/test-files.cmake b/cmake/test-files.cmake index 873afa3d9f..951514e38a 100644 --- a/cmake/test-files.cmake +++ b/cmake/test-files.cmake @@ -38,6 +38,9 @@ set(MBGL_TEST_FILES test/math/minmax.test.cpp test/math/wrap.test.cpp + # programs + test/programs/binary_program.test.cpp + # sprite test/sprite/sprite_atlas.test.cpp test/sprite/sprite_image.test.cpp diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index 02e14bea4e..6b07173747 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -41,7 +41,8 @@ public: MapMode mapMode = MapMode::Continuous, GLContextMode contextMode = GLContextMode::Unique, ConstrainMode constrainMode = ConstrainMode::HeightOnly, - ViewportMode viewportMode = ViewportMode::Default); + ViewportMode viewportMode = ViewportMode::Default, + const std::string& programCacheDir = ""); ~Map(); // Register a callback that will get called (on the render thread) when all resources have 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 1460f08e10..a9394d0b66 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 @@ -97,7 +97,8 @@ final class NativeMapView { onMapChangedListeners = new CopyOnWriteArrayList<>(); this.mapView = mapView; - nativeInitialize(this, fileSource, pixelRatio, availableProcessors, totalMemory); + String programCacheDir = context.getCacheDir().getAbsolutePath(); + nativeInitialize(this, fileSource, pixelRatio, programCacheDir, availableProcessors, totalMemory); } // @@ -957,8 +958,12 @@ final class NativeMapView { // JNI methods // - private native void nativeInitialize(NativeMapView nativeMapView, FileSource fileSource, - float pixelRatio, int availableProcessors, long totalMemory); + private native void nativeInitialize(NativeMapView nativeMapView, + FileSource fileSource, + float pixelRatio, + String programCacheDir, + int availableProcessors, + long totalMemory); private native void nativeDestroy(); diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp index 696849b11b..529ea23304 100755 --- a/platform/android/src/native_map_view.cpp +++ b/platform/android/src/native_map_view.cpp @@ -48,13 +48,18 @@ namespace mbgl { namespace android { -NativeMapView::NativeMapView(jni::JNIEnv& _env, jni::Object _obj, jni::Object jFileSource, - jni::jfloat _pixelRatio, jni::jint _availableProcessors, jni::jlong _totalMemory) : - javaPeer(_obj.NewWeakGlobalRef(_env)), - pixelRatio(_pixelRatio), - availableProcessors(_availableProcessors), - totalMemory(_totalMemory), - threadPool(sharedThreadPool()) { +NativeMapView::NativeMapView(jni::JNIEnv& _env, + jni::Object _obj, + jni::Object jFileSource, + jni::jfloat _pixelRatio, + jni::String _programCacheDir, + jni::jint _availableProcessors, + jni::jlong _totalMemory) + : javaPeer(_obj.NewWeakGlobalRef(_env)), + pixelRatio(_pixelRatio), + availableProcessors(_availableProcessors), + totalMemory(_totalMemory), + threadPool(sharedThreadPool()) { // Get a reference to the JavaVM for callbacks if (_env.GetJavaVM(&vm) < 0) { @@ -65,8 +70,9 @@ NativeMapView::NativeMapView(jni::JNIEnv& _env, jni::Object _obj, // Create the core map map = std::make_unique( *this, mbgl::Size{ static_cast(width), static_cast(height) }, - pixelRatio, mbgl::android::FileSource::getDefaultFileSource(_env, jFileSource) - , *threadPool, MapMode::Continuous); + pixelRatio, mbgl::android::FileSource::getDefaultFileSource(_env, jFileSource), *threadPool, + MapMode::Continuous, GLContextMode::Unique, ConstrainMode::HeightOnly, + ViewportMode::Default, jni::Make(_env, _programCacheDir)); //Calculate a fitting cache size based on device parameters float zoomFactor = map->getMaxZoom() - map->getMinZoom() + 1; @@ -1398,7 +1404,7 @@ void NativeMapView::registerNative(jni::JNIEnv& env) { // Register the peer jni::RegisterNativePeer(env, NativeMapView::javaClass, "nativePtr", - std::make_unique, jni::Object, jni::jfloat, jni::jint, jni::jlong>, + std::make_unique, jni::Object, jni::jfloat, jni::String, jni::jint, jni::jlong>, "nativeInitialize", "nativeDestroy", METHOD(&NativeMapView::render, "nativeRender"), diff --git a/platform/android/src/native_map_view.hpp b/platform/android/src/native_map_view.hpp index 4afea036bf..08133b85cd 100755 --- a/platform/android/src/native_map_view.hpp +++ b/platform/android/src/native_map_view.hpp @@ -40,7 +40,13 @@ public: static void registerNative(jni::JNIEnv&); - NativeMapView(jni::JNIEnv&, jni::Object, jni::Object, jni::jfloat, jni::jint, jni::jlong); + NativeMapView(jni::JNIEnv&, + jni::Object, + jni::Object, + jni::jfloat pixelRatio, + jni::String programCacheDir, + jni::jint availableProcessors, + jni::jlong totalMemory); virtual ~NativeMapView(); diff --git a/proto/binary_program.proto b/proto/binary_program.proto new file mode 100644 index 0000000000..9d06a209c3 --- /dev/null +++ b/proto/binary_program.proto @@ -0,0 +1,18 @@ +// Protocol Version 1 + +package mapboxgl.binary_program; + +option optimize_for = LITE_RUNTIME; + +message binding { + required string name = 1; + required uint32 value = 2; +} + +message binary_program { + required uint32 format = 1; + required bytes code = 2; + repeated binding attribute = 3; + repeated binding uniform = 4; + optional string identifier = 5; +} diff --git a/src/mbgl/gl/attribute.hpp b/src/mbgl/gl/attribute.hpp index 43e2c2d794..e23c4f9e47 100644 --- a/src/mbgl/gl/attribute.hpp +++ b/src/mbgl/gl/attribute.hpp @@ -7,6 +7,7 @@ #include #include +#include #include namespace mbgl { @@ -241,16 +242,26 @@ public: using VariableBindings = IndexedTuple< TypeList, TypeList...>>; + using NamedLocations = std::vector>; using Vertex = detail::Vertex; template static constexpr std::size_t Index = TypeIndex::value; - static Locations locations(const ProgramID& id) { + static Locations bindLocations(const ProgramID& id) { return Locations { bindAttributeLocation(id, Index, As::name())... }; } + template + static Locations loadNamedLocations(const Program& program) { + return Locations{ program.attributeLocation(As::name())... }; + } + + static NamedLocations getNamedLocations(const Locations& locations) { + return NamedLocations{ { As::name(), locations.template get() }... }; + } + template static Bindings allVariableBindings(const VertexBuffer& buffer) { return Bindings { As::variableBinding(buffer, Index)... }; diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp index 9c2031ccfd..97ebf687f9 100644 --- a/src/mbgl/gl/context.cpp +++ b/src/mbgl/gl/context.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -34,6 +35,8 @@ static_assert(std::is_same, GLenum>::value static_assert(underlying_type(TextureFormat::RGBA) == GL_RGBA, "OpenGL type mismatch"); static_assert(underlying_type(TextureFormat::Alpha) == GL_ALPHA, "OpenGL type mismatch"); +static_assert(std::is_same::value, "OpenGL type mismatch"); + Context::~Context() { reset(); } @@ -72,9 +75,27 @@ UniqueProgram Context::createProgram(ShaderID vertexShader, ShaderID fragmentSha return result; } +#if MBGL_HAS_BINARY_PROGRAMS +UniqueProgram Context::createProgram(BinaryProgramFormat binaryFormat, + const std::string& binaryProgram) { + UniqueProgram result{ MBGL_CHECK_ERROR(glCreateProgram()), { this } }; + MBGL_CHECK_ERROR(ProgramBinary(result, static_cast(binaryFormat), binaryProgram.data(), + static_cast(binaryProgram.size()))); + verifyProgramLinkage(result); + return result; +} +#else +UniqueProgram Context::createProgram(BinaryProgramFormat, const std::string&) { + throw std::runtime_error("binary programs are not supported"); +} +#endif + void Context::linkProgram(ProgramID program_) { MBGL_CHECK_ERROR(glLinkProgram(program_)); + verifyProgramLinkage(program_); +} +void Context::verifyProgramLinkage(ProgramID program_) { GLint status; MBGL_CHECK_ERROR(glGetProgramiv(program_, GL_LINK_STATUS, &status)); if (status == GL_TRUE) { @@ -129,6 +150,34 @@ bool Context::supportsVertexArrays() const { !disableVAOExtension; } +#if MBGL_HAS_BINARY_PROGRAMS +bool Context::supportsProgramBinaries() const { + return gl::ProgramBinary && gl::GetProgramBinary; +} + +optional> +Context::getBinaryProgram(ProgramID program_) const { + if (!supportsProgramBinaries()) { + return {}; + } + GLint binaryLength; + MBGL_CHECK_ERROR(glGetProgramiv(program_, GL_PROGRAM_BINARY_LENGTH, &binaryLength)); + std::string binary; + binary.resize(binaryLength); + GLenum binaryFormat; + MBGL_CHECK_ERROR(GetProgramBinary(program_, binaryLength, &binaryLength, &binaryFormat, + const_cast(binary.data()))); + if (size_t(binaryLength) != binary.size()) { + return {}; + } + return { { binaryFormat, std::move(binary) } }; +} +#else +optional> Context::getBinaryProgram(ProgramID) const { + return {}; +} +#endif + UniqueVertexArray Context::createVertexArray() { assert(supportsVertexArrays()); VertexArrayID id = 0; diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp index 9d3ecec662..fd6683a0cc 100644 --- a/src/mbgl/gl/context.hpp +++ b/src/mbgl/gl/context.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -37,12 +38,21 @@ public: UniqueShader createShader(ShaderType type, const std::string& source); UniqueProgram createProgram(ShaderID vertexShader, ShaderID fragmentShader); + UniqueProgram createProgram(BinaryProgramFormat binaryFormat, const std::string& binaryProgram); + void verifyProgramLinkage(ProgramID); void linkProgram(ProgramID); UniqueTexture createTexture(); bool supportsVertexArrays() const; UniqueVertexArray createVertexArray(); +#if MBGL_HAS_BINARY_PROGRAMS + bool supportsProgramBinaries() const; +#else + constexpr bool supportsProgramBinaries() const { return false; } +#endif + optional> getBinaryProgram(ProgramID) const; + template VertexBuffer createVertexBuffer(VertexVector&& v) { return VertexBuffer { diff --git a/src/mbgl/gl/features.hpp b/src/mbgl/gl/features.hpp new file mode 100644 index 0000000000..04dc4fa02e --- /dev/null +++ b/src/mbgl/gl/features.hpp @@ -0,0 +1,7 @@ +#pragma once + +#if __APPLE__ + #define MBGL_HAS_BINARY_PROGRAMS 0 +#else + #define MBGL_HAS_BINARY_PROGRAMS 1 +#endif \ No newline at end of file diff --git a/src/mbgl/gl/program.hpp b/src/mbgl/gl/program.hpp index fa0470796e..7d7fca5263 100644 --- a/src/mbgl/gl/program.hpp +++ b/src/mbgl/gl/program.hpp @@ -24,11 +24,29 @@ public: using AttributeBindings = typename Attributes::Bindings; Program(Context& context, const std::string& vertexSource, const std::string& fragmentSource) - : vertexShader(context.createShader(ShaderType::Vertex, vertexSource)), - fragmentShader(context.createShader(ShaderType::Fragment, fragmentSource)), - program(context.createProgram(vertexShader, fragmentShader)), - attributeLocations(Attributes::locations(program)), - uniformsState((context.linkProgram(program), Uniforms::state(program))) {} + : program( + context.createProgram(context.createShader(ShaderType::Vertex, vertexSource), + context.createShader(ShaderType::Fragment, fragmentSource))), + attributeLocations(Attributes::bindLocations(program)), + uniformsState((context.linkProgram(program), Uniforms::bindLocations(program))) { + } + + template + Program(Context& context, const BinaryProgram& binaryProgram) + : program(context.createProgram(binaryProgram.format(), binaryProgram.code())), + attributeLocations(Attributes::loadNamedLocations(binaryProgram)), + uniformsState(Uniforms::loadNamedLocations(binaryProgram)) { + } + + template + optional get(Context& context, const std::string& identifier) const { + if (auto binaryProgram = context.getBinaryProgram(program)) { + return BinaryProgram{ binaryProgram->first, std::move(binaryProgram->second), + identifier, Attributes::getNamedLocations(attributeLocations), + Uniforms::getNamedLocations(uniformsState) }; + } + return {}; + } template void draw(Context& context, @@ -64,8 +82,6 @@ public: } private: - UniqueShader vertexShader; - UniqueShader fragmentShader; UniqueProgram program; typename Attributes::Locations attributeLocations; diff --git a/src/mbgl/gl/program_binary.cpp b/src/mbgl/gl/program_binary.cpp new file mode 100644 index 0000000000..ad147c819f --- /dev/null +++ b/src/mbgl/gl/program_binary.cpp @@ -0,0 +1,24 @@ +#include + +#if MBGL_HAS_BINARY_PROGRAMS + +namespace mbgl { +namespace gl { + +ExtensionFunction< + void(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary)> + GetProgramBinary({ + { "GL_OES_get_program_binary", "glGetProgramBinaryOES" }, + { "GL_ARB_get_program_binary", "glGetProgramBinary" }, + }); + +ExtensionFunction + ProgramBinary({ + { "GL_OES_get_program_binary", "glProgramBinaryOES" }, + { "GL_ARB_get_program_binary", "glProgramBinary" }, + }); + +} // namespace gl +} // namespace mbgl + +#endif diff --git a/src/mbgl/gl/program_binary.hpp b/src/mbgl/gl/program_binary.hpp new file mode 100644 index 0000000000..e888ed3d4a --- /dev/null +++ b/src/mbgl/gl/program_binary.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include +#include +#include + +#if MBGL_HAS_BINARY_PROGRAMS + +#define GL_PROGRAM_BINARY_LENGTH 0x8741 +#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE +#define GL_PROGRAM_BINARY_FORMATS 0x87FF + +namespace mbgl { +namespace gl { + +extern ExtensionFunction + GetProgramBinary; + +extern ExtensionFunction + ProgramBinary; + +} // namespace gl +} // namespace mbgl + +#endif diff --git a/src/mbgl/gl/types.hpp b/src/mbgl/gl/types.hpp index 565ca5754f..7d436693c9 100644 --- a/src/mbgl/gl/types.hpp +++ b/src/mbgl/gl/types.hpp @@ -73,5 +73,7 @@ constexpr bool operator!=(const PixelStorageType& a, const PixelStorageType& b) #endif // MBGL_USE_GLES2 +using BinaryProgramFormat = uint32_t; + } // namespace gl } // namespace mbgl diff --git a/src/mbgl/gl/uniform.hpp b/src/mbgl/gl/uniform.hpp index 92136b61c2..34a32aeee9 100644 --- a/src/mbgl/gl/uniform.hpp +++ b/src/mbgl/gl/uniform.hpp @@ -6,6 +6,7 @@ #include #include +#include #include namespace mbgl { @@ -66,11 +67,21 @@ public: using Types = TypeList; using State = IndexedTuple, TypeList>; using Values = IndexedTuple, TypeList>; + using NamedLocations = std::vector>; - static State state(const ProgramID& id) { + static State bindLocations(const ProgramID& id) { return State { { uniformLocation(id, Us::name()) }... }; } + template + static State loadNamedLocations(const Program& program) { + return State{ { program.uniformLocation(Us::name()) }... }; + } + + static NamedLocations getNamedLocations(const State& state) { + return NamedLocations{ { Us::name(), state.template get().location }... }; + } + static void bind(State& state, Values&& values) { util::ignore({ (state.template get() = values.template get(), 0)... }); } diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index f4e994c931..aca1b77e7a 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -56,7 +56,8 @@ public: MapMode, GLContextMode, ConstrainMode, - ViewportMode); + ViewportMode, + const std::string& programCacheDir); void onSourceAttributionChanged(style::Source&, const std::string&) override; void onUpdate(Update) override; @@ -80,6 +81,7 @@ public: const MapMode mode; const GLContextMode contextMode; const float pixelRatio; + const std::string programCacheDir; MapDebugOptions debugOptions { MapDebugOptions::NoDebug }; @@ -111,7 +113,8 @@ Map::Map(Backend& backend, MapMode mapMode, GLContextMode contextMode, ConstrainMode constrainMode, - ViewportMode viewportMode) + ViewportMode viewportMode, + const std::string& programCacheDir) : impl(std::make_unique(*this, backend, pixelRatio, @@ -120,7 +123,8 @@ Map::Map(Backend& backend, mapMode, contextMode, constrainMode, - viewportMode)) { + viewportMode, + programCacheDir)) { impl->transform.resize(size); } @@ -132,7 +136,8 @@ Map::Impl::Impl(Map& map_, MapMode mode_, GLContextMode contextMode_, ConstrainMode constrainMode_, - ViewportMode viewportMode_) + ViewportMode viewportMode_, + const std::string& programCacheDir_) : map(map_), backend(backend_), fileSource(fileSource_), @@ -143,6 +148,7 @@ Map::Impl::Impl(Map& map_, mode(mode_), contextMode(contextMode_), pixelRatio(pixelRatio_), + programCacheDir(programCacheDir_), annotationManager(std::make_unique(pixelRatio)), asyncInvalidate([this] { if (mode == MapMode::Continuous) { @@ -259,7 +265,7 @@ void Map::Impl::render(View& view) { updateFlags = Update::Nothing; if (!painter) { - painter = std::make_unique(backend.getContext(), transform.getState(), pixelRatio); + painter = std::make_unique(backend.getContext(), transform.getState(), pixelRatio, programCacheDir); } if (mode == MapMode::Continuous) { diff --git a/src/mbgl/programs/binary_program.cpp b/src/mbgl/programs/binary_program.cpp new file mode 100644 index 0000000000..3b37cfa442 --- /dev/null +++ b/src/mbgl/programs/binary_program.cpp @@ -0,0 +1,117 @@ +#include + +#include +#include + +template +static std::pair parseBinding(protozero::pbf_reader&& pbf) { + bool hasName = false, hasValue = false; + std::pair binding; + while (pbf.next()) { + switch (pbf.tag()) { + case 1: // name + binding.first = pbf.get_string(); + hasName = true; + break; + case 2: // value + binding.second = pbf.get_uint32(); + hasValue = true; + break; + default: + pbf.skip(); + break; + } + } + if (!hasName || !hasValue) { + throw std::runtime_error("BinaryProgram binding is missing required fields"); + } + return binding; +} + +namespace mbgl { + +BinaryProgram::BinaryProgram(std::string&& data) { + bool hasFormat = false, hasCode = false; + protozero::pbf_reader pbf(data); + while (pbf.next()) { + switch (pbf.tag()) { + case 1: // format + binaryFormat = pbf.get_uint32(); + hasFormat = true; + break; + case 2: // code + binaryCode = pbf.get_bytes(); + hasCode = true; + break; + case 3: // variable + attributes.emplace_back(parseBinding(pbf.get_message())); + break; + case 4: // uniform + uniforms.emplace_back(parseBinding(pbf.get_message())); + break; + case 5: // identifier + default: + binaryIdentifier = pbf.get_string(); + break; + } + } + + if (!hasFormat || !hasCode) { + throw std::runtime_error("BinaryProgram is missing required fields"); + } +} + +BinaryProgram::BinaryProgram( + gl::BinaryProgramFormat binaryFormat_, + std::string&& binaryCode_, + const std::string& binaryIdentifier_, + std::vector>&& attributes_, + std::vector>&& uniforms_) + : binaryFormat(binaryFormat_), + binaryCode(std::move(binaryCode_)), + binaryIdentifier(binaryIdentifier_), + attributes(std::move(attributes_)), + uniforms(std::move(uniforms_)) { +} + +std::string BinaryProgram::serialize() const { + std::string data; + data.reserve(32 + binaryCode.size() + uniforms.size() * 32 + attributes.size() * 32); + protozero::pbf_writer pbf(data); + pbf.add_uint32(1 /* format */, binaryFormat); + pbf.add_bytes(2 /* code */, binaryCode.data(), binaryCode.size()); + for (const auto& binding : attributes) { + protozero::pbf_writer pbf_binding(pbf, 3 /* attribute */); + pbf_binding.add_string(1 /* name */, binding.first); + pbf_binding.add_uint32(2 /* value */, binding.second); + } + for (const auto& binding : uniforms) { + protozero::pbf_writer pbf_binding(pbf, 4 /* uniform */); + pbf_binding.add_string(1 /* name */, binding.first); + pbf_binding.add_uint32(2 /* value */, binding.second); + } + if (!binaryIdentifier.empty()) { + pbf.add_string(5 /* identifier */, binaryIdentifier); + } + return data; +} + +gl::AttributeLocation BinaryProgram::attributeLocation(const std::string& name) const { + for (const auto& pair : attributes) { + if (pair.first == name) { + return pair.second; + } + } + return {}; +} + +gl::UniformLocation BinaryProgram::uniformLocation(const std::string& name) const { + for (const auto& pair : uniforms) { + if (pair.first == name) { + return pair.second; + } + } + return {}; +} + +} // namespace mbgl diff --git a/src/mbgl/programs/binary_program.hpp b/src/mbgl/programs/binary_program.hpp new file mode 100644 index 0000000000..8ff3863dc1 --- /dev/null +++ b/src/mbgl/programs/binary_program.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include + +#include +#include + +namespace mbgl { + +class BinaryProgram { +public: + // Initialize a BinaryProgram object from a serialized represenation. + BinaryProgram(std::string&& data); + + BinaryProgram(gl::BinaryProgramFormat, + std::string&& binaryCode, + const std::string& binaryIdentifier, + std::vector>&&, + std::vector>&&); + + std::string serialize() const; + + gl::BinaryProgramFormat format() const { + return binaryFormat; + } + const std::string& code() const { + return binaryCode; + } + const std::string& identifier() const { + return binaryIdentifier; + } + gl::AttributeLocation attributeLocation(const std::string& name) const; + gl::UniformLocation uniformLocation(const std::string& name) const; + +private: + gl::BinaryProgramFormat binaryFormat = 0; + std::string binaryCode; + std::string binaryIdentifier; + std::vector> attributes; + std::vector> uniforms; +}; + +} // namespace mbgl diff --git a/src/mbgl/programs/program.hpp b/src/mbgl/programs/program.hpp index 8437e3a651..8925bc75d6 100644 --- a/src/mbgl/programs/program.hpp +++ b/src/mbgl/programs/program.hpp @@ -1,9 +1,13 @@ #pragma once #include +#include +#include #include +#include #include #include +#include namespace mbgl { @@ -30,10 +34,56 @@ public: ProgramType program; Program(gl::Context& context, const ProgramParameters& programParameters) - : program(context, - shaders::vertexSource(programParameters, Shaders::vertexSource), - shaders::fragmentSource(programParameters, Shaders::fragmentSource)) - {} + : program([&] { +#if MBGL_HAS_BINARY_PROGRAMS + if (!programParameters.cacheDir.empty() && context.supportsProgramBinaries()) { + const std::string vertexSource = + shaders::vertexSource(programParameters, Shaders::vertexSource); + const std::string fragmentSource = + shaders::fragmentSource(programParameters, Shaders::fragmentSource); + const std::string cachePath = + shaders::programCachePath(programParameters, Shaders::name); + const std::string identifier = + shaders::programIdentifier(vertexSource, fragmentSource); + + try { + if (auto cachedBinaryProgram = util::readFile(cachePath)) { + const BinaryProgram binaryProgram(std::move(*cachedBinaryProgram)); + if (binaryProgram.identifier() == identifier) { + return ProgramType{ context, binaryProgram }; + } else { + Log::Warning(Event::OpenGL, + "Cached program %s changed. Recompilation required.", + Shaders::name); + } + } + } catch (std::runtime_error& error) { + Log::Warning(Event::OpenGL, "Could not load cached program: %s", + error.what()); + } + + // Compile the shader + ProgramType result{ context, vertexSource, fragmentSource }; + + try { + if (const auto binaryProgram = + result.template get(context, identifier)) { + 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()); + } + + return std::move(result); + } +#endif + return ProgramType{ + context, shaders::vertexSource(programParameters, Shaders::vertexSource), + shaders::fragmentSource(programParameters, Shaders::fragmentSource) + }; + }()) { + } template void draw(gl::Context& context, diff --git a/src/mbgl/programs/program_parameters.hpp b/src/mbgl/programs/program_parameters.hpp index ad8cbf1bf8..b91b41f358 100644 --- a/src/mbgl/programs/program_parameters.hpp +++ b/src/mbgl/programs/program_parameters.hpp @@ -1,15 +1,20 @@ #pragma once +#include + namespace mbgl { class ProgramParameters { public: - ProgramParameters(float pixelRatio_ = 1.0, bool overdraw_ = false) - : pixelRatio(pixelRatio_), - overdraw(overdraw_) {} + ProgramParameters(float pixelRatio_ = 1.0, + bool overdraw_ = false, + const std::string& cacheDir_ = "") + : pixelRatio(pixelRatio_), overdraw(overdraw_), cacheDir(cacheDir_) { + } - float pixelRatio; - bool overdraw; + const float pixelRatio; + const bool overdraw; + const std::string cacheDir; }; } // namespace mbgl diff --git a/src/mbgl/programs/programs.hpp b/src/mbgl/programs/programs.hpp index 742c5a221b..dbf5b9e87d 100644 --- a/src/mbgl/programs/programs.hpp +++ b/src/mbgl/programs/programs.hpp @@ -26,8 +26,8 @@ public: symbolIcon(context, programParameters), symbolIconSDF(context, programParameters), symbolGlyph(context, programParameters), - debug(context, ProgramParameters(programParameters.pixelRatio, false)), - collisionBox(context, ProgramParameters(programParameters.pixelRatio, false)) { + debug(context, ProgramParameters(programParameters.pixelRatio, false, programParameters.cacheDir)), + collisionBox(context, ProgramParameters(programParameters.pixelRatio, false, programParameters.cacheDir)) { } CircleProgram circle; diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp index 27d24d14a9..754959438b 100644 --- a/src/mbgl/renderer/painter.cpp +++ b/src/mbgl/renderer/painter.cpp @@ -33,6 +33,8 @@ #include +#include + #include #include #include @@ -77,7 +79,10 @@ static gl::VertexVector rasterVertices() { return result; } -Painter::Painter(gl::Context& context_, const TransformState& state_, float pixelRatio) +Painter::Painter(gl::Context& context_, + const TransformState& state_, + float pixelRatio, + const std::string& programCacheDir) : context(context_), state(state_), tileVertexBuffer(context.createVertexBuffer(tileVertices())), @@ -91,12 +96,11 @@ Painter::Painter(gl::Context& context_, const TransformState& state_, float pixe gl::debugging::enable(); - ProgramParameters programParameters{ pixelRatio, false }; - programs = std::make_unique(context, programParameters); + programs = std::make_unique(context, + ProgramParameters{ pixelRatio, false, programCacheDir }); #ifndef NDEBUG - - ProgramParameters programParametersOverdraw{ pixelRatio, true }; - overdrawPrograms = std::make_unique(context, programParametersOverdraw); + overdrawPrograms = + std::make_unique(context, ProgramParameters{ pixelRatio, true, programCacheDir }); #endif } diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp index 91f329a6eb..3dcc1d5d46 100644 --- a/src/mbgl/renderer/painter.hpp +++ b/src/mbgl/renderer/painter.hpp @@ -68,7 +68,7 @@ struct FrameData { class Painter : private util::noncopyable { public: - Painter(gl::Context&, const TransformState&, float pixelRatio); + Painter(gl::Context&, const TransformState&, float pixelRatio, const std::string& programCacheDir); ~Painter(); void render(const style::Style&, diff --git a/src/mbgl/shaders/shaders.cpp b/src/mbgl/shaders/shaders.cpp index f7f5b4d44f..03d796edba 100644 --- a/src/mbgl/shaders/shaders.cpp +++ b/src/mbgl/shaders/shaders.cpp @@ -4,6 +4,7 @@ #include #include +#include namespace mbgl { namespace shaders { @@ -29,5 +30,18 @@ std::string vertexSource(const ProgramParameters& parameters, const char* vertex return pixelRatioDefine(parameters) + vertexPrelude + vertexSource; } +std::string programCachePath(const ProgramParameters& parameters, const char* name) { + return parameters.cacheDir + "/com.mapbox.gl.shader." + name + + (parameters.overdraw ? ".overdraw.pbf" : ".pbf"); +} + +std::string programIdentifier(const std::string& vertexSource, const std::string& fragmentSource) { + std::ostringstream ss; + ss << std::setfill('0') << std::setw(sizeof(size_t) * 2) << std::hex; + ss << std::hash()(vertexSource); + ss << std::hash()(fragmentSource); + return ss.str(); +} + } // namespace shaders } // namespace mbgl diff --git a/src/mbgl/shaders/shaders.hpp b/src/mbgl/shaders/shaders.hpp index e2912c5688..126c64bb9e 100644 --- a/src/mbgl/shaders/shaders.hpp +++ b/src/mbgl/shaders/shaders.hpp @@ -10,6 +10,8 @@ namespace shaders { std::string fragmentSource(const ProgramParameters&, const char* fragmentSource); std::string vertexSource(const ProgramParameters&, const char* vertexSource); +std::string programCachePath(const ProgramParameters&, const char* name); +std::string programIdentifier(const std::string& vertexSource, const std::string& fragmentSource); } // namespace shaders } // namespace mbgl diff --git a/src/mbgl/util/io.cpp b/src/mbgl/util/io.cpp index f37ce09cff..9adc3b8988 100644 --- a/src/mbgl/util/io.cpp +++ b/src/mbgl/util/io.cpp @@ -32,6 +32,16 @@ std::string read_file(const std::string &filename) { } } +optional readFile(const std::string &filename) { + std::ifstream file(filename); + if (file.good()) { + std::stringstream data; + data << file.rdbuf(); + return data.str(); + } + return {}; +} + void deleteFile(const std::string& filename) { const int ret = unlink(filename.c_str()); if (ret == -1) { diff --git a/src/mbgl/util/io.hpp b/src/mbgl/util/io.hpp index 795a465328..847271acf0 100644 --- a/src/mbgl/util/io.hpp +++ b/src/mbgl/util/io.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include #include @@ -15,6 +17,7 @@ struct IOException : std::runtime_error { void write_file(const std::string &filename, const std::string &data); std::string read_file(const std::string &filename); +optional readFile(const std::string &filename); void deleteFile(const std::string& filename); } // namespace util diff --git a/test/programs/binary_program.test.cpp b/test/programs/binary_program.test.cpp new file mode 100644 index 0000000000..ce544e7652 --- /dev/null +++ b/test/programs/binary_program.test.cpp @@ -0,0 +1,39 @@ +#include + +#include + +using namespace mbgl; + +TEST(BinaryProgram, ObtainValues) { + const BinaryProgram binaryProgram{ 42, + "binary code", + "identifier", + { { "a_pos", 1 }, { "a_data", 4 } }, + { { "u_world", 1 }, { "u_ratio", 3 } } }; + + EXPECT_EQ(42u, binaryProgram.format()); + EXPECT_EQ("binary code", binaryProgram.code()); + EXPECT_EQ("identifier", binaryProgram.identifier()); + EXPECT_EQ(1, binaryProgram.attributeLocation("a_pos")); + EXPECT_EQ(0, binaryProgram.attributeLocation("u_world")); + EXPECT_EQ(4, binaryProgram.attributeLocation("a_data")); + EXPECT_EQ(1, binaryProgram.uniformLocation("u_world")); + EXPECT_EQ(3, binaryProgram.uniformLocation("u_ratio")); + EXPECT_EQ(0, binaryProgram.uniformLocation("a_data")); + + auto serialized = binaryProgram.serialize(); + + const BinaryProgram binaryProgram2(std::move(serialized)); + + EXPECT_EQ(42u, binaryProgram2.format()); + EXPECT_EQ("binary code", binaryProgram2.code()); + EXPECT_EQ("identifier", binaryProgram2.identifier()); + EXPECT_EQ(1, binaryProgram2.attributeLocation("a_pos")); + EXPECT_EQ(0, binaryProgram2.attributeLocation("u_world")); + EXPECT_EQ(4, binaryProgram2.attributeLocation("a_data")); + EXPECT_EQ(1, binaryProgram2.uniformLocation("u_world")); + EXPECT_EQ(3, binaryProgram2.uniformLocation("u_ratio")); + EXPECT_EQ(0, binaryProgram2.uniformLocation("a_data")); + + EXPECT_THROW(BinaryProgram(""), std::runtime_error); +} -- cgit v1.2.1 From fc382f7108f039480c7652557722e413e2626ca1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Sun, 2 Apr 2017 04:21:00 -0700 Subject: [macos] Fixed broken images in DDS guide --- .../docs/img/data-driven-styling/categorical1.png | Bin 0 -> 105968 bytes .../docs/img/data-driven-styling/categorical2.png | Bin 0 -> 125698 bytes .../darwin/docs/img/data-driven-styling/citibikes.png | Bin 0 -> 152843 bytes .../img/data-driven-styling/exponential-function-1.png | Bin 0 -> 69991 bytes .../img/data-driven-styling/exponential-function.png | Bin 0 -> 70066 bytes .../docs/img/data-driven-styling/exponential.png | Bin 0 -> 86910 bytes .../darwin/docs/img/data-driven-styling/identity.png | Bin 0 -> 68837 bytes .../darwin/docs/img/data-driven-styling/interval.png | Bin 0 -> 83927 bytes .../docs/img/data-driven-styling/polylineExample.png | Bin 0 -> 156800 bytes .../ios/docs/img/data-driven-styling/categorical1.png | Bin 105968 -> 0 bytes .../ios/docs/img/data-driven-styling/categorical2.png | Bin 125698 -> 0 bytes .../ios/docs/img/data-driven-styling/citibikes.png | Bin 152843 -> 0 bytes .../img/data-driven-styling/exponential-function-1.png | Bin 69991 -> 0 bytes .../img/data-driven-styling/exponential-function.png | Bin 70066 -> 0 bytes .../ios/docs/img/data-driven-styling/exponential.png | Bin 86910 -> 0 bytes platform/ios/docs/img/data-driven-styling/identity.png | Bin 68837 -> 0 bytes platform/ios/docs/img/data-driven-styling/interval.png | Bin 83927 -> 0 bytes .../docs/img/data-driven-styling/polylineExample.png | Bin 156800 -> 0 bytes platform/ios/scripts/document.sh | 3 ++- platform/macos/scripts/document.sh | 3 ++- 20 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 platform/darwin/docs/img/data-driven-styling/categorical1.png create mode 100644 platform/darwin/docs/img/data-driven-styling/categorical2.png create mode 100644 platform/darwin/docs/img/data-driven-styling/citibikes.png create mode 100644 platform/darwin/docs/img/data-driven-styling/exponential-function-1.png create mode 100644 platform/darwin/docs/img/data-driven-styling/exponential-function.png create mode 100644 platform/darwin/docs/img/data-driven-styling/exponential.png create mode 100644 platform/darwin/docs/img/data-driven-styling/identity.png create mode 100644 platform/darwin/docs/img/data-driven-styling/interval.png create mode 100644 platform/darwin/docs/img/data-driven-styling/polylineExample.png delete mode 100644 platform/ios/docs/img/data-driven-styling/categorical1.png delete mode 100644 platform/ios/docs/img/data-driven-styling/categorical2.png delete mode 100644 platform/ios/docs/img/data-driven-styling/citibikes.png delete mode 100644 platform/ios/docs/img/data-driven-styling/exponential-function-1.png delete mode 100644 platform/ios/docs/img/data-driven-styling/exponential-function.png delete mode 100644 platform/ios/docs/img/data-driven-styling/exponential.png delete mode 100644 platform/ios/docs/img/data-driven-styling/identity.png delete mode 100644 platform/ios/docs/img/data-driven-styling/interval.png delete mode 100644 platform/ios/docs/img/data-driven-styling/polylineExample.png diff --git a/platform/darwin/docs/img/data-driven-styling/categorical1.png b/platform/darwin/docs/img/data-driven-styling/categorical1.png new file mode 100644 index 0000000000..969846b41b Binary files /dev/null and b/platform/darwin/docs/img/data-driven-styling/categorical1.png differ diff --git a/platform/darwin/docs/img/data-driven-styling/categorical2.png b/platform/darwin/docs/img/data-driven-styling/categorical2.png new file mode 100644 index 0000000000..5008c522ed Binary files /dev/null and b/platform/darwin/docs/img/data-driven-styling/categorical2.png differ diff --git a/platform/darwin/docs/img/data-driven-styling/citibikes.png b/platform/darwin/docs/img/data-driven-styling/citibikes.png new file mode 100644 index 0000000000..a616672a32 Binary files /dev/null and b/platform/darwin/docs/img/data-driven-styling/citibikes.png differ diff --git a/platform/darwin/docs/img/data-driven-styling/exponential-function-1.png b/platform/darwin/docs/img/data-driven-styling/exponential-function-1.png new file mode 100644 index 0000000000..6aa129a305 Binary files /dev/null and b/platform/darwin/docs/img/data-driven-styling/exponential-function-1.png differ diff --git a/platform/darwin/docs/img/data-driven-styling/exponential-function.png b/platform/darwin/docs/img/data-driven-styling/exponential-function.png new file mode 100644 index 0000000000..c14969f0a8 Binary files /dev/null and b/platform/darwin/docs/img/data-driven-styling/exponential-function.png differ diff --git a/platform/darwin/docs/img/data-driven-styling/exponential.png b/platform/darwin/docs/img/data-driven-styling/exponential.png new file mode 100644 index 0000000000..87ddc1350e Binary files /dev/null and b/platform/darwin/docs/img/data-driven-styling/exponential.png differ diff --git a/platform/darwin/docs/img/data-driven-styling/identity.png b/platform/darwin/docs/img/data-driven-styling/identity.png new file mode 100644 index 0000000000..632ccdf3d5 Binary files /dev/null and b/platform/darwin/docs/img/data-driven-styling/identity.png differ diff --git a/platform/darwin/docs/img/data-driven-styling/interval.png b/platform/darwin/docs/img/data-driven-styling/interval.png new file mode 100644 index 0000000000..d15aff2025 Binary files /dev/null and b/platform/darwin/docs/img/data-driven-styling/interval.png differ diff --git a/platform/darwin/docs/img/data-driven-styling/polylineExample.png b/platform/darwin/docs/img/data-driven-styling/polylineExample.png new file mode 100644 index 0000000000..cd9b39bae4 Binary files /dev/null and b/platform/darwin/docs/img/data-driven-styling/polylineExample.png differ diff --git a/platform/ios/docs/img/data-driven-styling/categorical1.png b/platform/ios/docs/img/data-driven-styling/categorical1.png deleted file mode 100644 index 969846b41b..0000000000 Binary files a/platform/ios/docs/img/data-driven-styling/categorical1.png and /dev/null differ diff --git a/platform/ios/docs/img/data-driven-styling/categorical2.png b/platform/ios/docs/img/data-driven-styling/categorical2.png deleted file mode 100644 index 5008c522ed..0000000000 Binary files a/platform/ios/docs/img/data-driven-styling/categorical2.png and /dev/null differ diff --git a/platform/ios/docs/img/data-driven-styling/citibikes.png b/platform/ios/docs/img/data-driven-styling/citibikes.png deleted file mode 100644 index a616672a32..0000000000 Binary files a/platform/ios/docs/img/data-driven-styling/citibikes.png and /dev/null differ diff --git a/platform/ios/docs/img/data-driven-styling/exponential-function-1.png b/platform/ios/docs/img/data-driven-styling/exponential-function-1.png deleted file mode 100644 index 6aa129a305..0000000000 Binary files a/platform/ios/docs/img/data-driven-styling/exponential-function-1.png and /dev/null differ diff --git a/platform/ios/docs/img/data-driven-styling/exponential-function.png b/platform/ios/docs/img/data-driven-styling/exponential-function.png deleted file mode 100644 index c14969f0a8..0000000000 Binary files a/platform/ios/docs/img/data-driven-styling/exponential-function.png and /dev/null differ diff --git a/platform/ios/docs/img/data-driven-styling/exponential.png b/platform/ios/docs/img/data-driven-styling/exponential.png deleted file mode 100644 index 87ddc1350e..0000000000 Binary files a/platform/ios/docs/img/data-driven-styling/exponential.png and /dev/null differ diff --git a/platform/ios/docs/img/data-driven-styling/identity.png b/platform/ios/docs/img/data-driven-styling/identity.png deleted file mode 100644 index 632ccdf3d5..0000000000 Binary files a/platform/ios/docs/img/data-driven-styling/identity.png and /dev/null differ diff --git a/platform/ios/docs/img/data-driven-styling/interval.png b/platform/ios/docs/img/data-driven-styling/interval.png deleted file mode 100644 index d15aff2025..0000000000 Binary files a/platform/ios/docs/img/data-driven-styling/interval.png and /dev/null differ diff --git a/platform/ios/docs/img/data-driven-styling/polylineExample.png b/platform/ios/docs/img/data-driven-styling/polylineExample.png deleted file mode 100644 index cd9b39bae4..0000000000 Binary files a/platform/ios/docs/img/data-driven-styling/polylineExample.png and /dev/null differ diff --git a/platform/ios/scripts/document.sh b/platform/ios/scripts/document.sh index d66742a33f..170debb625 100755 --- a/platform/ios/scripts/document.sh +++ b/platform/ios/scripts/document.sh @@ -30,7 +30,8 @@ sed -n -e '/^## /{' -e ':a' -e 'n' -e '/^## /q' -e 'p' -e 'ba' -e '}' platform/i rm -rf ${OUTPUT} mkdir -p ${OUTPUT} -cp -r platform/ios/docs/img "${OUTPUT}/img" +cp -r platform/darwin/docs/img "${OUTPUT}" +cp -r platform/ios/docs/img "${OUTPUT}" DEFAULT_THEME="platform/darwin/docs/theme" THEME=${JAZZY_THEME:-$DEFAULT_THEME} diff --git a/platform/macos/scripts/document.sh b/platform/macos/scripts/document.sh index 69c9aaa871..2e53dc359b 100755 --- a/platform/macos/scripts/document.sh +++ b/platform/macos/scripts/document.sh @@ -36,7 +36,8 @@ sed -n -e '/^## /{' -e ':a' -e 'n' -e '/^## /q' -e 'p' -e 'ba' -e '}' platform/m rm -rf ${OUTPUT} mkdir -p ${OUTPUT} -cp -r platform/macos/docs/img "${OUTPUT}/img" +cp -r platform/darwin/docs/img "${OUTPUT}" +cp -r platform/macos/docs/img "${OUTPUT}" jazzy \ --config platform/macos/jazzy.yml \ -- cgit v1.2.1 From 6718d2cc5145497bb7503ab0bb9db4cbe6e1deb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Sun, 2 Apr 2017 04:21:27 -0700 Subject: [macos] Removed MGLUserTrackingMode from jazzy ToC --- platform/macos/jazzy.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/platform/macos/jazzy.yml b/platform/macos/jazzy.yml index 9323119718..fd6052c9f2 100644 --- a/platform/macos/jazzy.yml +++ b/platform/macos/jazzy.yml @@ -27,7 +27,6 @@ custom_categories: - MGLMapCamera - MGLMapView - MGLMapViewDelegate - - MGLUserTrackingMode - name: Shapes and Annotations children: - MGLAnnotation -- cgit v1.2.1 From e34b4718422438af365fe5ede67d1c490e95d9cc Mon Sep 17 00:00:00 2001 From: Tobrun Date: Tue, 4 Apr 2017 21:14:32 +0200 Subject: Release android v5.0.2 (#8629) * [android] - update CHANGELOG.md for v5.0.2 release * [android] - bump version name to 5.0.2 * [android] - fixup javadoc errors * bump SNAPSHOT version --- platform/android/CHANGELOG.md | 1 + .../java/com/mapbox/mapboxsdk/camera/CameraPosition.java | 2 +- .../java/com/mapbox/mapboxsdk/location/LocationSource.java | 9 ++++----- .../com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java | 12 ++++++------ 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index 01d7b1ab5b..2b0e40f21e 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -6,6 +6,7 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to 5.0.2 is a patch release that contains the following changes: +* Binary shader caching [#8604](https://github.com/mapbox/mapbox-gl-native/pull/8604) * Fix resource transform callback [#8582](https://github.com/mapbox/mapbox-gl-native/pull/8582) * Restore onTouch behaviour to 4.x version [#8585](https://github.com/mapbox/mapbox-gl-native/pull/8585) * Restore anchoring after updating MarkerView Icon [#8519](https://github.com/mapbox/mapbox-gl-native/pull/8519) diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java index 74170bb72b..a8fc58d51c 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java @@ -293,7 +293,7 @@ public final class CameraPosition implements Parcelable { * Set the tilt in degrees *

* value is clamped to 0 and 60. - *

+ *

* * @param tilt Tilt value * @return Builder diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationSource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationSource.java index f41a022fa2..dd6e43d06a 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationSource.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationSource.java @@ -18,11 +18,10 @@ import java.lang.ref.WeakReference; /** * Manages locational updates. Contains methods to register and unregister location listeners. *
    - *
  • You can register a {@link LocationEngineListener} with - * {@link #addLocationEngineListener(LocationEngineListener)} to receive - * location updates.
  • - *
  • You can unregister a {@link LocationEngineListener} with - * {@link #removeLocationEngineListener(LocationEngineListener)} to stop receiving location updates.
  • + *
  • You can register a LocationEngineListener with LocationSource#addLocationEngineListener(LocationEngineListener) + * to receive location updates.
  • + *
  • You can unregister a LocationEngineListener with + * LocationEngine#removeLocationEngineListener(LocationEngineListener)} to stop receiving location updates.
  • *
*

* Note: If registering a listener in your Activity.onStart() implementation, you should unregister it in diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java index b253595713..5e9ca7d0a8 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java @@ -42,7 +42,7 @@ public class GeoJsonSource extends Source { } /** - * Create an empty GeoJsonSource with non-default {@link GeoJsonOptions} + * Create an empty GeoJsonSource with non-default GeoJsonOptions. * * @param id the source id * @param options options @@ -67,7 +67,7 @@ public class GeoJsonSource extends Source { } /** - * Create a GeoJsonSource from a raw json string and non-default {@link GeoJsonOptions} + * Create a GeoJsonSource from a raw json string and non-default GeoJsonOptions * * @param id the source id * @param geoJson raw Json body @@ -93,7 +93,7 @@ public class GeoJsonSource extends Source { } /** - * Create a GeoJsonSource from a remote geo json file and non-default {@link GeoJsonOptions} + * Create a GeoJsonSource from a remote geo json file and non-default GeoJsonOptions * * @param id the source id * @param url remote json file @@ -105,7 +105,7 @@ public class GeoJsonSource extends Source { } /** - * Create a GeoJsonSource from a {@link FeatureCollection} + * Create a GeoJsonSource from a FeatureCollection. * * @param id the source id * @param features the features @@ -116,7 +116,7 @@ public class GeoJsonSource extends Source { } /** - * Create a GeoJsonSource from a {@link FeatureCollection} and non-default {@link GeoJsonOptions} + * Create a GeoJsonSource from a FeatureCollection and non-default GeoJsonOptions. * * @param id the source id * @param features the features @@ -130,7 +130,7 @@ public class GeoJsonSource extends Source { /** * Updates the GeoJson * - * @param features the GeoJSON {@link FeatureCollection} + * @param features the GeoJSON FeatureCollection */ public void setGeoJson(FeatureCollection features) { checkValidity(); -- cgit v1.2.1 From ff7337121685b1ff091468dc96cfc23e567ab029 Mon Sep 17 00:00:00 2001 From: Jesse Bounds Date: Tue, 4 Apr 2017 15:25:59 -0700 Subject: [ios] Silence incompatible type warning for callout view (#8608) This silences a compatibility warning that was introduced in a previous refactor that changed the return type of the callout view for annotation delegate method. This also adds checks to ensure that the callout view provided by the delegate to the map view is of the correct type and conforms to the correct protocol. --- platform/ios/app/MBXViewController.m | 2 +- platform/ios/src/MGLMapView.mm | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/platform/ios/app/MBXViewController.m b/platform/ios/app/MBXViewController.m index 39458c4f31..25eb598231 100644 --- a/platform/ios/app/MBXViewController.m +++ b/platform/ios/app/MBXViewController.m @@ -1739,7 +1739,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { }]; } -- (UIView *)mapView:(__unused MGLMapView *)mapView calloutViewForAnnotation:(id)annotation +- (nullable id )mapView:(__unused MGLMapView *)mapView calloutViewForAnnotation:(id)annotation { if ([annotation respondsToSelector:@selector(title)] && [annotation isKindOfClass:[MBXCustomCalloutAnnotation class]]) diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 79467a065f..6f51d4b523 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -3777,7 +3777,14 @@ public: UIView *calloutView; if ([self.delegate respondsToSelector:@selector(mapView:calloutViewForAnnotation:)]) { - calloutView = [self.delegate mapView:self calloutViewForAnnotation:annotation]; + id providedCalloutView = [self.delegate mapView:self calloutViewForAnnotation:annotation]; + if (providedCalloutView) { + if (![providedCalloutView isKindOfClass:[UIView class]]) { + [NSException raise:NSInvalidArgumentException format:@"Callout view must be a kind of UIView"]; + } + NSAssert([providedCalloutView conformsToProtocol:@protocol(MGLCalloutView)], @"callout view must conform to MGLCalloutView"); + calloutView = providedCalloutView; + } } if (!calloutView) { -- cgit v1.2.1 From 8539d7092ee0dc584f6dd7f664d49ee96d4ddf0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Wed, 5 Apr 2017 01:25:37 -0700 Subject: [ios, macos] Preserve symlinks when zipping framework --- platform/ios/scripts/publish.sh | 2 +- platform/macos/CHANGELOG.md | 4 ++++ platform/macos/scripts/deploy-packages.sh | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/platform/ios/scripts/publish.sh b/platform/ios/scripts/publish.sh index e080ee825c..117a4ec0db 100755 --- a/platform/ios/scripts/publish.sh +++ b/platform/ios/scripts/publish.sh @@ -27,7 +27,7 @@ cd build/ios/pkg ZIP=mapbox-ios-sdk-${PUBLISH_VERSION}${PUBLISH_STYLE}.zip step "Compressing ${ZIP}…" rm -f ../${ZIP} -zip -r ../${ZIP} * +zip -yr ../${ZIP} * # # upload diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md index fa5822863f..cf2c1d4884 100644 --- a/platform/macos/CHANGELOG.md +++ b/platform/macos/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog for Mapbox macOS SDK +## 0.4.1 + +* Fixed an issue causing code signing failures and bloating the framework. ([#8640](https://github.com/mapbox/mapbox-gl-native/pull/8640)) + ## 0.4.0 This version of the Mapbox macOS SDK corresponds to version 3.5.1 of the Mapbox iOS SDK. diff --git a/platform/macos/scripts/deploy-packages.sh b/platform/macos/scripts/deploy-packages.sh index 8f61519244..d9d74b2867 100755 --- a/platform/macos/scripts/deploy-packages.sh +++ b/platform/macos/scripts/deploy-packages.sh @@ -37,7 +37,7 @@ buildPackageStyle() { step "Compressing ${file_name}…" cd build/macos/pkg rm -f ../deploy/${file_name} - zip -r ../deploy/${file_name} * + zip -yr ../deploy/${file_name} * cd - if [[ "${GITHUB_RELEASE}" == true ]]; then echo "Uploading ${file_name} to GitHub" -- cgit v1.2.1 From ec34813c905566bfb7a388a9d905d1e20711dc17 Mon Sep 17 00:00:00 2001 From: Fabian Guerra Soto Date: Wed, 5 Apr 2017 14:16:58 -0400 Subject: [ios] assertion to check if an annotationTag > 0 (#8588) * [ios] assertion to check if an annotationTag > 0 * [ios,macos] assertion and guard added to check annotations in visibleAnnotationsInRect --- platform/ios/src/MGLMapView.mm | 2 ++ platform/macos/src/MGLMapView.mm | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 6f51d4b523..ef4326556b 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -3060,10 +3060,12 @@ public: continue; } MGLAnnotationContext annotationContext = _annotationContextsByAnnotationTag.at(annotationTag); + NSAssert(annotationContext.annotation, @"Missing annotation for tag %u.", annotationTag); if (annotationContext.annotation) { [annotations addObject:annotationContext.annotation]; } + } return [annotations copy]; diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm index 8711950554..fc9834e016 100644 --- a/platform/macos/src/MGLMapView.mm +++ b/platform/macos/src/MGLMapView.mm @@ -1801,7 +1801,11 @@ public: continue; } MGLAnnotationContext annotationContext = _annotationContextsByAnnotationTag.at(annotationTag); - [annotations addObject:annotationContext.annotation]; + NSAssert(annotationContext.annotation, @"Missing annotation for tag %u.", annotationTag); + if (annotationContext.annotation) + { + [annotations addObject:annotationContext.annotation]; + } } return [annotations copy]; -- cgit v1.2.1 From 5d4d5dcf1b2f56f1dff3ef9dbca57fd076932c50 Mon Sep 17 00:00:00 2001 From: Jesse Bounds Date: Wed, 5 Apr 2017 12:05:29 -0700 Subject: [ios, macos] Rename Data-driven styling guide (#8627) * [ios, macos] Rename Data-driven styling guide This turns the Data-driven styling guide into a guide for working with style functions. This helps clarify that not all style functions are DDS specific but keeps the discussion of this related functionality in the same guide. --- .../darwin/docs/guides/Data-Driven Styling.md.ejs | 159 -------------------- .../darwin/docs/guides/For Style Authors.md.ejs | 3 +- .../guides/Using Style Functions at Runtime.md.ejs | 161 +++++++++++++++++++++ platform/darwin/scripts/generate-style-code.js | 6 +- platform/ios/CHANGELOG.md | 1 + platform/ios/docs/guides/Data-Driven Styling.md | 153 -------------------- platform/ios/docs/guides/For Style Authors.md | 3 +- .../guides/Using Style Functions at Runtime.md | 155 ++++++++++++++++++++ platform/ios/jazzy.yml | 2 +- platform/macos/CHANGELOG.md | 1 + platform/macos/docs/guides/Data-Driven Styling.md | 153 -------------------- platform/macos/docs/guides/For Style Authors.md | 3 +- .../guides/Using Style Functions at Runtime.md | 155 ++++++++++++++++++++ platform/macos/jazzy.yml | 2 +- 14 files changed, 481 insertions(+), 476 deletions(-) delete mode 100644 platform/darwin/docs/guides/Data-Driven Styling.md.ejs create mode 100644 platform/darwin/docs/guides/Using Style Functions at Runtime.md.ejs delete mode 100644 platform/ios/docs/guides/Data-Driven Styling.md create mode 100644 platform/ios/docs/guides/Using Style Functions at Runtime.md delete mode 100644 platform/macos/docs/guides/Data-Driven Styling.md create mode 100644 platform/macos/docs/guides/Using Style Functions at Runtime.md diff --git a/platform/darwin/docs/guides/Data-Driven Styling.md.ejs b/platform/darwin/docs/guides/Data-Driven Styling.md.ejs deleted file mode 100644 index 7b597c6737..0000000000 --- a/platform/darwin/docs/guides/Data-Driven Styling.md.ejs +++ /dev/null @@ -1,159 +0,0 @@ - -<% - const os = locals.os; - const iOS = os === 'iOS'; - const macOS = os === 'macOS'; - const cocoaPrefix = iOS ? 'UI' : 'NS'; --%> - - -# Data-Driven Styling - -Mapbox’s data-driven styling features allow you to use attributes in the data to style your maps. You can style map features automatically based on their individual attributes. - -Vary POI icons, transit route line colors, city polygon opacity, and more based on any attribute in your data. Need to visualize hotel data by price? You can have your map’s point radii and colors change automatically with your data. - -![available bikes](img/data-driven-styling/citibikes.png) ![subway lines](img/data-driven-styling/polylineExample.png) - -This guide uses earthquake data from the [U.S. Geological Survey](https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php) to style a map based on attributes. For more information about how to work with GeoJSON data in our iOS SDK, please see our [working with GeoJSON data](working-with-geojson-data.html) guide. - -## Style functions - -There are three subclasses of `MGLStyleFunction`: - -* `MGLCameraStyleFunction` is a style value that changes with zoom level. For example, you can make the radius of a circle increase according to zoom level. -* `MGLSourceStyleFunction` is a style value that changes with the attributes of a feature. For example, you can adjust the radius of a circle based on the magnitude of an earthquake. -* `MGLCompositeStyleFunction` is a style value that changes with both zoom level and attribute values. For example, you can add a circle layer where each circle has a radius based on both zoom level and the magnitude of an earthquake. - -The documentation for each individual style layer property notes which style functions are enabled for that property. - -## Stops - -Stops are key-value pairs that that determine a style value. With a `MGLCameraSourceFunction` stop, you can use a dictionary with a zoom level for a key and a `MGLStyleValue` for the value. For example, you can use a stops dictionary with zoom levels 0, 10, and 20 as keys, and yellow, orange, and red as the values. A `MGLSourceStyleFunction` uses the relevant attribute value as the key. - -```swift -let stops = [0: MGLStyleValue<<%- cocoaPrefix %>Color>(rawValue: .yellow), - 2.5: MGLStyleValue(rawValue: .orange), - 5: MGLStyleValue(rawValue: .red), - 7.5: MGLStyleValue(rawValue: .blue), - 10: MGLStyleValue(rawValue: .white)] -``` - -## Interpolation mode - -The effect a key has on the style value is determined by the interpolation mode. There are four interpolation modes that can be used with a source style function: exponential, interval, categorical, and identity. You can also use exponential and interval interpolation modes with a camera style function. - -### Linear - -`MGLInterpolationModeExponential` interpolates linearly or exponentially between style function stop values. By default, the `MGLStyleFunction` options parameter `MGLStyleFunctionOptionInterpolationBase` equals `1`, which represents linear interpolation and doesn’t need to be included in the options dictionary. - -The stops dictionary below, for example, shows colors that continuously shift from yellow to orange to red to blue to white based on the attribute value. - -``` swift -let url = URL(string: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson") -let symbolSource = MGLSource(identifier: "source") -let symbolLayer = MGLSymbolStyleLayer(identifier: "place-city-sm", source: symbolSource) - -let source = MGLShapeSource(identifier: "earthquakes", url: url, options: nil) -style.addSource(source) - -let stops = [0: MGLStyleValue<<%- cocoaPrefix %>Color>(rawValue: .yellow), - 2.5: MGLStyleValue(rawValue: .orange), - 5: MGLStyleValue(rawValue: .red), - 7.5: MGLStyleValue(rawValue: .blue), - 10: MGLStyleValue(rawValue: .white)] - -let layer = MGLCircleStyleLayer(identifier: "circles", source: source) -layer.circleColor = MGLStyleValue(interpolationMode: .exponential, - sourceStops: stops, - attributeName: "mag", - options: [.defaultValue: MGLStyleValue<<%- cocoaPrefix %>Color>(rawValue: .green)]) -layer.circleRadius = MGLStyleValue(rawValue: 10) -style.insertLayer(layer, below: symbolLayer) -``` - -![exponential mode](img/data-driven-styling/exponential.png) - -### Exponential - -By combining `MGLInterpolationModeExponential` with an `MGLStyleFunctionOptionInterpolationBase` greater than `0` (other than `1`), you can interpolate between values exponentially, create an accelerated ramp effect. - -Here’s a visualization from Mapbox Studio (see [Working with Mapbox Studio](working-with-mapbox-studio.html)) comparing interpolation base values of `1.5` and `0.5` based on zoom. - - - - -The example below increases a layer’s `circleRadius` exponentially based on a map’s zoom level. The `MGLStyleFunctionOptionInterpolationBase` is `1.5`. - -```swift -let stops = [12: MGLStyleValue(rawValue: 0.5), - 14: MGLStyleValue(rawValue: 2), - 18: MGLStyleValue(rawValue: 18)] - -layer.circleRadius = MGLStyleValue(interpolationMode: .exponential, - cameraStops: stops, - options: [.interpolationBase: 1.5]) -``` - -### Interval - -`MGLInterpolationModeInterval` creates a range using the keys from the stops dictionary. The range is from the given key to just less than the next key. The attribute values that fall into that range are then styled using the style value assigned to that key. - -When we use the stops dictionary given above with an interval interpolation mode, we create ranges where earthquakes with a magnitude of 0 to just less than 2.5 would be yellow, 2.5 to just less than 5 would be orange, and so on. - -``` swift -let stops = [0: MGLStyleValue<<%- cocoaPrefix %>Color>(rawValue: .yellow), - 2.5: MGLStyleValue(rawValue: .orange), - 5: MGLStyleValue(rawValue: .red), - 7.5: MGLStyleValue(rawValue: .blue), - 10: MGLStyleValue(rawValue: .white)] - -layer.circleColor = MGLStyleValue(interpolationMode: .interval, - sourceStops: stops, - attributeName: "mag", - options: [.defaultValue: MGLStyleValue<<%- cocoaPrefix %>Color>(rawValue: .green)]) -``` - -![interval mode](img/data-driven-styling/interval.png) - -### Categorical - -At each stop, `MGLInterpolationModeCategorical` produces an output value equal to the function input. We’re going to use a different stops dictionary than we did for the previous two modes. - -There are three main types of events in the dataset: earthquakes, explosions, and quarry blasts. In this case, the color of the circle layer will be determined by the type of event, with a default value of green to catch any events that do not fall into any of those categories. - -``` swift -let categoricalStops = ["earthquake": MGLStyleValue<<%- cocoaPrefix %>Color>(rawValue: .orange), - "explosion": MGLStyleValue(rawValue: .red), - "quarry blast": MGLStyleValue(rawValue: .yellow)] - -layer.circleColor = MGLStyleValue(interpolationMode: .categorical, - sourceStops: categoricalStops, - attributeName: "type", - options: [.defaultValue: MGLStyleValue<<%- cocoaPrefix %>Color>(rawValue: .blue)]) - -``` - -![categorical mode](img/data-driven-styling/categorical1.png) ![categorical mode](img/data-driven-styling/categorical2.png) - -### Identity - -`MGLInterpolationModeIdentity` uses the attribute’s value as the style value. For example, you can set the `circleRadius` to the earthquake’s magnitude. Since the attribute value itself will be used as the style value, `sourceStops` should be set to `nil`. - -``` swift -layer.circleRadius = MGLStyleValue(interpolationMode: .identity, - sourceStops: nil, - attributeName: "mag", - options: [.defaultValue: MGLStyleValue(rawValue: 0)]) - -``` - -![identity mode](img/data-driven-styling/identity.png) - -##Resources - -* [USGS](https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php) -* [For Style Authors](for-style-authors.html) diff --git a/platform/darwin/docs/guides/For Style Authors.md.ejs b/platform/darwin/docs/guides/For Style Authors.md.ejs index 93ca7014a3..86f8c46f53 100644 --- a/platform/darwin/docs/guides/For Style Authors.md.ejs +++ b/platform/darwin/docs/guides/For Style Authors.md.ejs @@ -308,8 +308,7 @@ iOS. A _style function_ allows you to vary the value of a layout or paint attribute based on the zoom level, data provided by content sources, or both. For more -information about style functions that incorporate data from sources, see -“[Data-Driven Styling](data-driven-styling.html)”. +information about style functions, see “[Using Style Functions at Runtime](using-style-functions-at-runtime.html)”. Each kind of style function is represented by a distinct class, but you typically create style functions as you create any other style value, using diff --git a/platform/darwin/docs/guides/Using Style Functions at Runtime.md.ejs b/platform/darwin/docs/guides/Using Style Functions at Runtime.md.ejs new file mode 100644 index 0000000000..bd477042c7 --- /dev/null +++ b/platform/darwin/docs/guides/Using Style Functions at Runtime.md.ejs @@ -0,0 +1,161 @@ + +<% + const os = locals.os; + const iOS = os === 'iOS'; + const macOS = os === 'macOS'; + const cocoaPrefix = iOS ? 'UI' : 'NS'; +-%> + + +# Using Style Functions at Runtime + +[Runtime Styling](runtime-styling.html) enables you to modify every aspect of the map’s appearance dynamically as a user interacts with your application. Much of the runtime styling API allows you to specify _style functions_ instead of constant values. A style function allows you to specify in advance how a layout or paint attribute will vary as the zoom level changes or how the appearance of individual features vary based on metadata provided by a content source. + +Style functions spare you the inconvenience of manually calculating intermediate values between different zoom levels or creating a multitude of style layers to handle homogeneous features in the map content. For example, if your content source indicates the prices of hotels in an area, you can color-code the hotels by price, relying on a style function to smoothly interpolate among desired colors without having to specify the color for each exact price. + +_Data-driven styling_ specifically refers to the use of style functions to vary the map’s appearance based on data in a content source. + +You can also specify style functions in a style JSON file, to be applied automatically when the map loads. See the [Mapbox Style Specification](https://www.mapbox.com/mapbox-gl-js/style-spec/#types-function) for details. + +![available bikes](img/data-driven-styling/citibikes.png) ![subway lines](img/data-driven-styling/polylineExample.png) + +This guide uses earthquake data from the [U.S. Geological Survey](https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php) and data-driven styling to style a map based on attributes. For more information about how to work with GeoJSON data in our iOS SDK, please see our [working with GeoJSON data](working-with-geojson-data.html) guide. + +A style function is represented at runtime by the `MGLStyleFunction` class. There are three subclasses of `MGLStyleFunction`: + +* `MGLCameraStyleFunction` is a style value that changes with zoom level. For example, you can make the radius of a circle increase according to zoom level. +* `MGLSourceStyleFunction` is a style value that changes with the attributes of a feature. For example, you can adjust the radius of a circle based on the magnitude of an earthquake. +* `MGLCompositeStyleFunction` is a style value that changes with both zoom level and attribute values. For example, you can add a circle layer where each circle has a radius based on both zoom level and the magnitude of an earthquake. + +The documentation for each individual style layer property notes which style functions are enabled for that property. + +## Stops + +Stops are key-value pairs that that determine a style value. With a `MGLCameraSourceFunction` stop, you can use a dictionary with a zoom level for a key and a `MGLStyleValue` for the value. For example, you can use a stops dictionary with zoom levels 0, 10, and 20 as keys, and yellow, orange, and red as the values. A `MGLSourceStyleFunction` uses the relevant attribute value as the key. + +```swift +let stops = [0: MGLStyleValue<<%- cocoaPrefix %>Color>(rawValue: .yellow), + 2.5: MGLStyleValue(rawValue: .orange), + 5: MGLStyleValue(rawValue: .red), + 7.5: MGLStyleValue(rawValue: .blue), + 10: MGLStyleValue(rawValue: .white)] +``` + +## Interpolation mode + +The effect a key has on the style value is determined by the interpolation mode. There are four interpolation modes that can be used with a source style function: exponential, interval, categorical, and identity. You can also use exponential and interval interpolation modes with a camera style function. + +### Linear + +`MGLInterpolationModeExponential` interpolates linearly or exponentially between style function stop values. By default, the `MGLStyleFunction` options parameter `MGLStyleFunctionOptionInterpolationBase` equals `1`, which represents linear interpolation and doesn’t need to be included in the options dictionary. + +The stops dictionary below, for example, shows colors that continuously shift from yellow to orange to red to blue to white based on the attribute value. + +``` swift +let url = URL(string: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson") +let symbolSource = MGLSource(identifier: "source") +let symbolLayer = MGLSymbolStyleLayer(identifier: "place-city-sm", source: symbolSource) + +let source = MGLShapeSource(identifier: "earthquakes", url: url, options: nil) +style.addSource(source) + +let stops = [0: MGLStyleValue<<%- cocoaPrefix %>Color>(rawValue: .yellow), + 2.5: MGLStyleValue(rawValue: .orange), + 5: MGLStyleValue(rawValue: .red), + 7.5: MGLStyleValue(rawValue: .blue), + 10: MGLStyleValue(rawValue: .white)] + +let layer = MGLCircleStyleLayer(identifier: "circles", source: source) +layer.circleColor = MGLStyleValue(interpolationMode: .exponential, + sourceStops: stops, + attributeName: "mag", + options: [.defaultValue: MGLStyleValue<<%- cocoaPrefix %>Color>(rawValue: .green)]) +layer.circleRadius = MGLStyleValue(rawValue: 10) +style.insertLayer(layer, below: symbolLayer) +``` + +![exponential mode](img/data-driven-styling/exponential.png) + +### Exponential + +By combining `MGLInterpolationModeExponential` with an `MGLStyleFunctionOptionInterpolationBase` greater than `0` (other than `1`), you can interpolate between values exponentially, create an accelerated ramp effect. + +Here’s a visualization from Mapbox Studio (see [Working with Mapbox Studio](working-with-mapbox-studio.html)) comparing interpolation base values of `1.5` and `0.5` based on zoom. + + + + +The example below increases a layer’s `circleRadius` exponentially based on a map’s zoom level. The `MGLStyleFunctionOptionInterpolationBase` is `1.5`. + +```swift +let stops = [12: MGLStyleValue(rawValue: 0.5), + 14: MGLStyleValue(rawValue: 2), + 18: MGLStyleValue(rawValue: 18)] + +layer.circleRadius = MGLStyleValue(interpolationMode: .exponential, + cameraStops: stops, + options: [.interpolationBase: 1.5]) +``` + +### Interval + +`MGLInterpolationModeInterval` creates a range using the keys from the stops dictionary. The range is from the given key to just less than the next key. The attribute values that fall into that range are then styled using the style value assigned to that key. + +When we use the stops dictionary given above with an interval interpolation mode, we create ranges where earthquakes with a magnitude of 0 to just less than 2.5 would be yellow, 2.5 to just less than 5 would be orange, and so on. + +``` swift +let stops = [0: MGLStyleValue<<%- cocoaPrefix %>Color>(rawValue: .yellow), + 2.5: MGLStyleValue(rawValue: .orange), + 5: MGLStyleValue(rawValue: .red), + 7.5: MGLStyleValue(rawValue: .blue), + 10: MGLStyleValue(rawValue: .white)] + +layer.circleColor = MGLStyleValue(interpolationMode: .interval, + sourceStops: stops, + attributeName: "mag", + options: [.defaultValue: MGLStyleValue<<%- cocoaPrefix %>Color>(rawValue: .green)]) +``` + +![interval mode](img/data-driven-styling/interval.png) + +### Categorical + +At each stop, `MGLInterpolationModeCategorical` produces an output value equal to the function input. We’re going to use a different stops dictionary than we did for the previous two modes. + +There are three main types of events in the dataset: earthquakes, explosions, and quarry blasts. In this case, the color of the circle layer will be determined by the type of event, with a default value of blue to catch any events that do not fall into any of those categories. + +``` swift +let categoricalStops = ["earthquake": MGLStyleValue<<%- cocoaPrefix %>Color>(rawValue: .orange), + "explosion": MGLStyleValue(rawValue: .red), + "quarry blast": MGLStyleValue(rawValue: .yellow)] + +layer.circleColor = MGLStyleValue(interpolationMode: .categorical, + sourceStops: categoricalStops, + attributeName: "type", + options: [.defaultValue: MGLStyleValue<<%- cocoaPrefix %>Color>(rawValue: .blue)]) + +``` + +![categorical mode](img/data-driven-styling/categorical1.png) ![categorical mode](img/data-driven-styling/categorical2.png) + +### Identity + +`MGLInterpolationModeIdentity` uses the attribute’s value as the style value. For example, you can set the `circleRadius` to the earthquake’s magnitude. Since the attribute value itself will be used as the style value, `sourceStops` should be set to `nil`. + +``` swift +layer.circleRadius = MGLStyleValue(interpolationMode: .identity, + sourceStops: nil, + attributeName: "mag", + options: [.defaultValue: MGLStyleValue(rawValue: 0)]) + +``` + +![identity mode](img/data-driven-styling/identity.png) + +##Resources + +* [USGS](https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php) +* [For Style Authors](for-style-authors.html) diff --git a/platform/darwin/scripts/generate-style-code.js b/platform/darwin/scripts/generate-style-code.js index 9c4569709d..7e798154e4 100644 --- a/platform/darwin/scripts/generate-style-code.js +++ b/platform/darwin/scripts/generate-style-code.js @@ -528,7 +528,7 @@ const layerH = ejs.compile(fs.readFileSync('platform/darwin/src/MGLStyleLayer.h. const layerM = ejs.compile(fs.readFileSync('platform/darwin/src/MGLStyleLayer.mm.ejs', 'utf8'), { strict: true}); const testLayers = ejs.compile(fs.readFileSync('platform/darwin/test/MGLStyleLayerTests.mm.ejs', 'utf8'), { strict: true}); const guideMD = ejs.compile(fs.readFileSync('platform/darwin/docs/guides/For Style Authors.md.ejs', 'utf8'), { strict: true }); -const ddsGuideMD = ejs.compile(fs.readFileSync('platform/darwin/docs/guides/Data-Driven Styling.md.ejs', 'utf8'), { strict: true }); +const ddsGuideMD = ejs.compile(fs.readFileSync('platform/darwin/docs/guides/Using Style Functions at Runtime.md.ejs', 'utf8'), { strict: true }); const layers = _(spec.layer.type.values).map((value, layerType) => { const layoutProperties = Object.keys(spec[`layout_${layerType}`]).reduce((memo, name) => { @@ -615,9 +615,9 @@ fs.writeFileSync(`platform/macos/docs/guides/For Style Authors.md`, guideMD({ renamedProperties: renamedPropertiesByLayerType, layers: layers, })); -fs.writeFileSync(`platform/ios/docs/guides/Data-Driven Styling.md`, ddsGuideMD({ +fs.writeFileSync(`platform/ios/docs/guides/Using Style Functions at Runtime.md`, ddsGuideMD({ os: 'iOS', })); -fs.writeFileSync(`platform/macos/docs/guides/Data-Driven Styling.md`, ddsGuideMD({ +fs.writeFileSync(`platform/macos/docs/guides/Using Style Functions at Runtime.md`, ddsGuideMD({ os: 'macOS', })); diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index 8b1d6219a3..c79347e572 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -7,6 +7,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT * Fixed an issue that caused the return type of a map view delegate method to bridge incorrectly to applications written in Swift. ([#8541](https://github.com/mapbox/mapbox-gl-native/pull/8541)) * Fixed a crash that could occur when calling `-[MGLShapeSource featuresMatchingPredicate:]` or `-[MGLVectorSource featuresInSourceLayersWithIdentifiers:predicate:]`. ([#8553](https://github.com/mapbox/mapbox-gl-native/pull/8553)) * Fixed a crash that could occur after adding view-backed annotations to the map. ([#8513](https://github.com/mapbox/mapbox-gl-native/pull/8513)) +* Renamed the "Data-Driven Styling" guide to "Using Style Functions at Runtime" and clarified the meaning of data-driven styling in the guide's discussion of runtime style functions. ([#8627](https://github.com/mapbox/mapbox-gl-native/pull/8627)) ## 3.5.0 diff --git a/platform/ios/docs/guides/Data-Driven Styling.md b/platform/ios/docs/guides/Data-Driven Styling.md deleted file mode 100644 index a5ed874b5d..0000000000 --- a/platform/ios/docs/guides/Data-Driven Styling.md +++ /dev/null @@ -1,153 +0,0 @@ - - - -# Data-Driven Styling - -Mapbox’s data-driven styling features allow you to use attributes in the data to style your maps. You can style map features automatically based on their individual attributes. - -Vary POI icons, transit route line colors, city polygon opacity, and more based on any attribute in your data. Need to visualize hotel data by price? You can have your map’s point radii and colors change automatically with your data. - -![available bikes](img/data-driven-styling/citibikes.png) ![subway lines](img/data-driven-styling/polylineExample.png) - -This guide uses earthquake data from the [U.S. Geological Survey](https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php) to style a map based on attributes. For more information about how to work with GeoJSON data in our iOS SDK, please see our [working with GeoJSON data](working-with-geojson-data.html) guide. - -## Style functions - -There are three subclasses of `MGLStyleFunction`: - -* `MGLCameraStyleFunction` is a style value that changes with zoom level. For example, you can make the radius of a circle increase according to zoom level. -* `MGLSourceStyleFunction` is a style value that changes with the attributes of a feature. For example, you can adjust the radius of a circle based on the magnitude of an earthquake. -* `MGLCompositeStyleFunction` is a style value that changes with both zoom level and attribute values. For example, you can add a circle layer where each circle has a radius based on both zoom level and the magnitude of an earthquake. - -The documentation for each individual style layer property notes which style functions are enabled for that property. - -## Stops - -Stops are key-value pairs that that determine a style value. With a `MGLCameraSourceFunction` stop, you can use a dictionary with a zoom level for a key and a `MGLStyleValue` for the value. For example, you can use a stops dictionary with zoom levels 0, 10, and 20 as keys, and yellow, orange, and red as the values. A `MGLSourceStyleFunction` uses the relevant attribute value as the key. - -```swift -let stops = [0: MGLStyleValue(rawValue: .yellow), - 2.5: MGLStyleValue(rawValue: .orange), - 5: MGLStyleValue(rawValue: .red), - 7.5: MGLStyleValue(rawValue: .blue), - 10: MGLStyleValue(rawValue: .white)] -``` - -## Interpolation mode - -The effect a key has on the style value is determined by the interpolation mode. There are four interpolation modes that can be used with a source style function: exponential, interval, categorical, and identity. You can also use exponential and interval interpolation modes with a camera style function. - -### Linear - -`MGLInterpolationModeExponential` interpolates linearly or exponentially between style function stop values. By default, the `MGLStyleFunction` options parameter `MGLStyleFunctionOptionInterpolationBase` equals `1`, which represents linear interpolation and doesn’t need to be included in the options dictionary. - -The stops dictionary below, for example, shows colors that continuously shift from yellow to orange to red to blue to white based on the attribute value. - -``` swift -let url = URL(string: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson") -let symbolSource = MGLSource(identifier: "source") -let symbolLayer = MGLSymbolStyleLayer(identifier: "place-city-sm", source: symbolSource) - -let source = MGLShapeSource(identifier: "earthquakes", url: url, options: nil) -style.addSource(source) - -let stops = [0: MGLStyleValue(rawValue: .yellow), - 2.5: MGLStyleValue(rawValue: .orange), - 5: MGLStyleValue(rawValue: .red), - 7.5: MGLStyleValue(rawValue: .blue), - 10: MGLStyleValue(rawValue: .white)] - -let layer = MGLCircleStyleLayer(identifier: "circles", source: source) -layer.circleColor = MGLStyleValue(interpolationMode: .exponential, - sourceStops: stops, - attributeName: "mag", - options: [.defaultValue: MGLStyleValue(rawValue: .green)]) -layer.circleRadius = MGLStyleValue(rawValue: 10) -style.insertLayer(layer, below: symbolLayer) -``` - -![exponential mode](img/data-driven-styling/exponential.png) - -### Exponential - -By combining `MGLInterpolationModeExponential` with an `MGLStyleFunctionOptionInterpolationBase` greater than `0` (other than `1`), you can interpolate between values exponentially, create an accelerated ramp effect. - -Here’s a visualization from Mapbox Studio (see [Working with Mapbox Studio](working-with-mapbox-studio.html)) comparing interpolation base values of `1.5` and `0.5` based on zoom. - - - - -The example below increases a layer’s `circleRadius` exponentially based on a map’s zoom level. The `MGLStyleFunctionOptionInterpolationBase` is `1.5`. - -```swift -let stops = [12: MGLStyleValue(rawValue: 0.5), - 14: MGLStyleValue(rawValue: 2), - 18: MGLStyleValue(rawValue: 18)] - -layer.circleRadius = MGLStyleValue(interpolationMode: .exponential, - cameraStops: stops, - options: [.interpolationBase: 1.5]) -``` - -### Interval - -`MGLInterpolationModeInterval` creates a range using the keys from the stops dictionary. The range is from the given key to just less than the next key. The attribute values that fall into that range are then styled using the style value assigned to that key. - -When we use the stops dictionary given above with an interval interpolation mode, we create ranges where earthquakes with a magnitude of 0 to just less than 2.5 would be yellow, 2.5 to just less than 5 would be orange, and so on. - -``` swift -let stops = [0: MGLStyleValue(rawValue: .yellow), - 2.5: MGLStyleValue(rawValue: .orange), - 5: MGLStyleValue(rawValue: .red), - 7.5: MGLStyleValue(rawValue: .blue), - 10: MGLStyleValue(rawValue: .white)] - -layer.circleColor = MGLStyleValue(interpolationMode: .interval, - sourceStops: stops, - attributeName: "mag", - options: [.defaultValue: MGLStyleValue(rawValue: .green)]) -``` - -![interval mode](img/data-driven-styling/interval.png) - -### Categorical - -At each stop, `MGLInterpolationModeCategorical` produces an output value equal to the function input. We’re going to use a different stops dictionary than we did for the previous two modes. - -There are three main types of events in the dataset: earthquakes, explosions, and quarry blasts. In this case, the color of the circle layer will be determined by the type of event, with a default value of green to catch any events that do not fall into any of those categories. - -``` swift -let categoricalStops = ["earthquake": MGLStyleValue(rawValue: .orange), - "explosion": MGLStyleValue(rawValue: .red), - "quarry blast": MGLStyleValue(rawValue: .yellow)] - -layer.circleColor = MGLStyleValue(interpolationMode: .categorical, - sourceStops: categoricalStops, - attributeName: "type", - options: [.defaultValue: MGLStyleValue(rawValue: .blue)]) - -``` - -![categorical mode](img/data-driven-styling/categorical1.png) ![categorical mode](img/data-driven-styling/categorical2.png) - -### Identity - -`MGLInterpolationModeIdentity` uses the attribute’s value as the style value. For example, you can set the `circleRadius` to the earthquake’s magnitude. Since the attribute value itself will be used as the style value, `sourceStops` should be set to `nil`. - -``` swift -layer.circleRadius = MGLStyleValue(interpolationMode: .identity, - sourceStops: nil, - attributeName: "mag", - options: [.defaultValue: MGLStyleValue(rawValue: 0)]) - -``` - -![identity mode](img/data-driven-styling/identity.png) - -##Resources - -* [USGS](https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php) -* [For Style Authors](for-style-authors.html) diff --git a/platform/ios/docs/guides/For Style Authors.md b/platform/ios/docs/guides/For Style Authors.md index d3ba331e09..ed9018b121 100644 --- a/platform/ios/docs/guides/For Style Authors.md +++ b/platform/ios/docs/guides/For Style Authors.md @@ -288,8 +288,7 @@ defined by the style specification. A _style function_ allows you to vary the value of a layout or paint attribute based on the zoom level, data provided by content sources, or both. For more -information about style functions that incorporate data from sources, see -“[Data-Driven Styling](data-driven-styling.html)”. +information about style functions, see “[Using Style Functions at Runtime](using-style-functions-at-runtime.html)”. Each kind of style function is represented by a distinct class, but you typically create style functions as you create any other style value, using diff --git a/platform/ios/docs/guides/Using Style Functions at Runtime.md b/platform/ios/docs/guides/Using Style Functions at Runtime.md new file mode 100644 index 0000000000..13c4cc0bbc --- /dev/null +++ b/platform/ios/docs/guides/Using Style Functions at Runtime.md @@ -0,0 +1,155 @@ + + + +# Using Style Functions at Runtime + +[Runtime Styling](runtime-styling.html) enables you to modify every aspect of the map’s appearance dynamically as a user interacts with your application. Much of the runtime styling API allows you to specify _style functions_ instead of constant values. A style function allows you to specify in advance how a layout or paint attribute will vary as the zoom level changes or how the appearance of individual features vary based on metadata provided by a content source. + +Style functions spare you the inconvenience of manually calculating intermediate values between different zoom levels or creating a multitude of style layers to handle homogeneous features in the map content. For example, if your content source indicates the prices of hotels in an area, you can color-code the hotels by price, relying on a style function to smoothly interpolate among desired colors without having to specify the color for each exact price. + +_Data-driven styling_ specifically refers to the use of style functions to vary the map’s appearance based on data in a content source. + +You can also specify style functions in a style JSON file, to be applied automatically when the map loads. See the [Mapbox Style Specification](https://www.mapbox.com/mapbox-gl-js/style-spec/#types-function) for details. + +![available bikes](img/data-driven-styling/citibikes.png) ![subway lines](img/data-driven-styling/polylineExample.png) + +This guide uses earthquake data from the [U.S. Geological Survey](https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php) and data-driven styling to style a map based on attributes. For more information about how to work with GeoJSON data in our iOS SDK, please see our [working with GeoJSON data](working-with-geojson-data.html) guide. + +A style function is represented at runtime by the `MGLStyleFunction` class. There are three subclasses of `MGLStyleFunction`: + +* `MGLCameraStyleFunction` is a style value that changes with zoom level. For example, you can make the radius of a circle increase according to zoom level. +* `MGLSourceStyleFunction` is a style value that changes with the attributes of a feature. For example, you can adjust the radius of a circle based on the magnitude of an earthquake. +* `MGLCompositeStyleFunction` is a style value that changes with both zoom level and attribute values. For example, you can add a circle layer where each circle has a radius based on both zoom level and the magnitude of an earthquake. + +The documentation for each individual style layer property notes which style functions are enabled for that property. + +## Stops + +Stops are key-value pairs that that determine a style value. With a `MGLCameraSourceFunction` stop, you can use a dictionary with a zoom level for a key and a `MGLStyleValue` for the value. For example, you can use a stops dictionary with zoom levels 0, 10, and 20 as keys, and yellow, orange, and red as the values. A `MGLSourceStyleFunction` uses the relevant attribute value as the key. + +```swift +let stops = [0: MGLStyleValue(rawValue: .yellow), + 2.5: MGLStyleValue(rawValue: .orange), + 5: MGLStyleValue(rawValue: .red), + 7.5: MGLStyleValue(rawValue: .blue), + 10: MGLStyleValue(rawValue: .white)] +``` + +## Interpolation mode + +The effect a key has on the style value is determined by the interpolation mode. There are four interpolation modes that can be used with a source style function: exponential, interval, categorical, and identity. You can also use exponential and interval interpolation modes with a camera style function. + +### Linear + +`MGLInterpolationModeExponential` interpolates linearly or exponentially between style function stop values. By default, the `MGLStyleFunction` options parameter `MGLStyleFunctionOptionInterpolationBase` equals `1`, which represents linear interpolation and doesn’t need to be included in the options dictionary. + +The stops dictionary below, for example, shows colors that continuously shift from yellow to orange to red to blue to white based on the attribute value. + +``` swift +let url = URL(string: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson") +let symbolSource = MGLSource(identifier: "source") +let symbolLayer = MGLSymbolStyleLayer(identifier: "place-city-sm", source: symbolSource) + +let source = MGLShapeSource(identifier: "earthquakes", url: url, options: nil) +style.addSource(source) + +let stops = [0: MGLStyleValue(rawValue: .yellow), + 2.5: MGLStyleValue(rawValue: .orange), + 5: MGLStyleValue(rawValue: .red), + 7.5: MGLStyleValue(rawValue: .blue), + 10: MGLStyleValue(rawValue: .white)] + +let layer = MGLCircleStyleLayer(identifier: "circles", source: source) +layer.circleColor = MGLStyleValue(interpolationMode: .exponential, + sourceStops: stops, + attributeName: "mag", + options: [.defaultValue: MGLStyleValue(rawValue: .green)]) +layer.circleRadius = MGLStyleValue(rawValue: 10) +style.insertLayer(layer, below: symbolLayer) +``` + +![exponential mode](img/data-driven-styling/exponential.png) + +### Exponential + +By combining `MGLInterpolationModeExponential` with an `MGLStyleFunctionOptionInterpolationBase` greater than `0` (other than `1`), you can interpolate between values exponentially, create an accelerated ramp effect. + +Here’s a visualization from Mapbox Studio (see [Working with Mapbox Studio](working-with-mapbox-studio.html)) comparing interpolation base values of `1.5` and `0.5` based on zoom. + + + + +The example below increases a layer’s `circleRadius` exponentially based on a map’s zoom level. The `MGLStyleFunctionOptionInterpolationBase` is `1.5`. + +```swift +let stops = [12: MGLStyleValue(rawValue: 0.5), + 14: MGLStyleValue(rawValue: 2), + 18: MGLStyleValue(rawValue: 18)] + +layer.circleRadius = MGLStyleValue(interpolationMode: .exponential, + cameraStops: stops, + options: [.interpolationBase: 1.5]) +``` + +### Interval + +`MGLInterpolationModeInterval` creates a range using the keys from the stops dictionary. The range is from the given key to just less than the next key. The attribute values that fall into that range are then styled using the style value assigned to that key. + +When we use the stops dictionary given above with an interval interpolation mode, we create ranges where earthquakes with a magnitude of 0 to just less than 2.5 would be yellow, 2.5 to just less than 5 would be orange, and so on. + +``` swift +let stops = [0: MGLStyleValue(rawValue: .yellow), + 2.5: MGLStyleValue(rawValue: .orange), + 5: MGLStyleValue(rawValue: .red), + 7.5: MGLStyleValue(rawValue: .blue), + 10: MGLStyleValue(rawValue: .white)] + +layer.circleColor = MGLStyleValue(interpolationMode: .interval, + sourceStops: stops, + attributeName: "mag", + options: [.defaultValue: MGLStyleValue(rawValue: .green)]) +``` + +![interval mode](img/data-driven-styling/interval.png) + +### Categorical + +At each stop, `MGLInterpolationModeCategorical` produces an output value equal to the function input. We’re going to use a different stops dictionary than we did for the previous two modes. + +There are three main types of events in the dataset: earthquakes, explosions, and quarry blasts. In this case, the color of the circle layer will be determined by the type of event, with a default value of blue to catch any events that do not fall into any of those categories. + +``` swift +let categoricalStops = ["earthquake": MGLStyleValue(rawValue: .orange), + "explosion": MGLStyleValue(rawValue: .red), + "quarry blast": MGLStyleValue(rawValue: .yellow)] + +layer.circleColor = MGLStyleValue(interpolationMode: .categorical, + sourceStops: categoricalStops, + attributeName: "type", + options: [.defaultValue: MGLStyleValue(rawValue: .blue)]) + +``` + +![categorical mode](img/data-driven-styling/categorical1.png) ![categorical mode](img/data-driven-styling/categorical2.png) + +### Identity + +`MGLInterpolationModeIdentity` uses the attribute’s value as the style value. For example, you can set the `circleRadius` to the earthquake’s magnitude. Since the attribute value itself will be used as the style value, `sourceStops` should be set to `nil`. + +``` swift +layer.circleRadius = MGLStyleValue(interpolationMode: .identity, + sourceStops: nil, + attributeName: "mag", + options: [.defaultValue: MGLStyleValue(rawValue: 0)]) + +``` + +![identity mode](img/data-driven-styling/identity.png) + +##Resources + +* [USGS](https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php) +* [For Style Authors](for-style-authors.html) diff --git a/platform/ios/jazzy.yml b/platform/ios/jazzy.yml index 5d39e276b6..87af09a9b9 100644 --- a/platform/ios/jazzy.yml +++ b/platform/ios/jazzy.yml @@ -19,7 +19,7 @@ custom_categories: children: - Adding Points to a Map - Runtime Styling - - Data-Driven Styling + - Using Style Functions at Runtime - Working with Mapbox Studio - Working with GeoJSON Data - For Style Authors diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md index cf2c1d4884..326a70ebb2 100644 --- a/platform/macos/CHANGELOG.md +++ b/platform/macos/CHANGELOG.md @@ -3,6 +3,7 @@ ## 0.4.1 * Fixed an issue causing code signing failures and bloating the framework. ([#8640](https://github.com/mapbox/mapbox-gl-native/pull/8640)) +* Renamed the "Data-Driven Styling" guide to "Using Style Functions at Runtime" and clarified the meaning of data-driven styling in the guide's discussion of runtime style functions. ([#8627](https://github.com/mapbox/mapbox-gl-native/pull/8627)) ## 0.4.0 diff --git a/platform/macos/docs/guides/Data-Driven Styling.md b/platform/macos/docs/guides/Data-Driven Styling.md deleted file mode 100644 index 2adb0197d1..0000000000 --- a/platform/macos/docs/guides/Data-Driven Styling.md +++ /dev/null @@ -1,153 +0,0 @@ - - - -# Data-Driven Styling - -Mapbox’s data-driven styling features allow you to use attributes in the data to style your maps. You can style map features automatically based on their individual attributes. - -Vary POI icons, transit route line colors, city polygon opacity, and more based on any attribute in your data. Need to visualize hotel data by price? You can have your map’s point radii and colors change automatically with your data. - -![available bikes](img/data-driven-styling/citibikes.png) ![subway lines](img/data-driven-styling/polylineExample.png) - -This guide uses earthquake data from the [U.S. Geological Survey](https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php) to style a map based on attributes. For more information about how to work with GeoJSON data in our iOS SDK, please see our [working with GeoJSON data](working-with-geojson-data.html) guide. - -## Style functions - -There are three subclasses of `MGLStyleFunction`: - -* `MGLCameraStyleFunction` is a style value that changes with zoom level. For example, you can make the radius of a circle increase according to zoom level. -* `MGLSourceStyleFunction` is a style value that changes with the attributes of a feature. For example, you can adjust the radius of a circle based on the magnitude of an earthquake. -* `MGLCompositeStyleFunction` is a style value that changes with both zoom level and attribute values. For example, you can add a circle layer where each circle has a radius based on both zoom level and the magnitude of an earthquake. - -The documentation for each individual style layer property notes which style functions are enabled for that property. - -## Stops - -Stops are key-value pairs that that determine a style value. With a `MGLCameraSourceFunction` stop, you can use a dictionary with a zoom level for a key and a `MGLStyleValue` for the value. For example, you can use a stops dictionary with zoom levels 0, 10, and 20 as keys, and yellow, orange, and red as the values. A `MGLSourceStyleFunction` uses the relevant attribute value as the key. - -```swift -let stops = [0: MGLStyleValue(rawValue: .yellow), - 2.5: MGLStyleValue(rawValue: .orange), - 5: MGLStyleValue(rawValue: .red), - 7.5: MGLStyleValue(rawValue: .blue), - 10: MGLStyleValue(rawValue: .white)] -``` - -## Interpolation mode - -The effect a key has on the style value is determined by the interpolation mode. There are four interpolation modes that can be used with a source style function: exponential, interval, categorical, and identity. You can also use exponential and interval interpolation modes with a camera style function. - -### Linear - -`MGLInterpolationModeExponential` interpolates linearly or exponentially between style function stop values. By default, the `MGLStyleFunction` options parameter `MGLStyleFunctionOptionInterpolationBase` equals `1`, which represents linear interpolation and doesn’t need to be included in the options dictionary. - -The stops dictionary below, for example, shows colors that continuously shift from yellow to orange to red to blue to white based on the attribute value. - -``` swift -let url = URL(string: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson") -let symbolSource = MGLSource(identifier: "source") -let symbolLayer = MGLSymbolStyleLayer(identifier: "place-city-sm", source: symbolSource) - -let source = MGLShapeSource(identifier: "earthquakes", url: url, options: nil) -style.addSource(source) - -let stops = [0: MGLStyleValue(rawValue: .yellow), - 2.5: MGLStyleValue(rawValue: .orange), - 5: MGLStyleValue(rawValue: .red), - 7.5: MGLStyleValue(rawValue: .blue), - 10: MGLStyleValue(rawValue: .white)] - -let layer = MGLCircleStyleLayer(identifier: "circles", source: source) -layer.circleColor = MGLStyleValue(interpolationMode: .exponential, - sourceStops: stops, - attributeName: "mag", - options: [.defaultValue: MGLStyleValue(rawValue: .green)]) -layer.circleRadius = MGLStyleValue(rawValue: 10) -style.insertLayer(layer, below: symbolLayer) -``` - -![exponential mode](img/data-driven-styling/exponential.png) - -### Exponential - -By combining `MGLInterpolationModeExponential` with an `MGLStyleFunctionOptionInterpolationBase` greater than `0` (other than `1`), you can interpolate between values exponentially, create an accelerated ramp effect. - -Here’s a visualization from Mapbox Studio (see [Working with Mapbox Studio](working-with-mapbox-studio.html)) comparing interpolation base values of `1.5` and `0.5` based on zoom. - - - - -The example below increases a layer’s `circleRadius` exponentially based on a map’s zoom level. The `MGLStyleFunctionOptionInterpolationBase` is `1.5`. - -```swift -let stops = [12: MGLStyleValue(rawValue: 0.5), - 14: MGLStyleValue(rawValue: 2), - 18: MGLStyleValue(rawValue: 18)] - -layer.circleRadius = MGLStyleValue(interpolationMode: .exponential, - cameraStops: stops, - options: [.interpolationBase: 1.5]) -``` - -### Interval - -`MGLInterpolationModeInterval` creates a range using the keys from the stops dictionary. The range is from the given key to just less than the next key. The attribute values that fall into that range are then styled using the style value assigned to that key. - -When we use the stops dictionary given above with an interval interpolation mode, we create ranges where earthquakes with a magnitude of 0 to just less than 2.5 would be yellow, 2.5 to just less than 5 would be orange, and so on. - -``` swift -let stops = [0: MGLStyleValue(rawValue: .yellow), - 2.5: MGLStyleValue(rawValue: .orange), - 5: MGLStyleValue(rawValue: .red), - 7.5: MGLStyleValue(rawValue: .blue), - 10: MGLStyleValue(rawValue: .white)] - -layer.circleColor = MGLStyleValue(interpolationMode: .interval, - sourceStops: stops, - attributeName: "mag", - options: [.defaultValue: MGLStyleValue(rawValue: .green)]) -``` - -![interval mode](img/data-driven-styling/interval.png) - -### Categorical - -At each stop, `MGLInterpolationModeCategorical` produces an output value equal to the function input. We’re going to use a different stops dictionary than we did for the previous two modes. - -There are three main types of events in the dataset: earthquakes, explosions, and quarry blasts. In this case, the color of the circle layer will be determined by the type of event, with a default value of green to catch any events that do not fall into any of those categories. - -``` swift -let categoricalStops = ["earthquake": MGLStyleValue(rawValue: .orange), - "explosion": MGLStyleValue(rawValue: .red), - "quarry blast": MGLStyleValue(rawValue: .yellow)] - -layer.circleColor = MGLStyleValue(interpolationMode: .categorical, - sourceStops: categoricalStops, - attributeName: "type", - options: [.defaultValue: MGLStyleValue(rawValue: .blue)]) - -``` - -![categorical mode](img/data-driven-styling/categorical1.png) ![categorical mode](img/data-driven-styling/categorical2.png) - -### Identity - -`MGLInterpolationModeIdentity` uses the attribute’s value as the style value. For example, you can set the `circleRadius` to the earthquake’s magnitude. Since the attribute value itself will be used as the style value, `sourceStops` should be set to `nil`. - -``` swift -layer.circleRadius = MGLStyleValue(interpolationMode: .identity, - sourceStops: nil, - attributeName: "mag", - options: [.defaultValue: MGLStyleValue(rawValue: 0)]) - -``` - -![identity mode](img/data-driven-styling/identity.png) - -##Resources - -* [USGS](https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php) -* [For Style Authors](for-style-authors.html) diff --git a/platform/macos/docs/guides/For Style Authors.md b/platform/macos/docs/guides/For Style Authors.md index f576921857..9ed69ac9ea 100644 --- a/platform/macos/docs/guides/For Style Authors.md +++ b/platform/macos/docs/guides/For Style Authors.md @@ -283,8 +283,7 @@ iOS. A _style function_ allows you to vary the value of a layout or paint attribute based on the zoom level, data provided by content sources, or both. For more -information about style functions that incorporate data from sources, see -“[Data-Driven Styling](data-driven-styling.html)”. +information about style functions, see “[Using Style Functions at Runtime](using-style-functions-at-runtime.html)”. Each kind of style function is represented by a distinct class, but you typically create style functions as you create any other style value, using diff --git a/platform/macos/docs/guides/Using Style Functions at Runtime.md b/platform/macos/docs/guides/Using Style Functions at Runtime.md new file mode 100644 index 0000000000..b3098dfe04 --- /dev/null +++ b/platform/macos/docs/guides/Using Style Functions at Runtime.md @@ -0,0 +1,155 @@ + + + +# Using Style Functions at Runtime + +[Runtime Styling](runtime-styling.html) enables you to modify every aspect of the map’s appearance dynamically as a user interacts with your application. Much of the runtime styling API allows you to specify _style functions_ instead of constant values. A style function allows you to specify in advance how a layout or paint attribute will vary as the zoom level changes or how the appearance of individual features vary based on metadata provided by a content source. + +Style functions spare you the inconvenience of manually calculating intermediate values between different zoom levels or creating a multitude of style layers to handle homogeneous features in the map content. For example, if your content source indicates the prices of hotels in an area, you can color-code the hotels by price, relying on a style function to smoothly interpolate among desired colors without having to specify the color for each exact price. + +_Data-driven styling_ specifically refers to the use of style functions to vary the map’s appearance based on data in a content source. + +You can also specify style functions in a style JSON file, to be applied automatically when the map loads. See the [Mapbox Style Specification](https://www.mapbox.com/mapbox-gl-js/style-spec/#types-function) for details. + +![available bikes](img/data-driven-styling/citibikes.png) ![subway lines](img/data-driven-styling/polylineExample.png) + +This guide uses earthquake data from the [U.S. Geological Survey](https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php) and data-driven styling to style a map based on attributes. For more information about how to work with GeoJSON data in our iOS SDK, please see our [working with GeoJSON data](working-with-geojson-data.html) guide. + +A style function is represented at runtime by the `MGLStyleFunction` class. There are three subclasses of `MGLStyleFunction`: + +* `MGLCameraStyleFunction` is a style value that changes with zoom level. For example, you can make the radius of a circle increase according to zoom level. +* `MGLSourceStyleFunction` is a style value that changes with the attributes of a feature. For example, you can adjust the radius of a circle based on the magnitude of an earthquake. +* `MGLCompositeStyleFunction` is a style value that changes with both zoom level and attribute values. For example, you can add a circle layer where each circle has a radius based on both zoom level and the magnitude of an earthquake. + +The documentation for each individual style layer property notes which style functions are enabled for that property. + +## Stops + +Stops are key-value pairs that that determine a style value. With a `MGLCameraSourceFunction` stop, you can use a dictionary with a zoom level for a key and a `MGLStyleValue` for the value. For example, you can use a stops dictionary with zoom levels 0, 10, and 20 as keys, and yellow, orange, and red as the values. A `MGLSourceStyleFunction` uses the relevant attribute value as the key. + +```swift +let stops = [0: MGLStyleValue(rawValue: .yellow), + 2.5: MGLStyleValue(rawValue: .orange), + 5: MGLStyleValue(rawValue: .red), + 7.5: MGLStyleValue(rawValue: .blue), + 10: MGLStyleValue(rawValue: .white)] +``` + +## Interpolation mode + +The effect a key has on the style value is determined by the interpolation mode. There are four interpolation modes that can be used with a source style function: exponential, interval, categorical, and identity. You can also use exponential and interval interpolation modes with a camera style function. + +### Linear + +`MGLInterpolationModeExponential` interpolates linearly or exponentially between style function stop values. By default, the `MGLStyleFunction` options parameter `MGLStyleFunctionOptionInterpolationBase` equals `1`, which represents linear interpolation and doesn’t need to be included in the options dictionary. + +The stops dictionary below, for example, shows colors that continuously shift from yellow to orange to red to blue to white based on the attribute value. + +``` swift +let url = URL(string: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson") +let symbolSource = MGLSource(identifier: "source") +let symbolLayer = MGLSymbolStyleLayer(identifier: "place-city-sm", source: symbolSource) + +let source = MGLShapeSource(identifier: "earthquakes", url: url, options: nil) +style.addSource(source) + +let stops = [0: MGLStyleValue(rawValue: .yellow), + 2.5: MGLStyleValue(rawValue: .orange), + 5: MGLStyleValue(rawValue: .red), + 7.5: MGLStyleValue(rawValue: .blue), + 10: MGLStyleValue(rawValue: .white)] + +let layer = MGLCircleStyleLayer(identifier: "circles", source: source) +layer.circleColor = MGLStyleValue(interpolationMode: .exponential, + sourceStops: stops, + attributeName: "mag", + options: [.defaultValue: MGLStyleValue(rawValue: .green)]) +layer.circleRadius = MGLStyleValue(rawValue: 10) +style.insertLayer(layer, below: symbolLayer) +``` + +![exponential mode](img/data-driven-styling/exponential.png) + +### Exponential + +By combining `MGLInterpolationModeExponential` with an `MGLStyleFunctionOptionInterpolationBase` greater than `0` (other than `1`), you can interpolate between values exponentially, create an accelerated ramp effect. + +Here’s a visualization from Mapbox Studio (see [Working with Mapbox Studio](working-with-mapbox-studio.html)) comparing interpolation base values of `1.5` and `0.5` based on zoom. + + + + +The example below increases a layer’s `circleRadius` exponentially based on a map’s zoom level. The `MGLStyleFunctionOptionInterpolationBase` is `1.5`. + +```swift +let stops = [12: MGLStyleValue(rawValue: 0.5), + 14: MGLStyleValue(rawValue: 2), + 18: MGLStyleValue(rawValue: 18)] + +layer.circleRadius = MGLStyleValue(interpolationMode: .exponential, + cameraStops: stops, + options: [.interpolationBase: 1.5]) +``` + +### Interval + +`MGLInterpolationModeInterval` creates a range using the keys from the stops dictionary. The range is from the given key to just less than the next key. The attribute values that fall into that range are then styled using the style value assigned to that key. + +When we use the stops dictionary given above with an interval interpolation mode, we create ranges where earthquakes with a magnitude of 0 to just less than 2.5 would be yellow, 2.5 to just less than 5 would be orange, and so on. + +``` swift +let stops = [0: MGLStyleValue(rawValue: .yellow), + 2.5: MGLStyleValue(rawValue: .orange), + 5: MGLStyleValue(rawValue: .red), + 7.5: MGLStyleValue(rawValue: .blue), + 10: MGLStyleValue(rawValue: .white)] + +layer.circleColor = MGLStyleValue(interpolationMode: .interval, + sourceStops: stops, + attributeName: "mag", + options: [.defaultValue: MGLStyleValue(rawValue: .green)]) +``` + +![interval mode](img/data-driven-styling/interval.png) + +### Categorical + +At each stop, `MGLInterpolationModeCategorical` produces an output value equal to the function input. We’re going to use a different stops dictionary than we did for the previous two modes. + +There are three main types of events in the dataset: earthquakes, explosions, and quarry blasts. In this case, the color of the circle layer will be determined by the type of event, with a default value of blue to catch any events that do not fall into any of those categories. + +``` swift +let categoricalStops = ["earthquake": MGLStyleValue(rawValue: .orange), + "explosion": MGLStyleValue(rawValue: .red), + "quarry blast": MGLStyleValue(rawValue: .yellow)] + +layer.circleColor = MGLStyleValue(interpolationMode: .categorical, + sourceStops: categoricalStops, + attributeName: "type", + options: [.defaultValue: MGLStyleValue(rawValue: .blue)]) + +``` + +![categorical mode](img/data-driven-styling/categorical1.png) ![categorical mode](img/data-driven-styling/categorical2.png) + +### Identity + +`MGLInterpolationModeIdentity` uses the attribute’s value as the style value. For example, you can set the `circleRadius` to the earthquake’s magnitude. Since the attribute value itself will be used as the style value, `sourceStops` should be set to `nil`. + +``` swift +layer.circleRadius = MGLStyleValue(interpolationMode: .identity, + sourceStops: nil, + attributeName: "mag", + options: [.defaultValue: MGLStyleValue(rawValue: 0)]) + +``` + +![identity mode](img/data-driven-styling/identity.png) + +##Resources + +* [USGS](https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php) +* [For Style Authors](for-style-authors.html) diff --git a/platform/macos/jazzy.yml b/platform/macos/jazzy.yml index fd6052c9f2..1f0e2fbc74 100644 --- a/platform/macos/jazzy.yml +++ b/platform/macos/jazzy.yml @@ -19,7 +19,7 @@ custom_categories: children: - Working with GeoJSON Data - For Style Authors - - Data-Driven Styling + - Using Style Functions at Runtime - Info.plist Keys - name: Maps children: -- cgit v1.2.1 From 5bfbe9603b8f306e8725ef54a642e3fa57fe9141 Mon Sep 17 00:00:00 2001 From: Jordan Kiley Date: Wed, 5 Apr 2017 13:09:07 -0700 Subject: [ios] replaced link to select a feature example (#8651) --- platform/ios/docs/guides/Adding Points to a Map.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/ios/docs/guides/Adding Points to a Map.md b/platform/ios/docs/guides/Adding Points to a Map.md index 17e8ad3592..ab1702a076 100644 --- a/platform/ios/docs/guides/Adding Points to a Map.md +++ b/platform/ios/docs/guides/Adding Points to a Map.md @@ -79,5 +79,5 @@ From there, you can create one or many `MGLSymbolStyleLayer` or `MGLCircleStyleL **Cons** -* Currently you must implement your own tap gesture recognizer together with `MGLMapView.visibleFeaturesAtPoint` to recognize taps and manually show callouts ([example](https://www.mapbox.com/ios-sdk/examples/select-feature)). +* Currently you must implement your own tap gesture recognizer together with `MGLMapView.visibleFeaturesAtPoint` to recognize taps and manually show callouts ([example](https://www.mapbox.com/ios-sdk/examples/select-layer/)). * Currently no SDK support for animations. If you need animations, consider using an NSTimer and updating the layer properties accordingly. -- cgit v1.2.1 From d39ea23b0975bf39f54bb181b14f3caed69a4767 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Tue, 4 Apr 2017 21:08:50 -0700 Subject: [ios, macos] Hardened std::map usage in MGLMapVIew Replaced std::map::operator[] usage with std::map::at(). Backed up an assertion on iOS with a guard when -annotationTagsInRect: returns the tag of a nonexistent annotation, for consistency with macOS. Removed an unnecessary and risky subscript into _annotationContextsByAnnotationTag in -positioningRectForCalloutForAnnotationWithTag: on iOS. --- platform/ios/src/MGLMapView.mm | 12 +++++++----- platform/macos/src/MGLMapView.mm | 4 ++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index ef4326556b..7458c39299 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -1452,7 +1452,7 @@ public: } else { - nextElement = _annotationContextsByAnnotationTag[_selectedAnnotationTag].accessibilityElement; + nextElement = _annotationContextsByAnnotationTag.at(_selectedAnnotationTag).accessibilityElement; } [self deselectAnnotation:self.selectedAnnotation animated:YES]; UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nextElement); @@ -3082,7 +3082,7 @@ public: return nil; } - MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag[tag]; + MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(tag); return annotationContext.annotation; } @@ -3552,8 +3552,12 @@ public: { id annotation = [self annotationWithTag:annotationTag]; NSAssert(annotation, @"Unknown annotation found nearby tap"); + if ( ! annotation) + { + return true; + } - MGLAnnotationContext annotationContext = _annotationContextsByAnnotationTag[annotationTag]; + MGLAnnotationContext annotationContext = _annotationContextsByAnnotationTag.at(annotationTag); CGRect annotationRect; MGLAnnotationView *annotationView = annotationContext.annotationView; @@ -3867,8 +3871,6 @@ public: /// and is appropriate for positioning a popover. - (CGRect)positioningRectForCalloutForAnnotationWithTag:(MGLAnnotationTag)annotationTag { - MGLAnnotationContext annotationContext = _annotationContextsByAnnotationTag[annotationTag]; - id annotation = [self annotationWithTag:annotationTag]; if ( ! annotation) { diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm index fc9834e016..a5a5c53df3 100644 --- a/platform/macos/src/MGLMapView.mm +++ b/platform/macos/src/MGLMapView.mm @@ -1820,7 +1820,7 @@ public: return nil; } - MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag[tag]; + MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(tag); return annotationContext.annotation; } @@ -2057,8 +2057,8 @@ public: // Filter out any annotation whose image is unselectable or for which // hit testing fails. auto end = std::remove_if(nearbyAnnotations.begin(), nearbyAnnotations.end(), [&](const MGLAnnotationTag annotationTag) { - NSAssert(_annotationContextsByAnnotationTag.count(annotationTag) != 0, @"Unknown annotation found nearby click"); id annotation = [self annotationWithTag:annotationTag]; + NSAssert(annotation, @"Unknown annotation found nearby click"); if (!annotation) { return true; } -- cgit v1.2.1 From 371919555f82c4f7aeaf8eb9addad15b6851cc5b Mon Sep 17 00:00:00 2001 From: Jason Wray Date: Wed, 5 Apr 2017 20:11:53 -0400 Subject: [ios] Update podspecs and changelog for v3.5.1 --- platform/ios/CHANGELOG.md | 6 +++--- platform/ios/Mapbox-iOS-SDK-symbols.podspec | 2 +- platform/ios/Mapbox-iOS-SDK.podspec | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index c79347e572..bd542eeeb3 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -2,14 +2,14 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONTRIBUTING.md](../../CONTRIBUTING.md) to get started. -## 3.5.1 +## 3.5.1 - April 5, 2017 * Fixed an issue that caused the return type of a map view delegate method to bridge incorrectly to applications written in Swift. ([#8541](https://github.com/mapbox/mapbox-gl-native/pull/8541)) * Fixed a crash that could occur when calling `-[MGLShapeSource featuresMatchingPredicate:]` or `-[MGLVectorSource featuresInSourceLayersWithIdentifiers:predicate:]`. ([#8553](https://github.com/mapbox/mapbox-gl-native/pull/8553)) * Fixed a crash that could occur after adding view-backed annotations to the map. ([#8513](https://github.com/mapbox/mapbox-gl-native/pull/8513)) -* Renamed the "Data-Driven Styling" guide to "Using Style Functions at Runtime" and clarified the meaning of data-driven styling in the guide's discussion of runtime style functions. ([#8627](https://github.com/mapbox/mapbox-gl-native/pull/8627)) +* Renamed the “Data-Driven Styling” guide to “Using Style Functions at Runtime” and clarified the meaning of data-driven styling in the guide’s discussion of runtime style functions. ([#8627](https://github.com/mapbox/mapbox-gl-native/pull/8627)) -## 3.5.0 +## 3.5.0 - March 21, 2017 ### Packaging diff --git a/platform/ios/Mapbox-iOS-SDK-symbols.podspec b/platform/ios/Mapbox-iOS-SDK-symbols.podspec index cc0fb07e27..64e3442808 100644 --- a/platform/ios/Mapbox-iOS-SDK-symbols.podspec +++ b/platform/ios/Mapbox-iOS-SDK-symbols.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |m| - version = '3.5.0' + version = '3.5.1' m.name = 'Mapbox-iOS-SDK-symbols' m.version = "#{version}-symbols" diff --git a/platform/ios/Mapbox-iOS-SDK.podspec b/platform/ios/Mapbox-iOS-SDK.podspec index 987e9fed15..5f35de84a7 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 = '3.5.0' + version = '3.5.1' m.name = 'Mapbox-iOS-SDK' m.version = version -- cgit v1.2.1 From 03d10bb67a72153e1aca0e7c67eaf022769d75b9 Mon Sep 17 00:00:00 2001 From: Jesse Bounds Date: Fri, 7 Apr 2017 15:23:39 -0700 Subject: [ios, macos] Guard against looking up annotation contexts MGLAnnotationTagNotFound (#8686) --- platform/ios/CHANGELOG.md | 4 +++ platform/ios/src/MGLMapView.mm | 74 ++++++++++++++++++++++------------------ platform/macos/CHANGELOG.md | 1 + platform/macos/src/MGLMapView.mm | 11 ++++-- 4 files changed, 54 insertions(+), 36 deletions(-) diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index bd542eeeb3..fcbb3a26a6 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -2,6 +2,10 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONTRIBUTING.md](../../CONTRIBUTING.md) to get started. +## 3.5.2 + +* Fixed an issue that caused a crash when the user location annotation was presenting a callout view and the map was moved. ([#8686](https://github.com/mapbox/mapbox-gl-native/pull/8686)) + ## 3.5.1 - April 5, 2017 * Fixed an issue that caused the return type of a map view delegate method to bridge incorrectly to applications written in Swift. ([#8541](https://github.com/mapbox/mapbox-gl-native/pull/8541)) diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 7458c39299..540f6de861 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -1452,7 +1452,9 @@ public: } else { - nextElement = _annotationContextsByAnnotationTag.at(_selectedAnnotationTag).accessibilityElement; + if (_selectedAnnotationTag != MGLAnnotationTagNotFound) { + nextElement = _annotationContextsByAnnotationTag.at(_selectedAnnotationTag).accessibilityElement; + } } [self deselectAnnotation:self.selectedAnnotation animated:YES]; UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nextElement); @@ -2002,19 +2004,21 @@ public: { const mbgl::Point point = MGLPointFromLocationCoordinate2D(annotation.coordinate); - MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(annotationTag); - if (annotationContext.annotationView) - { - // Redundantly move the associated annotation view outside the scope of the animation-less transaction block in -updateAnnotationViews. - annotationContext.annotationView.center = [self convertCoordinate:annotationContext.annotation.coordinate toPointToView:self]; - } + if (annotationTag != MGLAnnotationTagNotFound) { + MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(annotationTag); + if (annotationContext.annotationView) + { + // Redundantly move the associated annotation view outside the scope of the animation-less transaction block in -updateAnnotationViews. + annotationContext.annotationView.center = [self convertCoordinate:annotationContext.annotation.coordinate toPointToView:self]; + } - MGLAnnotationImage *annotationImage = [self imageOfAnnotationWithTag:annotationTag]; - NSString *symbolName = annotationImage.styleIconIdentifier; + MGLAnnotationImage *annotationImage = [self imageOfAnnotationWithTag:annotationTag]; + NSString *symbolName = annotationImage.styleIconIdentifier; - // Update the annotation’s backing geometry to match the annotation model object. Any associated annotation view is also moved by side effect. However, -updateAnnotationViews disables the view’s animation actions, because it can’t distinguish between moves due to the viewport changing and moves due to the annotation’s coordinate changing. - _mbglMap->updateAnnotation(annotationTag, mbgl::SymbolAnnotation { point, symbolName.UTF8String }); - [self updateCalloutView]; + // Update the annotation’s backing geometry to match the annotation model object. Any associated annotation view is also moved by side effect. However, -updateAnnotationViews disables the view’s animation actions, because it can’t distinguish between moves due to the viewport changing and moves due to the annotation’s coordinate changing. + _mbglMap->updateAnnotation(annotationTag, mbgl::SymbolAnnotation { point, symbolName.UTF8String }); + [self updateCalloutView]; + } } } else if ([keyPath isEqualToString:@"coordinates"] && [object isKindOfClass:[MGLMultiPoint class]]) @@ -3055,17 +3059,18 @@ public: for (auto const& annotationTag: annotationTags) { - if (!_annotationContextsByAnnotationTag.count(annotationTag)) + if (!_annotationContextsByAnnotationTag.count(annotationTag) || + annotationTag == MGLAnnotationTagNotFound) { continue; } + MGLAnnotationContext annotationContext = _annotationContextsByAnnotationTag.at(annotationTag); NSAssert(annotationContext.annotation, @"Missing annotation for tag %u.", annotationTag); if (annotationContext.annotation) { [annotations addObject:annotationContext.annotation]; } - } return [annotations copy]; @@ -3077,8 +3082,8 @@ public: /// Returns the annotation assigned the given tag. Cheap. - (id )annotationWithTag:(MGLAnnotationTag)tag { - if ( ! _annotationContextsByAnnotationTag.count(tag)) - { + if ( ! _annotationContextsByAnnotationTag.count(tag) || + tag == MGLAnnotationTagNotFound) { return nil; } @@ -3680,10 +3685,12 @@ public: { return self.userLocation; } - if ( ! _annotationContextsByAnnotationTag.count(_selectedAnnotationTag)) - { + + if ( ! _annotationContextsByAnnotationTag.count(_selectedAnnotationTag) || + _selectedAnnotationTag == MGLAnnotationTagNotFound) { return nil; } + MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(_selectedAnnotationTag); return annotationContext.annotation; } @@ -3749,19 +3756,16 @@ public: MGLAnnotationView *annotationView = nil; if (annotation != self.userLocation) - { - MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(annotationTag); - - annotationView = annotationContext.annotationView; - - if (annotationView && annotationView.enabled) - { - // Annotations represented by views use the view frame as the positioning rect. - positioningRect = annotationView.frame; - - [annotationView.superview bringSubviewToFront:annotationView]; - - [annotationView setSelected:YES animated:animated]; + if (annotationTag != MGLAnnotationTagNotFound) { + MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(annotationTag); + annotationView = annotationContext.annotationView; + if (annotationView && annotationView.enabled) { + { + // Annotations represented by views use the view frame as the positioning rect. + positioningRect = annotationView.frame; + [annotationView.superview bringSubviewToFront:annotationView]; + [annotationView setSelected:YES animated:animated]; + } } } @@ -5039,8 +5043,12 @@ public: if (isAnchoredToAnnotation) { MGLAnnotationTag tag = [self annotationTagForAnnotation:annotation]; - MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(tag); - MGLAnnotationView *annotationView = annotationContext.annotationView; + MGLAnnotationView *annotationView = nil; + + if (tag != MGLAnnotationTagNotFound) { + MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(tag); + annotationView = annotationContext.annotationView; + } CGRect rect = [self positioningRectForCalloutForAnnotationWithTag:tag]; diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md index 326a70ebb2..1d24f2a6e8 100644 --- a/platform/macos/CHANGELOG.md +++ b/platform/macos/CHANGELOG.md @@ -3,6 +3,7 @@ ## 0.4.1 * Fixed an issue causing code signing failures and bloating the framework. ([#8640](https://github.com/mapbox/mapbox-gl-native/pull/8640)) +* Fixed an issue that could cause a crash if annotations unknown to the map view were interacted with. ([#8686](https://github.com/mapbox/mapbox-gl-native/pull/8686)) * Renamed the "Data-Driven Styling" guide to "Using Style Functions at Runtime" and clarified the meaning of data-driven styling in the guide's discussion of runtime style functions. ([#8627](https://github.com/mapbox/mapbox-gl-native/pull/8627)) ## 0.4.0 diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm index a5a5c53df3..a873d9ef82 100644 --- a/platform/macos/src/MGLMapView.mm +++ b/platform/macos/src/MGLMapView.mm @@ -1796,10 +1796,12 @@ public: for (auto const& annotationTag: annotationTags) { - if (!_annotationContextsByAnnotationTag.count(annotationTag)) + if (!_annotationContextsByAnnotationTag.count(annotationTag) || + annotationTag == MGLAnnotationTagNotFound) { continue; } + MGLAnnotationContext annotationContext = _annotationContextsByAnnotationTag.at(annotationTag); NSAssert(annotationContext.annotation, @"Missing annotation for tag %u.", annotationTag); if (annotationContext.annotation) @@ -1816,7 +1818,8 @@ public: /// Returns the annotation assigned the given tag. Cheap. - (id )annotationWithTag:(MGLAnnotationTag)tag { - if (!_annotationContextsByAnnotationTag.count(tag)) { + if ( ! _annotationContextsByAnnotationTag.count(tag) || + tag == MGLAnnotationTagNotFound) { return nil; } @@ -2147,9 +2150,11 @@ public: } - (id )selectedAnnotation { - if (!_annotationContextsByAnnotationTag.count(_selectedAnnotationTag)) { + if ( ! _annotationContextsByAnnotationTag.count(_selectedAnnotationTag) || + _selectedAnnotationTag == MGLAnnotationTagNotFound) { return nil; } + MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(_selectedAnnotationTag); return annotationContext.annotation; } -- cgit v1.2.1 From acfa49dd9f71b9c630be455702a288a501ac8a64 Mon Sep 17 00:00:00 2001 From: Jason Wray Date: Fri, 7 Apr 2017 19:23:04 -0400 Subject: [ios] Update podspecs and changelog for v3.5.2 --- platform/ios/CHANGELOG.md | 3 ++- platform/ios/Mapbox-iOS-SDK-symbols.podspec | 2 +- platform/ios/Mapbox-iOS-SDK.podspec | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index fcbb3a26a6..deb108a1d8 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -2,9 +2,10 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONTRIBUTING.md](../../CONTRIBUTING.md) to get started. -## 3.5.2 +## 3.5.2 - April 7, 2017 * Fixed an issue that caused a crash when the user location annotation was presenting a callout view and the map was moved. ([#8686](https://github.com/mapbox/mapbox-gl-native/pull/8686)) +* This release was built with Xcode 8.3.1, which fixed [a significant bitcode issue](http://www.openradar.me/31302382) introduced in Xcode 8.3 that caused Mapbox iOS SDK 3.5.1 to be 2× larger than 3.5.0. ## 3.5.1 - April 5, 2017 diff --git a/platform/ios/Mapbox-iOS-SDK-symbols.podspec b/platform/ios/Mapbox-iOS-SDK-symbols.podspec index 64e3442808..190087afaf 100644 --- a/platform/ios/Mapbox-iOS-SDK-symbols.podspec +++ b/platform/ios/Mapbox-iOS-SDK-symbols.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |m| - version = '3.5.1' + version = '3.5.2' m.name = 'Mapbox-iOS-SDK-symbols' m.version = "#{version}-symbols" diff --git a/platform/ios/Mapbox-iOS-SDK.podspec b/platform/ios/Mapbox-iOS-SDK.podspec index 5f35de84a7..ae9e470e87 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 = '3.5.1' + version = '3.5.2' m.name = 'Mapbox-iOS-SDK' m.version = version -- cgit v1.2.1 From b16d6bfcf6609e2061080d007142c5ee303bc7c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Fri, 7 Apr 2017 07:32:49 -0700 Subject: macos-v0.4.1 --- platform/macos/CHANGELOG.md | 6 ++++-- platform/macos/Mapbox-macOS-SDK-symbols.podspec | 2 +- platform/macos/Mapbox-macOS-SDK.podspec | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md index 1d24f2a6e8..85047bf02e 100644 --- a/platform/macos/CHANGELOG.md +++ b/platform/macos/CHANGELOG.md @@ -2,11 +2,13 @@ ## 0.4.1 +This version of the Mapbox macOS SDK corresponds to version 3.5.2 of the Mapbox iOS SDK. + * Fixed an issue causing code signing failures and bloating the framework. ([#8640](https://github.com/mapbox/mapbox-gl-native/pull/8640)) * Fixed an issue that could cause a crash if annotations unknown to the map view were interacted with. ([#8686](https://github.com/mapbox/mapbox-gl-native/pull/8686)) -* Renamed the "Data-Driven Styling" guide to "Using Style Functions at Runtime" and clarified the meaning of data-driven styling in the guide's discussion of runtime style functions. ([#8627](https://github.com/mapbox/mapbox-gl-native/pull/8627)) +* Renamed the “Data-Driven Styling” guide to “Using Style Functions at Runtime” and clarified the meaning of data-driven styling in the guide’s discussion of runtime style functions. ([#8627](https://github.com/mapbox/mapbox-gl-native/pull/8627)) -## 0.4.0 +## 0.4.0 - April 2, 2017 This version of the Mapbox macOS SDK corresponds to version 3.5.1 of the Mapbox iOS SDK. diff --git a/platform/macos/Mapbox-macOS-SDK-symbols.podspec b/platform/macos/Mapbox-macOS-SDK-symbols.podspec index 4bac6dff2d..c621a7312b 100644 --- a/platform/macos/Mapbox-macOS-SDK-symbols.podspec +++ b/platform/macos/Mapbox-macOS-SDK-symbols.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |m| - version = '0.4.0' + version = '0.4.1' m.name = 'Mapbox-macOS-SDK-symbols' m.version = "#{version}-symbols" diff --git a/platform/macos/Mapbox-macOS-SDK.podspec b/platform/macos/Mapbox-macOS-SDK.podspec index a7ecb7423e..2417fb11ec 100644 --- a/platform/macos/Mapbox-macOS-SDK.podspec +++ b/platform/macos/Mapbox-macOS-SDK.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |m| - version = '0.4.0' + version = '0.4.1' m.name = 'Mapbox-macOS-SDK' m.version = version -- cgit v1.2.1 From 4d0605a004844726fc5f5e015c6d4320a880bfa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Sat, 8 Apr 2017 15:45:37 -0700 Subject: [qt] Renamed qt5 formula to qt Cherry-picked from 3172a9744f2e296d9e8a68558e11c884c9c30aca. --- platform/qt/bitrise-qt5.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/platform/qt/bitrise-qt5.yml b/platform/qt/bitrise-qt5.yml index 036ec044c5..d9b7d4bc69 100644 --- a/platform/qt/bitrise-qt5.yml +++ b/platform/qt/bitrise-qt5.yml @@ -31,12 +31,12 @@ workflows: set -eu -o pipefail sudo chown -R $USER /usr/local brew install cmake - brew install qt5 - brew link qt5 --force - brew linkapps qt5 - export HOMEBREW_QT5_VERSION=$(brew list --versions qt5 | rev | cut -d' ' -f1 | rev) - ln -s /usr/local/Cellar/qt5/$HOMEBREW_QT5_VERSION/mkspecs /usr/local/mkspecs - ln -s /usr/local/Cellar/qt5/$HOMEBREW_QT5_VERSION/plugins /usr/local/plugins + brew install qt + brew link qt --force + brew linkapps qt + export HOMEBREW_QT5_VERSION=$(brew list --versions qt | rev | cut -d' ' -f1 | rev) + ln -s /usr/local/Cellar/qt/$HOMEBREW_QT5_VERSION/mkspecs /usr/local/mkspecs + ln -s /usr/local/Cellar/qt/$HOMEBREW_QT5_VERSION/plugins /usr/local/plugins export BUILDTYPE=Debug make qt-app make run-qt-test -- cgit v1.2.1