diff options
author | John Firebaugh <john.firebaugh@gmail.com> | 2017-03-08 17:31:03 -0800 |
---|---|---|
committer | John Firebaugh <john.firebaugh@gmail.com> | 2017-03-08 17:31:03 -0800 |
commit | 65f74224ab4d2e037fda30662470af8a061ffbaf (patch) | |
tree | 8341e6802dd3308abbc08778f086da1fe9a6565d | |
parent | e115d55ef6b960153ba40aba297b00608f3f3baf (diff) | |
parent | e044e0aab9f63883e935d94e0cf9aceb37f4e6eb (diff) | |
download | qtlocation-mapboxgl-65f74224ab4d2e037fda30662470af8a061ffbaf.tar.gz |
Merge master into release-ios-v3.5.0-android-v5.0.0
132 files changed, 1772 insertions, 3116 deletions
diff --git a/.travis.yml b/.travis.yml index 3b13902776..391520319f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -189,7 +189,6 @@ matrix: - mapbox_export_mesa_library_path script: - make qt-app - - make qt-qml-app - make qt-test - make qt-docs - scripts/valgrind.sh build/qt-linux-x86_64/Release/mbgl-test --gtest_filter=-*.Load --gtest_filter=-Memory.Vector diff --git a/CMakeLists.txt b/CMakeLists.txt index 90f5bf7e1c..123158e2eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,6 +66,7 @@ if(APPLE) # -Wno-error=unused-command-line-argument is required due to https://llvm.org/bugs/show_bug.cgi?id=7798 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=unused-command-line-argument") endif() +set(CMAKE_CXX_FLAGS_RELEASE "-Os -DNDEBUG") if(CMAKE_COMPILER_IS_GNUCXX) # https://svn.boost.org/trac/boost/ticket/9240 @@ -405,7 +405,6 @@ $(MACOS_QT_PROJ_PATH): $(BUILD_DEPS) @# Create Xcode schemes so that we can use xcodebuild from the command line. CMake doesn't @# create these automatically. XCODEPROJ=$(MACOS_QT_PROJ_PATH) SCHEME_NAME=mbgl-qt SCHEME_TYPE=executable platform/macos/scripts/create_scheme.sh - XCODEPROJ=$(MACOS_QT_PROJ_PATH) SCHEME_NAME=mbgl-qt-qml SCHEME_TYPE=executable platform/macos/scripts/create_scheme.sh XCODEPROJ=$(MACOS_QT_PROJ_PATH) SCHEME_NAME=mbgl-test SCHEME_TYPE=executable platform/macos/scripts/create_scheme.sh XCODEPROJ=$(MACOS_QT_PROJ_PATH) SCHEME_NAME=mbgl-benchmark SCHEME_TYPE=executable platform/macos/scripts/create_scheme.sh XCODEPROJ=$(MACOS_QT_PROJ_PATH) SCHEME_NAME=mbgl-core SCHEME_TYPE=library BUILDABLE_NAME=libmbgl-core.a BLUEPRINT_NAME=mbgl-core platform/macos/scripts/create_scheme.sh @@ -429,14 +428,6 @@ qt-app: $(QT_BUILD) run-qt-app: qt-app $(QT_OUTPUT_PATH)/mbgl-qt -.PHONY: qt-qml-app -qt-qml-app: $(QT_BUILD) - $(NINJA) $(NINJA_ARGS) -j$(JOBS) -C $(QT_OUTPUT_PATH) mbgl-qt-qml - -.PHONY: run-qt-qml-app -run-qt-qml-app: qt-qml-app - $(QT_OUTPUT_PATH)/mbgl-qt-qml - .PHONY: qt-test qt-test: $(QT_BUILD) $(NINJA) $(NINJA_ARGS) -j$(JOBS) -C $(QT_OUTPUT_PATH) mbgl-test diff --git a/benchmark/api/query.benchmark.cpp b/benchmark/api/query.benchmark.cpp index f7474dd2ee..53a524b450 100644 --- a/benchmark/api/query.benchmark.cpp +++ b/benchmark/api/query.benchmark.cpp @@ -55,7 +55,7 @@ static void API_queryRenderedFeaturesLayerFromLowDensity(::benchmark::State& sta QueryBenchmark bench; while (state.KeepRunning()) { - bench.map.queryRenderedFeatures(bench.box, {{ "testlayer" }}); + bench.map.queryRenderedFeatures(bench.box, {{{ "testlayer" }}, {}}); } } @@ -63,7 +63,7 @@ static void API_queryRenderedFeaturesLayerFromHighDensity(::benchmark::State& st QueryBenchmark bench; while (state.KeepRunning()) { - bench.map.queryRenderedFeatures(bench.box, {{ "road-street" }}); + bench.map.queryRenderedFeatures(bench.box, {{{"road-street" }}, {}}); } } diff --git a/cmake/core-files.cmake b/cmake/core-files.cmake index 5173b92c05..b5baff264c 100644 --- a/cmake/core-files.cmake +++ b/cmake/core-files.cmake @@ -108,6 +108,7 @@ set(MBGL_CORE_FILES include/mbgl/map/camera.hpp include/mbgl/map/map.hpp include/mbgl/map/mode.hpp + include/mbgl/map/query.hpp include/mbgl/map/view.hpp src/mbgl/map/backend.cpp src/mbgl/map/backend_scope.cpp @@ -204,6 +205,8 @@ set(MBGL_CORE_FILES src/mbgl/shaders/line_pattern.hpp src/mbgl/shaders/line_sdf.cpp src/mbgl/shaders/line_sdf.hpp + src/mbgl/shaders/preludes.cpp + src/mbgl/shaders/preludes.hpp src/mbgl/shaders/raster.cpp src/mbgl/shaders/raster.hpp src/mbgl/shaders/symbol_icon.cpp @@ -271,7 +274,6 @@ set(MBGL_CORE_FILES src/mbgl/style/property_evaluator.hpp src/mbgl/style/property_parsing.cpp src/mbgl/style/property_parsing.hpp - src/mbgl/style/query_parameters.hpp src/mbgl/style/rapidjson_conversion.hpp src/mbgl/style/source.cpp src/mbgl/style/source_impl.cpp diff --git a/include/mbgl/gl/gl.hpp b/include/mbgl/gl/gl.hpp index 7521b4c80d..3a577b289b 100644 --- a/include/mbgl/gl/gl.hpp +++ b/include/mbgl/gl/gl.hpp @@ -22,9 +22,9 @@ #define GL_GLEXT_PROTOTYPES #include <GLES2/gl2.h> #include <GLES2/gl2ext.h> -#elif __QT__ +#elif __QT_ && QT_VERSION >= 0x050000 #define GL_GLEXT_PROTOTYPES - #include <QtOpenGL> + #include <QtGui/qopengl.h> #else #define GL_GLEXT_PROTOTYPES #include <GL/gl.h> diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index 95a82ebd74..7e4eeb8d5b 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -10,6 +10,7 @@ #include <mbgl/annotation/annotation.hpp> #include <mbgl/style/transition_options.hpp> #include <mbgl/map/camera.hpp> +#include <mbgl/map/query.hpp> #include <cstdint> #include <string> @@ -24,8 +25,6 @@ class View; class FileSource; class Scheduler; class SpriteImage; -struct CameraOptions; -struct AnimationOptions; namespace style { class Source; @@ -183,8 +182,9 @@ public: double getDefaultPitch() const; // Feature queries - std::vector<Feature> queryRenderedFeatures(const ScreenCoordinate&, const optional<std::vector<std::string>>& layerIDs = {}); - std::vector<Feature> queryRenderedFeatures(const ScreenBox&, const optional<std::vector<std::string>>& layerIDs = {}); + std::vector<Feature> queryRenderedFeatures(const ScreenCoordinate&, const QueryOptions& options = {}); + std::vector<Feature> queryRenderedFeatures(const ScreenBox&, const QueryOptions& options = {}); + AnnotationIDs queryPointAnnotations(const ScreenBox&); // Memory diff --git a/include/mbgl/map/query.hpp b/include/mbgl/map/query.hpp new file mode 100644 index 0000000000..e864dbaa67 --- /dev/null +++ b/include/mbgl/map/query.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include <mbgl/util/optional.hpp> +#include <mbgl/style/filter.hpp> + +namespace mbgl { + +/** + * Options for Map queries. + */ +class QueryOptions { +public: + /** layerIDs to include in the query */ + optional<std::vector<std::string>> layerIDs; + + optional<style::Filter> filter; +}; + +} diff --git a/include/mbgl/style/conversion/make_property_setters.hpp b/include/mbgl/style/conversion/make_property_setters.hpp index 32fa810f0b..623cc09098 100644 --- a/include/mbgl/style/conversion/make_property_setters.hpp +++ b/include/mbgl/style/conversion/make_property_setters.hpp @@ -25,45 +25,45 @@ auto makeLayoutPropertySetters() { result["visibility"] = &setVisibility<V>; - result["line-cap"] = makePropertySetter<V>(&LineLayer::setLineCap); - result["line-join"] = makePropertySetter<V>(&LineLayer::setLineJoin); - result["line-miter-limit"] = makePropertySetter<V>(&LineLayer::setLineMiterLimit); - result["line-round-limit"] = makePropertySetter<V>(&LineLayer::setLineRoundLimit); - - result["symbol-placement"] = makePropertySetter<V>(&SymbolLayer::setSymbolPlacement); - result["symbol-spacing"] = makePropertySetter<V>(&SymbolLayer::setSymbolSpacing); - result["symbol-avoid-edges"] = makePropertySetter<V>(&SymbolLayer::setSymbolAvoidEdges); - result["icon-allow-overlap"] = makePropertySetter<V>(&SymbolLayer::setIconAllowOverlap); - result["icon-ignore-placement"] = makePropertySetter<V>(&SymbolLayer::setIconIgnorePlacement); - result["icon-optional"] = makePropertySetter<V>(&SymbolLayer::setIconOptional); - result["icon-rotation-alignment"] = makePropertySetter<V>(&SymbolLayer::setIconRotationAlignment); - result["icon-size"] = makePropertySetter<V>(&SymbolLayer::setIconSize); - result["icon-text-fit"] = makePropertySetter<V>(&SymbolLayer::setIconTextFit); - result["icon-text-fit-padding"] = makePropertySetter<V>(&SymbolLayer::setIconTextFitPadding); - result["icon-image"] = makePropertySetter<V>(&SymbolLayer::setIconImage); - result["icon-rotate"] = makePropertySetter<V>(&SymbolLayer::setIconRotate); - result["icon-padding"] = makePropertySetter<V>(&SymbolLayer::setIconPadding); - result["icon-keep-upright"] = makePropertySetter<V>(&SymbolLayer::setIconKeepUpright); - result["icon-offset"] = makePropertySetter<V>(&SymbolLayer::setIconOffset); - result["text-pitch-alignment"] = makePropertySetter<V>(&SymbolLayer::setTextPitchAlignment); - result["text-rotation-alignment"] = makePropertySetter<V>(&SymbolLayer::setTextRotationAlignment); - result["text-field"] = makePropertySetter<V>(&SymbolLayer::setTextField); - result["text-font"] = makePropertySetter<V>(&SymbolLayer::setTextFont); - result["text-size"] = makePropertySetter<V>(&SymbolLayer::setTextSize); - result["text-max-width"] = makePropertySetter<V>(&SymbolLayer::setTextMaxWidth); - result["text-line-height"] = makePropertySetter<V>(&SymbolLayer::setTextLineHeight); - result["text-letter-spacing"] = makePropertySetter<V>(&SymbolLayer::setTextLetterSpacing); - result["text-justify"] = makePropertySetter<V>(&SymbolLayer::setTextJustify); - result["text-anchor"] = makePropertySetter<V>(&SymbolLayer::setTextAnchor); - result["text-max-angle"] = makePropertySetter<V>(&SymbolLayer::setTextMaxAngle); - result["text-rotate"] = makePropertySetter<V>(&SymbolLayer::setTextRotate); - result["text-padding"] = makePropertySetter<V>(&SymbolLayer::setTextPadding); - result["text-keep-upright"] = makePropertySetter<V>(&SymbolLayer::setTextKeepUpright); - result["text-transform"] = makePropertySetter<V>(&SymbolLayer::setTextTransform); - result["text-offset"] = makePropertySetter<V>(&SymbolLayer::setTextOffset); - result["text-allow-overlap"] = makePropertySetter<V>(&SymbolLayer::setTextAllowOverlap); - result["text-ignore-placement"] = makePropertySetter<V>(&SymbolLayer::setTextIgnorePlacement); - result["text-optional"] = makePropertySetter<V>(&SymbolLayer::setTextOptional); + result["line-cap"] = &setLayoutProperty<V, LineLayer, PropertyValue<LineCapType>, &LineLayer::setLineCap>; + result["line-join"] = &setLayoutProperty<V, LineLayer, PropertyValue<LineJoinType>, &LineLayer::setLineJoin>; + result["line-miter-limit"] = &setLayoutProperty<V, LineLayer, PropertyValue<float>, &LineLayer::setLineMiterLimit>; + result["line-round-limit"] = &setLayoutProperty<V, LineLayer, PropertyValue<float>, &LineLayer::setLineRoundLimit>; + + result["symbol-placement"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<SymbolPlacementType>, &SymbolLayer::setSymbolPlacement>; + result["symbol-spacing"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<float>, &SymbolLayer::setSymbolSpacing>; + result["symbol-avoid-edges"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setSymbolAvoidEdges>; + result["icon-allow-overlap"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setIconAllowOverlap>; + result["icon-ignore-placement"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setIconIgnorePlacement>; + result["icon-optional"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setIconOptional>; + result["icon-rotation-alignment"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<AlignmentType>, &SymbolLayer::setIconRotationAlignment>; + result["icon-size"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<float>, &SymbolLayer::setIconSize>; + result["icon-text-fit"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<IconTextFitType>, &SymbolLayer::setIconTextFit>; + result["icon-text-fit-padding"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<std::array<float, 4>>, &SymbolLayer::setIconTextFitPadding>; + result["icon-image"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<std::string>, &SymbolLayer::setIconImage>; + result["icon-rotate"] = &setLayoutProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconRotate>; + result["icon-padding"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<float>, &SymbolLayer::setIconPadding>; + result["icon-keep-upright"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setIconKeepUpright>; + result["icon-offset"] = &setLayoutProperty<V, SymbolLayer, DataDrivenPropertyValue<std::array<float, 2>>, &SymbolLayer::setIconOffset>; + result["text-pitch-alignment"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<AlignmentType>, &SymbolLayer::setTextPitchAlignment>; + result["text-rotation-alignment"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<AlignmentType>, &SymbolLayer::setTextRotationAlignment>; + result["text-field"] = &setLayoutProperty<V, SymbolLayer, DataDrivenPropertyValue<std::string>, &SymbolLayer::setTextField>; + result["text-font"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<std::vector<std::string>>, &SymbolLayer::setTextFont>; + result["text-size"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextSize>; + result["text-max-width"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextMaxWidth>; + result["text-line-height"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextLineHeight>; + result["text-letter-spacing"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextLetterSpacing>; + result["text-justify"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<TextJustifyType>, &SymbolLayer::setTextJustify>; + result["text-anchor"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<TextAnchorType>, &SymbolLayer::setTextAnchor>; + result["text-max-angle"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextMaxAngle>; + result["text-rotate"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextRotate>; + result["text-padding"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextPadding>; + result["text-keep-upright"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setTextKeepUpright>; + result["text-transform"] = &setLayoutProperty<V, SymbolLayer, DataDrivenPropertyValue<TextTransformType>, &SymbolLayer::setTextTransform>; + result["text-offset"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<std::array<float, 2>>, &SymbolLayer::setTextOffset>; + result["text-allow-overlap"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setTextAllowOverlap>; + result["text-ignore-placement"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setTextIgnorePlacement>; + result["text-optional"] = &setLayoutProperty<V, SymbolLayer, PropertyValue<bool>, &SymbolLayer::setTextOptional>; @@ -76,128 +76,128 @@ template <class V> auto makePaintPropertySetters() { std::unordered_map<std::string, PaintPropertySetter<V>> result; - result["fill-antialias"] = makePropertySetter<V>(&FillLayer::setFillAntialias); - result["fill-antialias-transition"] = makeTransitionSetter<V>(&FillLayer::setFillAntialiasTransition); - result["fill-opacity"] = makePropertySetter<V>(&FillLayer::setFillOpacity); - result["fill-opacity-transition"] = makeTransitionSetter<V>(&FillLayer::setFillOpacityTransition); - result["fill-color"] = makePropertySetter<V>(&FillLayer::setFillColor); - result["fill-color-transition"] = makeTransitionSetter<V>(&FillLayer::setFillColorTransition); - result["fill-outline-color"] = makePropertySetter<V>(&FillLayer::setFillOutlineColor); - result["fill-outline-color-transition"] = makeTransitionSetter<V>(&FillLayer::setFillOutlineColorTransition); - result["fill-translate"] = makePropertySetter<V>(&FillLayer::setFillTranslate); - result["fill-translate-transition"] = makeTransitionSetter<V>(&FillLayer::setFillTranslateTransition); - result["fill-translate-anchor"] = makePropertySetter<V>(&FillLayer::setFillTranslateAnchor); - result["fill-translate-anchor-transition"] = makeTransitionSetter<V>(&FillLayer::setFillTranslateAnchorTransition); - result["fill-pattern"] = makePropertySetter<V>(&FillLayer::setFillPattern); - result["fill-pattern-transition"] = makeTransitionSetter<V>(&FillLayer::setFillPatternTransition); - - result["line-opacity"] = makePropertySetter<V>(&LineLayer::setLineOpacity); - result["line-opacity-transition"] = makeTransitionSetter<V>(&LineLayer::setLineOpacityTransition); - result["line-color"] = makePropertySetter<V>(&LineLayer::setLineColor); - result["line-color-transition"] = makeTransitionSetter<V>(&LineLayer::setLineColorTransition); - result["line-translate"] = makePropertySetter<V>(&LineLayer::setLineTranslate); - result["line-translate-transition"] = makeTransitionSetter<V>(&LineLayer::setLineTranslateTransition); - result["line-translate-anchor"] = makePropertySetter<V>(&LineLayer::setLineTranslateAnchor); - result["line-translate-anchor-transition"] = makeTransitionSetter<V>(&LineLayer::setLineTranslateAnchorTransition); - result["line-width"] = makePropertySetter<V>(&LineLayer::setLineWidth); - result["line-width-transition"] = makeTransitionSetter<V>(&LineLayer::setLineWidthTransition); - result["line-gap-width"] = makePropertySetter<V>(&LineLayer::setLineGapWidth); - result["line-gap-width-transition"] = makeTransitionSetter<V>(&LineLayer::setLineGapWidthTransition); - result["line-offset"] = makePropertySetter<V>(&LineLayer::setLineOffset); - result["line-offset-transition"] = makeTransitionSetter<V>(&LineLayer::setLineOffsetTransition); - result["line-blur"] = makePropertySetter<V>(&LineLayer::setLineBlur); - result["line-blur-transition"] = makeTransitionSetter<V>(&LineLayer::setLineBlurTransition); - result["line-dasharray"] = makePropertySetter<V>(&LineLayer::setLineDasharray); - result["line-dasharray-transition"] = makeTransitionSetter<V>(&LineLayer::setLineDasharrayTransition); - result["line-pattern"] = makePropertySetter<V>(&LineLayer::setLinePattern); - result["line-pattern-transition"] = makeTransitionSetter<V>(&LineLayer::setLinePatternTransition); - - result["icon-opacity"] = makePropertySetter<V>(&SymbolLayer::setIconOpacity); - result["icon-opacity-transition"] = makeTransitionSetter<V>(&SymbolLayer::setIconOpacityTransition); - result["icon-color"] = makePropertySetter<V>(&SymbolLayer::setIconColor); - result["icon-color-transition"] = makeTransitionSetter<V>(&SymbolLayer::setIconColorTransition); - result["icon-halo-color"] = makePropertySetter<V>(&SymbolLayer::setIconHaloColor); - result["icon-halo-color-transition"] = makeTransitionSetter<V>(&SymbolLayer::setIconHaloColorTransition); - result["icon-halo-width"] = makePropertySetter<V>(&SymbolLayer::setIconHaloWidth); - result["icon-halo-width-transition"] = makeTransitionSetter<V>(&SymbolLayer::setIconHaloWidthTransition); - result["icon-halo-blur"] = makePropertySetter<V>(&SymbolLayer::setIconHaloBlur); - result["icon-halo-blur-transition"] = makeTransitionSetter<V>(&SymbolLayer::setIconHaloBlurTransition); - result["icon-translate"] = makePropertySetter<V>(&SymbolLayer::setIconTranslate); - result["icon-translate-transition"] = makeTransitionSetter<V>(&SymbolLayer::setIconTranslateTransition); - result["icon-translate-anchor"] = makePropertySetter<V>(&SymbolLayer::setIconTranslateAnchor); - result["icon-translate-anchor-transition"] = makeTransitionSetter<V>(&SymbolLayer::setIconTranslateAnchorTransition); - result["text-opacity"] = makePropertySetter<V>(&SymbolLayer::setTextOpacity); - result["text-opacity-transition"] = makeTransitionSetter<V>(&SymbolLayer::setTextOpacityTransition); - result["text-color"] = makePropertySetter<V>(&SymbolLayer::setTextColor); - result["text-color-transition"] = makeTransitionSetter<V>(&SymbolLayer::setTextColorTransition); - result["text-halo-color"] = makePropertySetter<V>(&SymbolLayer::setTextHaloColor); - result["text-halo-color-transition"] = makeTransitionSetter<V>(&SymbolLayer::setTextHaloColorTransition); - result["text-halo-width"] = makePropertySetter<V>(&SymbolLayer::setTextHaloWidth); - result["text-halo-width-transition"] = makeTransitionSetter<V>(&SymbolLayer::setTextHaloWidthTransition); - result["text-halo-blur"] = makePropertySetter<V>(&SymbolLayer::setTextHaloBlur); - result["text-halo-blur-transition"] = makeTransitionSetter<V>(&SymbolLayer::setTextHaloBlurTransition); - result["text-translate"] = makePropertySetter<V>(&SymbolLayer::setTextTranslate); - result["text-translate-transition"] = makeTransitionSetter<V>(&SymbolLayer::setTextTranslateTransition); - result["text-translate-anchor"] = makePropertySetter<V>(&SymbolLayer::setTextTranslateAnchor); - result["text-translate-anchor-transition"] = makeTransitionSetter<V>(&SymbolLayer::setTextTranslateAnchorTransition); - - result["circle-radius"] = makePropertySetter<V>(&CircleLayer::setCircleRadius); - result["circle-radius-transition"] = makeTransitionSetter<V>(&CircleLayer::setCircleRadiusTransition); - result["circle-color"] = makePropertySetter<V>(&CircleLayer::setCircleColor); - result["circle-color-transition"] = makeTransitionSetter<V>(&CircleLayer::setCircleColorTransition); - result["circle-blur"] = makePropertySetter<V>(&CircleLayer::setCircleBlur); - result["circle-blur-transition"] = makeTransitionSetter<V>(&CircleLayer::setCircleBlurTransition); - result["circle-opacity"] = makePropertySetter<V>(&CircleLayer::setCircleOpacity); - result["circle-opacity-transition"] = makeTransitionSetter<V>(&CircleLayer::setCircleOpacityTransition); - result["circle-translate"] = makePropertySetter<V>(&CircleLayer::setCircleTranslate); - result["circle-translate-transition"] = makeTransitionSetter<V>(&CircleLayer::setCircleTranslateTransition); - result["circle-translate-anchor"] = makePropertySetter<V>(&CircleLayer::setCircleTranslateAnchor); - result["circle-translate-anchor-transition"] = makeTransitionSetter<V>(&CircleLayer::setCircleTranslateAnchorTransition); - result["circle-pitch-scale"] = makePropertySetter<V>(&CircleLayer::setCirclePitchScale); - result["circle-pitch-scale-transition"] = makeTransitionSetter<V>(&CircleLayer::setCirclePitchScaleTransition); - result["circle-stroke-width"] = makePropertySetter<V>(&CircleLayer::setCircleStrokeWidth); - result["circle-stroke-width-transition"] = makeTransitionSetter<V>(&CircleLayer::setCircleStrokeWidthTransition); - result["circle-stroke-color"] = makePropertySetter<V>(&CircleLayer::setCircleStrokeColor); - result["circle-stroke-color-transition"] = makeTransitionSetter<V>(&CircleLayer::setCircleStrokeColorTransition); - result["circle-stroke-opacity"] = makePropertySetter<V>(&CircleLayer::setCircleStrokeOpacity); - result["circle-stroke-opacity-transition"] = makeTransitionSetter<V>(&CircleLayer::setCircleStrokeOpacityTransition); - - result["fill-extrusion-opacity"] = makePropertySetter<V>(&FillExtrusionLayer::setFillExtrusionOpacity); - result["fill-extrusion-opacity-transition"] = makeTransitionSetter<V>(&FillExtrusionLayer::setFillExtrusionOpacityTransition); - result["fill-extrusion-color"] = makePropertySetter<V>(&FillExtrusionLayer::setFillExtrusionColor); - result["fill-extrusion-color-transition"] = makeTransitionSetter<V>(&FillExtrusionLayer::setFillExtrusionColorTransition); - result["fill-extrusion-translate"] = makePropertySetter<V>(&FillExtrusionLayer::setFillExtrusionTranslate); - result["fill-extrusion-translate-transition"] = makeTransitionSetter<V>(&FillExtrusionLayer::setFillExtrusionTranslateTransition); - result["fill-extrusion-translate-anchor"] = makePropertySetter<V>(&FillExtrusionLayer::setFillExtrusionTranslateAnchor); - result["fill-extrusion-translate-anchor-transition"] = makeTransitionSetter<V>(&FillExtrusionLayer::setFillExtrusionTranslateAnchorTransition); - result["fill-extrusion-pattern"] = makePropertySetter<V>(&FillExtrusionLayer::setFillExtrusionPattern); - result["fill-extrusion-pattern-transition"] = makeTransitionSetter<V>(&FillExtrusionLayer::setFillExtrusionPatternTransition); - result["fill-extrusion-height"] = makePropertySetter<V>(&FillExtrusionLayer::setFillExtrusionHeight); - result["fill-extrusion-height-transition"] = makeTransitionSetter<V>(&FillExtrusionLayer::setFillExtrusionHeightTransition); - result["fill-extrusion-base"] = makePropertySetter<V>(&FillExtrusionLayer::setFillExtrusionBase); - result["fill-extrusion-base-transition"] = makeTransitionSetter<V>(&FillExtrusionLayer::setFillExtrusionBaseTransition); - - result["raster-opacity"] = makePropertySetter<V>(&RasterLayer::setRasterOpacity); - result["raster-opacity-transition"] = makeTransitionSetter<V>(&RasterLayer::setRasterOpacityTransition); - result["raster-hue-rotate"] = makePropertySetter<V>(&RasterLayer::setRasterHueRotate); - result["raster-hue-rotate-transition"] = makeTransitionSetter<V>(&RasterLayer::setRasterHueRotateTransition); - result["raster-brightness-min"] = makePropertySetter<V>(&RasterLayer::setRasterBrightnessMin); - result["raster-brightness-min-transition"] = makeTransitionSetter<V>(&RasterLayer::setRasterBrightnessMinTransition); - result["raster-brightness-max"] = makePropertySetter<V>(&RasterLayer::setRasterBrightnessMax); - result["raster-brightness-max-transition"] = makeTransitionSetter<V>(&RasterLayer::setRasterBrightnessMaxTransition); - result["raster-saturation"] = makePropertySetter<V>(&RasterLayer::setRasterSaturation); - result["raster-saturation-transition"] = makeTransitionSetter<V>(&RasterLayer::setRasterSaturationTransition); - result["raster-contrast"] = makePropertySetter<V>(&RasterLayer::setRasterContrast); - result["raster-contrast-transition"] = makeTransitionSetter<V>(&RasterLayer::setRasterContrastTransition); - result["raster-fade-duration"] = makePropertySetter<V>(&RasterLayer::setRasterFadeDuration); - result["raster-fade-duration-transition"] = makeTransitionSetter<V>(&RasterLayer::setRasterFadeDurationTransition); - - result["background-color"] = makePropertySetter<V>(&BackgroundLayer::setBackgroundColor); - result["background-color-transition"] = makeTransitionSetter<V>(&BackgroundLayer::setBackgroundColorTransition); - result["background-pattern"] = makePropertySetter<V>(&BackgroundLayer::setBackgroundPattern); - result["background-pattern-transition"] = makeTransitionSetter<V>(&BackgroundLayer::setBackgroundPatternTransition); - result["background-opacity"] = makePropertySetter<V>(&BackgroundLayer::setBackgroundOpacity); - result["background-opacity-transition"] = makeTransitionSetter<V>(&BackgroundLayer::setBackgroundOpacityTransition); + result["fill-antialias"] = &setPaintProperty<V, FillLayer, PropertyValue<bool>, &FillLayer::setFillAntialias>; + result["fill-antialias-transition"] = &setTransition<V, FillLayer, &FillLayer::setFillAntialiasTransition>; + result["fill-opacity"] = &setPaintProperty<V, FillLayer, DataDrivenPropertyValue<float>, &FillLayer::setFillOpacity>; + result["fill-opacity-transition"] = &setTransition<V, FillLayer, &FillLayer::setFillOpacityTransition>; + result["fill-color"] = &setPaintProperty<V, FillLayer, DataDrivenPropertyValue<Color>, &FillLayer::setFillColor>; + result["fill-color-transition"] = &setTransition<V, FillLayer, &FillLayer::setFillColorTransition>; + result["fill-outline-color"] = &setPaintProperty<V, FillLayer, DataDrivenPropertyValue<Color>, &FillLayer::setFillOutlineColor>; + result["fill-outline-color-transition"] = &setTransition<V, FillLayer, &FillLayer::setFillOutlineColorTransition>; + result["fill-translate"] = &setPaintProperty<V, FillLayer, PropertyValue<std::array<float, 2>>, &FillLayer::setFillTranslate>; + result["fill-translate-transition"] = &setTransition<V, FillLayer, &FillLayer::setFillTranslateTransition>; + result["fill-translate-anchor"] = &setPaintProperty<V, FillLayer, PropertyValue<TranslateAnchorType>, &FillLayer::setFillTranslateAnchor>; + result["fill-translate-anchor-transition"] = &setTransition<V, FillLayer, &FillLayer::setFillTranslateAnchorTransition>; + result["fill-pattern"] = &setPaintProperty<V, FillLayer, PropertyValue<std::string>, &FillLayer::setFillPattern>; + result["fill-pattern-transition"] = &setTransition<V, FillLayer, &FillLayer::setFillPatternTransition>; + + result["line-opacity"] = &setPaintProperty<V, LineLayer, DataDrivenPropertyValue<float>, &LineLayer::setLineOpacity>; + result["line-opacity-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineOpacityTransition>; + result["line-color"] = &setPaintProperty<V, LineLayer, DataDrivenPropertyValue<Color>, &LineLayer::setLineColor>; + result["line-color-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineColorTransition>; + result["line-translate"] = &setPaintProperty<V, LineLayer, PropertyValue<std::array<float, 2>>, &LineLayer::setLineTranslate>; + result["line-translate-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineTranslateTransition>; + result["line-translate-anchor"] = &setPaintProperty<V, LineLayer, PropertyValue<TranslateAnchorType>, &LineLayer::setLineTranslateAnchor>; + result["line-translate-anchor-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineTranslateAnchorTransition>; + result["line-width"] = &setPaintProperty<V, LineLayer, PropertyValue<float>, &LineLayer::setLineWidth>; + result["line-width-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineWidthTransition>; + result["line-gap-width"] = &setPaintProperty<V, LineLayer, DataDrivenPropertyValue<float>, &LineLayer::setLineGapWidth>; + result["line-gap-width-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineGapWidthTransition>; + result["line-offset"] = &setPaintProperty<V, LineLayer, DataDrivenPropertyValue<float>, &LineLayer::setLineOffset>; + result["line-offset-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineOffsetTransition>; + result["line-blur"] = &setPaintProperty<V, LineLayer, DataDrivenPropertyValue<float>, &LineLayer::setLineBlur>; + result["line-blur-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineBlurTransition>; + result["line-dasharray"] = &setPaintProperty<V, LineLayer, PropertyValue<std::vector<float>>, &LineLayer::setLineDasharray>; + result["line-dasharray-transition"] = &setTransition<V, LineLayer, &LineLayer::setLineDasharrayTransition>; + result["line-pattern"] = &setPaintProperty<V, LineLayer, PropertyValue<std::string>, &LineLayer::setLinePattern>; + result["line-pattern-transition"] = &setTransition<V, LineLayer, &LineLayer::setLinePatternTransition>; + + result["icon-opacity"] = &setPaintProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconOpacity>; + result["icon-opacity-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setIconOpacityTransition>; + result["icon-color"] = &setPaintProperty<V, SymbolLayer, DataDrivenPropertyValue<Color>, &SymbolLayer::setIconColor>; + result["icon-color-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setIconColorTransition>; + result["icon-halo-color"] = &setPaintProperty<V, SymbolLayer, DataDrivenPropertyValue<Color>, &SymbolLayer::setIconHaloColor>; + result["icon-halo-color-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setIconHaloColorTransition>; + result["icon-halo-width"] = &setPaintProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconHaloWidth>; + result["icon-halo-width-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setIconHaloWidthTransition>; + result["icon-halo-blur"] = &setPaintProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconHaloBlur>; + result["icon-halo-blur-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setIconHaloBlurTransition>; + result["icon-translate"] = &setPaintProperty<V, SymbolLayer, PropertyValue<std::array<float, 2>>, &SymbolLayer::setIconTranslate>; + result["icon-translate-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setIconTranslateTransition>; + result["icon-translate-anchor"] = &setPaintProperty<V, SymbolLayer, PropertyValue<TranslateAnchorType>, &SymbolLayer::setIconTranslateAnchor>; + result["icon-translate-anchor-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setIconTranslateAnchorTransition>; + result["text-opacity"] = &setPaintProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextOpacity>; + result["text-opacity-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setTextOpacityTransition>; + result["text-color"] = &setPaintProperty<V, SymbolLayer, DataDrivenPropertyValue<Color>, &SymbolLayer::setTextColor>; + result["text-color-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setTextColorTransition>; + result["text-halo-color"] = &setPaintProperty<V, SymbolLayer, DataDrivenPropertyValue<Color>, &SymbolLayer::setTextHaloColor>; + result["text-halo-color-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setTextHaloColorTransition>; + result["text-halo-width"] = &setPaintProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextHaloWidth>; + result["text-halo-width-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setTextHaloWidthTransition>; + result["text-halo-blur"] = &setPaintProperty<V, SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setTextHaloBlur>; + result["text-halo-blur-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setTextHaloBlurTransition>; + result["text-translate"] = &setPaintProperty<V, SymbolLayer, PropertyValue<std::array<float, 2>>, &SymbolLayer::setTextTranslate>; + result["text-translate-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setTextTranslateTransition>; + result["text-translate-anchor"] = &setPaintProperty<V, SymbolLayer, PropertyValue<TranslateAnchorType>, &SymbolLayer::setTextTranslateAnchor>; + result["text-translate-anchor-transition"] = &setTransition<V, SymbolLayer, &SymbolLayer::setTextTranslateAnchorTransition>; + + result["circle-radius"] = &setPaintProperty<V, CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleRadius>; + result["circle-radius-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleRadiusTransition>; + result["circle-color"] = &setPaintProperty<V, CircleLayer, DataDrivenPropertyValue<Color>, &CircleLayer::setCircleColor>; + result["circle-color-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleColorTransition>; + result["circle-blur"] = &setPaintProperty<V, CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleBlur>; + result["circle-blur-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleBlurTransition>; + result["circle-opacity"] = &setPaintProperty<V, CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleOpacity>; + result["circle-opacity-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleOpacityTransition>; + result["circle-translate"] = &setPaintProperty<V, CircleLayer, PropertyValue<std::array<float, 2>>, &CircleLayer::setCircleTranslate>; + result["circle-translate-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleTranslateTransition>; + result["circle-translate-anchor"] = &setPaintProperty<V, CircleLayer, PropertyValue<TranslateAnchorType>, &CircleLayer::setCircleTranslateAnchor>; + result["circle-translate-anchor-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleTranslateAnchorTransition>; + result["circle-pitch-scale"] = &setPaintProperty<V, CircleLayer, PropertyValue<CirclePitchScaleType>, &CircleLayer::setCirclePitchScale>; + result["circle-pitch-scale-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCirclePitchScaleTransition>; + result["circle-stroke-width"] = &setPaintProperty<V, CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleStrokeWidth>; + result["circle-stroke-width-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleStrokeWidthTransition>; + result["circle-stroke-color"] = &setPaintProperty<V, CircleLayer, DataDrivenPropertyValue<Color>, &CircleLayer::setCircleStrokeColor>; + result["circle-stroke-color-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleStrokeColorTransition>; + result["circle-stroke-opacity"] = &setPaintProperty<V, CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleStrokeOpacity>; + result["circle-stroke-opacity-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleStrokeOpacityTransition>; + + result["fill-extrusion-opacity"] = &setPaintProperty<V, FillExtrusionLayer, PropertyValue<float>, &FillExtrusionLayer::setFillExtrusionOpacity>; + result["fill-extrusion-opacity-transition"] = &setTransition<V, FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionOpacityTransition>; + result["fill-extrusion-color"] = &setPaintProperty<V, FillExtrusionLayer, DataDrivenPropertyValue<Color>, &FillExtrusionLayer::setFillExtrusionColor>; + result["fill-extrusion-color-transition"] = &setTransition<V, FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionColorTransition>; + result["fill-extrusion-translate"] = &setPaintProperty<V, FillExtrusionLayer, PropertyValue<std::array<float, 2>>, &FillExtrusionLayer::setFillExtrusionTranslate>; + result["fill-extrusion-translate-transition"] = &setTransition<V, FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionTranslateTransition>; + result["fill-extrusion-translate-anchor"] = &setPaintProperty<V, FillExtrusionLayer, PropertyValue<TranslateAnchorType>, &FillExtrusionLayer::setFillExtrusionTranslateAnchor>; + result["fill-extrusion-translate-anchor-transition"] = &setTransition<V, FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionTranslateAnchorTransition>; + result["fill-extrusion-pattern"] = &setPaintProperty<V, FillExtrusionLayer, PropertyValue<std::string>, &FillExtrusionLayer::setFillExtrusionPattern>; + result["fill-extrusion-pattern-transition"] = &setTransition<V, FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionPatternTransition>; + result["fill-extrusion-height"] = &setPaintProperty<V, FillExtrusionLayer, DataDrivenPropertyValue<float>, &FillExtrusionLayer::setFillExtrusionHeight>; + result["fill-extrusion-height-transition"] = &setTransition<V, FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionHeightTransition>; + result["fill-extrusion-base"] = &setPaintProperty<V, FillExtrusionLayer, DataDrivenPropertyValue<float>, &FillExtrusionLayer::setFillExtrusionBase>; + result["fill-extrusion-base-transition"] = &setTransition<V, FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionBaseTransition>; + + result["raster-opacity"] = &setPaintProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterOpacity>; + result["raster-opacity-transition"] = &setTransition<V, RasterLayer, &RasterLayer::setRasterOpacityTransition>; + result["raster-hue-rotate"] = &setPaintProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterHueRotate>; + result["raster-hue-rotate-transition"] = &setTransition<V, RasterLayer, &RasterLayer::setRasterHueRotateTransition>; + result["raster-brightness-min"] = &setPaintProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterBrightnessMin>; + result["raster-brightness-min-transition"] = &setTransition<V, RasterLayer, &RasterLayer::setRasterBrightnessMinTransition>; + result["raster-brightness-max"] = &setPaintProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterBrightnessMax>; + result["raster-brightness-max-transition"] = &setTransition<V, RasterLayer, &RasterLayer::setRasterBrightnessMaxTransition>; + result["raster-saturation"] = &setPaintProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterSaturation>; + result["raster-saturation-transition"] = &setTransition<V, RasterLayer, &RasterLayer::setRasterSaturationTransition>; + result["raster-contrast"] = &setPaintProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterContrast>; + result["raster-contrast-transition"] = &setTransition<V, RasterLayer, &RasterLayer::setRasterContrastTransition>; + result["raster-fade-duration"] = &setPaintProperty<V, RasterLayer, PropertyValue<float>, &RasterLayer::setRasterFadeDuration>; + result["raster-fade-duration-transition"] = &setTransition<V, RasterLayer, &RasterLayer::setRasterFadeDurationTransition>; + + result["background-color"] = &setPaintProperty<V, BackgroundLayer, PropertyValue<Color>, &BackgroundLayer::setBackgroundColor>; + result["background-color-transition"] = &setTransition<V, BackgroundLayer, &BackgroundLayer::setBackgroundColorTransition>; + result["background-pattern"] = &setPaintProperty<V, BackgroundLayer, PropertyValue<std::string>, &BackgroundLayer::setBackgroundPattern>; + result["background-pattern-transition"] = &setTransition<V, BackgroundLayer, &BackgroundLayer::setBackgroundPatternTransition>; + result["background-opacity"] = &setPaintProperty<V, BackgroundLayer, PropertyValue<float>, &BackgroundLayer::setBackgroundOpacity>; + result["background-opacity-transition"] = &setTransition<V, BackgroundLayer, &BackgroundLayer::setBackgroundOpacityTransition>; return result; } diff --git a/include/mbgl/style/conversion/make_property_setters.hpp.ejs b/include/mbgl/style/conversion/make_property_setters.hpp.ejs index 65fbdea63e..a99e75aec7 100644 --- a/include/mbgl/style/conversion/make_property_setters.hpp.ejs +++ b/include/mbgl/style/conversion/make_property_setters.hpp.ejs @@ -22,7 +22,7 @@ auto makeLayoutPropertySetters() { <% for (const layer of locals.layers) { -%> <% for (const property of layer.layoutProperties) { -%> - result["<%- property.name %>"] = makePropertySetter<V>(&<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>); + result["<%- property.name %>"] = &setLayoutProperty<V, <%- camelize(layer.type) %>Layer, <%- propertyValueType(property) %>, &<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>>; <% } -%> <% } -%> @@ -35,8 +35,8 @@ auto makePaintPropertySetters() { <% for (const layer of locals.layers) { -%> <% for (const property of layer.paintProperties) { -%> - result["<%- property.name %>"] = makePropertySetter<V>(&<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>); - result["<%- property.name %>-transition"] = makeTransitionSetter<V>(&<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>Transition); + result["<%- property.name %>"] = &setPaintProperty<V, <%- camelize(layer.type) %>Layer, <%- propertyValueType(property) %>, &<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>>; + result["<%- property.name %>-transition"] = &setTransition<V, <%- camelize(layer.type) %>Layer, &<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>Transition>; <% } -%> <% } -%> diff --git a/include/mbgl/style/conversion/property_setter.hpp b/include/mbgl/style/conversion/property_setter.hpp index 6a15c64026..51ec4778d9 100644 --- a/include/mbgl/style/conversion/property_setter.hpp +++ b/include/mbgl/style/conversion/property_setter.hpp @@ -7,7 +7,6 @@ #include <mbgl/style/conversion/data_driven_property_value.hpp> #include <mbgl/style/conversion/transition_options.hpp> -#include <functional> #include <string> namespace mbgl { @@ -15,45 +14,57 @@ namespace style { namespace conversion { template <class V> -using LayoutPropertySetter = std::function<optional<Error> (Layer&, const V&)>; +using LayoutPropertySetter = optional<Error> (*) (Layer&, const V&); template <class V> -using PaintPropertySetter = std::function<optional<Error> (Layer&, const V&, const optional<std::string>&)>; - -template <class V, class L, class PropertyValue, class...Args> -auto makePropertySetter(void (L::*setter)(PropertyValue, const Args&...args)) { - return [setter] (Layer& layer, const V& value, const Args&...args) -> optional<Error> { - L* typedLayer = layer.as<L>(); - if (!typedLayer) { - return Error { "layer doesn't support this property" }; - } - - Result<PropertyValue> typedValue = convert<PropertyValue>(value); - if (!typedValue) { - return typedValue.error(); - } - - (typedLayer->*setter)(*typedValue, args...); - return {}; - }; +using PaintPropertySetter = optional<Error> (*) (Layer&, const V&, const optional<std::string>&); + +template <class V, class L, class PropertyValue, void (L::*setter)(PropertyValue)> +optional<Error> setLayoutProperty(Layer& layer, const V& value) { + L* typedLayer = layer.as<L>(); + if (!typedLayer) { + return Error { "layer doesn't support this property" }; + } + + Result<PropertyValue> typedValue = convert<PropertyValue>(value); + if (!typedValue) { + return typedValue.error(); + } + + (typedLayer->*setter)(*typedValue); + return {}; +} + +template <class V, class L, class PropertyValue, void (L::*setter)(PropertyValue, const optional<std::string>&)> +optional<Error> setPaintProperty(Layer& layer, const V& value, const optional<std::string>& klass) { + L* typedLayer = layer.as<L>(); + if (!typedLayer) { + return Error { "layer doesn't support this property" }; + } + + Result<PropertyValue> typedValue = convert<PropertyValue>(value); + if (!typedValue) { + return typedValue.error(); + } + + (typedLayer->*setter)(*typedValue, klass); + return {}; } -template <class V, class L, class...Args> -auto makeTransitionSetter(void (L::*setter)(const TransitionOptions&, const Args&...args)) { - return [setter] (Layer& layer, const V& value, const Args&...args) -> optional<Error> { - L* typedLayer = layer.as<L>(); - if (!typedLayer) { - return Error { "layer doesn't support this property" }; - } +template <class V, class L, void (L::*setter)(const TransitionOptions&, const optional<std::string>&)> +optional<Error> setTransition(Layer& layer, const V& value, const optional<std::string>& klass) { + L* typedLayer = layer.as<L>(); + if (!typedLayer) { + return Error { "layer doesn't support this property" }; + } - Result<TransitionOptions> transition = convert<TransitionOptions>(value); - if (!transition) { - return transition.error(); - } + Result<TransitionOptions> transition = convert<TransitionOptions>(value); + if (!transition) { + return transition.error(); + } - (typedLayer->*setter)(*transition, args...); - return {}; - }; + (typedLayer->*setter)(*transition, klass); + return {}; } template <class V> diff --git a/include/mbgl/style/filter.hpp b/include/mbgl/style/filter.hpp index 5e61adf064..a204a2b17a 100644 --- a/include/mbgl/style/filter.hpp +++ b/include/mbgl/style/filter.hpp @@ -266,6 +266,9 @@ public: bool operator()(const Feature&) const; + template <class GeometryTileFeature> + bool operator()(const GeometryTileFeature&) const; + template <class PropertyAccessor> bool operator()(FeatureType type, optional<FeatureIdentifier> id, PropertyAccessor accessor) const; }; diff --git a/include/mbgl/style/filter_evaluator.hpp b/include/mbgl/style/filter_evaluator.hpp index 370064445a..66223d7282 100644 --- a/include/mbgl/style/filter_evaluator.hpp +++ b/include/mbgl/style/filter_evaluator.hpp @@ -246,6 +246,11 @@ inline bool Filter::operator()(const Feature& feature) const { }); } +template <class GeometryTileFeature> +bool Filter::operator()(const GeometryTileFeature& feature) const { + return operator()(feature.getType(), feature.getID(), [&] (const auto& key) { return feature.getValue(key); }); +} + template <class PropertyAccessor> bool Filter::operator()(FeatureType type, optional<FeatureIdentifier> id, PropertyAccessor accessor) const { return FilterBase::visit(*this, FilterEvaluator<PropertyAccessor> { type, id, accessor }); diff --git a/include/mbgl/style/property_value.hpp b/include/mbgl/style/property_value.hpp index e784633aa7..1b7429dae6 100644 --- a/include/mbgl/style/property_value.hpp +++ b/include/mbgl/style/property_value.hpp @@ -29,6 +29,7 @@ public: bool isUndefined() const { return value.which() == 0; } bool isConstant() const { return value.which() == 1; } bool isCameraFunction() const { return value.which() == 2; } + bool isDataDriven() const { return false; } const T & asConstant() const { return value.template get< T >(); } const CameraFunction<T>& asCameraFunction() const { return value.template get<CameraFunction<T>>(); } diff --git a/include/mbgl/util/event.hpp b/include/mbgl/util/event.hpp index 7ad3d914e8..5fe0baae3c 100644 --- a/include/mbgl/util/event.hpp +++ b/include/mbgl/util/event.hpp @@ -40,7 +40,7 @@ struct EventPermutation { }; constexpr EventSeverity disabledEventSeverities[] = { -#ifdef NDEBUG +#ifndef NDEBUG EventSeverity(-1) // Avoid zero size array #else EventSeverity::Debug diff --git a/include/mbgl/util/traits.hpp b/include/mbgl/util/traits.hpp index 9d6f947cd2..5b9401aad7 100644 --- a/include/mbgl/util/traits.hpp +++ b/include/mbgl/util/traits.hpp @@ -1,5 +1,6 @@ #pragma once +#include <cstdint> #include <type_traits> namespace mbgl { @@ -9,4 +10,19 @@ constexpr auto underlying_type(T t) -> typename std::underlying_type_t<T> { return typename std::underlying_type_t<T>(t); } +template <typename T> struct is_utf16char_like: std::false_type {}; +template <typename T> struct is_utf16char_like<const T>: is_utf16char_like<T> {}; +template <> struct is_utf16char_like<char16_t>: std::true_type {}; +template <> struct is_utf16char_like<wchar_t>: std::true_type {}; +template <> struct is_utf16char_like<uint16_t>: std::true_type {}; + +template <typename T> using is_utf16char_like_pointer = std::integral_constant<bool, std::is_pointer<T>::value + && is_utf16char_like<typename std::remove_pointer<T>::type>::value>; + +template <class OutPointer, class InChar> +typename std::enable_if<is_utf16char_like<InChar>::value && is_utf16char_like_pointer<OutPointer>::value, OutPointer>::type utf16char_cast(InChar *in) +{ + return reinterpret_cast<OutPointer>(in); +} + } // namespace mbgl diff --git a/mapbox-gl-js b/mapbox-gl-js -Subproject 7804faf89741cf7db90582d9e0881253cb9d4cd +Subproject 69bb05cef27c99722f6616867032d64b5f12ee5 diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java index f954073974..296d93d0ca 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java @@ -43,7 +43,7 @@ public final class Mapbox { return INSTANCE; } - private Mapbox(@NonNull Context context, @NonNull String accessToken) { + Mapbox(@NonNull Context context, @NonNull String accessToken) { this.context = context; this.accessToken = accessToken; } 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 17a1866379..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 @@ -636,6 +636,7 @@ public class MarkerViewManager implements MapView.OnMapChangedListener { viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.imageView.setImageBitmap(marker.getIcon().getBitmap()); + viewHolder.imageView.setContentDescription(marker.getTitle()); return convertView; } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java index 16b7bf1800..8fa2d0b152 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java @@ -118,6 +118,9 @@ public class MapView extends FrameLayout { ImageView attrView = (ImageView) view.findViewById(R.id.attributionView); initalizeDrawingSurface(context, options); + // add accessibility support + setContentDescription(context.getString(R.string.mapbox_mapActionDescription)); + // create native Map object nativeMapView = new NativeMapView(this); diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java index e3e33ec067..46c5e269c0 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java @@ -37,6 +37,7 @@ import com.mapbox.mapboxsdk.constants.MyLocationTracking; import com.mapbox.mapboxsdk.constants.Style; import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.maps.widgets.MyLocationViewSettings; +import com.mapbox.mapboxsdk.style.layers.Filter; import com.mapbox.mapboxsdk.style.layers.Layer; import com.mapbox.mapboxsdk.style.sources.Source; import com.mapbox.services.commons.geojson.Feature; @@ -1674,7 +1675,23 @@ public final class MapboxMap { @NonNull public List<Feature> queryRenderedFeatures(@NonNull PointF coordinates, @Nullable String... layerIds) { - return nativeMapView.queryRenderedFeatures(coordinates, layerIds); + return nativeMapView.queryRenderedFeatures(coordinates, layerIds, null); + } + + /** + * Queries the map for rendered features + * + * @param coordinates the point to query + * @param filter filters the returned features + * @param layerIds optionally - only query these layers + * @return the list of feature + */ + @UiThread + @NonNull + public List<Feature> queryRenderedFeatures(@NonNull PointF coordinates, + @Nullable Filter.Statement filter, + @Nullable String... layerIds) { + return nativeMapView.queryRenderedFeatures(coordinates, layerIds, filter); } /** @@ -1686,9 +1703,25 @@ public final class MapboxMap { */ @UiThread @NonNull - public List<Feature> queryRenderedFeatures(@NonNull RectF coordinates, @Nullable String... - layerIds) { - return nativeMapView.queryRenderedFeatures(coordinates, layerIds); + public List<Feature> queryRenderedFeatures(@NonNull RectF coordinates, + @Nullable String... layerIds) { + return nativeMapView.queryRenderedFeatures(coordinates, layerIds, null); + } + + /** + * Queries the map for rendered features + * + * @param coordinates the box to query + * @param filter filters the returned features + * @param layerIds optionally - only query these layers + * @return the list of feature + */ + @UiThread + @NonNull + public List<Feature> queryRenderedFeatures(@NonNull RectF coordinates, + @Nullable Filter.Statement filter, + @Nullable String... layerIds) { + return nativeMapView.queryRenderedFeatures(coordinates, layerIds, filter); } // 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 e02a0f3d36..7c68a48c4d 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 @@ -22,6 +22,7 @@ import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.geometry.ProjectedMeters; import com.mapbox.mapboxsdk.storage.FileSource; import com.mapbox.mapboxsdk.style.layers.CannotAddLayerException; +import com.mapbox.mapboxsdk.style.layers.Filter; import com.mapbox.mapboxsdk.style.layers.Layer; import com.mapbox.mapboxsdk.style.sources.CannotAddSourceException; import com.mapbox.mapboxsdk.style.sources.Source; @@ -881,27 +882,31 @@ final class NativeMapView { // Feature querying @NonNull - public List<Feature> queryRenderedFeatures(PointF coordinates, String... layerIds) { + public List<Feature> queryRenderedFeatures(@NonNull PointF coordinates, + @Nullable String[] layerIds, + @Nullable Filter.Statement filter) { if (isDestroyedOn("queryRenderedFeatures")) { return new ArrayList<>(); } Feature[] features = nativeQueryRenderedFeaturesForPoint(coordinates.x / pixelRatio, - coordinates.y / pixelRatio, layerIds); + coordinates.y / pixelRatio, layerIds, filter != null ? filter.toArray() : null); return features != null ? Arrays.asList(features) : new ArrayList<Feature>(); } @NonNull - public List<Feature> queryRenderedFeatures(RectF coordinates, String... layerIds) { + public List<Feature> queryRenderedFeatures(@NonNull RectF coordinates, + @Nullable String[] layerIds, + @Nullable Filter.Statement filter) { if (isDestroyedOn("queryRenderedFeatures")) { return new ArrayList<>(); } Feature[] features = nativeQueryRenderedFeaturesForBox( - coordinates.left / pixelRatio, coordinates.top / pixelRatio, coordinates.right / pixelRatio, coordinates.bottom / pixelRatio, - layerIds); + layerIds, + filter != null ? filter.toArray() : null); return features != null ? Arrays.asList(features) : new ArrayList<Feature>(); } @@ -1139,12 +1144,14 @@ final class NativeMapView { private native void nativeTakeSnapshot(); - private native Feature[] nativeQueryRenderedFeaturesForPoint(float x, float y, String[] - layerIds); + private native Feature[] nativeQueryRenderedFeaturesForPoint(float x, float y, + String[] layerIds, + Object[] filter); private native Feature[] nativeQueryRenderedFeaturesForBox(float left, float top, float right, float bottom, - String[] layerIds); + String[] layerIds, + Object[] filter); int getWidth() { if (isDestroyedOn("")) { diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java index 6d8adc1e2a..5c9cf93ebc 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java @@ -56,7 +56,6 @@ public final class CompassView extends AppCompatImageView implements Runnable, F private void initialize(Context context) { setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.mapbox_compass_icon)); - setContentDescription(getResources().getString(R.string.mapbox_compassContentDescription)); setEnabled(false); // Layout params diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/CompositeFunction.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/CompositeFunction.java index 1db14afc5f..8ded7ecd34 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/CompositeFunction.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/CompositeFunction.java @@ -8,6 +8,7 @@ import com.mapbox.mapboxsdk.style.functions.stops.ExponentialStops; import com.mapbox.mapboxsdk.style.functions.stops.IntervalStops; import com.mapbox.mapboxsdk.style.functions.stops.Stop; import com.mapbox.mapboxsdk.style.functions.stops.Stops; +import com.mapbox.mapboxsdk.style.layers.PropertyValue; import java.util.Map; @@ -27,7 +28,7 @@ import java.util.Map; public class CompositeFunction<Z extends Number, I, O> extends Function<Stop.CompositeValue<Z, I>, O> { private final String property; - private O defaultValue; + private PropertyValue<O> defaultValue; CompositeFunction(@NonNull String property, @NonNull CategoricalStops<Stop.CompositeValue<Z, I>, O> stops) { @@ -51,7 +52,7 @@ public class CompositeFunction<Z extends Number, I, O> extends Function<Stop.Com private CompositeFunction(@Nullable O defaultValue, @NonNull String property, @NonNull Stops<Stop.CompositeValue<Z, I>, O> stops) { super(stops); - this.defaultValue = defaultValue; + this.defaultValue = new PropertyValue<>(property, defaultValue); this.property = property; } @@ -61,7 +62,7 @@ public class CompositeFunction<Z extends Number, I, O> extends Function<Stop.Com * @param defaultValue the default value to use when no other applies * @return this (for chaining) */ - public CompositeFunction<Z, I, O> withDefaultValue(O defaultValue) { + public CompositeFunction<Z, I, O> withDefaultValue(PropertyValue<O> defaultValue) { this.defaultValue = defaultValue; return this; } @@ -70,7 +71,7 @@ public class CompositeFunction<Z extends Number, I, O> extends Function<Stop.Com * @return the defaultValue */ @Nullable - public O getDefaultValue() { + public PropertyValue<O> getDefaultValue() { return defaultValue; } @@ -91,7 +92,7 @@ public class CompositeFunction<Z extends Number, I, O> extends Function<Stop.Com Map<String, Object> valueObject = super.toValueObject(); valueObject.put(PROPERTY_KEY, property); if (defaultValue != null) { - valueObject.put(DEFAULT_VALUE_KEY, defaultValue); + valueObject.put(DEFAULT_VALUE_KEY, defaultValue.value); } return valueObject; } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/SourceFunction.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/SourceFunction.java index f0eed760a4..33f436ae71 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/SourceFunction.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/SourceFunction.java @@ -4,6 +4,7 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import com.mapbox.mapboxsdk.style.functions.stops.Stops; +import com.mapbox.mapboxsdk.style.layers.PropertyValue; import java.util.Map; @@ -25,7 +26,7 @@ import java.util.Map; public class SourceFunction<I, O> extends Function<I, O> { private final String property; - private O defaultValue; + private PropertyValue<O> defaultValue; SourceFunction(@NonNull String property, @NonNull Stops<I, O> stops) { this(null, property, stops); @@ -37,7 +38,7 @@ public class SourceFunction<I, O> extends Function<I, O> { private SourceFunction(@Nullable O defaultValue, @NonNull String property, @NonNull Stops<I, O> stops) { super(stops); this.property = property; - this.defaultValue = defaultValue; + this.defaultValue = defaultValue != null ? new PropertyValue<>(property, defaultValue) : null; } @@ -56,7 +57,7 @@ public class SourceFunction<I, O> extends Function<I, O> { * @param defaultValue the default value to use when no other applies * @return this (for chaining) */ - public SourceFunction<I, O> withDefaultValue(O defaultValue) { + public SourceFunction<I, O> withDefaultValue(PropertyValue<O> defaultValue) { this.defaultValue = defaultValue; return this; } @@ -65,7 +66,7 @@ public class SourceFunction<I, O> extends Function<I, O> { * @return the defaultValue */ @Nullable - public O getDefaultValue() { + public PropertyValue<O> getDefaultValue() { return defaultValue; } @@ -77,7 +78,7 @@ public class SourceFunction<I, O> extends Function<I, O> { Map<String, Object> valueObject = super.toValueObject(); valueObject.put(PROPERTY_KEY, property); if (defaultValue != null) { - valueObject.put(DEFAULT_VALUE_KEY, defaultValue); + valueObject.put(DEFAULT_VALUE_KEY, defaultValue.value); } return valueObject; } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyValue.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyValue.java index 5286e6916d..68727c8a4f 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyValue.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyValue.java @@ -1,9 +1,12 @@ package com.mapbox.mapboxsdk.style.layers; +import android.support.annotation.ColorInt; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import com.mapbox.mapboxsdk.exceptions.ConversionException; import com.mapbox.mapboxsdk.style.functions.Function; +import com.mapbox.mapboxsdk.utils.ColorUtils; import timber.log.Timber; @@ -15,7 +18,14 @@ public class PropertyValue<T> { public final String name; public final T value; - /* package */ PropertyValue(@NonNull String name, T value) { + /** + * Not part of the public API. + * + * @param name the property name + * @param value the property value + * @see PropertyFactory for construction of {@link PropertyValue}s + */ + public PropertyValue(@NonNull String name, T value) { this.name = name; this.value = value; } @@ -54,6 +64,22 @@ public class PropertyValue<T> { } } + @ColorInt + @Nullable + public Integer getColorInt() { + if (!isValue() || !(value instanceof String)) { + Timber.e("%s is not a String value and can not be converted to a color it", name); + return null; + } + + try { + return ColorUtils.rgbaToColor((String) value); + } catch (ConversionException ex) { + Timber.e("%s could not be converted to a Color int: %s", name, ex.getMessage()); + return null; + } + } + @Override public String toString() { return String.format("%s: %s", name, value); diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml b/platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml index e786aaca4c..641020906a 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml +++ b/platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml @@ -74,6 +74,12 @@ <!-- Deprecated to use TextureView--> <public name="mapbox_renderTextureMode" type="attr" /> + <!-- Exposed content descriptions --> + <public name="mapbox_compassContentDescription" type="string" /> + <public name="mapbox_attributionsIconContentDescription" type="string" /> + <public name="mapbox_myLocationViewContentDescription" type="string" /> + <public name="mapbox_logoContentDescription" type="string" /> + <!-- Exposed styles --> <public name="mapbox_style_mapbox_streets" type="string" /> <public name="mapbox_style_emerald" type="string" /> 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 9810e8900b..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 @@ -5,30 +5,34 @@ android:id="@+id/surfaceView" android:layout_width="match_parent" android:layout_height="match_parent" - android:visibility="gone" /> + android:contentDescription="@null" + android:visibility="gone"/> <FrameLayout android:id="@+id/markerViewContainer" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@android:color/transparent" /> + android:background="@android:color/transparent" + android:contentDescription="@null"/> <com.mapbox.mapboxsdk.maps.widgets.MyLocationView android:id="@+id/userLocationView" android:layout_width="match_parent" - android:layout_height="match_parent" /> + android:layout_height="match_parent" + android:contentDescription="@string/mapbox_myLocationViewContentDescription"/> <com.mapbox.mapboxsdk.maps.widgets.CompassView android:id="@+id/compassView" android:layout_width="wrap_content" - android:layout_height="wrap_content" /> + android:layout_height="wrap_content" + android:contentDescription="@string/mapbox_compassContentDescription"/> <ImageView android:id="@+id/logoView" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:contentDescription="@string/mapbox_iconContentDescription" - android:src="@drawable/mapbox_logo_icon" /> + android:contentDescription="@null" + android:src="@drawable/mapbox_logo_icon"/> <ImageView android:id="@+id/attributionView" @@ -39,6 +43,6 @@ android:clickable="true" android:contentDescription="@string/mapbox_attributionsIconContentDescription" android:padding="7dp" - android:src="@drawable/mapbox_info_bg_selector" /> + android:src="@drawable/mapbox_info_bg_selector"/> </merge> diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_preview.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_preview.xml index d87f443586..d015bc5785 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_preview.xml +++ b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_preview.xml @@ -17,8 +17,8 @@ android:layout_alignParentLeft="true" android:layout_marginBottom="@dimen/mapbox_eight_dp" android:layout_marginLeft="@dimen/mapbox_eight_dp" - android:contentDescription="@string/mapbox_iconContentDescription" - android:src="@drawable/mapbox_logo_icon" /> + android:contentDescription="@null" + android:src="@drawable/mapbox_logo_icon"/> <ImageView android:layout_width="wrap_content" diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/strings.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/strings.xml index 5905878350..0d8e9bdc49 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/strings.xml +++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/strings.xml @@ -1,14 +1,15 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - <string name="mapbox_compassContentDescription">Map compass. Click to reset the map rotation to North.</string> - <string name="mapbox_attributionsIconContentDescription">Attribution icon. Click to show attribution dialog.</string> + <string name="mapbox_compassContentDescription">Map compass. Activate to reset the map rotation to North.</string> + <string name="mapbox_attributionsIconContentDescription">Attribution icon. Activate to show attribution dialog.</string> + <string name="mapbox_myLocationViewContentDescription">Location View. This shows your location on the map.</string> + <string name="mapbox_mapActionDescription">Showing a Map created with Mapbox. Scroll by dragging two fingers. Zoom by pinching two fingers.</string> <string name="mapbox_attributionsDialogTitle">Mapbox Android SDK</string> <string name="mapbox_attributionTelemetryTitle">Make Mapbox Maps Better</string> <string name="mapbox_attributionTelemetryMessage">You are helping to make OpenStreetMap and Mapbox maps better by contributing anonymous usage data.</string> <string name="mapbox_attributionTelemetryPositive">Agree</string> <string name="mapbox_attributionTelemetryNegative">Disagree</string> <string name="mapbox_attributionTelemetryNeutral">More info</string> - <string name="mapbox_iconContentDescription">The Mapbox logo.</string> <string name="mapbox_infoWindowTitle">Title</string> <string name="mapbox_infoWindowDescription">Description</string> <string name="mapbox_infoWindowAddress">Address</string> diff --git a/platform/android/MapboxGLAndroidSDKTestApp/build.gradle b/platform/android/MapboxGLAndroidSDKTestApp/build.gradle index 1b4d54106d..10baf2e108 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/build.gradle +++ b/platform/android/MapboxGLAndroidSDKTestApp/build.gradle @@ -46,6 +46,12 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + + dexOptions { + maxProcessCount 8 + javaMaxHeapSize "2g" + preDexLibraries true + } } dependencies { diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerTest.java index c48a6f1d68..a8f35356b5 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerTest.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerTest.java @@ -177,7 +177,7 @@ public class CircleLayerTest extends BaseStyleTest { categorical( stop(1.0f, circleRadius(0.3f)) ) - ).withDefaultValue(0.3f) + ).withDefaultValue(circleRadius(0.3f)) ) ); @@ -187,7 +187,9 @@ public class CircleLayerTest extends BaseStyleTest { assertEquals(SourceFunction.class, layer.getCircleRadius().getFunction().getClass()); assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleRadius().getFunction()).getProperty()); assertEquals(CategoricalStops.class, layer.getCircleRadius().getFunction().getStops().getClass()); - assertEquals(0.3f, ((SourceFunction) layer.getCircleRadius().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getCircleRadius().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getCircleRadius().getFunction()).getDefaultValue().getValue()); + assertEquals(0.3f, ((SourceFunction) layer.getCircleRadius().getFunction()).getDefaultValue().getValue()); } @Test @@ -204,7 +206,7 @@ public class CircleLayerTest extends BaseStyleTest { exponential( stop(0, 0.3f, circleRadius(0.9f)) ).withBase(0.5f) - ).withDefaultValue(0.3f) + ).withDefaultValue(circleRadius(0.3f)) ) ); @@ -320,7 +322,7 @@ public class CircleLayerTest extends BaseStyleTest { categorical( stop("valueA", circleColor(Color.RED)) ) - ) + ).withDefaultValue(circleColor(Color.GREEN)) ) ); @@ -330,6 +332,9 @@ public class CircleLayerTest extends BaseStyleTest { assertEquals(SourceFunction.class, layer.getCircleColor().getFunction().getClass()); assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleColor().getFunction()).getProperty()); assertEquals(CategoricalStops.class, layer.getCircleColor().getFunction().getStops().getClass()); + assertNotNull(((SourceFunction) layer.getCircleColor().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getCircleColor().getFunction()).getDefaultValue().getValue()); + assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getCircleColor().getFunction()).getDefaultValue().getColorInt()); } @Test @@ -439,7 +444,7 @@ public class CircleLayerTest extends BaseStyleTest { categorical( stop(1.0f, circleBlur(0.3f)) ) - ).withDefaultValue(0.3f) + ).withDefaultValue(circleBlur(0.3f)) ) ); @@ -449,7 +454,9 @@ public class CircleLayerTest extends BaseStyleTest { assertEquals(SourceFunction.class, layer.getCircleBlur().getFunction().getClass()); assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleBlur().getFunction()).getProperty()); assertEquals(CategoricalStops.class, layer.getCircleBlur().getFunction().getStops().getClass()); - assertEquals(0.3f, ((SourceFunction) layer.getCircleBlur().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getCircleBlur().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getCircleBlur().getFunction()).getDefaultValue().getValue()); + assertEquals(0.3f, ((SourceFunction) layer.getCircleBlur().getFunction()).getDefaultValue().getValue()); } @Test @@ -466,7 +473,7 @@ public class CircleLayerTest extends BaseStyleTest { exponential( stop(0, 0.3f, circleBlur(0.9f)) ).withBase(0.5f) - ).withDefaultValue(0.3f) + ).withDefaultValue(circleBlur(0.3f)) ) ); @@ -582,7 +589,7 @@ public class CircleLayerTest extends BaseStyleTest { categorical( stop(1.0f, circleOpacity(0.3f)) ) - ).withDefaultValue(0.3f) + ).withDefaultValue(circleOpacity(0.3f)) ) ); @@ -592,7 +599,9 @@ public class CircleLayerTest extends BaseStyleTest { assertEquals(SourceFunction.class, layer.getCircleOpacity().getFunction().getClass()); assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleOpacity().getFunction()).getProperty()); assertEquals(CategoricalStops.class, layer.getCircleOpacity().getFunction().getStops().getClass()); - assertEquals(0.3f, ((SourceFunction) layer.getCircleOpacity().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getCircleOpacity().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getCircleOpacity().getFunction()).getDefaultValue().getValue()); + assertEquals(0.3f, ((SourceFunction) layer.getCircleOpacity().getFunction()).getDefaultValue().getValue()); } @Test @@ -609,7 +618,7 @@ public class CircleLayerTest extends BaseStyleTest { exponential( stop(0, 0.3f, circleOpacity(0.9f)) ).withBase(0.5f) - ).withDefaultValue(0.3f) + ).withDefaultValue(circleOpacity(0.3f)) ) ); @@ -834,7 +843,7 @@ public class CircleLayerTest extends BaseStyleTest { categorical( stop(1.0f, circleStrokeWidth(0.3f)) ) - ).withDefaultValue(0.3f) + ).withDefaultValue(circleStrokeWidth(0.3f)) ) ); @@ -844,7 +853,9 @@ public class CircleLayerTest extends BaseStyleTest { assertEquals(SourceFunction.class, layer.getCircleStrokeWidth().getFunction().getClass()); assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeWidth().getFunction()).getProperty()); assertEquals(CategoricalStops.class, layer.getCircleStrokeWidth().getFunction().getStops().getClass()); - assertEquals(0.3f, ((SourceFunction) layer.getCircleStrokeWidth().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getCircleStrokeWidth().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getCircleStrokeWidth().getFunction()).getDefaultValue().getValue()); + assertEquals(0.3f, ((SourceFunction) layer.getCircleStrokeWidth().getFunction()).getDefaultValue().getValue()); } @Test @@ -861,7 +872,7 @@ public class CircleLayerTest extends BaseStyleTest { exponential( stop(0, 0.3f, circleStrokeWidth(0.9f)) ).withBase(0.5f) - ).withDefaultValue(0.3f) + ).withDefaultValue(circleStrokeWidth(0.3f)) ) ); @@ -977,7 +988,7 @@ public class CircleLayerTest extends BaseStyleTest { categorical( stop("valueA", circleStrokeColor(Color.RED)) ) - ) + ).withDefaultValue(circleStrokeColor(Color.GREEN)) ) ); @@ -987,6 +998,9 @@ public class CircleLayerTest extends BaseStyleTest { assertEquals(SourceFunction.class, layer.getCircleStrokeColor().getFunction().getClass()); assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeColor().getFunction()).getProperty()); assertEquals(CategoricalStops.class, layer.getCircleStrokeColor().getFunction().getStops().getClass()); + assertNotNull(((SourceFunction) layer.getCircleStrokeColor().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getCircleStrokeColor().getFunction()).getDefaultValue().getValue()); + assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getCircleStrokeColor().getFunction()).getDefaultValue().getColorInt()); } @Test @@ -1096,7 +1110,7 @@ public class CircleLayerTest extends BaseStyleTest { categorical( stop(1.0f, circleStrokeOpacity(0.3f)) ) - ).withDefaultValue(0.3f) + ).withDefaultValue(circleStrokeOpacity(0.3f)) ) ); @@ -1106,7 +1120,9 @@ public class CircleLayerTest extends BaseStyleTest { assertEquals(SourceFunction.class, layer.getCircleStrokeOpacity().getFunction().getClass()); assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeOpacity().getFunction()).getProperty()); assertEquals(CategoricalStops.class, layer.getCircleStrokeOpacity().getFunction().getStops().getClass()); - assertEquals(0.3f, ((SourceFunction) layer.getCircleStrokeOpacity().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getCircleStrokeOpacity().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getCircleStrokeOpacity().getFunction()).getDefaultValue().getValue()); + assertEquals(0.3f, ((SourceFunction) layer.getCircleStrokeOpacity().getFunction()).getDefaultValue().getValue()); } @Test @@ -1123,7 +1139,7 @@ public class CircleLayerTest extends BaseStyleTest { exponential( stop(0, 0.3f, circleStrokeOpacity(0.9f)) ).withBase(0.5f) - ).withDefaultValue(0.3f) + ).withDefaultValue(circleStrokeOpacity(0.3f)) ) ); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerTest.java index dd59b97525..a1d362f0f9 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerTest.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerTest.java @@ -213,7 +213,7 @@ public class FillLayerTest extends BaseStyleTest { categorical( stop(1.0f, fillOpacity(0.3f)) ) - ).withDefaultValue(0.3f) + ).withDefaultValue(fillOpacity(0.3f)) ) ); @@ -223,7 +223,9 @@ public class FillLayerTest extends BaseStyleTest { assertEquals(SourceFunction.class, layer.getFillOpacity().getFunction().getClass()); assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillOpacity().getFunction()).getProperty()); assertEquals(CategoricalStops.class, layer.getFillOpacity().getFunction().getStops().getClass()); - assertEquals(0.3f, ((SourceFunction) layer.getFillOpacity().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getFillOpacity().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getFillOpacity().getFunction()).getDefaultValue().getValue()); + assertEquals(0.3f, ((SourceFunction) layer.getFillOpacity().getFunction()).getDefaultValue().getValue()); } @Test @@ -240,7 +242,7 @@ public class FillLayerTest extends BaseStyleTest { exponential( stop(0, 0.3f, fillOpacity(0.9f)) ).withBase(0.5f) - ).withDefaultValue(0.3f) + ).withDefaultValue(fillOpacity(0.3f)) ) ); @@ -356,7 +358,7 @@ public class FillLayerTest extends BaseStyleTest { categorical( stop("valueA", fillColor(Color.RED)) ) - ) + ).withDefaultValue(fillColor(Color.GREEN)) ) ); @@ -366,6 +368,9 @@ public class FillLayerTest extends BaseStyleTest { assertEquals(SourceFunction.class, layer.getFillColor().getFunction().getClass()); assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillColor().getFunction()).getProperty()); assertEquals(CategoricalStops.class, layer.getFillColor().getFunction().getStops().getClass()); + assertNotNull(((SourceFunction) layer.getFillColor().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getFillColor().getFunction()).getDefaultValue().getValue()); + assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getFillColor().getFunction()).getDefaultValue().getColorInt()); } @Test @@ -475,7 +480,7 @@ public class FillLayerTest extends BaseStyleTest { categorical( stop("valueA", fillOutlineColor(Color.RED)) ) - ) + ).withDefaultValue(fillOutlineColor(Color.GREEN)) ) ); @@ -485,6 +490,9 @@ public class FillLayerTest extends BaseStyleTest { assertEquals(SourceFunction.class, layer.getFillOutlineColor().getFunction().getClass()); assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillOutlineColor().getFunction()).getProperty()); assertEquals(CategoricalStops.class, layer.getFillOutlineColor().getFunction().getStops().getClass()); + assertNotNull(((SourceFunction) layer.getFillOutlineColor().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getFillOutlineColor().getFunction()).getDefaultValue().getValue()); + assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getFillOutlineColor().getFunction()).getDefaultValue().getColorInt()); } @Test diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java index 740393ad36..466873f9e5 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java @@ -323,7 +323,7 @@ public class LineLayerTest extends BaseStyleTest { categorical( stop(1.0f, lineOpacity(0.3f)) ) - ).withDefaultValue(0.3f) + ).withDefaultValue(lineOpacity(0.3f)) ) ); @@ -333,7 +333,9 @@ public class LineLayerTest extends BaseStyleTest { assertEquals(SourceFunction.class, layer.getLineOpacity().getFunction().getClass()); assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineOpacity().getFunction()).getProperty()); assertEquals(CategoricalStops.class, layer.getLineOpacity().getFunction().getStops().getClass()); - assertEquals(0.3f, ((SourceFunction) layer.getLineOpacity().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getLineOpacity().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getLineOpacity().getFunction()).getDefaultValue().getValue()); + assertEquals(0.3f, ((SourceFunction) layer.getLineOpacity().getFunction()).getDefaultValue().getValue()); } @Test @@ -350,7 +352,7 @@ public class LineLayerTest extends BaseStyleTest { exponential( stop(0, 0.3f, lineOpacity(0.9f)) ).withBase(0.5f) - ).withDefaultValue(0.3f) + ).withDefaultValue(lineOpacity(0.3f)) ) ); @@ -466,7 +468,7 @@ public class LineLayerTest extends BaseStyleTest { categorical( stop("valueA", lineColor(Color.RED)) ) - ) + ).withDefaultValue(lineColor(Color.GREEN)) ) ); @@ -476,6 +478,9 @@ public class LineLayerTest extends BaseStyleTest { assertEquals(SourceFunction.class, layer.getLineColor().getFunction().getClass()); assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineColor().getFunction()).getProperty()); assertEquals(CategoricalStops.class, layer.getLineColor().getFunction().getStops().getClass()); + assertNotNull(((SourceFunction) layer.getLineColor().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getLineColor().getFunction()).getDefaultValue().getValue()); + assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getLineColor().getFunction()).getDefaultValue().getColorInt()); } @Test @@ -695,7 +700,7 @@ public class LineLayerTest extends BaseStyleTest { categorical( stop(1.0f, lineGapWidth(0.3f)) ) - ).withDefaultValue(0.3f) + ).withDefaultValue(lineGapWidth(0.3f)) ) ); @@ -705,7 +710,9 @@ public class LineLayerTest extends BaseStyleTest { assertEquals(SourceFunction.class, layer.getLineGapWidth().getFunction().getClass()); assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineGapWidth().getFunction()).getProperty()); assertEquals(CategoricalStops.class, layer.getLineGapWidth().getFunction().getStops().getClass()); - assertEquals(0.3f, ((SourceFunction) layer.getLineGapWidth().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getLineGapWidth().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getLineGapWidth().getFunction()).getDefaultValue().getValue()); + assertEquals(0.3f, ((SourceFunction) layer.getLineGapWidth().getFunction()).getDefaultValue().getValue()); } @Test @@ -722,7 +729,7 @@ public class LineLayerTest extends BaseStyleTest { exponential( stop(0, 0.3f, lineGapWidth(0.9f)) ).withBase(0.5f) - ).withDefaultValue(0.3f) + ).withDefaultValue(lineGapWidth(0.3f)) ) ); @@ -838,7 +845,7 @@ public class LineLayerTest extends BaseStyleTest { categorical( stop(1.0f, lineOffset(0.3f)) ) - ).withDefaultValue(0.3f) + ).withDefaultValue(lineOffset(0.3f)) ) ); @@ -848,7 +855,9 @@ public class LineLayerTest extends BaseStyleTest { assertEquals(SourceFunction.class, layer.getLineOffset().getFunction().getClass()); assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineOffset().getFunction()).getProperty()); assertEquals(CategoricalStops.class, layer.getLineOffset().getFunction().getStops().getClass()); - assertEquals(0.3f, ((SourceFunction) layer.getLineOffset().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getLineOffset().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getLineOffset().getFunction()).getDefaultValue().getValue()); + assertEquals(0.3f, ((SourceFunction) layer.getLineOffset().getFunction()).getDefaultValue().getValue()); } @Test @@ -865,7 +874,7 @@ public class LineLayerTest extends BaseStyleTest { exponential( stop(0, 0.3f, lineOffset(0.9f)) ).withBase(0.5f) - ).withDefaultValue(0.3f) + ).withDefaultValue(lineOffset(0.3f)) ) ); @@ -981,7 +990,7 @@ public class LineLayerTest extends BaseStyleTest { categorical( stop(1.0f, lineBlur(0.3f)) ) - ).withDefaultValue(0.3f) + ).withDefaultValue(lineBlur(0.3f)) ) ); @@ -991,7 +1000,9 @@ public class LineLayerTest extends BaseStyleTest { assertEquals(SourceFunction.class, layer.getLineBlur().getFunction().getClass()); assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineBlur().getFunction()).getProperty()); assertEquals(CategoricalStops.class, layer.getLineBlur().getFunction().getStops().getClass()); - assertEquals(0.3f, ((SourceFunction) layer.getLineBlur().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getLineBlur().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getLineBlur().getFunction()).getDefaultValue().getValue()); + assertEquals(0.3f, ((SourceFunction) layer.getLineBlur().getFunction()).getDefaultValue().getValue()); } @Test @@ -1008,7 +1019,7 @@ public class LineLayerTest extends BaseStyleTest { exponential( stop(0, 0.3f, lineBlur(0.9f)) ).withBase(0.5f) - ).withDefaultValue(0.3f) + ).withDefaultValue(lineBlur(0.3f)) ) ); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java index 3b3bc9c8b5..c90af339b1 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java @@ -576,7 +576,7 @@ public class SymbolLayerTest extends BaseStyleTest { categorical( stop(1.0f, iconRotate(0.3f)) ) - ).withDefaultValue(0.3f) + ).withDefaultValue(iconRotate(0.3f)) ) ); @@ -586,7 +586,9 @@ public class SymbolLayerTest extends BaseStyleTest { assertEquals(SourceFunction.class, layer.getIconRotate().getFunction().getClass()); assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconRotate().getFunction()).getProperty()); assertEquals(CategoricalStops.class, layer.getIconRotate().getFunction().getStops().getClass()); - assertEquals(0.3f, ((SourceFunction) layer.getIconRotate().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getIconRotate().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getIconRotate().getFunction()).getDefaultValue().getValue()); + assertEquals(0.3f, ((SourceFunction) layer.getIconRotate().getFunction()).getDefaultValue().getValue()); } @Test @@ -603,7 +605,7 @@ public class SymbolLayerTest extends BaseStyleTest { exponential( stop(0, 0.3f, iconRotate(0.9f)) ).withBase(0.5f) - ).withDefaultValue(0.3f) + ).withDefaultValue(iconRotate(0.3f)) ) ); @@ -1656,7 +1658,7 @@ public class SymbolLayerTest extends BaseStyleTest { categorical( stop(1.0f, iconOpacity(0.3f)) ) - ).withDefaultValue(0.3f) + ).withDefaultValue(iconOpacity(0.3f)) ) ); @@ -1666,7 +1668,9 @@ public class SymbolLayerTest extends BaseStyleTest { assertEquals(SourceFunction.class, layer.getIconOpacity().getFunction().getClass()); assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconOpacity().getFunction()).getProperty()); assertEquals(CategoricalStops.class, layer.getIconOpacity().getFunction().getStops().getClass()); - assertEquals(0.3f, ((SourceFunction) layer.getIconOpacity().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getIconOpacity().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getIconOpacity().getFunction()).getDefaultValue().getValue()); + assertEquals(0.3f, ((SourceFunction) layer.getIconOpacity().getFunction()).getDefaultValue().getValue()); } @Test @@ -1683,7 +1687,7 @@ public class SymbolLayerTest extends BaseStyleTest { exponential( stop(0, 0.3f, iconOpacity(0.9f)) ).withBase(0.5f) - ).withDefaultValue(0.3f) + ).withDefaultValue(iconOpacity(0.3f)) ) ); @@ -1799,7 +1803,7 @@ public class SymbolLayerTest extends BaseStyleTest { categorical( stop("valueA", iconColor(Color.RED)) ) - ) + ).withDefaultValue(iconColor(Color.GREEN)) ) ); @@ -1809,6 +1813,9 @@ public class SymbolLayerTest extends BaseStyleTest { assertEquals(SourceFunction.class, layer.getIconColor().getFunction().getClass()); assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconColor().getFunction()).getProperty()); assertEquals(CategoricalStops.class, layer.getIconColor().getFunction().getStops().getClass()); + assertNotNull(((SourceFunction) layer.getIconColor().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getIconColor().getFunction()).getDefaultValue().getValue()); + assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getIconColor().getFunction()).getDefaultValue().getColorInt()); } @Test @@ -1918,7 +1925,7 @@ public class SymbolLayerTest extends BaseStyleTest { categorical( stop("valueA", iconHaloColor(Color.RED)) ) - ) + ).withDefaultValue(iconHaloColor(Color.GREEN)) ) ); @@ -1928,6 +1935,9 @@ public class SymbolLayerTest extends BaseStyleTest { assertEquals(SourceFunction.class, layer.getIconHaloColor().getFunction().getClass()); assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloColor().getFunction()).getProperty()); assertEquals(CategoricalStops.class, layer.getIconHaloColor().getFunction().getStops().getClass()); + assertNotNull(((SourceFunction) layer.getIconHaloColor().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getIconHaloColor().getFunction()).getDefaultValue().getValue()); + assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getIconHaloColor().getFunction()).getDefaultValue().getColorInt()); } @Test @@ -2037,7 +2047,7 @@ public class SymbolLayerTest extends BaseStyleTest { categorical( stop(1.0f, iconHaloWidth(0.3f)) ) - ).withDefaultValue(0.3f) + ).withDefaultValue(iconHaloWidth(0.3f)) ) ); @@ -2047,7 +2057,9 @@ public class SymbolLayerTest extends BaseStyleTest { assertEquals(SourceFunction.class, layer.getIconHaloWidth().getFunction().getClass()); assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloWidth().getFunction()).getProperty()); assertEquals(CategoricalStops.class, layer.getIconHaloWidth().getFunction().getStops().getClass()); - assertEquals(0.3f, ((SourceFunction) layer.getIconHaloWidth().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getIconHaloWidth().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getIconHaloWidth().getFunction()).getDefaultValue().getValue()); + assertEquals(0.3f, ((SourceFunction) layer.getIconHaloWidth().getFunction()).getDefaultValue().getValue()); } @Test @@ -2064,7 +2076,7 @@ public class SymbolLayerTest extends BaseStyleTest { exponential( stop(0, 0.3f, iconHaloWidth(0.9f)) ).withBase(0.5f) - ).withDefaultValue(0.3f) + ).withDefaultValue(iconHaloWidth(0.3f)) ) ); @@ -2180,7 +2192,7 @@ public class SymbolLayerTest extends BaseStyleTest { categorical( stop(1.0f, iconHaloBlur(0.3f)) ) - ).withDefaultValue(0.3f) + ).withDefaultValue(iconHaloBlur(0.3f)) ) ); @@ -2190,7 +2202,9 @@ public class SymbolLayerTest extends BaseStyleTest { assertEquals(SourceFunction.class, layer.getIconHaloBlur().getFunction().getClass()); assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloBlur().getFunction()).getProperty()); assertEquals(CategoricalStops.class, layer.getIconHaloBlur().getFunction().getStops().getClass()); - assertEquals(0.3f, ((SourceFunction) layer.getIconHaloBlur().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getIconHaloBlur().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getIconHaloBlur().getFunction()).getDefaultValue().getValue()); + assertEquals(0.3f, ((SourceFunction) layer.getIconHaloBlur().getFunction()).getDefaultValue().getValue()); } @Test @@ -2207,7 +2221,7 @@ public class SymbolLayerTest extends BaseStyleTest { exponential( stop(0, 0.3f, iconHaloBlur(0.9f)) ).withBase(0.5f) - ).withDefaultValue(0.3f) + ).withDefaultValue(iconHaloBlur(0.3f)) ) ); @@ -2396,7 +2410,7 @@ public class SymbolLayerTest extends BaseStyleTest { categorical( stop(1.0f, textOpacity(0.3f)) ) - ).withDefaultValue(0.3f) + ).withDefaultValue(textOpacity(0.3f)) ) ); @@ -2406,7 +2420,9 @@ public class SymbolLayerTest extends BaseStyleTest { assertEquals(SourceFunction.class, layer.getTextOpacity().getFunction().getClass()); assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextOpacity().getFunction()).getProperty()); assertEquals(CategoricalStops.class, layer.getTextOpacity().getFunction().getStops().getClass()); - assertEquals(0.3f, ((SourceFunction) layer.getTextOpacity().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getTextOpacity().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getTextOpacity().getFunction()).getDefaultValue().getValue()); + assertEquals(0.3f, ((SourceFunction) layer.getTextOpacity().getFunction()).getDefaultValue().getValue()); } @Test @@ -2423,7 +2439,7 @@ public class SymbolLayerTest extends BaseStyleTest { exponential( stop(0, 0.3f, textOpacity(0.9f)) ).withBase(0.5f) - ).withDefaultValue(0.3f) + ).withDefaultValue(textOpacity(0.3f)) ) ); @@ -2539,7 +2555,7 @@ public class SymbolLayerTest extends BaseStyleTest { categorical( stop("valueA", textColor(Color.RED)) ) - ) + ).withDefaultValue(textColor(Color.GREEN)) ) ); @@ -2549,6 +2565,9 @@ public class SymbolLayerTest extends BaseStyleTest { assertEquals(SourceFunction.class, layer.getTextColor().getFunction().getClass()); assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextColor().getFunction()).getProperty()); assertEquals(CategoricalStops.class, layer.getTextColor().getFunction().getStops().getClass()); + assertNotNull(((SourceFunction) layer.getTextColor().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getTextColor().getFunction()).getDefaultValue().getValue()); + assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getTextColor().getFunction()).getDefaultValue().getColorInt()); } @Test @@ -2658,7 +2677,7 @@ public class SymbolLayerTest extends BaseStyleTest { categorical( stop("valueA", textHaloColor(Color.RED)) ) - ) + ).withDefaultValue(textHaloColor(Color.GREEN)) ) ); @@ -2668,6 +2687,9 @@ public class SymbolLayerTest extends BaseStyleTest { assertEquals(SourceFunction.class, layer.getTextHaloColor().getFunction().getClass()); assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloColor().getFunction()).getProperty()); assertEquals(CategoricalStops.class, layer.getTextHaloColor().getFunction().getStops().getClass()); + assertNotNull(((SourceFunction) layer.getTextHaloColor().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getTextHaloColor().getFunction()).getDefaultValue().getValue()); + assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getTextHaloColor().getFunction()).getDefaultValue().getColorInt()); } @Test @@ -2777,7 +2799,7 @@ public class SymbolLayerTest extends BaseStyleTest { categorical( stop(1.0f, textHaloWidth(0.3f)) ) - ).withDefaultValue(0.3f) + ).withDefaultValue(textHaloWidth(0.3f)) ) ); @@ -2787,7 +2809,9 @@ public class SymbolLayerTest extends BaseStyleTest { assertEquals(SourceFunction.class, layer.getTextHaloWidth().getFunction().getClass()); assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloWidth().getFunction()).getProperty()); assertEquals(CategoricalStops.class, layer.getTextHaloWidth().getFunction().getStops().getClass()); - assertEquals(0.3f, ((SourceFunction) layer.getTextHaloWidth().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getTextHaloWidth().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getTextHaloWidth().getFunction()).getDefaultValue().getValue()); + assertEquals(0.3f, ((SourceFunction) layer.getTextHaloWidth().getFunction()).getDefaultValue().getValue()); } @Test @@ -2804,7 +2828,7 @@ public class SymbolLayerTest extends BaseStyleTest { exponential( stop(0, 0.3f, textHaloWidth(0.9f)) ).withBase(0.5f) - ).withDefaultValue(0.3f) + ).withDefaultValue(textHaloWidth(0.3f)) ) ); @@ -2920,7 +2944,7 @@ public class SymbolLayerTest extends BaseStyleTest { categorical( stop(1.0f, textHaloBlur(0.3f)) ) - ).withDefaultValue(0.3f) + ).withDefaultValue(textHaloBlur(0.3f)) ) ); @@ -2930,7 +2954,9 @@ public class SymbolLayerTest extends BaseStyleTest { assertEquals(SourceFunction.class, layer.getTextHaloBlur().getFunction().getClass()); assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloBlur().getFunction()).getProperty()); assertEquals(CategoricalStops.class, layer.getTextHaloBlur().getFunction().getStops().getClass()); - assertEquals(0.3f, ((SourceFunction) layer.getTextHaloBlur().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getTextHaloBlur().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getTextHaloBlur().getFunction()).getDefaultValue().getValue()); + assertEquals(0.3f, ((SourceFunction) layer.getTextHaloBlur().getFunction()).getDefaultValue().getValue()); } @Test @@ -2947,7 +2973,7 @@ public class SymbolLayerTest extends BaseStyleTest { exponential( stop(0, 0.3f, textHaloBlur(0.9f)) ).withBase(0.5f) - ).withDefaultValue(0.3f) + ).withDefaultValue(textHaloBlur(0.3f)) ) ); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/layer.junit.ejs b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/layer.junit.ejs index f1d68caa24..3dc88d29bb 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/layer.junit.ejs +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/layer.junit.ejs @@ -269,11 +269,11 @@ public class <%- camelize(type) %>LayerTest extends BaseStyleTest { <% if (property.type == 'color') { -%> stop("valueA", <%- camelizeWithLeadingLowercase(property.name) %>(Color.RED)) ) - ) + ).withDefaultValue(<%- camelizeWithLeadingLowercase(property.name) %>(Color.GREEN)) <% } else {-%> stop(1.0f, <%- camelizeWithLeadingLowercase(property.name) %>(<%- defaultValueJava(property) %>)) ) - ).withDefaultValue(<%- defaultValueJava(property) %>) + ).withDefaultValue(<%- camelizeWithLeadingLowercase(property.name) %>(<%- defaultValueJava(property) %>)) <% } -%> ) ); @@ -284,8 +284,12 @@ public class <%- camelize(type) %>LayerTest extends BaseStyleTest { assertEquals(SourceFunction.class, layer.get<%- camelize(property.name) %>().getFunction().getClass()); assertEquals("FeaturePropertyA", ((SourceFunction) layer.get<%- camelize(property.name) %>().getFunction()).getProperty()); assertEquals(CategoricalStops.class, layer.get<%- camelize(property.name) %>().getFunction().getStops().getClass()); -<% if (property.type !== 'color') { -%> - assertEquals(<%- defaultValueJava(property) %>, ((SourceFunction) layer.get<%- camelize(property.name) %>().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.get<%- camelize(property.name) %>().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.get<%- camelize(property.name) %>().getFunction()).getDefaultValue().getValue()); +<% if (property.type === 'color') { -%> + assertEquals(Color.GREEN, (int) ((SourceFunction) layer.get<%- camelize(property.name) %>().getFunction()).getDefaultValue().getColorInt()); +<% } else { -%> + assertEquals(<%- defaultValueJava(property) %>, ((SourceFunction) layer.get<%- camelize(property.name) %>().getFunction()).getDefaultValue().getValue()); <% } -%> } <% if (property.type !== 'color') { -%> @@ -305,7 +309,7 @@ public class <%- camelize(type) %>LayerTest extends BaseStyleTest { stop(0, 0.3f, <%- camelizeWithLeadingLowercase(property.name) %>(0.9f)) ).withBase(0.5f) <% if (property.type == 'number') { -%> - ).withDefaultValue(<%- defaultValueJava(property) %>) + ).withDefaultValue(<%- camelizeWithLeadingLowercase(property.name) %>(<%- defaultValueJava(property) %>)) <% } else { -%> ) <% } -%> diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AddRemoveMarkerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AddRemoveMarkerActivity.java index abadc3e5d9..27958c3d0c 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AddRemoveMarkerActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AddRemoveMarkerActivity.java @@ -1,10 +1,18 @@ package com.mapbox.mapboxsdk.testapp.activity.annotation; +import android.annotation.SuppressLint; +import android.graphics.Bitmap; +import android.graphics.Color; import android.os.Bundle; -import android.support.v4.content.ContextCompat; +import android.support.annotation.DrawableRes; import android.support.v7.app.AppCompatActivity; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; import com.mapbox.mapboxsdk.annotations.Icon; +import com.mapbox.mapboxsdk.annotations.IconFactory; import com.mapbox.mapboxsdk.annotations.Marker; import com.mapbox.mapboxsdk.annotations.MarkerOptions; import com.mapbox.mapboxsdk.camera.CameraPosition; @@ -14,7 +22,7 @@ import com.mapbox.mapboxsdk.maps.MapView; import com.mapbox.mapboxsdk.maps.MapboxMap; import com.mapbox.mapboxsdk.maps.OnMapReadyCallback; import com.mapbox.mapboxsdk.testapp.R; -import com.mapbox.mapboxsdk.testapp.utils.IconUtils; +import com.mapbox.mapboxsdk.testapp.utils.ViewToBitmapUtil; import timber.log.Timber; @@ -40,20 +48,20 @@ public class AddRemoveMarkerActivity extends AppCompatActivity { super.onCreate(savedInstanceState); setContentView(R.layout.activity_add_remove_marker); - // ShapeDrawable to Icon - final Icon shapeDrawableIcon = IconUtils.drawableToIcon(this, R.drawable.ic_circle, - ContextCompat.getColor(this, R.color.redAccent)); - - // VectorDrawable to Icon - final Icon vectorDrawableIcon = IconUtils.drawableToIcon(this, R.drawable.ic_layers, - ContextCompat.getColor(this, R.color.blueAccent)); + View lowThresholdView = generateView("Low", R.drawable.ic_circle); + Bitmap lowThresholdBitmap = ViewToBitmapUtil.convertToBitmap(lowThresholdView); + Icon lowThresholdIcon = IconFactory.getInstance(this).fromBitmap(lowThresholdBitmap); lowThresholdMarker = new MarkerOptions() - .icon(shapeDrawableIcon) - .position(new LatLng(-0.1, 0)); + .icon(lowThresholdIcon) + .position(new LatLng(0.1, 0)); + + View highThesholdView = generateView("High", R.drawable.ic_circle); + Bitmap highThresholdBitmap = ViewToBitmapUtil.convertToBitmap(highThesholdView); + Icon highThresholdIcon = IconFactory.getInstance(this).fromBitmap(highThresholdBitmap); highThresholdMarker = new MarkerOptions() - .icon(vectorDrawableIcon) + .icon(highThresholdIcon) .position(new LatLng(0.1, 0)); mapView = (MapView) findViewById(R.id.mapView); @@ -74,6 +82,17 @@ public class AddRemoveMarkerActivity extends AppCompatActivity { }); } + @SuppressLint("InflateParams") + private View generateView(String text, @DrawableRes int drawableRes) { + View view = LayoutInflater.from(this).inflate(R.layout.view_custom_marker, null); + TextView textView = (TextView) view.findViewById(R.id.textView); + textView.setText(text); + textView.setTextColor(Color.WHITE); + ImageView imageView = (ImageView) view.findViewById(R.id.imageView); + imageView.setImageResource(drawableRes); + return view; + } + private void updateZoom(double zoom) { if (lastZoom == zoom) { return; diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxHighlightActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxHighlightActivity.java index ca4fe4e4fd..1d15efef84 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxHighlightActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxHighlightActivity.java @@ -11,6 +11,7 @@ import com.mapbox.mapboxsdk.maps.MapView; import com.mapbox.mapboxsdk.maps.MapboxMap; import com.mapbox.mapboxsdk.maps.OnMapReadyCallback; import com.mapbox.mapboxsdk.style.layers.FillLayer; +import com.mapbox.mapboxsdk.style.layers.Filter; import com.mapbox.mapboxsdk.style.sources.GeoJsonSource; import com.mapbox.mapboxsdk.testapp.R; import com.mapbox.services.commons.geojson.Feature; @@ -53,7 +54,7 @@ public class QueryRenderedFeaturesBoxHighlightActivity extends AppCompatActivity int left = selectionBox.getLeft() - mapView.getLeft(); RectF box = new RectF(left, top, left + selectionBox.getWidth(), top + selectionBox.getHeight()); Timber.i(String.format("Querying box %s for buildings", box)); - List<Feature> features = mapboxMap.queryRenderedFeatures(box, "building"); + List<Feature> features = mapboxMap.queryRenderedFeatures(box, Filter.lt("height", 10), "building"); // Show count Toast.makeText( diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ViewToBitmapUtil.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ViewToBitmapUtil.java new file mode 100644 index 0000000000..e8091248f4 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ViewToBitmapUtil.java @@ -0,0 +1,22 @@ +package com.mapbox.mapboxsdk.testapp.utils; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.support.annotation.NonNull; +import android.view.View; + +/** + * Converts a View to a Bitmap so we can use an Android SDK View as a Symbol. + */ +public class ViewToBitmapUtil { + + public static Bitmap convertToBitmap(@NonNull View view) { + view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), + View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); + view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight()); + Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + view.draw(canvas); + return bitmap; + } +} diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/view_custom_marker.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/view_custom_marker.xml index c2bbdae775..324a4861c3 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/view_custom_marker.xml +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/view_custom_marker.xml @@ -11,11 +11,10 @@ <TextView android:id="@id/textView" android:layout_width="wrap_content" - android:textColor="@android:color/white" android:layout_height="wrap_content" - android:textStyle="bold" - android:layout_alignBottom="@id/imageView" - android:layout_centerHorizontal="true" - android:padding="2dp"/> + android:layout_centerInParent="true" + android:padding="2dp" + android:textColor="@android:color/white" + android:textStyle="bold"/> </RelativeLayout> diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/MapboxTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/MapboxTest.java new file mode 100644 index 0000000000..0c1f28515d --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/MapboxTest.java @@ -0,0 +1,92 @@ +package com.mapbox.mapboxsdk; + +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; + +import com.mapbox.mapboxsdk.exceptions.InvalidAccessTokenException; + +import org.junit.Before; +import org.junit.Test; + +import java.lang.reflect.Field; + +import static junit.framework.TestCase.assertNotNull; +import static junit.framework.TestCase.assertSame; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class MapboxTest { + + private Context context; + private Context appContext; + + @Before + public void before() { + context = mock(Context.class); + appContext = mock(Context.class); + when(context.getApplicationContext()).thenReturn(appContext); + } + + @Test + public void testGetAccessToken() { + final String accessToken = "pk.0000000001"; + injectMapboxSingleton(accessToken); + assertSame(accessToken, Mapbox.getAccessToken()); + } + + @Test(expected = InvalidAccessTokenException.class) + public void testGetInvalidAccessToken() { + final String accessToken = "dummy"; + injectMapboxSingleton(accessToken); + assertSame(accessToken, Mapbox.getAccessToken()); + } + + @Test + public void testApplicationContext() { + injectMapboxSingleton("dummy"); + assertNotNull(Mapbox.getApplicationContext()); + assertNotEquals(context, appContext); + assertEquals(appContext, appContext); + } + + @Test + public void testConnected() { + injectMapboxSingleton("dummy"); + + // test Android connectivity + ConnectivityManager connectivityManager = mock(ConnectivityManager.class); + NetworkInfo networkInfo = mock(NetworkInfo.class); + when(appContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(connectivityManager); + when(connectivityManager.getActiveNetworkInfo()).thenReturn(networkInfo); + when(networkInfo.isConnected()).thenReturn(false); + assertFalse(Mapbox.isConnected()); + when(networkInfo.isConnected()).thenReturn(true); + assertTrue(Mapbox.isConnected()); + + // test manual connectivity + Mapbox.setConnected(true); + assertTrue(Mapbox.isConnected()); + Mapbox.setConnected(false); + assertFalse(Mapbox.isConnected()); + + // reset to Android connectivity + Mapbox.setConnected(null); + assertTrue(Mapbox.isConnected()); + } + + private void injectMapboxSingleton(String accessToken) { + Mapbox mapbox = new Mapbox(appContext, accessToken); + try { + Field field = Mapbox.class.getDeclaredField("INSTANCE"); + field.setAccessible(true); + field.set(mapbox, mapbox); + } catch (Exception exception) { + throw new AssertionError(); + } + } +} diff --git a/platform/android/build.gradle b/platform/android/build.gradle index 69eb6616d1..4219f2bdee 100644 --- a/platform/android/build.gradle +++ b/platform/android/build.gradle @@ -3,7 +3,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.2.3' + classpath 'com.android.tools.build:gradle:2.3.0' classpath 'com.amazonaws:aws-devicefarm-gradle-plugin:1.2' classpath 'com.stanfy.spoon:spoon-gradle-plugin:1.2.1' } diff --git a/platform/android/config.cmake b/platform/android/config.cmake index 18458deba6..3dd8e7f67d 100644 --- a/platform/android/config.cmake +++ b/platform/android/config.cmake @@ -20,7 +20,7 @@ mason_use(libzip VERSION 1.1.3) mason_use(nunicode VERSION 1.7.1) mason_use(sqlite VERSION 3.14.2) mason_use(gtest VERSION 1.8.0) -mason_use(icu VERSION 58.1) +mason_use(icu VERSION 58.1-min-size) set(ANDROID_SDK_PROJECT_DIR ${CMAKE_SOURCE_DIR}/platform/android/MapboxGLAndroidSDK) set(ANDROID_JNI_TARGET_DIR ${ANDROID_SDK_PROJECT_DIR}/src/main/jniLibs/${ANDROID_ABI}) @@ -218,7 +218,6 @@ macro(mbgl_platform_core) PRIVATE -fvisibility=hidden PRIVATE -ffunction-sections PRIVATE -fdata-sections - PRIVATE -Os ) target_link_libraries(mbgl-core @@ -244,7 +243,6 @@ target_compile_options(mapbox-gl PRIVATE -fvisibility=hidden PRIVATE -ffunction-sections PRIVATE -fdata-sections - PRIVATE -Os ) target_link_libraries(mapbox-gl @@ -285,7 +283,6 @@ target_sources(mbgl-test target_compile_options(mbgl-test PRIVATE -fvisibility=hidden - PRIVATE -Os ) target_compile_definitions(mbgl-test @@ -329,7 +326,6 @@ target_compile_options(example-custom-layer PRIVATE -fvisibility=hidden PRIVATE -ffunction-sections PRIVATE -fdata-sections - PRIVATE -Os ) target_link_libraries(example-custom-layer diff --git a/platform/android/dependencies.gradle b/platform/android/dependencies.gradle index 2cdb455190..3eb28452c6 100644 --- a/platform/android/dependencies.gradle +++ b/platform/android/dependencies.gradle @@ -7,7 +7,7 @@ ext { versionCode = 11 versionName = "5.0.0" - supportLibVersion = "25.1.1" + supportLibVersion = "25.2.0" leakCanaryVersion = '1.5' wearableVersion = '2.0.0' diff --git a/platform/android/gradle/wrapper/gradle-wrapper.properties b/platform/android/gradle/wrapper/gradle-wrapper.properties index 20b2b0894c..c7ad166b13 100644 --- a/platform/android/gradle/wrapper/gradle-wrapper.properties +++ b/platform/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon Dec 12 10:58:15 CET 2016 +#Fri Mar 03 10:22:19 EST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.2.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp index 1930d1854d..c97bdbbfe3 100755 --- a/platform/android/src/native_map_view.cpp +++ b/platform/android/src/native_map_view.cpp @@ -26,7 +26,14 @@ #include <mbgl/util/logging.hpp> #include <mbgl/util/platform.hpp> #include <mbgl/sprite/sprite_image.hpp> +#include <mbgl/style/filter.hpp> +// Java -> C++ conversion +#include "style/android_conversion.hpp" +#include <mbgl/style/conversion.hpp> +#include <mbgl/style/conversion/filter.hpp> + +// C++ -> Java conversion #include "conversion/conversion.hpp" #include "conversion/collection.hpp" #include "geometry/conversion/feature.hpp" @@ -694,6 +701,9 @@ void NativeMapView::setTransitionDelay(JNIEnv&, jlong delay) { } jni::Array<jlong> NativeMapView::queryPointAnnotations(JNIEnv& env, jni::Object<RectF> rect) { + using namespace mbgl::style; + using namespace mbgl::style::conversion; + // Convert input mbgl::ScreenBox box = { { RectF::getLeft(env, rect), RectF::getTop(env, rect) }, @@ -711,20 +721,40 @@ jni::Array<jlong> NativeMapView::queryPointAnnotations(JNIEnv& env, jni::Object< return result; } -jni::Array<jni::Object<Feature>> NativeMapView::queryRenderedFeaturesForPoint(JNIEnv& env, jni::jfloat x, jni::jfloat y, jni::Array<jni::String> layerIds) { +static inline optional<mbgl::style::Filter> toFilter(jni::JNIEnv& env, jni::Array<jni::Object<>> jfilter) { + using namespace mbgl::style; + using namespace mbgl::style::conversion; + + mbgl::optional<Filter> filter; + if (jfilter) { + Value filterValue(env, jfilter); + auto converted = convert<Filter>(filterValue); + if (!converted) { + mbgl::Log::Error(mbgl::Event::JNI, "Error setting filter: " + converted.error().message); + } + filter = std::move(*converted); + } + return filter; +} + +jni::Array<jni::Object<Feature>> NativeMapView::queryRenderedFeaturesForPoint(JNIEnv& env, jni::jfloat x, jni::jfloat y, + jni::Array<jni::String> layerIds, + jni::Array<jni::Object<>> jfilter) { using namespace mbgl::android::conversion; using namespace mapbox::geometry; mbgl::optional<std::vector<std::string>> layers; if (layerIds != nullptr && layerIds.Length(env) > 0) { - layers = toVector(env, layerIds); + layers = android::conversion::toVector(env, layerIds); } point<double> point = {x, y}; - return *convert<jni::Array<jni::Object<Feature>>, std::vector<mbgl::Feature>>(env, map->queryRenderedFeatures(point, layers)); + return *convert<jni::Array<jni::Object<Feature>>, std::vector<mbgl::Feature>>(env, map->queryRenderedFeatures(point, { layers, toFilter(env, jfilter) })); } -jni::Array<jni::Object<Feature>> NativeMapView::queryRenderedFeaturesForBox(JNIEnv& env, jni::jfloat left, jni::jfloat top, jni::jfloat right, jni::jfloat bottom, jni::Array<jni::String> layerIds) { +jni::Array<jni::Object<Feature>> NativeMapView::queryRenderedFeaturesForBox(JNIEnv& env, jni::jfloat left, jni::jfloat top, + jni::jfloat right, jni::jfloat bottom, jni::Array<jni::String> layerIds, + jni::Array<jni::Object<>> jfilter) { using namespace mbgl::android::conversion; using namespace mapbox::geometry; @@ -734,7 +764,7 @@ jni::Array<jni::Object<Feature>> NativeMapView::queryRenderedFeaturesForBox(JNIE } box<double> box = { point<double>{ left, top}, point<double>{ right, bottom } }; - return *convert<jni::Array<jni::Object<Feature>>, std::vector<mbgl::Feature>>(env, map->queryRenderedFeatures(box, layers)); + return *convert<jni::Array<jni::Object<Feature>>, std::vector<mbgl::Feature>>(env, map->queryRenderedFeatures(box, { layers, toFilter(env, jfilter) })); } jni::Array<jni::Object<Layer>> NativeMapView::getLayers(JNIEnv& env) { diff --git a/platform/android/src/native_map_view.hpp b/platform/android/src/native_map_view.hpp index c38afd3e6c..b7bf03402e 100755 --- a/platform/android/src/native_map_view.hpp +++ b/platform/android/src/native_map_view.hpp @@ -197,9 +197,13 @@ public: jni::Array<jlong> queryPointAnnotations(JNIEnv&, jni::Object<RectF>); - jni::Array<jni::Object<Feature>> queryRenderedFeaturesForPoint(JNIEnv&, jni::jfloat, jni::jfloat, jni::Array<jni::String>); + jni::Array<jni::Object<Feature>> queryRenderedFeaturesForPoint(JNIEnv&, jni::jfloat, jni::jfloat, + jni::Array<jni::String>, + jni::Array<jni::Object<>> jfilter); - jni::Array<jni::Object<Feature>> queryRenderedFeaturesForBox(JNIEnv&, jni::jfloat, jni::jfloat, jni::jfloat, jni::jfloat, jni::Array<jni::String>); + jni::Array<jni::Object<Feature>> queryRenderedFeaturesForBox(JNIEnv&, jni::jfloat, jni::jfloat, jni::jfloat, + jni::jfloat, jni::Array<jni::String>, + jni::Array<jni::Object<>> jfilter); jni::Array<jni::Object<Layer>> getLayers(JNIEnv&); diff --git a/platform/default/bidi.cpp b/platform/default/bidi.cpp index 08a02ee60f..d9ed2658ef 100644 --- a/platform/default/bidi.cpp +++ b/platform/default/bidi.cpp @@ -1,9 +1,11 @@ -#include <memory> - #include <mbgl/text/bidi.hpp> +#include <mbgl/util/traits.hpp> + #include <unicode/ubidi.h> #include <unicode/ushape.h> +#include <memory> + namespace mbgl { class BiDiImpl { @@ -28,7 +30,7 @@ std::u16string applyArabicShaping(const std::u16string& input) { UErrorCode errorCode = U_ZERO_ERROR; const int32_t outputLength = - u_shapeArabic(input.c_str(), static_cast<int32_t>(input.size()), NULL, 0, + u_shapeArabic(mbgl::utf16char_cast<const UChar*>(input.c_str()), static_cast<int32_t>(input.size()), NULL, 0, (U_SHAPE_LETTERS_SHAPE & U_SHAPE_LETTERS_MASK) | (U_SHAPE_TEXT_DIRECTION_LOGICAL & U_SHAPE_TEXT_DIRECTION_MASK), &errorCode); @@ -38,7 +40,7 @@ std::u16string applyArabicShaping(const std::u16string& input) { std::u16string outputText(outputLength, 0); - u_shapeArabic(input.c_str(), static_cast<int32_t>(input.size()), &outputText[0], outputLength, + u_shapeArabic(mbgl::utf16char_cast<const UChar*>(input.c_str()), static_cast<int32_t>(input.size()), mbgl::utf16char_cast<UChar*>(&outputText[0]), outputLength, (U_SHAPE_LETTERS_SHAPE & U_SHAPE_LETTERS_MASK) | (U_SHAPE_TEXT_DIRECTION_LOGICAL & U_SHAPE_TEXT_DIRECTION_MASK), &errorCode); @@ -89,7 +91,7 @@ std::vector<std::u16string> BiDi::processText(const std::u16string& input, std::set<std::size_t> lineBreakPoints) { UErrorCode errorCode = U_ZERO_ERROR; - ubidi_setPara(impl->bidiText, input.c_str(), static_cast<int32_t>(input.size()), + ubidi_setPara(impl->bidiText, mbgl::utf16char_cast<const UChar*>(input.c_str()), static_cast<int32_t>(input.size()), UBIDI_DEFAULT_LTR, NULL, &errorCode); if (U_FAILURE(errorCode)) { diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index bfbb854289..680984b018 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -60,6 +60,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT * Fixed an issue that sometimes caused crashes when the SDK interacted with the file system in the background. ([#8125](https://github.com/mapbox/mapbox-gl-native/pull/8125)) * Added a `MGLDistanceFormatter` class for formatting geographic distances. ([#7888](https://github.com/mapbox/mapbox-gl-native/pull/7888)) * Fixed an issue that was causing the system location indicator to stay on in background after telemetry was disabled. ([#7833](https://github.com/mapbox/mapbox-gl-native/pull/7833)) +* Added support for predicates in rendered feature querying [8256](https://github.com/mapbox/mapbox-gl-native/pull/8246) ## 3.4.2 - February 21, 2017 diff --git a/platform/ios/config.cmake b/platform/ios/config.cmake index 72e1c88525..cab8fd1357 100644 --- a/platform/ios/config.cmake +++ b/platform/ios/config.cmake @@ -1,6 +1,6 @@ add_definitions(-DMBGL_USE_GLES2=1) -mason_use(icu VERSION 58.1) +mason_use(icu VERSION 58.1-min-size) macro(mbgl_platform_core) set_xcode_property(mbgl-core IPHONEOS_DEPLOYMENT_TARGET "8.0") diff --git a/platform/ios/src/MGLAnnotationView.h b/platform/ios/src/MGLAnnotationView.h index 532483350a..184efdb324 100644 --- a/platform/ios/src/MGLAnnotationView.h +++ b/platform/ios/src/MGLAnnotationView.h @@ -89,7 +89,7 @@ typedef NS_ENUM(NSUInteger, MGLAnnotationViewDragState) { contains a non-`nil` value while the annotation view is visible on the map. If the view is queued, waiting to be reused, the value is `nil`. */ -@property (nonatomic, readonly, nullable) id <MGLAnnotation> annotation; +@property (nonatomic, nullable) id <MGLAnnotation> annotation; /** The string that identifies that this annotation view is reusable. diff --git a/platform/ios/src/MGLAnnotationView.mm b/platform/ios/src/MGLAnnotationView.mm index 5b105cde72..0e904779d5 100644 --- a/platform/ios/src/MGLAnnotationView.mm +++ b/platform/ios/src/MGLAnnotationView.mm @@ -10,7 +10,6 @@ @interface MGLAnnotationView () <UIGestureRecognizerDelegate> @property (nonatomic, readwrite, nullable) NSString *reuseIdentifier; -@property (nonatomic, readwrite, nullable) id <MGLAnnotation> annotation; @property (nonatomic, readwrite) CATransform3D lastAppliedScaleTransform; @property (nonatomic, weak) UIPanGestureRecognizer *panGestureRecognizer; @property (nonatomic, weak) UILongPressGestureRecognizer *longPressRecognizer; @@ -240,6 +239,7 @@ } else if (dragState == MGLAnnotationViewDragStateCanceling) { + NSAssert(self.annotation, @"Annotation property should not be nil."); self.panGestureRecognizer.enabled = NO; self.longPressRecognizer.enabled = NO; self.center = [self.mapView convertCoordinate:self.annotation.coordinate toPointToView:self.mapView]; diff --git a/platform/ios/src/MGLAnnotationView_Private.h b/platform/ios/src/MGLAnnotationView_Private.h index 8a0af3565c..c4695051c5 100644 --- a/platform/ios/src/MGLAnnotationView_Private.h +++ b/platform/ios/src/MGLAnnotationView_Private.h @@ -8,7 +8,6 @@ NS_ASSUME_NONNULL_BEGIN @interface MGLAnnotationView (Private) @property (nonatomic, readwrite, nullable) NSString *reuseIdentifier; -@property (nonatomic, readwrite, nullable) id <MGLAnnotation> annotation; @property (nonatomic, weak) MGLMapView *mapView; @end diff --git a/platform/ios/src/MGLMapView.h b/platform/ios/src/MGLMapView.h index 5d6daf74c5..063818dc6e 100644 --- a/platform/ios/src/MGLMapView.h +++ b/platform/ios/src/MGLMapView.h @@ -1170,6 +1170,25 @@ IB_DESIGNABLE /** Returns an array of rendered map features that intersect with a given point, restricted to the given style layers. + + This method may return all features from the specified layers. To filter + the returned features, use the + `-visibleFeaturesAtPoint:inStyleLayersWithIdentifiers:predicate:` method. For more + information about searching for map features, see that method’s documentation. + + @param point A point expressed in the map view’s coordinate system. + @param styleLayerIdentifiers A set of strings that correspond to the names + of layers defined in the current style. Only the features contained in + these layers are included in the returned array. + @return An array of objects conforming to the `MGLFeature` protocol that + represent features in the sources used by the current style. + */ +- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesAtPoint:(CGPoint)point inStyleLayersWithIdentifiers:(nullable NS_SET_OF(NSString *) *)styleLayerIdentifiers NS_SWIFT_NAME(visibleFeatures(at:styleLayerIdentifiers:)); + +/** + Returns an array of rendered map features that intersect with a given point, + restricted to the given style layers and filtered by the given + predicate. Each object in the returned array represents a feature rendered by the current style and provides access to attributes specified by the relevant @@ -1217,10 +1236,11 @@ IB_DESIGNABLE @param styleLayerIdentifiers A set of strings that correspond to the names of layers defined in the current style. Only the features contained in these layers are included in the returned array. + @param predicate A predicate to filter the returned features. @return An array of objects conforming to the `MGLFeature` protocol that represent features in the sources used by the current style. */ -- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesAtPoint:(CGPoint)point inStyleLayersWithIdentifiers:(nullable NS_SET_OF(NSString *) *)styleLayerIdentifiers NS_SWIFT_NAME(visibleFeatures(at:styleLayerIdentifiers:)); +- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesAtPoint:(CGPoint)point inStyleLayersWithIdentifiers:(nullable NS_SET_OF(NSString *) *)styleLayerIdentifiers predicate:(nullable NSPredicate *)predicate NS_SWIFT_NAME(visibleFeatures(at:styleLayerIdentifiers:predicate:)); /** Returns an array of rendered map features that intersect with the given @@ -1240,7 +1260,27 @@ IB_DESIGNABLE /** Returns an array of rendered map features that intersect with the given rectangle, restricted to the given style layers. + + This method may return all features from the specified layers. To filter + the returned features, use the + `-visibleFeaturesAtPoint:inStyleLayersWithIdentifiers:predicate:` method. For + more information about searching for map features, see that method’s + documentation. + + @param rect A rectangle expressed in the map view’s coordinate system. + @param styleLayerIdentifiers A set of strings that correspond to the names of + layers defined in the current style. Only the features contained in these + layers are included in the returned array. + @return An array of objects conforming to the `MGLFeature` protocol that + represent features in the sources used by the current style. + */ +- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesInRect:(CGRect)rect inStyleLayersWithIdentifiers:(nullable NS_SET_OF(NSString *) *)styleLayerIdentifiers NS_SWIFT_NAME(visibleFeatures(in:styleLayerIdentifiers:)); +/** + Returns an array of rendered map features that intersect with the given + rectangle, restricted to the given style layers and filtered by the given + predicate. + Each object in the returned array represents a feature rendered by the current style and provides access to attributes specified by the relevant <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources">tile sources</a>. @@ -1277,21 +1317,22 @@ IB_DESIGNABLE <a href="https://www.mapbox.com/studio/">Mapbox Studio</a>. @note Layer identifiers are not guaranteed to exist across styles or different - versions of the same style. Applications that use this API must first set the - style URL to an explicitly versioned style using a convenience method like - `+[MGLStyle outdoorsStyleURLWithVersion:]`, `MGLMapView`’s “Style URL” - inspectable in Interface Builder, or a manually constructed `NSURL`. This - approach also avoids layer identifer name changes that will occur in the default - style’s layers over time. - + versions of the same style. Applications that use this API must first set the + style URL to an explicitly versioned style using a convenience method like + `+[MGLStyle outdoorsStyleURLWithVersion:]`, `MGLMapView`’s “Style URL” + inspectable in Interface Builder, or a manually constructed `NSURL`. This + approach also avoids layer identifer name changes that will occur in the default + style’s layers over time. + @param rect A rectangle expressed in the map view’s coordinate system. @param styleLayerIdentifiers A set of strings that correspond to the names of layers defined in the current style. Only the features contained in these layers are included in the returned array. + @param predicate A predicate to filter the returned features. @return An array of objects conforming to the `MGLFeature` protocol that represent features in the sources used by the current style. */ -- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesInRect:(CGRect)rect inStyleLayersWithIdentifiers:(nullable NS_SET_OF(NSString *) *)styleLayerIdentifiers NS_SWIFT_NAME(visibleFeatures(in:styleLayerIdentifiers:)); +- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesInRect:(CGRect)rect inStyleLayersWithIdentifiers:(nullable NS_SET_OF(NSString *) *)styleLayerIdentifiers predicate:(nullable NSPredicate *)predicate NS_SWIFT_NAME(visibleFeatures(in:styleLayerIdentifiers:predicate:)); #pragma mark Debugging the Map diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 35c6a3d0e8..f0aa2804a6 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -45,6 +45,7 @@ #import "NSException+MGLAdditions.h" #import "NSURL+MGLAdditions.h" #import "UIImage+MGLAdditions.h" +#import "NSPredicate+MGLAdditions.h" #import "MGLFaux3DUserLocationAnnotationView.h" #import "MGLUserLocationAnnotationView.h" @@ -1525,6 +1526,7 @@ public: { if (view.centerOffset.dx != 0 || view.centerOffset.dy != 0) { if (CGRectContainsPoint(view.frame, tapPoint)) { + NSAssert(view.annotation, @"Annotation's view annotation property should not be nil."); CGPoint annotationPoint = [self convertCoordinate:view.annotation.coordinate toPointToView:self]; tapPoint = annotationPoint; } @@ -4604,7 +4606,11 @@ public: return [self visibleFeaturesAtPoint:point inStyleLayersWithIdentifiers:nil]; } -- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesAtPoint:(CGPoint)point inStyleLayersWithIdentifiers:(NS_SET_OF(NSString *) *)styleLayerIdentifiers +- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesAtPoint:(CGPoint)point inStyleLayersWithIdentifiers:(NS_SET_OF(NSString *) *)styleLayerIdentifiers { + return [self visibleFeaturesAtPoint:point inStyleLayersWithIdentifiers:styleLayerIdentifiers predicate:nil]; +} + +- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesAtPoint:(CGPoint)point inStyleLayersWithIdentifiers:(NS_SET_OF(NSString *) *)styleLayerIdentifiers predicate:(NSPredicate *)predicate { mbgl::ScreenCoordinate screenCoordinate = { point.x, point.y }; @@ -4619,8 +4625,13 @@ public: }]; optionalLayerIDs = layerIDs; } + + mbgl::optional<mbgl::style::Filter> optionalFilter; + if (predicate) { + optionalFilter = predicate.mgl_filter; + } - std::vector<mbgl::Feature> features = _mbglMap->queryRenderedFeatures(screenCoordinate, optionalLayerIDs); + std::vector<mbgl::Feature> features = _mbglMap->queryRenderedFeatures(screenCoordinate, { optionalLayerIDs, optionalFilter }); return MGLFeaturesFromMBGLFeatures(features); } @@ -4629,6 +4640,10 @@ public: } - (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesInRect:(CGRect)rect inStyleLayersWithIdentifiers:(NS_SET_OF(NSString *) *)styleLayerIdentifiers { + return [self visibleFeaturesInRect:rect inStyleLayersWithIdentifiers:styleLayerIdentifiers predicate:nil]; +} + +- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesInRect:(CGRect)rect inStyleLayersWithIdentifiers:(NS_SET_OF(NSString *) *)styleLayerIdentifiers predicate:(NSPredicate *)predicate { mbgl::ScreenBox screenBox = { { CGRectGetMinX(rect), CGRectGetMinY(rect) }, { CGRectGetMaxX(rect), CGRectGetMaxY(rect) }, @@ -4643,8 +4658,13 @@ public: }]; optionalLayerIDs = layerIDs; } + + mbgl::optional<mbgl::style::Filter> optionalFilter; + if (predicate) { + optionalFilter = predicate.mgl_filter; + } - std::vector<mbgl::Feature> features = _mbglMap->queryRenderedFeatures(screenBox, optionalLayerIDs); + std::vector<mbgl::Feature> features = _mbglMap->queryRenderedFeatures(screenBox, { optionalLayerIDs, optionalFilter }); return MGLFeaturesFromMBGLFeatures(features); } diff --git a/platform/linux/config.cmake b/platform/linux/config.cmake index b2366540ae..ff2dcf4cfa 100644 --- a/platform/linux/config.cmake +++ b/platform/linux/config.cmake @@ -9,7 +9,7 @@ mason_use(libjpeg-turbo VERSION 1.5.0) mason_use(webp VERSION 0.5.1) mason_use(gtest VERSION 1.8.0${MASON_CXXABI_SUFFIX}) mason_use(benchmark VERSION 1.0.0-1) -mason_use(icu VERSION 58.1) +mason_use(icu VERSION 58.1-min-size) include(cmake/loop-uv.cmake) diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md index b809ef9a24..ff1fd22896 100644 --- a/platform/macos/CHANGELOG.md +++ b/platform/macos/CHANGELOG.md @@ -51,6 +51,7 @@ * Fixed an issue where translucent point annotations along tile boundaries would be drawn darker than expected. ([#6832](https://github.com/mapbox/mapbox-gl-native/pull/6832)) * Fixed flickering that occurred when panning past the antimeridian. ([#7574](https://github.com/mapbox/mapbox-gl-native/pull/7574)) * Added a `MGLDistanceFormatter` class for formatting geographic distances. ([#7888](https://github.com/mapbox/mapbox-gl-native/pull/7888)) +* Added support for predicates in rendered feature querying [8256](https://github.com/mapbox/mapbox-gl-native/pull/8246) ## 0.3.1 - February 21, 2017 diff --git a/platform/macos/config.cmake b/platform/macos/config.cmake index 309d8e82f3..cbaf3d492e 100644 --- a/platform/macos/config.cmake +++ b/platform/macos/config.cmake @@ -4,7 +4,7 @@ mason_use(glfw VERSION 2017-02-09-77a8f10) mason_use(boost_libprogram_options VERSION 1.62.0) mason_use(gtest VERSION 1.8.0) mason_use(benchmark VERSION 1.0.0-1) -mason_use(icu VERSION 58.1) +mason_use(icu VERSION 58.1-min-size) include(cmake/loop-darwin.cmake) diff --git a/platform/macos/src/MGLMapView.h b/platform/macos/src/MGLMapView.h index 4d1a2fc2c4..fa07821e19 100644 --- a/platform/macos/src/MGLMapView.h +++ b/platform/macos/src/MGLMapView.h @@ -789,6 +789,33 @@ MGL_EXPORT IB_DESIGNABLE Returns an array of rendered map features that intersect with a given point, restricted to the given style layers. + This method may return all features from the specified layers. To filter + the returned features, use the + `-visibleFeaturesAtPoint:inStyleLayersWithIdentifiers:predicate:` method. For more + information about searching for map features, see that method’s documentation. + + @note Layer identifiers are not guaranteed to exist across styles or different + versions of the same style. Applications that use this API must first set the + style URL to an explicitly versioned style using a convenience method like + `+[MGLStyle outdoorsStyleURLWithVersion:]`, `MGLMapView`’s “Style URL” + inspectable in Interface Builder, or a manually constructed `NSURL`. This + approach also avoids layer identifer name changes that will occur in the default + style’s layers over time. + + @param point A point expressed in the map view’s coordinate system. + @param styleLayerIdentifiers A set of strings that correspond to the names of + layers defined in the current style. Only the features contained in these + layers are included in the returned array. + @return An array of objects conforming to the `MGLFeature` protocol that + represent features in the sources used by the current style. + */ +- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesAtPoint:(NSPoint)point inStyleLayersWithIdentifiers:(nullable NS_SET_OF(NSString *) *)styleLayerIdentifiers NS_SWIFT_NAME(visibleFeatures(at:styleLayerIdentifiers:)); + +/** + Returns an array of rendered map features that intersect with a given point, + restricted to the given style layers and filtered by the given + predicate. + Each object in the returned array represents a feature rendered by the current style and provides access to attributes specified by the relevant <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources">tile sources</a>. @@ -824,21 +851,22 @@ MGL_EXPORT IB_DESIGNABLE <a href="https://www.mapbox.com/studio/">Mapbox Studio</a>. @note Layer identifiers are not guaranteed to exist across styles or different - versions of the same style. Applications that use this API must first set the - style URL to an explicitly versioned style using a convenience method like - `+[MGLStyle outdoorsStyleURLWithVersion:]`, `MGLMapView`’s “Style URL” - inspectable in Interface Builder, or a manually constructed `NSURL`. This - approach also avoids layer identifer name changes that will occur in the default - style’s layers over time. - + versions of the same style. Applications that use this API must first set the + style URL to an explicitly versioned style using a convenience method like + `+[MGLStyle outdoorsStyleURLWithVersion:]`, `MGLMapView`’s “Style URL” + inspectable in Interface Builder, or a manually constructed `NSURL`. This + approach also avoids layer identifer name changes that will occur in the default + style’s layers over time. + @param point A point expressed in the map view’s coordinate system. @param styleLayerIdentifiers A set of strings that correspond to the names of - layers defined in the current style. Only the features contained in these - layers are included in the returned array. + layers defined in the current style. Only the features contained in these + layers are included in the returned array. + @param predicate A predicate to filter the returned features. @return An array of objects conforming to the `MGLFeature` protocol that - represent features in the sources used by the current style. + represent features in the sources used by the current style. */ -- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesAtPoint:(NSPoint)point inStyleLayersWithIdentifiers:(nullable NS_SET_OF(NSString *) *)styleLayerIdentifiers NS_SWIFT_NAME(visibleFeatures(_:styleLayerIdentifiers:)); +- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesAtPoint:(NSPoint)point inStyleLayersWithIdentifiers:(nullable NS_SET_OF(NSString *) *)styleLayerIdentifiers predicate:(nullable NSPredicate *)predicate NS_SWIFT_NAME(visibleFeatures(at:styleLayerIdentifiers:predicate:)); /** Returns an array of rendered map features that intersect with the given @@ -858,7 +886,28 @@ MGL_EXPORT IB_DESIGNABLE /** Returns an array of rendered map features that intersect with the given rectangle, restricted to the given style layers. + + This method may return all features from the specified layers. To filter + the returned features, use the + `-visibleFeaturesAtPoint:inStyleLayersWithIdentifiers:predicate:` method. For + more information about searching for map features, see that method’s + documentation. + @param rect A rectangle expressed in the map view’s coordinate system. + @param styleLayerIdentifiers A set of strings that correspond to the names of + layers defined in the current style. Only the features contained in these + layers are included in the returned array. + @return An array of objects conforming to the `MGLFeature` protocol that + represent features in the sources used by the current style. + */ +- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesInRect:(NSRect)rect inStyleLayersWithIdentifiers:(nullable NS_SET_OF(NSString *) *)styleLayerIdentifiers NS_SWIFT_NAME(visibleFeatures(at:styleLayerIdentifiers:)); + +/** + Returns an array of rendered map features that intersect with the given + rectangle, restricted to the given style layers and filtered by the given + predicate. + + Each object in the returned array represents a feature rendered by the current style and provides access to attributes specified by the relevant <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources">tile sources</a>. @@ -895,21 +944,22 @@ MGL_EXPORT IB_DESIGNABLE <a href="https://www.mapbox.com/studio/">Mapbox Studio</a>. @note Layer identifiers are not guaranteed to exist across styles or different - versions of the same style. Applications that use this API must first set the - style URL to an explicitly versioned style using a convenience method like - `+[MGLStyle outdoorsStyleURLWithVersion:]`, `MGLMapView`’s “Style URL” - inspectable in Interface Builder, or a manually constructed `NSURL`. This - approach also avoids layer identifer name changes that will occur in the default - style’s layers over time. - + versions of the same style. Applications that use this API must first set the + style URL to an explicitly versioned style using a convenience method like + `+[MGLStyle outdoorsStyleURLWithVersion:]`, `MGLMapView`’s “Style URL” + inspectable in Interface Builder, or a manually constructed `NSURL`. This + approach also avoids layer identifer name changes that will occur in the default + style’s layers over time. + @param rect A rectangle expressed in the map view’s coordinate system. @param styleLayerIdentifiers A set of strings that correspond to the names of - layers defined in the current style. Only the features contained in these - layers are included in the returned array. + layers defined in the current style. Only the features contained in these + layers are included in the returned array. + @param predicate A predicate to filter the returned features. @return An array of objects conforming to the `MGLFeature` protocol that - represent features in the sources used by the current style. + represent features in the sources used by the current style. */ -- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesInRect:(NSRect)rect inStyleLayersWithIdentifiers:(nullable NS_SET_OF(NSString *) *)styleLayerIdentifiers NS_SWIFT_NAME(visibleFeatures(_:styleLayerIdentifiers:)); +- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesInRect:(NSRect)rect inStyleLayersWithIdentifiers:(nullable NS_SET_OF(NSString *) *)styleLayerIdentifiers predicate:(nullable NSPredicate *)predicate NS_SWIFT_NAME(visibleFeatures(in:styleLayerIdentifiers:predicate:)); #pragma mark Converting Geographic Coordinates diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm index 3e76fa9ad0..68f36e044b 100644 --- a/platform/macos/src/MGLMapView.mm +++ b/platform/macos/src/MGLMapView.mm @@ -50,6 +50,7 @@ #import "NSURL+MGLAdditions.h" #import "NSColor+MGLAdditions.h" #import "NSImage+MGLAdditions.h" +#import "NSPredicate+MGLAdditions.h" #import <QuartzCore/QuartzCore.h> @@ -2512,7 +2513,11 @@ public: return [self visibleFeaturesAtPoint:point inStyleLayersWithIdentifiers:nil]; } -- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesAtPoint:(NSPoint)point inStyleLayersWithIdentifiers:(NS_SET_OF(NSString *) *)styleLayerIdentifiers { +- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesAtPoint:(CGPoint)point inStyleLayersWithIdentifiers:(NS_SET_OF(NSString *) *)styleLayerIdentifiers { + return [self visibleFeaturesAtPoint:point inStyleLayersWithIdentifiers:styleLayerIdentifiers predicate:nil]; +} + +- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesAtPoint:(NSPoint)point inStyleLayersWithIdentifiers:(NS_SET_OF(NSString *) *)styleLayerIdentifiers predicate:(NSPredicate *)predicate { // Cocoa origin is at the lower-left corner. mbgl::ScreenCoordinate screenCoordinate = { point.x, NSHeight(self.bounds) - point.y }; @@ -2525,8 +2530,13 @@ public: }]; optionalLayerIDs = layerIDs; } - - std::vector<mbgl::Feature> features = _mbglMap->queryRenderedFeatures(screenCoordinate, optionalLayerIDs); + + mbgl::optional<mbgl::style::Filter> optionalFilter; + if (predicate) { + optionalFilter = predicate.mgl_filter; + } + + std::vector<mbgl::Feature> features = _mbglMap->queryRenderedFeatures(screenCoordinate, { optionalLayerIDs, optionalFilter }); return MGLFeaturesFromMBGLFeatures(features); } @@ -2534,7 +2544,11 @@ public: return [self visibleFeaturesInRect:rect inStyleLayersWithIdentifiers:nil]; } -- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesInRect:(NSRect)rect inStyleLayersWithIdentifiers:(NS_SET_OF(NSString *) *)styleLayerIdentifiers { +- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesInRect:(CGRect)rect inStyleLayersWithIdentifiers:(NS_SET_OF(NSString *) *)styleLayerIdentifiers { + return [self visibleFeaturesInRect:rect inStyleLayersWithIdentifiers:styleLayerIdentifiers predicate:nil]; +} + +- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesInRect:(NSRect)rect inStyleLayersWithIdentifiers:(NS_SET_OF(NSString *) *)styleLayerIdentifiers predicate:(NSPredicate *)predicate { // Cocoa origin is at the lower-left corner. mbgl::ScreenBox screenBox = { { NSMinX(rect), NSHeight(self.bounds) - NSMaxY(rect) }, @@ -2550,8 +2564,13 @@ public: }]; optionalLayerIDs = layerIDs; } - - std::vector<mbgl::Feature> features = _mbglMap->queryRenderedFeatures(screenBox, optionalLayerIDs); + + mbgl::optional<mbgl::style::Filter> optionalFilter; + if (predicate) { + optionalFilter = predicate.mgl_filter; + } + + std::vector<mbgl::Feature> features = _mbglMap->queryRenderedFeatures(screenBox, { optionalLayerIDs, optionalFilter }); return MGLFeaturesFromMBGLFeatures(features); } diff --git a/platform/node/src/node_map.cpp b/platform/node/src/node_map.cpp index 66cdb3eda7..174db7d737 100644 --- a/platform/node/src/node_map.cpp +++ b/platform/node/src/node_map.cpp @@ -10,6 +10,7 @@ #include <mbgl/style/conversion/layer.hpp> #include <mbgl/style/conversion/filter.hpp> #include <mbgl/sprite/sprite_image.cpp> +#include <mbgl/map/query.hpp> #include <unistd.h> @@ -866,6 +867,9 @@ void NodeMap::DumpDebugLogs(const Nan::FunctionCallbackInfo<v8::Value>& info) { } void NodeMap::QueryRenderedFeatures(const Nan::FunctionCallbackInfo<v8::Value>& info) { + using namespace mbgl::style; + using namespace mbgl::style::conversion; + auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(info.Holder()); if (!nodeMap->map) return Nan::ThrowError(releasedMessage()); @@ -878,6 +882,39 @@ void NodeMap::QueryRenderedFeatures(const Nan::FunctionCallbackInfo<v8::Value>& return Nan::ThrowTypeError("First argument must have two components"); } + mbgl::QueryOptions queryOptions; + if (!info[1]->IsNull() && !info[1]->IsUndefined()) { + if (!info[1]->IsObject()) { + return Nan::ThrowTypeError("options argument must be an object"); + } + + auto options = Nan::To<v8::Object>(info[1]).ToLocalChecked(); + + //Check if layers is set. If provided, it must be an array of strings + if (Nan::Has(options, Nan::New("layers").ToLocalChecked()).FromJust()) { + auto layersOption = Nan::Get(options, Nan::New("layers").ToLocalChecked()).ToLocalChecked(); + if (!layersOption->IsArray()) { + return Nan::ThrowTypeError("Requires options.layers property to be an array"); + } + auto layers = layersOption.As<v8::Array>(); + std::vector<std::string> layersVec; + for (uint32_t i=0; i < layers->Length(); i++) { + layersVec.push_back(*Nan::Utf8String(Nan::Get(layers,i).ToLocalChecked())); + } + queryOptions.layerIDs = layersVec; + } + + //Check if filter is provided. If set it must be a valid Filter object + if (Nan::Has(options, Nan::New("filter").ToLocalChecked()).FromJust()) { + auto filterOption = Nan::Get(options, Nan::New("filter").ToLocalChecked()).ToLocalChecked(); + Result<Filter> converted = convert<Filter>(filterOption); + if (!converted) { + return Nan::ThrowTypeError(converted.error().message.c_str()); + } + queryOptions.filter = std::move(*converted); + } + } + try { std::vector<mbgl::Feature> result; @@ -894,13 +931,13 @@ void NodeMap::QueryRenderedFeatures(const Nan::FunctionCallbackInfo<v8::Value>& Nan::Get(pos1, 0).ToLocalChecked()->NumberValue(), Nan::Get(pos1, 1).ToLocalChecked()->NumberValue() } - }); + }, queryOptions); } else { result = nodeMap->map->queryRenderedFeatures(mbgl::ScreenCoordinate { Nan::Get(posOrBox, 0).ToLocalChecked()->NumberValue(), Nan::Get(posOrBox, 1).ToLocalChecked()->NumberValue() - }); + }, queryOptions); } auto array = Nan::New<v8::Array>(); diff --git a/platform/node/test/suite_implementation.js b/platform/node/test/suite_implementation.js index 6648757a98..ef97652893 100644 --- a/platform/node/test/suite_implementation.js +++ b/platform/node/test/suite_implementation.js @@ -49,7 +49,7 @@ module.exports = function (style, options, callback) { applyOperations(options.operations, function() { map.render(options, function (err, pixels) { var results = options.queryGeometry ? - map.queryRenderedFeatures(options.queryGeometry) : + map.queryRenderedFeatures(options.queryGeometry, options.queryOptions || {}) : []; map.release(); if (timedOut) return; diff --git a/platform/qt/README.md b/platform/qt/README.md index dc17d69903..0123e3bda0 100644 --- a/platform/qt/README.md +++ b/platform/qt/README.md @@ -3,43 +3,10 @@ [![Travis](https://travis-ci.org/mapbox/mapbox-gl-native.svg?branch=master)](https://travis-ci.org/mapbox/mapbox-gl-native/builds) [![Bitrise](https://www.bitrise.io/app/96cfbc97e0245c22.svg?token=GxsqIOGPXhn0F23sSVSsYA&branch=master)](https://www.bitrise.io/app/96cfbc97e0245c22) -Provides [Qt](http://www.qt.io/) example applications and APIs via `QMapboxGL` -and `QQuickMapboxGL`: - -**QMapboxGL** - implements a C++03x-conformant API that has been tested from Qt -4.7 onwards (Travis CI currently builds it using both Qt 4 and Qt 5). - -**QQuickMapboxGL** - implements a Qt Quick (QML) item that can be added to a -scene. Because `QQuickFramebufferObject` has been added in Qt version 5.2, we -support this API from this version onwards. - -![Mapbox Qt QML -example](https://c2.staticflickr.com/8/7689/26247088394_01541b34de_o.png) - ### Developing -[Qt supports many platforms](https://www.qt.io/qt-framework/#section-4) - so far -we have been testing our code on Linux and macOS desktops, as well as embedded -devices such as Raspberry Pi 3. - -If you need to maintain backwards compatibility with prior releases of -Qt, chose `QMapboxGL`. Otherwise, go for `QQuickMapboxGL`. - -Both `QMapboxGL` and `QQuickMapboxGL` requires a [Mapbox access -token](https://www.mapbox.com/help/define-access-token/) at runtime - you need -to provide it by setting the environment variable `MAPBOX_ACCESS_TOKEN`: - - export MAPBOX_ACCESS_TOKEN=MYTOKEN - -Optionally, you can specify a custom style to the QMapboxGL example application: - - export MAPBOX_STYLE_URL=MYSTYLEURL - -#### Using QMapboxGL - -`QMapboxGL` is a [QObject](http://doc.qt.io/qt-5/qobject.html) - [MapWindow](https://github.com/mapbox/mapbox-gl-native/blob/master/platform/qt/app/mapwindow.hpp) provides an example [QGLWidget](http://doc.qt.io/qt-5/qglwidget.html) that contains a `QMapboxGL` object. If you use `QMapboxGL` in non-standard Qt widgets, make sure to initialize the GL extensions required by Mapbox whenever possible: - - QMapbox::initializeGLExtensions(); +This is the foundation for the Mapbox GL plugin available since Qt 5.9. Use the Qt bugtracker +for bugs related to the plugin and this GitHub repository for bugs related to Mapbox GL Native. #### Linux @@ -47,9 +14,7 @@ For Linux (Ubuntu) desktop, together with these [build instructions](https://github.com/mapbox/mapbox-gl-native/tree/master/platform/linux#build), you also need: - sudo apt-get install qt5-default qtlocation5-dev qtpositioning5-dev \ - qml-module-qtquick2 qml-module-qtpositioning qml-module-qtgraphicaleffects \ - qml-module-qtquick-layouts qml-module-qtquick-controls + sudo apt-get install qt5-default #### macOS @@ -59,7 +24,7 @@ For macOS desktop, you can install Qt 5 via [Homebrew](http://brew.sh): Since Homebrew doesn't add Qt to the path, you'll have to do that manually before running any Make target: - export PATH=/usr/local/opt/qt5:$PATH + export PATH=/usr/local/opt/qt5/bin:$PATH We provide the following build targets for our Qt SDK: @@ -74,8 +39,3 @@ can be found in [platform/qt/include](https://github.com/mapbox/mapbox-gl-native ```make qt-app``` or ```make run-qt-app``` to run the application at the end of build. - -#### QQuickMapboxGL example application: - -```make qt-qml-app``` or ```make run-qt-qml-app``` to run the application at the -end of build. diff --git a/platform/qt/bitrise-qt5.yml b/platform/qt/bitrise-qt5.yml index e0627f03e5..036ec044c5 100644 --- a/platform/qt/bitrise-qt5.yml +++ b/platform/qt/bitrise-qt5.yml @@ -39,7 +39,6 @@ workflows: ln -s /usr/local/Cellar/qt5/$HOMEBREW_QT5_VERSION/plugins /usr/local/plugins export BUILDTYPE=Debug make qt-app - make qt-qml-app make run-qt-test - is_debug: 'yes' - deploy-to-bitrise-io: diff --git a/platform/qt/config.cmake b/platform/qt/config.cmake index e97c6b340a..0f2bab0516 100644 --- a/platform/qt/config.cmake +++ b/platform/qt/config.cmake @@ -10,7 +10,7 @@ if(NOT WITH_QT_DECODERS) endif() if(NOT WITH_QT_I18N) - mason_use(icu VERSION 58.1) + mason_use(icu VERSION 58.1-min-size) endif() macro(mbgl_platform_core) @@ -72,7 +72,7 @@ macro(mbgl_platform_test) target_link_libraries(mbgl-test PRIVATE qmapboxgl - ${MBGL_QT_LIBRARIES} + ${MBGL_QT_TEST_LIBRARIES} ) endmacro() diff --git a/platform/qt/include/qquickmapboxgl.hpp b/platform/qt/include/qquickmapboxgl.hpp deleted file mode 100644 index 39b4395bd6..0000000000 --- a/platform/qt/include/qquickmapboxgl.hpp +++ /dev/null @@ -1,176 +0,0 @@ -#pragma once - -#include "qmapbox.hpp" -#include "qmapboxgl.hpp" -#include "qquickmapboxglmapparameter.hpp" - -#include <QColor> -#include <QGeoCoordinate> -#include <QGeoServiceProvider> -#include <QGeoShape> -#include <QImage> -#include <QPointF> -#include <QQmlListProperty> -#include <QQuickFramebufferObject> -#include <QQuickItem> - -class QDeclarativeGeoServiceProvider; -class QQuickMapboxGLRenderer; - -class Q_DECL_EXPORT QQuickMapboxGL : public QQuickFramebufferObject -{ - Q_OBJECT - - // Map QML Type interface. - Q_ENUMS(QGeoServiceProvider::Error) - Q_PROPERTY(QDeclarativeGeoServiceProvider *plugin READ plugin WRITE setPlugin NOTIFY pluginChanged) - Q_PROPERTY(qreal minimumZoomLevel READ minimumZoomLevel WRITE setMinimumZoomLevel NOTIFY minimumZoomLevelChanged) - Q_PROPERTY(qreal maximumZoomLevel READ maximumZoomLevel WRITE setMaximumZoomLevel NOTIFY maximumZoomLevelChanged) - Q_PROPERTY(qreal zoomLevel READ zoomLevel WRITE setZoomLevel NOTIFY zoomLevelChanged) - Q_PROPERTY(QGeoCoordinate center READ center WRITE setCenter NOTIFY centerChanged) - Q_PROPERTY(QGeoServiceProvider::Error error READ error NOTIFY errorChanged) - Q_PROPERTY(QString errorString READ errorString NOTIFY errorChanged) - Q_PROPERTY(QGeoShape visibleRegion READ visibleRegion WRITE setVisibleRegion) - Q_PROPERTY(bool copyrightsVisible READ copyrightsVisible WRITE setCopyrightsVisible NOTIFY copyrightsVisibleChanged) - Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) - - // Proposed Qt interface - based on the example documentation below: - // http://doc.qt.io/qt-5/qtqml-referenceexamples-properties-example.html - Q_PROPERTY(QQmlListProperty<QQuickMapboxGLMapParameter> parameters READ parameters) - -public: - QQuickMapboxGL(QQuickItem *parent = 0); - virtual ~QQuickMapboxGL(); - - // QQuickFramebufferObject implementation. - virtual Renderer *createRenderer() const Q_DECL_FINAL; - - // Map QML Type interface implementation. - void setPlugin(QDeclarativeGeoServiceProvider *plugin); - QDeclarativeGeoServiceProvider *plugin() const; - - void setMinimumZoomLevel(qreal minimumZoomLevel); - qreal minimumZoomLevel() const; - - void setMaximumZoomLevel(qreal maximumZoomLevel); - qreal maximumZoomLevel() const; - - void setZoomLevel(qreal zoomLevel); - qreal zoomLevel() const; - - QGeoCoordinate center() const; - - QGeoServiceProvider::Error error() const; - QString errorString() const; - - void setVisibleRegion(const QGeoShape &shape); - QGeoShape visibleRegion() const; - - void setCopyrightsVisible(bool visible); - bool copyrightsVisible() const; - - void setColor(const QColor &color); - QColor color() const; - - Q_INVOKABLE void pan(int dx, int dy); - - // Proposed Qt interface implementation. - QQmlListProperty<QQuickMapboxGLMapParameter> parameters(); - -protected: - // QQmlParserStatus implementation - void componentComplete() override; - -signals: - // Map QML Type signals. - void minimumZoomLevelChanged(); - void maximumZoomLevelChanged(); - void zoomLevelChanged(qreal zoomLevel); - void centerChanged(const QGeoCoordinate &coordinate); - void colorChanged(const QColor &color); - void errorChanged(); - - // Compatibility with Map QML Type, but no-op. - void pluginChanged(QDeclarativeGeoServiceProvider *plugin); - void copyrightLinkActivated(const QString &link); - void copyrightsVisibleChanged(bool visible); - -public slots: - void setCenter(const QGeoCoordinate ¢er); - -private slots: - void onMapChanged(QMapboxGL::MapChange); - void onParameterPropertyUpdated(const QString &name); - -private: - static void appendParameter(QQmlListProperty<QQuickMapboxGLMapParameter> *prop, QQuickMapboxGLMapParameter *mapObject); - static int countParameters(QQmlListProperty<QQuickMapboxGLMapParameter> *prop); - static QQuickMapboxGLMapParameter *parameterAt(QQmlListProperty<QQuickMapboxGLMapParameter> *prop, int index); - static void clearParameter(QQmlListProperty<QQuickMapboxGLMapParameter> *prop); - - enum SyncState { - NothingNeedsSync = 0, - ZoomNeedsSync = 1 << 0, - CenterNeedsSync = 1 << 1, - StyleNeedsSync = 1 << 2, - PanNeedsSync = 1 << 3, - BearingNeedsSync = 1 << 4, - PitchNeedsSync = 1 << 5, - }; - - struct Image { - QString name; - QImage sprite; - }; - - struct StyleProperty { - enum Type { - Paint = 0, - Layout - }; - - Type type; - QString layer; - QString property; - QVariant value; - QString klass; - }; - - void processMapParameter(QQuickMapboxGLMapParameter *); - bool parseImage(QQuickMapboxGLMapParameter *); - bool parseStyle(QQuickMapboxGLMapParameter *); - bool parseStyleProperty(QQuickMapboxGLMapParameter *, const QString &name); - bool parseStyleLayer(QQuickMapboxGLMapParameter *); - bool parseStyleSource(QQuickMapboxGLMapParameter *); - bool parseStyleFilter(QQuickMapboxGLMapParameter *); - bool parseBearing(QQuickMapboxGLMapParameter *); - bool parsePitch(QQuickMapboxGLMapParameter *); - - qreal m_minimumZoomLevel = 0; - qreal m_maximumZoomLevel = 20; - qreal m_zoomLevel = 20; - - QPointF m_pan; - - QGeoCoordinate m_center; - QGeoShape m_visibleRegion; - QColor m_color; - QString m_styleUrl; - QList<Image> m_imageChanges; - QList<StyleProperty> m_stylePropertyChanges; - QList<QVariantMap> m_layerChanges; - QList<QVariantMap> m_sourceChanges; - QList<QVariantMap> m_filterChanges; - QList<QQuickMapboxGLMapParameter*> m_parameters; - - QGeoServiceProvider::Error m_error = QGeoServiceProvider::NoError; - QString m_errorString; - - qreal m_bearing = 0; - qreal m_pitch = 0; - - int m_syncState = NothingNeedsSync; - bool m_styleLoaded = false; - - friend class QQuickMapboxGLRenderer; -}; diff --git a/platform/qt/include/qquickmapboxglmapparameter.hpp b/platform/qt/include/qquickmapboxglmapparameter.hpp deleted file mode 100644 index 1dca0cf55d..0000000000 --- a/platform/qt/include/qquickmapboxglmapparameter.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include <QObject> -#include <QQmlParserStatus> -#include <QString> -#include <qqml.h> - -class Q_DECL_EXPORT QQuickMapboxGLMapParameter : public QObject, public QQmlParserStatus -{ - Q_OBJECT - Q_INTERFACES(QQmlParserStatus) - -public: - QQuickMapboxGLMapParameter(QObject *parent = 0); - virtual ~QQuickMapboxGLMapParameter() {}; - - int propertyOffset() const { return m_metaPropertyOffset; } - -signals: - void propertyUpdated(const QString &name); - -protected: - // QQmlParserStatus implementation - void classBegin() override {} - void componentComplete() override; - -private slots: - void onPropertyUpdated(int index); - -private: - int m_metaPropertyOffset; -}; - -QML_DECLARE_TYPE(QQuickMapboxGLMapParameter) diff --git a/platform/qt/qmlapp/main.cpp b/platform/qt/qmlapp/main.cpp deleted file mode 100644 index 8606704002..0000000000 --- a/platform/qt/qmlapp/main.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include <QQuickMapboxGL> -#include <QQuickMapboxGLMapParameter> - -#include <QGuiApplication> -#include <QIcon> -#include <QQmlApplicationEngine> -#include <qqml.h> - -int main(int argc, char *argv[]) -{ - QGuiApplication app(argc, argv); - -#if QT_VERSION >= 0x050300 - app.setWindowIcon(QIcon(":icon.png")); -#endif - - qmlRegisterType<QQuickMapboxGL>("QQuickMapboxGL", 1, 0, "MapboxMap"); - qmlRegisterType<QQuickMapboxGLMapParameter>("QQuickMapboxGL", 1, 0, "MapParameter"); - - QQmlApplicationEngine engine; - engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); - - return app.exec(); -} diff --git a/platform/qt/qmlapp/main.qml b/platform/qt/qmlapp/main.qml deleted file mode 100644 index fd62193b42..0000000000 --- a/platform/qt/qmlapp/main.qml +++ /dev/null @@ -1,347 +0,0 @@ -import QtGraphicalEffects 1.0 -import QtPositioning 5.0 -import QtQuick 2.0 -import QtQuick.Controls 1.0 -import QtQuick.Dialogs 1.0 -import QtQuick.Layouts 1.0 - -import QQuickMapboxGL 1.0 - -ApplicationWindow { - title: "Mapbox GL QML example" - width: 1024 - height: 768 - visible: true - - MapboxMap { - id: map - anchors.fill: parent - - parameters: [ - MapParameter { - id: style - property var type: "style" - property var url: "mapbox://styles/mapbox/streets-v9" - }, - MapParameter { - id: waterPaint - property var type: "paint" - property var layer: "water" - property var fillColor: waterColorDialog.color - }, - MapParameter { - id: source - property var type: "source" - property var name: "routeSource" - property var sourceType: "geojson" - property var data: ":source1.geojson" - }, - MapParameter { - property var type: "layer" - property var name: "routeCase" - property var layerType: "line" - property var source: "routeSource" - }, - MapParameter { - property var type: "paint" - property var layer: "routeCase" - property var lineColor: "white" - property var lineWidth: 20.0 - }, - MapParameter { - property var type: "layout" - property var layer: "routeCase" - property var lineJoin: "round" - property var lineCap: lineJoin - property var visibility: toggleRoute.checked ? "visible" : "none" - }, - MapParameter { - property var type: "layer" - property var name: "route" - property var layerType: "line" - property var source: "routeSource" - }, - MapParameter { - id: linePaint - property var type: "paint" - property var layer: "route" - property var lineColor: "blue" - property var lineWidth: 8.0 - }, - MapParameter { - property var type: "layout" - property var layer: "route" - property var lineJoin: "round" - property var lineCap: "round" - property var visibility: toggleRoute.checked ? "visible" : "none" - }, - MapParameter { - property var type: "image" - property var name: "label-arrow" - property var sprite: ":label-arrow.svg" - }, - MapParameter { - property var type: "image" - property var name: "label-background" - property var sprite: ":label-background.svg" - }, - MapParameter { - property var type: "layer" - property var name: "markerArrow" - property var layerType: "symbol" - property var source: "routeSource" - }, - MapParameter { - property var type: "layout" - property var layer: "markerArrow" - property var iconImage: "label-arrow" - property var iconSize: 0.5 - property var iconIgnorePlacement: true - property var iconOffset: [ 0.0, -15.0 ] - property var visibility: toggleRoute.checked ? "visible" : "none" - }, - MapParameter { - property var type: "layer" - property var name: "markerBackground" - property var layerType: "symbol" - property var source: "routeSource" - }, - MapParameter { - property var type: "layout" - property var layer: "markerBackground" - property var iconImage: "label-background" - property var textField: "{name}" - property var iconTextFit: "both" - property var iconIgnorePlacement: true - property var textIgnorePlacement: true - property var textAnchor: "left" - property var textSize: 16.0 - property var textPadding: 0.0 - property var textLineHeight: 1.0 - property var textMaxWidth: 8.0 - property var iconTextFitPadding: [ 15.0, 10.0, 15.0, 10.0 ] - property var textOffset: [ -0.5, -1.5 ] - property var visibility: toggleRoute.checked ? "visible" : "none" - }, - MapParameter { - property var type: "paint" - property var layer: "markerBackground" - property var textColor: "white" - }, - MapParameter { - property var type: "filter" - property var layer: "markerArrow" - property var filter: [ "==", "$type", "Point" ] - }, - MapParameter { - property var type: "filter" - property var layer: "markerBackground" - property var filter: [ "==", "$type", "Point" ] - }, - MapParameter { - property var type: "bearing" - property var angle: bearingSlider.value - }, - MapParameter { - property var type: "pitch" - property var angle: pitchSlider.value - } - ] - - center: QtPositioning.coordinate(60.170448, 24.942046) // Helsinki - zoomLevel: 12.25 - minimumZoomLevel: 0 - maximumZoomLevel: 20 - - color: landColorDialog.color - copyrightsVisible: true - - states: State { - name: "moved"; when: mouseArea.pressed - PropertyChanges { target: linePaint; lineColor: "red"; } - } - - transitions: Transition { - ColorAnimation { properties: "lineColor"; easing.type: Easing.InOutQuad; duration: 500 } - } - - Image { - anchors.right: parent.right - anchors.bottom: parent.bottom - anchors.margins: 20 - - opacity: .75 - - sourceSize.width: 80 - sourceSize.height: 80 - - source: "icon.png" - } - - MouseArea { - id: mouseArea - anchors.fill: parent - - property var lastX: 0 - property var lastY: 0 - - onWheel: map.zoomLevel += 0.2 * wheel.angleDelta.y / 120 - - onPressed: { - lastX = mouse.x - lastY = mouse.y - } - - onPositionChanged: { - map.pan(mouse.x - lastX, mouse.y - lastY) - - lastX = mouse.x - lastY = mouse.y - } - } - } - - ColorDialog { - id: landColorDialog - title: "Land color" - color: "#e0ded8" - } - - ColorDialog { - id: waterColorDialog - title: "Water color" - color: "#63c5ee" - } - - Rectangle { - anchors.fill: menu - anchors.margins: -20 - radius: 30 - clip: true - } - - ColumnLayout { - id: menu - - anchors.right: parent.right - anchors.top: parent.top - anchors.margins: 30 - - Label { - text: "Bearing:" - } - - Slider { - id: bearingSlider - - anchors.left: parent.left - anchors.right: parent.right - maximumValue: 180 - } - - Label { - text: "Pitch:" - } - - Slider { - id: pitchSlider - - anchors.left: parent.left - anchors.right: parent.right - maximumValue: 60 - } - - GroupBox { - anchors.left: parent.left - anchors.right: parent.right - title: "Style:" - - ColumnLayout { - ExclusiveGroup { id: styleGroup } - RadioButton { - text: "Streets" - checked: true - exclusiveGroup: styleGroup - onClicked: { - style.url = "mapbox://styles/mapbox/streets-v9" - landColorDialog.color = "#e0ded8" - waterColorDialog.color = "#63c5ee" - } - } - RadioButton { - text: "Dark" - exclusiveGroup: styleGroup - onClicked: { - style.url = "mapbox://styles/mapbox/dark-v9" - landColorDialog.color = "#343332" - waterColorDialog.color = "#191a1a" - } - } - RadioButton { - text: "Satellite" - exclusiveGroup: styleGroup - onClicked: { - style.url = "mapbox://styles/mapbox/satellite-v9" - } - } - } - } - - Button { - anchors.left: parent.left - anchors.right: parent.right - text: "Select land color" - onClicked: landColorDialog.open() - } - - Button { - anchors.left: parent.left - anchors.right: parent.right - text: "Select water color" - onClicked: waterColorDialog.open() - } - - GroupBox { - anchors.left: parent.left - anchors.right: parent.right - title: "Route:" - - ColumnLayout { - ExclusiveGroup { id: sourceGroup } - RadioButton { - text: "Route 1" - checked: true - exclusiveGroup: sourceGroup - onClicked: { - source.data = ":source1.geojson" - } - } - RadioButton { - text: "Route 2" - exclusiveGroup: sourceGroup - onClicked: { - source.data = ":source2.geojson" - } - } - RadioButton { - text: "Route 3" - exclusiveGroup: sourceGroup - onClicked: { - source.data = '{ "type": "FeatureCollection", "features": \ - [{ "type": "Feature", "properties": {}, "geometry": { \ - "type": "LineString", "coordinates": [[ 24.934938848018646, \ - 60.16830257086771 ], [ 24.943315386772156, 60.16227776476442 ]]}}]}' - } - } - } - } - - CheckBox { - id: toggleRoute - anchors.left: parent.left - anchors.right: parent.right - text: "Toggle route" - checked: true - } - } -} diff --git a/platform/qt/qmlapp/qml.qrc b/platform/qt/qmlapp/qml.qrc deleted file mode 100644 index 5f6483ac33..0000000000 --- a/platform/qt/qmlapp/qml.qrc +++ /dev/null @@ -1,5 +0,0 @@ -<RCC> - <qresource prefix="/"> - <file>main.qml</file> - </qresource> -</RCC> diff --git a/platform/qt/qt4.cmake b/platform/qt/qt4.cmake index d6d7d89417..80fd4f00d3 100644 --- a/platform/qt/qt4.cmake +++ b/platform/qt/qt4.cmake @@ -8,6 +8,11 @@ set(MBGL_QT_LIBRARIES PRIVATE Qt4::QtSql ) +set(MBGL_QT_TEST_LIBRARIES + PRIVATE Qt4::QtCore + PRIVATE Qt4::QtOpenGL +) + target_link_libraries(qmapboxgl PRIVATE mbgl-core PRIVATE Qt4::QtCore diff --git a/platform/qt/qt5.cmake b/platform/qt/qt5.cmake index 7210a3d5f5..ed51051311 100644 --- a/platform/qt/qt5.cmake +++ b/platform/qt/qt5.cmake @@ -3,7 +3,6 @@ find_package(Qt5Gui REQUIRED) find_package(Qt5Location REQUIRED) find_package(Qt5Network REQUIRED) find_package(Qt5OpenGL REQUIRED) -find_package(Qt5Quick REQUIRED) find_package(Qt5Widgets REQUIRED) find_package(Qt5Sql REQUIRED) @@ -11,17 +10,14 @@ set(MBGL_QT_LIBRARIES PRIVATE Qt5::Core PRIVATE Qt5::Gui PRIVATE Qt5::Network - PRIVATE Qt5::OpenGL PRIVATE Qt5::Sql ) -target_sources(qmapboxgl - PRIVATE platform/qt/include/qquickmapboxgl.hpp - PRIVATE platform/qt/include/qquickmapboxglmapparameter.hpp - PRIVATE platform/qt/src/qquickmapboxgl.cpp - PRIVATE platform/qt/src/qquickmapboxglmapparameter.cpp - PRIVATE platform/qt/src/qquickmapboxglrenderer.cpp - PRIVATE platform/qt/src/qquickmapboxglrenderer.hpp +set(MBGL_QT_TEST_LIBRARIES + PRIVATE Qt5::Core + PRIVATE Qt5::Gui + PRIVATE Qt5::Widgets + PRIVATE Qt5::OpenGL ) target_link_libraries(qmapboxgl @@ -29,8 +25,6 @@ target_link_libraries(qmapboxgl PRIVATE Qt5::Core PRIVATE Qt5::Gui PRIVATE Qt5::Location - PRIVATE Qt5::OpenGL - PRIVATE Qt5::Quick PRIVATE Qt5::Sql ) @@ -39,16 +33,3 @@ target_link_libraries(mbgl-qt PRIVATE Qt5::OpenGL PRIVATE Qt5::Widgets ) - -# QtQuick app -add_executable(mbgl-qt-qml - platform/qt/qmlapp/main.cpp - platform/qt/qmlapp/qml.qrc - platform/qt/resources/common.qrc -) - -target_link_libraries(mbgl-qt-qml - PRIVATE qmapboxgl - PRIVATE Qt5::Location - PRIVATE Qt5::Quick -) diff --git a/platform/qt/src/qquickmapboxgl.cpp b/platform/qt/src/qquickmapboxgl.cpp deleted file mode 100644 index 7325bfe3c2..0000000000 --- a/platform/qt/src/qquickmapboxgl.cpp +++ /dev/null @@ -1,469 +0,0 @@ -#include "qquickmapboxgl.hpp" - -#include "qquickmapboxglmapparameter.hpp" -#include "qquickmapboxglrenderer.hpp" - -#include <mbgl/util/constants.hpp> - -#include <QDebug> -#include <QQuickItem> -#include <QRegularExpression> -#include <QString> -#include <QtGlobal> -#include <QQmlListProperty> -#include <QJSValue> - -namespace { - -static const QRegularExpression s_camelCase {"([a-z0-9])([A-Z])"}; -static const QStringList s_parameterTypes = QStringList() - << "style" << "paint" << "layout" << "layer" << "source" << "filter" << "image" - << "bearing" << "pitch"; - -} // namespace - -QQuickMapboxGL::QQuickMapboxGL(QQuickItem *parent_) - : QQuickFramebufferObject(parent_) -{ -} - -QQuickMapboxGL::~QQuickMapboxGL() -{ -} - -QQuickFramebufferObject::Renderer *QQuickMapboxGL::createRenderer() const -{ - return new QQuickMapboxGLRenderer; -} - -void QQuickMapboxGL::setPlugin(QDeclarativeGeoServiceProvider *) -{ - m_error = QGeoServiceProvider::NotSupportedError; - m_errorString = "QQuickMapboxGL does not support plugins."; - emit errorChanged(); -} - -QDeclarativeGeoServiceProvider *QQuickMapboxGL::plugin() const -{ - return nullptr; -} - -void QQuickMapboxGL::componentComplete() -{ - QQuickFramebufferObject::componentComplete(); - - for (const auto& param : m_parameters) { - processMapParameter(param); - } -} - -void QQuickMapboxGL::setMinimumZoomLevel(qreal zoom) -{ - zoom = qMax(mbgl::util::MIN_ZOOM, zoom); - zoom = qMin(m_maximumZoomLevel, zoom); - - if (m_minimumZoomLevel == zoom) { - return; - } - - m_minimumZoomLevel = zoom; - setZoomLevel(m_zoomLevel); // Constrain. - - emit minimumZoomLevelChanged(); -} - -qreal QQuickMapboxGL::minimumZoomLevel() const -{ - return m_minimumZoomLevel; -} - -void QQuickMapboxGL::setMaximumZoomLevel(qreal zoom) -{ - zoom = qMin(mbgl::util::MAX_ZOOM, zoom); - zoom = qMax(m_minimumZoomLevel, zoom); - - if (m_maximumZoomLevel == zoom) { - return; - } - - m_maximumZoomLevel = zoom; - setZoomLevel(m_zoomLevel); // Constrain. - - emit maximumZoomLevelChanged(); -} - -qreal QQuickMapboxGL::maximumZoomLevel() const -{ - return m_maximumZoomLevel; -} - -void QQuickMapboxGL::setZoomLevel(qreal zoom) -{ - zoom = qMin(m_maximumZoomLevel, zoom); - zoom = qMax(m_minimumZoomLevel, zoom); - - if (m_zoomLevel == zoom) { - return; - } - - m_zoomLevel = zoom; - - m_syncState |= ZoomNeedsSync; - update(); - - emit zoomLevelChanged(m_zoomLevel); -} - -qreal QQuickMapboxGL::zoomLevel() const -{ - return m_zoomLevel; -} - -void QQuickMapboxGL::setCenter(const QGeoCoordinate &coordinate) -{ - if (m_center == coordinate) { - return; - } - - m_center = coordinate; - - m_syncState |= CenterNeedsSync; - update(); - - emit centerChanged(m_center); -} - -QGeoCoordinate QQuickMapboxGL::center() const -{ - return m_center; -} - -QGeoServiceProvider::Error QQuickMapboxGL::error() const -{ - return m_error; -} - -QString QQuickMapboxGL::errorString() const -{ - return m_errorString; -} - -void QQuickMapboxGL::setVisibleRegion(const QGeoShape &shape) -{ - m_visibleRegion = shape; -} - -QGeoShape QQuickMapboxGL::visibleRegion() const -{ - return m_visibleRegion; -} - -void QQuickMapboxGL::setCopyrightsVisible(bool) -{ - qWarning() << Q_FUNC_INFO << "Not implemented."; -} - -bool QQuickMapboxGL::copyrightsVisible() const -{ - return false; -} - -void QQuickMapboxGL::setColor(const QColor &color) -{ - if (m_color == color) { - return; - } - - m_color = color; - - StyleProperty change; - change.type = StyleProperty::Paint; - change.layer = "background"; - change.property = "background-color"; - change.value = color; - m_stylePropertyChanges << change; - - update(); - - emit colorChanged(m_color); -} - -QColor QQuickMapboxGL::color() const -{ - return m_color; -} - -void QQuickMapboxGL::pan(int dx, int dy) -{ - m_pan += QPointF(dx, -dy); - - m_syncState |= PanNeedsSync; - update(); -} - -void QQuickMapboxGL::onMapChanged(QMapboxGL::MapChange change) -{ - if (change == QMapboxGL::MapChangeDidFinishLoadingStyle) { - m_styleLoaded = true; - update(); - } -} - -bool QQuickMapboxGL::parseImage(QQuickMapboxGLMapParameter *param) -{ - m_imageChanges << Image { - param->property("name").toString(), - QImage(param->property("sprite").toString()) - }; - return true; -} - -bool QQuickMapboxGL::parseStyle(QQuickMapboxGLMapParameter *param) -{ - QString url = param->property("url").toString(); - if (m_styleUrl == url) { - return false; - } - - // Reload parameters if switching style URLs. - if (!m_styleUrl.isEmpty()) { - for (const auto& param_ : m_parameters) { - if (param_->property("type").toString() == "style") continue; - processMapParameter(param_); - } - } - - m_styleUrl = url; - m_styleLoaded = false; - m_syncState |= StyleNeedsSync; - - return true; -} - -bool QQuickMapboxGL::parseStyleProperty(QQuickMapboxGLMapParameter *param, const QString &name) -{ - // Ignore meta-properties "type", "layer" and "class". - if (name == "type" || name == "layer" || name == "class") { - return false; - } - - QString formattedName(name); - formattedName = formattedName.replace(s_camelCase, "\\1-\\2").toLower(); - - QVariant value = param->property(name.toLatin1()); - if (value.canConvert<QJSValue>()) { - value = value.value<QJSValue>().toVariant(); - } - - m_stylePropertyChanges << QQuickMapboxGL::StyleProperty { - param->property("type").toString().at(0) == 'p' ? StyleProperty::Paint : StyleProperty::Layout, - param->property("layer").toString(), - formattedName, - value, - param->property("class").toString() - }; - return true; -} - -bool QQuickMapboxGL::parseStyleLayer(QQuickMapboxGLMapParameter *param) -{ - QVariantMap layer; - layer["id"] = param->property("name"); - layer["source"] = param->property("source"); - layer["type"] = param->property("layerType"); - if (param->property("sourceLayer").isValid()) { - layer["source-layer"] = param->property("sourceLayer"); - } - m_layerChanges << layer; - return true; -} - -bool QQuickMapboxGL::parseStyleSource(QQuickMapboxGLMapParameter *param) -{ - QString sourceType = param->property("sourceType").toString(); - - QVariantMap source; - source["id"] = param->property("name"); - source["type"] = sourceType; - if (sourceType == "vector" || sourceType == "raster") { - source["url"] = param->property("url"); - m_sourceChanges << source; - } else if (sourceType == "geojson") { - auto data = param->property("data").toString(); - if (data.startsWith(':')) { - QFile geojson(data); - geojson.open(QIODevice::ReadOnly); - source["data"] = geojson.readAll(); - } else { - source["data"] = data.toUtf8(); - } - m_sourceChanges << source; - } else { - m_error = QGeoServiceProvider::UnknownParameterError; - m_errorString = "Invalid source type: " + sourceType; - emit errorChanged(); - return false; - } - return true; -} - -bool QQuickMapboxGL::parseStyleFilter(QQuickMapboxGLMapParameter *param) -{ - QVariantMap filter; - filter["layer"] = param->property("layer"); - filter["filter"] = param->property("filter"); - m_filterChanges << filter; - return true; -} - -bool QQuickMapboxGL::parseBearing(QQuickMapboxGLMapParameter *param) -{ - qreal angle = param->property("angle").toReal(); - if (m_bearing == angle) return false; - m_bearing = angle; - m_syncState |= BearingNeedsSync; - update(); - return true; -} - -bool QQuickMapboxGL::parsePitch(QQuickMapboxGLMapParameter *param) -{ - qreal angle = param->property("angle").toReal(); - angle = qMin(qMax(0., angle), mbgl::util::PITCH_MAX * mbgl::util::RAD2DEG); - if (m_pitch == angle) return false; - m_pitch = angle; - m_syncState |= PitchNeedsSync; - update(); - return true; -} - -void QQuickMapboxGL::processMapParameter(QQuickMapboxGLMapParameter *param) -{ - bool needsUpdate = false; - switch (s_parameterTypes.indexOf(param->property("type").toString())) { - case -1: - m_error = QGeoServiceProvider::UnknownParameterError; - m_errorString = "Invalid value for property 'type': " + param->property("type").toString(); - emit errorChanged(); - break; - case 0: // style - needsUpdate |= parseStyle(param); - break; - case 1: // paint - case 2: // layout - for (int i = param->propertyOffset(); i < param->metaObject()->propertyCount(); ++i) { - needsUpdate |= parseStyleProperty(param, QString(param->metaObject()->property(i).name())); - } - break; - case 3: // layer - needsUpdate |= parseStyleLayer(param); - break; - case 4: // source - needsUpdate |= parseStyleSource(param); - break; - case 5: // filter - needsUpdate |= parseStyleFilter(param); - break; - case 6: // image - needsUpdate |= parseImage(param); - break; - case 7: // bearing - needsUpdate |= parseBearing(param); - break; - case 8: // pitch - needsUpdate |= parsePitch(param); - break; - } - if (needsUpdate) update(); -} - -void QQuickMapboxGL::onParameterPropertyUpdated(const QString &propertyName) -{ - QQuickMapboxGLMapParameter *param = qobject_cast<QQuickMapboxGLMapParameter *>(sender()); - if (!param) { - m_error = QGeoServiceProvider::NotSupportedError; - m_errorString = "QQuickMapboxGL::onParameterPropertyUpdated should be called from a QQuickMapboxGLMapParameter."; - emit errorChanged(); - return; - } - - if (propertyName == "type") { - m_error = QGeoServiceProvider::NotSupportedError; - m_errorString = "Property 'type' is a write-once."; - emit errorChanged(); - return; - } - - bool needsUpdate = false; - switch (s_parameterTypes.indexOf(param->property("type").toString())) { - case -1: - m_error = QGeoServiceProvider::UnknownParameterError; - m_errorString = "Invalid value for property 'type': " + param->property("type").toString(); - emit errorChanged(); - break; - case 0: // style - needsUpdate |= parseStyle(param); - break; - case 1: // paint - case 2: // layout - needsUpdate |= parseStyleProperty(param, propertyName); - break; - case 3: // layer - needsUpdate |= parseStyleLayer(param); - break; - case 4: // source - needsUpdate |= parseStyleSource(param); - break; - case 5: // filter - needsUpdate |= parseStyleFilter(param); - break; - case 6: // image - needsUpdate |= parseImage(param); - break; - case 7: // bearing - needsUpdate |= parseBearing(param); - break; - case 8: // pitch - needsUpdate |= parsePitch(param); - break; - } - if (needsUpdate) update(); -} - -void QQuickMapboxGL::appendParameter(QQmlListProperty<QQuickMapboxGLMapParameter> *prop, QQuickMapboxGLMapParameter *param) -{ - QQuickMapboxGL *map = static_cast<QQuickMapboxGL *>(prop->object); - map->m_parameters.append(param); - QObject::connect(param, SIGNAL(propertyUpdated(QString)), map, SLOT(onParameterPropertyUpdated(QString))); -} - -int QQuickMapboxGL::countParameters(QQmlListProperty<QQuickMapboxGLMapParameter> *prop) -{ - QQuickMapboxGL *map = static_cast<QQuickMapboxGL *>(prop->object); - return map->m_parameters.count(); -} - -QQuickMapboxGLMapParameter *QQuickMapboxGL::parameterAt(QQmlListProperty<QQuickMapboxGLMapParameter> *prop, int index) -{ - QQuickMapboxGL *map = static_cast<QQuickMapboxGL *>(prop->object); - return map->m_parameters[index]; -} - -void QQuickMapboxGL::clearParameter(QQmlListProperty<QQuickMapboxGLMapParameter> *prop) -{ - QQuickMapboxGL *map = static_cast<QQuickMapboxGL *>(prop->object); - for (auto param : map->m_parameters) { - QObject::disconnect(param, SIGNAL(propertyUpdated(QString)), map, SLOT(onParameterPropertyUpdated(QString))); - } - map->m_parameters.clear(); -} - -QQmlListProperty<QQuickMapboxGLMapParameter> QQuickMapboxGL::parameters() -{ - return QQmlListProperty<QQuickMapboxGLMapParameter>(this, - nullptr, - appendParameter, - countParameters, - parameterAt, - clearParameter); -} diff --git a/platform/qt/src/qquickmapboxglmapparameter.cpp b/platform/qt/src/qquickmapboxglmapparameter.cpp deleted file mode 100644 index abf6e5ff1c..0000000000 --- a/platform/qt/src/qquickmapboxglmapparameter.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "qquickmapboxglmapparameter.hpp" - -#include <QByteArray> -#include <QMetaObject> -#include <QMetaProperty> -#include <QSignalMapper> - -QQuickMapboxGLMapParameter::QQuickMapboxGLMapParameter(QObject *parent) - : QObject(parent) - , m_metaPropertyOffset(metaObject()->propertyCount()) -{ -} - -void QQuickMapboxGLMapParameter::componentComplete() -{ - for (int i = m_metaPropertyOffset; i < metaObject()->propertyCount(); ++i) { - QMetaProperty property = metaObject()->property(i); - - if (!property.hasNotifySignal()) { - return; - } - - auto mapper = new QSignalMapper(this); - mapper->setMapping(this, i); - - const QByteArray signalName = '2' + property.notifySignal().methodSignature(); - QObject::connect(this, signalName, mapper, SLOT(map())); - QObject::connect(mapper, SIGNAL(mapped(int)), this, SLOT(onPropertyUpdated(int))); - } -} - -void QQuickMapboxGLMapParameter::onPropertyUpdated(int index) -{ - emit propertyUpdated(metaObject()->property(index).name()); -} diff --git a/platform/qt/src/qquickmapboxglrenderer.cpp b/platform/qt/src/qquickmapboxglrenderer.cpp deleted file mode 100644 index 133bed40e2..0000000000 --- a/platform/qt/src/qquickmapboxglrenderer.cpp +++ /dev/null @@ -1,120 +0,0 @@ -#include "qquickmapboxglrenderer.hpp" - -#include "qmapboxgl.hpp" -#include "qquickmapboxgl.hpp" - -#include <QSize> -#include <QOpenGLFramebufferObject> -#include <QOpenGLFramebufferObjectFormat> -#include <QQuickWindow> -#include <QThread> - -QQuickMapboxGLRenderer::QQuickMapboxGLRenderer() -{ - QMapbox::initializeGLExtensions(); - - QMapboxGLSettings settings; - settings.setAccessToken(qgetenv("MAPBOX_ACCESS_TOKEN")); - settings.setCacheDatabasePath("/tmp/mbgl-cache.db"); - settings.setCacheDatabaseMaximumSize(20 * 1024 * 1024); - settings.setViewportMode(QMapboxGLSettings::FlippedYViewport); - - m_map.reset(new QMapboxGL(nullptr, settings, QSize(256, 256), 1)); -} - -QQuickMapboxGLRenderer::~QQuickMapboxGLRenderer() -{ -} - -QOpenGLFramebufferObject* QQuickMapboxGLRenderer::createFramebufferObject(const QSize &size) -{ - m_map->resize(size / m_pixelRatio, size); - - QOpenGLFramebufferObjectFormat format; - format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); - - return new QOpenGLFramebufferObject(size, format); -} - -void QQuickMapboxGLRenderer::render() -{ - framebufferObject()->bind(); - m_map->render(); - framebufferObject()->release(); -} - -void QQuickMapboxGLRenderer::synchronize(QQuickFramebufferObject *item) -{ - auto quickMap = qobject_cast<QQuickMapboxGL*>(item); - if (!m_initialized) { - QObject::connect(m_map.data(), &QMapboxGL::needsRendering, quickMap, &QQuickMapboxGL::update); - QObject::connect(m_map.data(), SIGNAL(mapChanged(QMapboxGL::MapChange)), quickMap, SLOT(onMapChanged(QMapboxGL::MapChange))); - QObject::connect(this, &QQuickMapboxGLRenderer::centerChanged, quickMap, &QQuickMapboxGL::setCenter); - m_initialized = true; - } - - if (auto window = quickMap->window()) { - m_pixelRatio = window->devicePixelRatio(); - } else { - m_pixelRatio = 1; - } - - auto syncStatus = quickMap->m_syncState; - quickMap->m_syncState = QQuickMapboxGL::NothingNeedsSync; - - if (syncStatus & QQuickMapboxGL::CenterNeedsSync || syncStatus & QQuickMapboxGL::ZoomNeedsSync) { - const auto& center = quickMap->center(); - m_map->setCoordinateZoom({ center.latitude(), center.longitude() }, quickMap->zoomLevel()); - } - - if (syncStatus & QQuickMapboxGL::StyleNeedsSync && !quickMap->m_styleUrl.isEmpty()) { - m_map->setStyleUrl(quickMap->m_styleUrl); - } - - if (syncStatus & QQuickMapboxGL::PanNeedsSync) { - m_map->moveBy(quickMap->m_pan); - quickMap->m_pan = QPointF(); - emit centerChanged(QGeoCoordinate(m_map->latitude(), m_map->longitude())); - } - - if (syncStatus & QQuickMapboxGL::BearingNeedsSync) { - m_map->setBearing(quickMap->m_bearing); - } - - if (syncStatus & QQuickMapboxGL::PitchNeedsSync) { - m_map->setPitch(quickMap->m_pitch); - } - - if (!quickMap->m_styleLoaded) { - return; - } - - for (const auto& change : quickMap->m_sourceChanges) { - m_map->updateSource(change.value("id").toString(), change); - } - quickMap->m_sourceChanges.clear(); - - for (const auto& change : quickMap->m_layerChanges) { - m_map->addLayer(change); - } - quickMap->m_layerChanges.clear(); - - for (const auto& change : quickMap->m_filterChanges) { - m_map->setFilter(change.value("layer").toString(), change.value("filter")); - } - quickMap->m_filterChanges.clear(); - - for (const auto& change : quickMap->m_imageChanges) { - m_map->addImage(change.name, change.sprite); - } - quickMap->m_imageChanges.clear(); - - for (const auto& change : quickMap->m_stylePropertyChanges) { - if (change.type == QQuickMapboxGL::StyleProperty::Paint) { - m_map->setPaintProperty(change.layer, change.property, change.value, change.klass); - } else { - m_map->setLayoutProperty(change.layer, change.property, change.value); - } - } - quickMap->m_stylePropertyChanges.clear(); -} diff --git a/platform/qt/src/qquickmapboxglrenderer.hpp b/platform/qt/src/qquickmapboxglrenderer.hpp deleted file mode 100644 index 1fb7a50f4a..0000000000 --- a/platform/qt/src/qquickmapboxglrenderer.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include "qmapbox.hpp" -#include "qmapboxgl.hpp" - -#include <QGeoCoordinate> -#include <QObject> -#include <QOpenGLFramebufferObject> -#include <QQuickFramebufferObject> -#include <QScopedPointer> -#include <QSize> - -class QQuickMapboxGLRenderer : public QObject, public QQuickFramebufferObject::Renderer -{ - Q_OBJECT - -public: - QQuickMapboxGLRenderer(); - virtual ~QQuickMapboxGLRenderer(); - - virtual QOpenGLFramebufferObject * createFramebufferObject(const QSize &); - - virtual void render(); - virtual void synchronize(QQuickFramebufferObject *); - -signals: - void centerChanged(const QGeoCoordinate &); - -private: - bool m_initialized = false; - qreal m_pixelRatio = 1; - - QScopedPointer<QMapboxGL> m_map; -}; diff --git a/platform/qt/test/headless_backend_qt.cpp b/platform/qt/test/headless_backend_qt.cpp index 00b519d5bf..401ce55a7f 100644 --- a/platform/qt/test/headless_backend_qt.cpp +++ b/platform/qt/test/headless_backend_qt.cpp @@ -1,10 +1,11 @@ #include <mbgl/gl/headless_backend.hpp> -#include <QGLContext> #include <QGLWidget> #if QT_VERSION >= 0x050000 #include <QOpenGLContext> +#else +#include <QGLContext> #endif #include <cassert> diff --git a/scripts/generate-shaders.js b/scripts/generate-shaders.js index 2949ebd007..cffe9d3854 100755 --- a/scripts/generate-shaders.js +++ b/scripts/generate-shaders.js @@ -8,6 +8,41 @@ const outputPath = 'src/mbgl/shaders'; require('./style-code'); +const vertexPrelude = fs.readFileSync(path.join(inputPath, '_prelude.vertex.glsl')); +const fragmentPrelude = fs.readFileSync(path.join(inputPath, '_prelude.fragment.glsl')); + +writeIfModified(path.join(outputPath, 'preludes.hpp'), `// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED. + +#pragma once + +namespace mbgl { +namespace shaders { + +extern const char* vertexPrelude; +extern const char* fragmentPrelude; + +} // namespace shaders +} // namespace mbgl +`); + +writeIfModified(path.join(outputPath, 'preludes.cpp'), `// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED. + +#include <mbgl/shaders/preludes.hpp> + +namespace mbgl { +namespace shaders { + +const char* vertexPrelude = R"MBGL_SHADER( +${vertexPrelude} +)MBGL_SHADER"; +const char* fragmentPrelude = R"MBGL_SHADER( +${fragmentPrelude} +)MBGL_SHADER"; + +} // namespace shaders +} // namespace mbgl +`); + [ 'circle', 'collision_box', @@ -25,34 +60,33 @@ require('./style-code'); ].forEach(function (shaderName) { function applyPragmas(source, pragmas) { return source.replace(/#pragma mapbox: ([\w]+) ([\w]+) ([\w]+) ([\w]+)/g, (match, operation, precision, type, name) => { + const a_type = type === "float" ? "vec2" : "vec4"; return pragmas[operation] .join("\n") .replace(/\{type\}/g, type) + .replace(/\{a_type}/g, a_type) .replace(/\{precision\}/g, precision) .replace(/\{name\}/g, name); }); } function vertexSource() { - const prelude = fs.readFileSync(path.join(inputPath, '_prelude.vertex.glsl')); const source = fs.readFileSync(path.join(inputPath, shaderName + '.vertex.glsl'), 'utf8'); - return prelude + applyPragmas(source, { + return applyPragmas(source, { define: [ "uniform lowp float a_{name}_t;", - "attribute {precision} {type} a_{name}_min;", - "attribute {precision} {type} a_{name}_max;", + "attribute {precision} {a_type} a_{name};", "varying {precision} {type} {name};" ], initialize: [ - "{name} = mix(a_{name}_min, a_{name}_max, a_{name}_t);" + "{name} = unpack_mix_{a_type}(a_{name}, a_{name}_t);" ] }); } function fragmentSource() { - const prelude = fs.readFileSync(path.join(inputPath, '_prelude.fragment.glsl')); const source = fs.readFileSync(path.join(inputPath, shaderName + '.fragment.glsl'), 'utf8'); - return prelude + applyPragmas(source, { + return applyPragmas(source, { define: [ "varying {precision} {type} {name};" ], diff --git a/scripts/publish_binary_size.sh b/scripts/publish_binary_size.sh index d5ab71b8c4..e515de7c96 100755 --- a/scripts/publish_binary_size.sh +++ b/scripts/publish_binary_size.sh @@ -24,9 +24,9 @@ function publish_binary_size { local DATE_END=$(date -u +${DATE_FORMAT}) if [ `uname -s` = 'Darwin' ]; then # BSD date - local DATE_BEGIN=$(date -jf "${DATE_FORMAT}" -v-30d "${DATE_END}" +"${DATE_FORMAT}") + local DATE_BEGIN=$(date -jf "${DATE_FORMAT}" -v-60d "${DATE_END}" +"${DATE_FORMAT}") else # GNU date - local DATE_BEGIN=$(date --date="${DATE_END} - 30 days" +"${DATE_FORMAT}") + local DATE_BEGIN=$(date --date="${DATE_END} - 60 days" +"${DATE_FORMAT}") fi # Download the metrics, gzip, and upload to S3. diff --git a/src/mbgl/geometry/anchor.hpp b/src/mbgl/geometry/anchor.hpp index 9bc979343e..3ed2b23e1b 100644 --- a/src/mbgl/geometry/anchor.hpp +++ b/src/mbgl/geometry/anchor.hpp @@ -6,17 +6,15 @@ namespace mbgl { -struct Anchor { +class Anchor { +public: Point<float> point; float angle = 0.0f; float scale = 0.0f; int segment = -1; - explicit Anchor(float x_, float y_, float angle_, float scale_) - : point(x_, y_), angle(angle_), scale(scale_) {} - explicit Anchor(float x_, float y_, float angle_, float scale_, int segment_) + Anchor(float x_, float y_, float angle_, float scale_, int segment_ = -1) : point(x_, y_), angle(angle_), scale(scale_), segment(segment_) {} - }; typedef std::vector<Anchor> Anchors; diff --git a/src/mbgl/geometry/feature_index.cpp b/src/mbgl/geometry/feature_index.cpp index 5019d888ca..64fb7bd247 100644 --- a/src/mbgl/geometry/feature_index.cpp +++ b/src/mbgl/geometry/feature_index.cpp @@ -7,6 +7,9 @@ #include <mbgl/util/constants.hpp> #include <mbgl/util/math.hpp> #include <mbgl/math/minmax.hpp> +#include <mbgl/map/query.hpp> +#include <mbgl/style/filter.hpp> +#include <mbgl/style/filter_evaluator.hpp> #include <mapbox/geometry/envelope.hpp> @@ -56,7 +59,7 @@ void FeatureIndex::query( const float bearing, const double tileSize, const double scale, - const optional<std::vector<std::string>>& filterLayerIDs, + const QueryOptions& queryOptions, const GeometryTileData& geometryTileData, const CanonicalTileID& tileID, const style::Style& style, @@ -76,7 +79,7 @@ void FeatureIndex::query( if (indexedFeature.sortIndex == previousSortIndex) continue; previousSortIndex = indexedFeature.sortIndex; - addFeature(result, indexedFeature, queryGeometry, filterLayerIDs, geometryTileData, tileID, style, bearing, pixelsToTileUnits); + addFeature(result, indexedFeature, queryGeometry, queryOptions, geometryTileData, tileID, style, bearing, pixelsToTileUnits); } // Query symbol features, if they've been placed. @@ -87,7 +90,7 @@ void FeatureIndex::query( std::vector<IndexedSubfeature> symbolFeatures = collisionTile->queryRenderedSymbols(queryGeometry, scale); std::sort(symbolFeatures.begin(), symbolFeatures.end(), topDownSymbols); for (const auto& symbolFeature : symbolFeatures) { - addFeature(result, symbolFeature, queryGeometry, filterLayerIDs, geometryTileData, tileID, style, bearing, pixelsToTileUnits); + addFeature(result, symbolFeature, queryGeometry, queryOptions, geometryTileData, tileID, style, bearing, pixelsToTileUnits); } } @@ -95,7 +98,7 @@ void FeatureIndex::addFeature( std::unordered_map<std::string, std::vector<Feature>>& result, const IndexedSubfeature& indexedFeature, const GeometryCoordinates& queryGeometry, - const optional<std::vector<std::string>>& filterLayerIDs, + const QueryOptions& options, const GeometryTileData& geometryTileData, const CanonicalTileID& tileID, const style::Style& style, @@ -103,7 +106,7 @@ void FeatureIndex::addFeature( const float pixelsToTileUnits) const { auto& layerIDs = bucketLayerIDs.at(indexedFeature.bucketName); - if (filterLayerIDs && !vectorsIntersect(layerIDs, *filterLayerIDs)) { + if (options.layerIDs && !vectorsIntersect(layerIDs, *options.layerIDs)) { return; } @@ -114,7 +117,7 @@ void FeatureIndex::addFeature( assert(geometryTileFeature); for (const auto& layerID : layerIDs) { - if (filterLayerIDs && !vectorContains(*filterLayerIDs, layerID)) { + if (options.layerIDs && !vectorContains(*options.layerIDs, layerID)) { continue; } @@ -125,6 +128,10 @@ void FeatureIndex::addFeature( continue; } + if (options.filter && !(*options.filter)(*geometryTileFeature)) { + continue; + } + result[layerID].push_back(convertFeature(*geometryTileFeature, tileID)); } } diff --git a/src/mbgl/geometry/feature_index.hpp b/src/mbgl/geometry/feature_index.hpp index ca813f4b6b..d2f68fd103 100644 --- a/src/mbgl/geometry/feature_index.hpp +++ b/src/mbgl/geometry/feature_index.hpp @@ -11,6 +11,8 @@ namespace mbgl { +class QueryOptions; + namespace style { class Style; } // namespace style @@ -39,7 +41,7 @@ public: const float bearing, const double tileSize, const double scale, - const optional<std::vector<std::string>>& layerIDs, + const QueryOptions& options, const GeometryTileData&, const CanonicalTileID&, const style::Style&, @@ -59,7 +61,7 @@ private: std::unordered_map<std::string, std::vector<Feature>>& result, const IndexedSubfeature&, const GeometryCoordinates& queryGeometry, - const optional<std::vector<std::string>>& filterLayerIDs, + const QueryOptions& options, const GeometryTileData&, const CanonicalTileID&, const style::Style&, diff --git a/src/mbgl/gl/attribute.cpp b/src/mbgl/gl/attribute.cpp index 2c16dac3fc..ff313fdcd0 100644 --- a/src/mbgl/gl/attribute.cpp +++ b/src/mbgl/gl/attribute.cpp @@ -38,7 +38,7 @@ void VariableAttributeBinding<T, N>::bind(Context& context, MBGL_CHECK_ERROR(glEnableVertexAttribArray(location)); MBGL_CHECK_ERROR(glVertexAttribPointer( location, - static_cast<GLint>(N), + static_cast<GLint>(attributeSize), static_cast<GLenum>(DataTypeOf<T>), static_cast<GLboolean>(IsNormalized<T>), static_cast<GLsizei>(vertexSize), diff --git a/src/mbgl/gl/attribute.hpp b/src/mbgl/gl/attribute.hpp index 6300ebb56b..43e2c2d794 100644 --- a/src/mbgl/gl/attribute.hpp +++ b/src/mbgl/gl/attribute.hpp @@ -17,10 +17,12 @@ class VariableAttributeBinding { public: VariableAttributeBinding(BufferID vertexBuffer_, std::size_t vertexSize_, - std::size_t attributeOffset_) + std::size_t attributeOffset_, + std::size_t attributeSize_ = N) : vertexBuffer(vertexBuffer_), vertexSize(vertexSize_), - attributeOffset(attributeOffset_) + attributeOffset(attributeOffset_), + attributeSize(attributeSize_) {} void bind(Context&, AttributeLocation, optional<VariableAttributeBinding<T, N>>&, std::size_t vertexOffset) const; @@ -29,13 +31,15 @@ public: const VariableAttributeBinding& rhs) { return lhs.vertexBuffer == rhs.vertexBuffer && lhs.vertexSize == rhs.vertexSize - && lhs.attributeOffset == rhs.attributeOffset; + && lhs.attributeOffset == rhs.attributeOffset + && lhs.attributeSize == rhs.attributeSize; } private: BufferID vertexBuffer; std::size_t vertexSize; std::size_t attributeOffset; + std::size_t attributeSize; }; template <class T, std::size_t N> @@ -58,9 +62,16 @@ private: std::array<T, N> value; }; +/* + gl::Attribute<T,N> manages the binding of a constant value or vertex buffer to a GL program attribute. + - T is the underlying primitive type (exposed as Attribute<T,N>::ValueType) + - N is the number of components in the attribute declared in the shader (exposed as Attribute<T,N>::Dimensions) +*/ template <class T, std::size_t N> class Attribute { public: + using ValueType = T; + static constexpr size_t Dimensions = N; using Value = std::array<T, N>; using VariableBinding = VariableAttributeBinding<T, N>; @@ -72,6 +83,25 @@ public: ConstantBinding, VariableBinding>; + /* + Create a variable (i.e. data-driven) binding for this attribute. The `attributeSize` + parameter may be used to override the number of components available in the buffer for + each vertex. Thus, a buffer with only one float for each vertex can be bound to a + `vec2` attribute + */ + template <class Vertex, class DrawMode> + static VariableBinding variableBinding(const VertexBuffer<Vertex, DrawMode>& buffer, + std::size_t attributeIndex, + std::size_t attributeSize = N) { + static_assert(std::is_standard_layout<Vertex>::value, "vertex type must use standard layout"); + return VariableBinding { + buffer.buffer, + sizeof(Vertex), + Vertex::attributeOffsets[attributeIndex], + attributeSize + }; + } + static void bind(Context& context, const Location& location, optional<VariableBinding>& oldBinding, @@ -223,15 +253,7 @@ public: template <class DrawMode> static Bindings allVariableBindings(const VertexBuffer<Vertex, DrawMode>& buffer) { - static_assert(std::is_standard_layout<Vertex>::value, "vertex type must use standard layout"); - - return Bindings { - typename As::VariableBinding { - buffer.buffer, - sizeof(Vertex), - Vertex::attributeOffsets[Index<As>] - }... - }; + return Bindings { As::variableBinding(buffer, Index<As>)... }; } static void bind(Context& context, diff --git a/src/mbgl/layout/symbol_instance.cpp b/src/mbgl/layout/symbol_instance.cpp index d81783b2f6..8bdc528bbb 100644 --- a/src/mbgl/layout/symbol_instance.cpp +++ b/src/mbgl/layout/symbol_instance.cpp @@ -5,12 +5,22 @@ namespace mbgl { using namespace style; -SymbolInstance::SymbolInstance(Anchor& anchor, const GeometryCoordinates& line, - const std::pair<Shaping, Shaping>& shapedTextOrientations, const PositionedIcon& shapedIcon, - const SymbolLayoutProperties::Evaluated& layout, const bool addToBuffers, const uint32_t index_, - const float textBoxScale, const float textPadding, const SymbolPlacementType textPlacement, - const float iconBoxScale, const float iconPadding, const SymbolPlacementType iconPlacement, - const GlyphPositions& face, const IndexedSubfeature& indexedFeature, const std::size_t featureIndex_) : +SymbolInstance::SymbolInstance(Anchor& anchor, + const GeometryCoordinates& line, + const std::pair<Shaping, Shaping>& shapedTextOrientations, + const PositionedIcon& shapedIcon, + const SymbolLayoutProperties::Evaluated& layout, + const bool addToBuffers, + const uint32_t index_, + const float textBoxScale, + const float textPadding, + const SymbolPlacementType textPlacement, + const float iconBoxScale, + const float iconPadding, + const SymbolPlacementType iconPlacement, + const GlyphPositions& face, + const IndexedSubfeature& indexedFeature, + const std::size_t featureIndex_) : point(anchor.point), index(index_), hasText(shapedTextOrientations.first || shapedTextOrientations.second), diff --git a/src/mbgl/layout/symbol_instance.hpp b/src/mbgl/layout/symbol_instance.hpp index 532a4d30d8..70ebfeefa2 100644 --- a/src/mbgl/layout/symbol_instance.hpp +++ b/src/mbgl/layout/symbol_instance.hpp @@ -7,17 +7,27 @@ namespace mbgl { -struct Anchor; +class Anchor; class IndexedSubfeature; class SymbolInstance { public: - explicit SymbolInstance(Anchor& anchor, const GeometryCoordinates& line, - const std::pair<Shaping, Shaping>& shapedTextOrientations, const PositionedIcon& shapedIcon, - const style::SymbolLayoutProperties::Evaluated&, const bool inside, const uint32_t index, - const float textBoxScale, const float textPadding, style::SymbolPlacementType textPlacement, - const float iconBoxScale, const float iconPadding, style::SymbolPlacementType iconPlacement, - const GlyphPositions& face, const IndexedSubfeature& indexedfeature, const std::size_t featureIndex); + SymbolInstance(Anchor& anchor, + const GeometryCoordinates& line, + const std::pair<Shaping, Shaping>& shapedTextOrientations, + const PositionedIcon& shapedIcon, + const style::SymbolLayoutProperties::Evaluated&, + const bool inside, + const uint32_t index, + const float textBoxScale, + const float textPadding, + style::SymbolPlacementType textPlacement, + const float iconBoxScale, + const float iconPadding, + style::SymbolPlacementType iconPlacement, + const GlyphPositions& face, + const IndexedSubfeature&, + const std::size_t featureIndex); Point<float> point; uint32_t index; diff --git a/src/mbgl/layout/symbol_layout.hpp b/src/mbgl/layout/symbol_layout.hpp index 491d0078da..c6e1743549 100644 --- a/src/mbgl/layout/symbol_layout.hpp +++ b/src/mbgl/layout/symbol_layout.hpp @@ -19,6 +19,7 @@ class CollisionTile; class SpriteAtlas; class GlyphAtlas; class SymbolBucket; +class Anchor; namespace style { class BucketParameters; @@ -26,8 +27,6 @@ class Filter; class Layer; } // namespace style -struct Anchor; - class SymbolLayout { public: SymbolLayout(const style::BucketParameters&, diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index 857f088b62..f4f4d67148 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -12,7 +12,6 @@ #include <mbgl/style/observer.hpp> #include <mbgl/style/transition_options.hpp> #include <mbgl/style/update_parameters.hpp> -#include <mbgl/style/query_parameters.hpp> #include <mbgl/renderer/painter.hpp> #include <mbgl/storage/file_source.hpp> #include <mbgl/storage/resource.hpp> @@ -810,20 +809,20 @@ void Map::removeAnnotation(AnnotationID annotation) { #pragma mark - Feature query api -std::vector<Feature> Map::queryRenderedFeatures(const ScreenCoordinate& point, const optional<std::vector<std::string>>& layerIDs) { +std::vector<Feature> Map::queryRenderedFeatures(const ScreenCoordinate& point, const QueryOptions& options) { if (!impl->style) return {}; - return impl->style->queryRenderedFeatures({ + return impl->style->queryRenderedFeatures( { point }, impl->transform.getState(), - layerIDs - }); + options + ); } -std::vector<Feature> Map::queryRenderedFeatures(const ScreenBox& box, const optional<std::vector<std::string>>& layerIDs) { +std::vector<Feature> Map::queryRenderedFeatures(const ScreenBox& box, const QueryOptions& options) { if (!impl->style) return {}; - return impl->style->queryRenderedFeatures({ + return impl->style->queryRenderedFeatures( { box.min, { box.max.x, box.min.y }, @@ -832,12 +831,14 @@ std::vector<Feature> Map::queryRenderedFeatures(const ScreenBox& box, const opti box.min }, impl->transform.getState(), - layerIDs - }); + options + ); } AnnotationIDs Map::queryPointAnnotations(const ScreenBox& box) { - auto features = queryRenderedFeatures(box, {{ AnnotationManager::PointLayerID }}); + QueryOptions options; + options.layerIDs = {{ AnnotationManager::PointLayerID }}; + auto features = queryRenderedFeatures(box, options); std::set<AnnotationID> set; for (auto &feature : features) { assert(feature.id); diff --git a/src/mbgl/programs/attributes.hpp b/src/mbgl/programs/attributes.hpp index bb90f2c13c..a2e0772762 100644 --- a/src/mbgl/programs/attributes.hpp +++ b/src/mbgl/programs/attributes.hpp @@ -13,6 +13,7 @@ namespace attributes { MBGL_DEFINE_ATTRIBUTE(int16_t, 2, a_pos); MBGL_DEFINE_ATTRIBUTE(int16_t, 2, a_extrude); +MBGL_DEFINE_ATTRIBUTE(int16_t, 4, a_pos_offset); MBGL_DEFINE_ATTRIBUTE(uint16_t, 2, a_texture_pos); template <std::size_t N> @@ -27,19 +28,30 @@ struct a_offset : gl::Attribute<int16_t, N> { // Paint attributes +/* + ZoomInterpolatedAttribute<Attr> is a 'compound' attribute, representing two values of the + the base attribute Attr. These two values are provided to the shader to allow interpolation + between zoom levels, without the need to repopulate vertex buffers each frame as the map is + being zoomed. +*/ template <class Attr> -struct Min : Attr { - static auto name() { - static const std::string name = Attr::name() + std::string("_min"); - return name.c_str(); - } -}; +struct ZoomInterpolatedAttribute : gl::Attribute<typename Attr::ValueType, Attr::Dimensions * 2> { + using Value = typename gl::Attribute<typename Attr::ValueType, Attr::Dimensions * 2>::Value; -template <class Attr> -struct Max : Attr { static auto name() { - static const std::string name = Attr::name() + std::string("_max"); - return name.c_str(); + return Attr::name(); + } + + template <class InputType> + static Value value(const InputType& min, const InputType& max){ + auto minValue = Attr::value(min); + auto maxValue = Attr::value(max); + Value result = {{}}; + for (size_t i = 0; i < Attr::Dimensions; i++) { + result[i] = minValue[i]; + result[Attr::Dimensions+i] = maxValue[i]; + } + return result; } }; @@ -51,70 +63,62 @@ struct InterpolationUniform : gl::UniformScalar<InterpolationUniform<Attr>, floa } }; -struct a_color : gl::Attribute<gl::Normalized<uint8_t>, 4> { +/* + Encode a four-component color value into a pair of floats. Since csscolorparser + uses 8-bit precision for each color component, for each float we use the upper 8 + bits for one component (e.g. (color.r * 255) * 256), and the lower 8 for another. + + Also note: + - Colors come in as floats 0..1, so we scale by 255. + - Casting the scaled values to ints is important: without doing this, e.g., the + fractional part of the `r` component would corrupt the lower-8 bits of the encoded + value, which must be reserved for the `g` component. +*/ +static std::array<float, 2> encodeColor (const Color& color) { + const auto v1 = static_cast<uint16_t>( static_cast<uint16_t>(color.r*255)*256 + color.g*255); + const auto v2 = static_cast<uint16_t>( static_cast<uint16_t>(color.b*255)*256 + color.a*255); + return {{ static_cast<float>(v1), static_cast<float>(v2) }}; +} + +struct a_color : gl::Attribute<float, 2> { static auto name() { return "a_color"; } static Value value(const Color& color) { - return {{ - gl::Normalized<uint8_t>(color.r), - gl::Normalized<uint8_t>(color.g), - gl::Normalized<uint8_t>(color.b), - gl::Normalized<uint8_t>(color.a) - }}; + return encodeColor(color); } }; // used in the symbol sdf shader -struct a_fill_color : gl::Attribute<gl::Normalized<uint8_t>, 4> { +struct a_fill_color : gl::Attribute<float, 2> { static auto name() { return "a_fill_color"; } static Value value(const Color& color) { - return {{ - gl::Normalized<uint8_t>(color.r), - gl::Normalized<uint8_t>(color.g), - gl::Normalized<uint8_t>(color.b), - gl::Normalized<uint8_t>(color.a) - }}; + return encodeColor(color); } }; // used in the symbol sdf shader -struct a_halo_color : gl::Attribute<gl::Normalized<uint8_t>, 4> { +struct a_halo_color : gl::Attribute<float, 2> { static auto name() { return "a_halo_color"; } - static Value value(const Color& color) { - return {{ - gl::Normalized<uint8_t>(color.r), - gl::Normalized<uint8_t>(color.g), - gl::Normalized<uint8_t>(color.b), - gl::Normalized<uint8_t>(color.a) - }}; + static Value value(const Color& color) { + return encodeColor(color); } }; -struct a_stroke_color : gl::Attribute<gl::Normalized<uint8_t>, 4> { +struct a_stroke_color : gl::Attribute<float, 2> { static auto name() { return "a_stroke_color"; } static Value value(const Color& color) { - return {{ - gl::Normalized<uint8_t>(color.r), - gl::Normalized<uint8_t>(color.g), - gl::Normalized<uint8_t>(color.b), - gl::Normalized<uint8_t>(color.a) - }}; + return encodeColor(color); } }; -struct a_outline_color : gl::Attribute<gl::Normalized<uint8_t>, 4> { +struct a_outline_color : gl::Attribute<float, 2> { static auto name() { return "a_outline_color"; } static Value value(const Color& color) { - return {{ - gl::Normalized<uint8_t>(color.r), - gl::Normalized<uint8_t>(color.g), - gl::Normalized<uint8_t>(color.b), - gl::Normalized<uint8_t>(color.a) - }}; + return encodeColor(color); } }; diff --git a/src/mbgl/programs/program.hpp b/src/mbgl/programs/program.hpp index e75dbebf18..ffad767c3a 100644 --- a/src/mbgl/programs/program.hpp +++ b/src/mbgl/programs/program.hpp @@ -4,6 +4,7 @@ #include <mbgl/programs/program_parameters.hpp> #include <mbgl/programs/attributes.hpp> #include <mbgl/style/paint_property.hpp> +#include <mbgl/shaders/preludes.hpp> #include <sstream> #include <cassert> @@ -45,7 +46,7 @@ public: } static std::string fragmentSource(const ProgramParameters& parameters) { - std::string source = pixelRatioDefine(parameters) + Shaders::fragmentSource; + 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"); @@ -54,7 +55,7 @@ public: } static std::string vertexSource(const ProgramParameters& parameters) { - return pixelRatioDefine(parameters) + Shaders::vertexSource; + return pixelRatioDefine(parameters) + shaders::vertexPrelude + Shaders::vertexSource; } template <class DrawMode> diff --git a/src/mbgl/programs/symbol_program.hpp b/src/mbgl/programs/symbol_program.hpp index 0537c25a2c..fdd1aa5c3b 100644 --- a/src/mbgl/programs/symbol_program.hpp +++ b/src/mbgl/programs/symbol_program.hpp @@ -35,8 +35,7 @@ MBGL_DEFINE_UNIFORM_SCALAR(float, u_gamma_scale); } // namespace uniforms struct SymbolLayoutAttributes : gl::Attributes< - attributes::a_pos, - attributes::a_offset<2>, + attributes::a_pos_offset, attributes::a_texture_pos, attributes::a_data<4>> { @@ -49,11 +48,10 @@ struct SymbolLayoutAttributes : gl::Attributes< float labelminzoom, uint8_t labelangle) { return Vertex { + // combining pos and offset to reduce number of vertex attributes passed to shader (8 max for some devices) {{ static_cast<int16_t>(a.x), - static_cast<int16_t>(a.y) - }}, - {{ + static_cast<int16_t>(a.y), static_cast<int16_t>(::round(o.x * 64)), // use 1/64 pixels for placement static_cast<int16_t>(::round(o.y * 64)) }}, diff --git a/src/mbgl/shaders/circle.cpp b/src/mbgl/shaders/circle.cpp index 592a883fb3..b479f1d40c 100644 --- a/src/mbgl/shaders/circle.cpp +++ b/src/mbgl/shaders/circle.cpp @@ -7,60 +7,6 @@ namespace shaders { const char* circle::name = "circle"; const char* circle::vertexSource = R"MBGL_SHADER( -#ifdef GL_ES -precision highp float; -#else - -#if !defined(lowp) -#define lowp -#endif - -#if !defined(mediump) -#define mediump -#endif - -#if !defined(highp) -#define highp -#endif - -#endif - -float evaluate_zoom_function_1(const vec4 values, const float t) { - if (t < 1.0) { - return mix(values[0], values[1], t); - } else if (t < 2.0) { - return mix(values[1], values[2], t - 1.0); - } else { - return mix(values[2], values[3], t - 2.0); - } -} -vec4 evaluate_zoom_function_4(const vec4 value0, const vec4 value1, const vec4 value2, const vec4 value3, const float t) { - if (t < 1.0) { - return mix(value0, value1, t); - } else if (t < 2.0) { - return mix(value1, value2, t - 1.0); - } else { - return mix(value2, value3, t - 2.0); - } -} - -// The offset depends on how many pixels are between the world origin and the edge of the tile: -// vec2 offset = mod(pixel_coord, size) -// -// At high zoom levels there are a ton of pixels between the world origin and the edge of the tile. -// The glsl spec only guarantees 16 bits of precision for highp floats. We need more than that. -// -// The pixel_coord is passed in as two 16 bit values: -// pixel_coord_upper = floor(pixel_coord / 2^16) -// pixel_coord_lower = mod(pixel_coord, 2^16) -// -// The offset is calculated in a series of steps that should preserve this precision: -vec2 get_pattern_pos(const vec2 pixel_coord_upper, const vec2 pixel_coord_lower, - const vec2 pattern_size, const float tile_units_to_pixels, const vec2 pos) { - - vec2 offset = mod(mod(mod(pixel_coord_upper, pattern_size) * 256.0, pattern_size) * 256.0 + pixel_coord_lower, pattern_size); - return (tile_units_to_pixels * pos + offset) / pattern_size; -} uniform mat4 u_matrix; uniform bool u_scale_with_map; uniform vec2 u_extrude_scale; @@ -68,45 +14,38 @@ uniform vec2 u_extrude_scale; attribute vec2 a_pos; uniform lowp float a_color_t; -attribute lowp vec4 a_color_min; -attribute lowp vec4 a_color_max; +attribute lowp vec4 a_color; varying lowp vec4 color; uniform lowp float a_radius_t; -attribute mediump float a_radius_min; -attribute mediump float a_radius_max; +attribute mediump vec2 a_radius; varying mediump float radius; uniform lowp float a_blur_t; -attribute lowp float a_blur_min; -attribute lowp float a_blur_max; +attribute lowp vec2 a_blur; varying lowp float blur; uniform lowp float a_opacity_t; -attribute lowp float a_opacity_min; -attribute lowp float a_opacity_max; +attribute lowp vec2 a_opacity; varying lowp float opacity; uniform lowp float a_stroke_color_t; -attribute lowp vec4 a_stroke_color_min; -attribute lowp vec4 a_stroke_color_max; +attribute lowp vec4 a_stroke_color; varying lowp vec4 stroke_color; uniform lowp float a_stroke_width_t; -attribute mediump float a_stroke_width_min; -attribute mediump float a_stroke_width_max; +attribute mediump vec2 a_stroke_width; varying mediump float stroke_width; uniform lowp float a_stroke_opacity_t; -attribute lowp float a_stroke_opacity_min; -attribute lowp float a_stroke_opacity_max; +attribute lowp vec2 a_stroke_opacity; varying lowp float stroke_opacity; varying vec2 v_extrude; varying lowp float v_antialiasblur; void main(void) { - color = mix(a_color_min, a_color_max, a_color_t); - radius = mix(a_radius_min, a_radius_max, a_radius_t); - blur = mix(a_blur_min, a_blur_max, a_blur_t); - opacity = mix(a_opacity_min, a_opacity_max, a_opacity_t); - stroke_color = mix(a_stroke_color_min, a_stroke_color_max, a_stroke_color_t); - stroke_width = mix(a_stroke_width_min, a_stroke_width_max, a_stroke_width_t); - stroke_opacity = mix(a_stroke_opacity_min, a_stroke_opacity_max, a_stroke_opacity_t); + color = unpack_mix_vec4(a_color, a_color_t); + radius = unpack_mix_vec2(a_radius, a_radius_t); + blur = unpack_mix_vec2(a_blur, a_blur_t); + opacity = unpack_mix_vec2(a_opacity, a_opacity_t); + stroke_color = unpack_mix_vec4(a_stroke_color, a_stroke_color_t); + stroke_width = unpack_mix_vec2(a_stroke_width, a_stroke_width_t); + stroke_opacity = unpack_mix_vec2(a_stroke_opacity, a_stroke_opacity_t); // unencode the extrusion vector that we snuck into the a_pos vector v_extrude = vec2(mod(a_pos, 2.0) * 2.0 - 1.0); @@ -130,23 +69,6 @@ void main(void) { )MBGL_SHADER"; const char* circle::fragmentSource = R"MBGL_SHADER( -#ifdef GL_ES -precision mediump float; -#else - -#if !defined(lowp) -#define lowp -#endif - -#if !defined(mediump) -#define mediump -#endif - -#if !defined(highp) -#define highp -#endif - -#endif varying lowp vec4 color; varying mediump float radius; varying lowp float blur; diff --git a/src/mbgl/shaders/collision_box.cpp b/src/mbgl/shaders/collision_box.cpp index 6f2b9f3824..5f733c6a1e 100644 --- a/src/mbgl/shaders/collision_box.cpp +++ b/src/mbgl/shaders/collision_box.cpp @@ -7,60 +7,6 @@ namespace shaders { const char* collision_box::name = "collision_box"; const char* collision_box::vertexSource = R"MBGL_SHADER( -#ifdef GL_ES -precision highp float; -#else - -#if !defined(lowp) -#define lowp -#endif - -#if !defined(mediump) -#define mediump -#endif - -#if !defined(highp) -#define highp -#endif - -#endif - -float evaluate_zoom_function_1(const vec4 values, const float t) { - if (t < 1.0) { - return mix(values[0], values[1], t); - } else if (t < 2.0) { - return mix(values[1], values[2], t - 1.0); - } else { - return mix(values[2], values[3], t - 2.0); - } -} -vec4 evaluate_zoom_function_4(const vec4 value0, const vec4 value1, const vec4 value2, const vec4 value3, const float t) { - if (t < 1.0) { - return mix(value0, value1, t); - } else if (t < 2.0) { - return mix(value1, value2, t - 1.0); - } else { - return mix(value2, value3, t - 2.0); - } -} - -// The offset depends on how many pixels are between the world origin and the edge of the tile: -// vec2 offset = mod(pixel_coord, size) -// -// At high zoom levels there are a ton of pixels between the world origin and the edge of the tile. -// The glsl spec only guarantees 16 bits of precision for highp floats. We need more than that. -// -// The pixel_coord is passed in as two 16 bit values: -// pixel_coord_upper = floor(pixel_coord / 2^16) -// pixel_coord_lower = mod(pixel_coord, 2^16) -// -// The offset is calculated in a series of steps that should preserve this precision: -vec2 get_pattern_pos(const vec2 pixel_coord_upper, const vec2 pixel_coord_lower, - const vec2 pattern_size, const float tile_units_to_pixels, const vec2 pos) { - - vec2 offset = mod(mod(mod(pixel_coord_upper, pattern_size) * 256.0, pattern_size) * 256.0 + pixel_coord_lower, pattern_size); - return (tile_units_to_pixels * pos + offset) / pattern_size; -} attribute vec2 a_pos; attribute vec2 a_extrude; attribute vec2 a_data; @@ -80,23 +26,6 @@ void main() { )MBGL_SHADER"; const char* collision_box::fragmentSource = R"MBGL_SHADER( -#ifdef GL_ES -precision mediump float; -#else - -#if !defined(lowp) -#define lowp -#endif - -#if !defined(mediump) -#define mediump -#endif - -#if !defined(highp) -#define highp -#endif - -#endif uniform float u_zoom; uniform float u_maxzoom; diff --git a/src/mbgl/shaders/debug.cpp b/src/mbgl/shaders/debug.cpp index 2659b2ca79..27a15698d4 100644 --- a/src/mbgl/shaders/debug.cpp +++ b/src/mbgl/shaders/debug.cpp @@ -7,60 +7,6 @@ namespace shaders { const char* debug::name = "debug"; const char* debug::vertexSource = R"MBGL_SHADER( -#ifdef GL_ES -precision highp float; -#else - -#if !defined(lowp) -#define lowp -#endif - -#if !defined(mediump) -#define mediump -#endif - -#if !defined(highp) -#define highp -#endif - -#endif - -float evaluate_zoom_function_1(const vec4 values, const float t) { - if (t < 1.0) { - return mix(values[0], values[1], t); - } else if (t < 2.0) { - return mix(values[1], values[2], t - 1.0); - } else { - return mix(values[2], values[3], t - 2.0); - } -} -vec4 evaluate_zoom_function_4(const vec4 value0, const vec4 value1, const vec4 value2, const vec4 value3, const float t) { - if (t < 1.0) { - return mix(value0, value1, t); - } else if (t < 2.0) { - return mix(value1, value2, t - 1.0); - } else { - return mix(value2, value3, t - 2.0); - } -} - -// The offset depends on how many pixels are between the world origin and the edge of the tile: -// vec2 offset = mod(pixel_coord, size) -// -// At high zoom levels there are a ton of pixels between the world origin and the edge of the tile. -// The glsl spec only guarantees 16 bits of precision for highp floats. We need more than that. -// -// The pixel_coord is passed in as two 16 bit values: -// pixel_coord_upper = floor(pixel_coord / 2^16) -// pixel_coord_lower = mod(pixel_coord, 2^16) -// -// The offset is calculated in a series of steps that should preserve this precision: -vec2 get_pattern_pos(const vec2 pixel_coord_upper, const vec2 pixel_coord_lower, - const vec2 pattern_size, const float tile_units_to_pixels, const vec2 pos) { - - vec2 offset = mod(mod(mod(pixel_coord_upper, pattern_size) * 256.0, pattern_size) * 256.0 + pixel_coord_lower, pattern_size); - return (tile_units_to_pixels * pos + offset) / pattern_size; -} attribute vec2 a_pos; uniform mat4 u_matrix; @@ -71,23 +17,6 @@ void main() { )MBGL_SHADER"; const char* debug::fragmentSource = R"MBGL_SHADER( -#ifdef GL_ES -precision mediump float; -#else - -#if !defined(lowp) -#define lowp -#endif - -#if !defined(mediump) -#define mediump -#endif - -#if !defined(highp) -#define highp -#endif - -#endif uniform lowp vec4 u_color; void main() { diff --git a/src/mbgl/shaders/fill.cpp b/src/mbgl/shaders/fill.cpp index 066adee447..a1fba4d749 100644 --- a/src/mbgl/shaders/fill.cpp +++ b/src/mbgl/shaders/fill.cpp @@ -7,99 +7,26 @@ namespace shaders { const char* fill::name = "fill"; const char* fill::vertexSource = R"MBGL_SHADER( -#ifdef GL_ES -precision highp float; -#else - -#if !defined(lowp) -#define lowp -#endif - -#if !defined(mediump) -#define mediump -#endif - -#if !defined(highp) -#define highp -#endif - -#endif - -float evaluate_zoom_function_1(const vec4 values, const float t) { - if (t < 1.0) { - return mix(values[0], values[1], t); - } else if (t < 2.0) { - return mix(values[1], values[2], t - 1.0); - } else { - return mix(values[2], values[3], t - 2.0); - } -} -vec4 evaluate_zoom_function_4(const vec4 value0, const vec4 value1, const vec4 value2, const vec4 value3, const float t) { - if (t < 1.0) { - return mix(value0, value1, t); - } else if (t < 2.0) { - return mix(value1, value2, t - 1.0); - } else { - return mix(value2, value3, t - 2.0); - } -} - -// The offset depends on how many pixels are between the world origin and the edge of the tile: -// vec2 offset = mod(pixel_coord, size) -// -// At high zoom levels there are a ton of pixels between the world origin and the edge of the tile. -// The glsl spec only guarantees 16 bits of precision for highp floats. We need more than that. -// -// The pixel_coord is passed in as two 16 bit values: -// pixel_coord_upper = floor(pixel_coord / 2^16) -// pixel_coord_lower = mod(pixel_coord, 2^16) -// -// The offset is calculated in a series of steps that should preserve this precision: -vec2 get_pattern_pos(const vec2 pixel_coord_upper, const vec2 pixel_coord_lower, - const vec2 pattern_size, const float tile_units_to_pixels, const vec2 pos) { - - vec2 offset = mod(mod(mod(pixel_coord_upper, pattern_size) * 256.0, pattern_size) * 256.0 + pixel_coord_lower, pattern_size); - return (tile_units_to_pixels * pos + offset) / pattern_size; -} attribute vec2 a_pos; uniform mat4 u_matrix; uniform lowp float a_color_t; -attribute lowp vec4 a_color_min; -attribute lowp vec4 a_color_max; +attribute lowp vec4 a_color; varying lowp vec4 color; uniform lowp float a_opacity_t; -attribute lowp float a_opacity_min; -attribute lowp float a_opacity_max; +attribute lowp vec2 a_opacity; varying lowp float opacity; void main() { - color = mix(a_color_min, a_color_max, a_color_t); - opacity = mix(a_opacity_min, a_opacity_max, a_opacity_t); + color = unpack_mix_vec4(a_color, a_color_t); + opacity = unpack_mix_vec2(a_opacity, a_opacity_t); gl_Position = u_matrix * vec4(a_pos, 0, 1); } )MBGL_SHADER"; const char* fill::fragmentSource = R"MBGL_SHADER( -#ifdef GL_ES -precision mediump float; -#else - -#if !defined(lowp) -#define lowp -#endif - -#if !defined(mediump) -#define mediump -#endif - -#if !defined(highp) -#define highp -#endif - -#endif varying lowp vec4 color; varying lowp float opacity; diff --git a/src/mbgl/shaders/fill_outline.cpp b/src/mbgl/shaders/fill_outline.cpp index 0f0f3806a9..74201b518d 100644 --- a/src/mbgl/shaders/fill_outline.cpp +++ b/src/mbgl/shaders/fill_outline.cpp @@ -7,60 +7,6 @@ namespace shaders { const char* fill_outline::name = "fill_outline"; const char* fill_outline::vertexSource = R"MBGL_SHADER( -#ifdef GL_ES -precision highp float; -#else - -#if !defined(lowp) -#define lowp -#endif - -#if !defined(mediump) -#define mediump -#endif - -#if !defined(highp) -#define highp -#endif - -#endif - -float evaluate_zoom_function_1(const vec4 values, const float t) { - if (t < 1.0) { - return mix(values[0], values[1], t); - } else if (t < 2.0) { - return mix(values[1], values[2], t - 1.0); - } else { - return mix(values[2], values[3], t - 2.0); - } -} -vec4 evaluate_zoom_function_4(const vec4 value0, const vec4 value1, const vec4 value2, const vec4 value3, const float t) { - if (t < 1.0) { - return mix(value0, value1, t); - } else if (t < 2.0) { - return mix(value1, value2, t - 1.0); - } else { - return mix(value2, value3, t - 2.0); - } -} - -// The offset depends on how many pixels are between the world origin and the edge of the tile: -// vec2 offset = mod(pixel_coord, size) -// -// At high zoom levels there are a ton of pixels between the world origin and the edge of the tile. -// The glsl spec only guarantees 16 bits of precision for highp floats. We need more than that. -// -// The pixel_coord is passed in as two 16 bit values: -// pixel_coord_upper = floor(pixel_coord / 2^16) -// pixel_coord_lower = mod(pixel_coord, 2^16) -// -// The offset is calculated in a series of steps that should preserve this precision: -vec2 get_pattern_pos(const vec2 pixel_coord_upper, const vec2 pixel_coord_lower, - const vec2 pattern_size, const float tile_units_to_pixels, const vec2 pos) { - - vec2 offset = mod(mod(mod(pixel_coord_upper, pattern_size) * 256.0, pattern_size) * 256.0 + pixel_coord_lower, pattern_size); - return (tile_units_to_pixels * pos + offset) / pattern_size; -} attribute vec2 a_pos; uniform mat4 u_matrix; @@ -69,17 +15,15 @@ uniform vec2 u_world; varying vec2 v_pos; uniform lowp float a_outline_color_t; -attribute lowp vec4 a_outline_color_min; -attribute lowp vec4 a_outline_color_max; +attribute lowp vec4 a_outline_color; varying lowp vec4 outline_color; uniform lowp float a_opacity_t; -attribute lowp float a_opacity_min; -attribute lowp float a_opacity_max; +attribute lowp vec2 a_opacity; varying lowp float opacity; void main() { - outline_color = mix(a_outline_color_min, a_outline_color_max, a_outline_color_t); - opacity = mix(a_opacity_min, a_opacity_max, a_opacity_t); + outline_color = unpack_mix_vec4(a_outline_color, a_outline_color_t); + opacity = unpack_mix_vec2(a_opacity, a_opacity_t); gl_Position = u_matrix * vec4(a_pos, 0, 1); v_pos = (gl_Position.xy / gl_Position.w + 1.0) / 2.0 * u_world; @@ -87,23 +31,6 @@ void main() { )MBGL_SHADER"; const char* fill_outline::fragmentSource = R"MBGL_SHADER( -#ifdef GL_ES -precision mediump float; -#else - -#if !defined(lowp) -#define lowp -#endif - -#if !defined(mediump) -#define mediump -#endif - -#if !defined(highp) -#define highp -#endif - -#endif varying lowp vec4 outline_color; varying lowp float opacity; diff --git a/src/mbgl/shaders/fill_outline_pattern.cpp b/src/mbgl/shaders/fill_outline_pattern.cpp index 3921a83e6b..5e38023382 100644 --- a/src/mbgl/shaders/fill_outline_pattern.cpp +++ b/src/mbgl/shaders/fill_outline_pattern.cpp @@ -7,60 +7,6 @@ namespace shaders { const char* fill_outline_pattern::name = "fill_outline_pattern"; const char* fill_outline_pattern::vertexSource = R"MBGL_SHADER( -#ifdef GL_ES -precision highp float; -#else - -#if !defined(lowp) -#define lowp -#endif - -#if !defined(mediump) -#define mediump -#endif - -#if !defined(highp) -#define highp -#endif - -#endif - -float evaluate_zoom_function_1(const vec4 values, const float t) { - if (t < 1.0) { - return mix(values[0], values[1], t); - } else if (t < 2.0) { - return mix(values[1], values[2], t - 1.0); - } else { - return mix(values[2], values[3], t - 2.0); - } -} -vec4 evaluate_zoom_function_4(const vec4 value0, const vec4 value1, const vec4 value2, const vec4 value3, const float t) { - if (t < 1.0) { - return mix(value0, value1, t); - } else if (t < 2.0) { - return mix(value1, value2, t - 1.0); - } else { - return mix(value2, value3, t - 2.0); - } -} - -// The offset depends on how many pixels are between the world origin and the edge of the tile: -// vec2 offset = mod(pixel_coord, size) -// -// At high zoom levels there are a ton of pixels between the world origin and the edge of the tile. -// The glsl spec only guarantees 16 bits of precision for highp floats. We need more than that. -// -// The pixel_coord is passed in as two 16 bit values: -// pixel_coord_upper = floor(pixel_coord / 2^16) -// pixel_coord_lower = mod(pixel_coord, 2^16) -// -// The offset is calculated in a series of steps that should preserve this precision: -vec2 get_pattern_pos(const vec2 pixel_coord_upper, const vec2 pixel_coord_lower, - const vec2 pattern_size, const float tile_units_to_pixels, const vec2 pos) { - - vec2 offset = mod(mod(mod(pixel_coord_upper, pattern_size) * 256.0, pattern_size) * 256.0 + pixel_coord_lower, pattern_size); - return (tile_units_to_pixels * pos + offset) / pattern_size; -} uniform mat4 u_matrix; uniform vec2 u_world; uniform vec2 u_pattern_size_a; @@ -78,12 +24,11 @@ varying vec2 v_pos_b; varying vec2 v_pos; uniform lowp float a_opacity_t; -attribute lowp float a_opacity_min; -attribute lowp float a_opacity_max; +attribute lowp vec2 a_opacity; varying lowp float opacity; void main() { - opacity = mix(a_opacity_min, a_opacity_max, a_opacity_t); + opacity = unpack_mix_vec2(a_opacity, a_opacity_t); gl_Position = u_matrix * vec4(a_pos, 0, 1); @@ -95,23 +40,6 @@ void main() { )MBGL_SHADER"; const char* fill_outline_pattern::fragmentSource = R"MBGL_SHADER( -#ifdef GL_ES -precision mediump float; -#else - -#if !defined(lowp) -#define lowp -#endif - -#if !defined(mediump) -#define mediump -#endif - -#if !defined(highp) -#define highp -#endif - -#endif uniform vec2 u_pattern_tl_a; uniform vec2 u_pattern_br_a; uniform vec2 u_pattern_tl_b; diff --git a/src/mbgl/shaders/fill_pattern.cpp b/src/mbgl/shaders/fill_pattern.cpp index 822a0f7b8f..0357fed40e 100644 --- a/src/mbgl/shaders/fill_pattern.cpp +++ b/src/mbgl/shaders/fill_pattern.cpp @@ -7,60 +7,6 @@ namespace shaders { const char* fill_pattern::name = "fill_pattern"; const char* fill_pattern::vertexSource = R"MBGL_SHADER( -#ifdef GL_ES -precision highp float; -#else - -#if !defined(lowp) -#define lowp -#endif - -#if !defined(mediump) -#define mediump -#endif - -#if !defined(highp) -#define highp -#endif - -#endif - -float evaluate_zoom_function_1(const vec4 values, const float t) { - if (t < 1.0) { - return mix(values[0], values[1], t); - } else if (t < 2.0) { - return mix(values[1], values[2], t - 1.0); - } else { - return mix(values[2], values[3], t - 2.0); - } -} -vec4 evaluate_zoom_function_4(const vec4 value0, const vec4 value1, const vec4 value2, const vec4 value3, const float t) { - if (t < 1.0) { - return mix(value0, value1, t); - } else if (t < 2.0) { - return mix(value1, value2, t - 1.0); - } else { - return mix(value2, value3, t - 2.0); - } -} - -// The offset depends on how many pixels are between the world origin and the edge of the tile: -// vec2 offset = mod(pixel_coord, size) -// -// At high zoom levels there are a ton of pixels between the world origin and the edge of the tile. -// The glsl spec only guarantees 16 bits of precision for highp floats. We need more than that. -// -// The pixel_coord is passed in as two 16 bit values: -// pixel_coord_upper = floor(pixel_coord / 2^16) -// pixel_coord_lower = mod(pixel_coord, 2^16) -// -// The offset is calculated in a series of steps that should preserve this precision: -vec2 get_pattern_pos(const vec2 pixel_coord_upper, const vec2 pixel_coord_lower, - const vec2 pattern_size, const float tile_units_to_pixels, const vec2 pos) { - - vec2 offset = mod(mod(mod(pixel_coord_upper, pattern_size) * 256.0, pattern_size) * 256.0 + pixel_coord_lower, pattern_size); - return (tile_units_to_pixels * pos + offset) / pattern_size; -} uniform mat4 u_matrix; uniform vec2 u_pattern_size_a; uniform vec2 u_pattern_size_b; @@ -76,12 +22,11 @@ varying vec2 v_pos_a; varying vec2 v_pos_b; uniform lowp float a_opacity_t; -attribute lowp float a_opacity_min; -attribute lowp float a_opacity_max; +attribute lowp vec2 a_opacity; varying lowp float opacity; void main() { - opacity = mix(a_opacity_min, a_opacity_max, a_opacity_t); + opacity = unpack_mix_vec2(a_opacity, a_opacity_t); gl_Position = u_matrix * vec4(a_pos, 0, 1); @@ -91,23 +36,6 @@ void main() { )MBGL_SHADER"; const char* fill_pattern::fragmentSource = R"MBGL_SHADER( -#ifdef GL_ES -precision mediump float; -#else - -#if !defined(lowp) -#define lowp -#endif - -#if !defined(mediump) -#define mediump -#endif - -#if !defined(highp) -#define highp -#endif - -#endif uniform vec2 u_pattern_tl_a; uniform vec2 u_pattern_br_a; uniform vec2 u_pattern_tl_b; diff --git a/src/mbgl/shaders/line.cpp b/src/mbgl/shaders/line.cpp index 59fa9f0cf2..dc4aa774dc 100644 --- a/src/mbgl/shaders/line.cpp +++ b/src/mbgl/shaders/line.cpp @@ -7,60 +7,6 @@ namespace shaders { const char* line::name = "line"; const char* line::vertexSource = R"MBGL_SHADER( -#ifdef GL_ES -precision highp float; -#else - -#if !defined(lowp) -#define lowp -#endif - -#if !defined(mediump) -#define mediump -#endif - -#if !defined(highp) -#define highp -#endif - -#endif - -float evaluate_zoom_function_1(const vec4 values, const float t) { - if (t < 1.0) { - return mix(values[0], values[1], t); - } else if (t < 2.0) { - return mix(values[1], values[2], t - 1.0); - } else { - return mix(values[2], values[3], t - 2.0); - } -} -vec4 evaluate_zoom_function_4(const vec4 value0, const vec4 value1, const vec4 value2, const vec4 value3, const float t) { - if (t < 1.0) { - return mix(value0, value1, t); - } else if (t < 2.0) { - return mix(value1, value2, t - 1.0); - } else { - return mix(value2, value3, t - 2.0); - } -} - -// The offset depends on how many pixels are between the world origin and the edge of the tile: -// vec2 offset = mod(pixel_coord, size) -// -// At high zoom levels there are a ton of pixels between the world origin and the edge of the tile. -// The glsl spec only guarantees 16 bits of precision for highp floats. We need more than that. -// -// The pixel_coord is passed in as two 16 bit values: -// pixel_coord_upper = floor(pixel_coord / 2^16) -// pixel_coord_lower = mod(pixel_coord, 2^16) -// -// The offset is calculated in a series of steps that should preserve this precision: -vec2 get_pattern_pos(const vec2 pixel_coord_upper, const vec2 pixel_coord_lower, - const vec2 pattern_size, const float tile_units_to_pixels, const vec2 pos) { - - vec2 offset = mod(mod(mod(pixel_coord_upper, pattern_size) * 256.0, pattern_size) * 256.0 + pixel_coord_lower, pattern_size); - return (tile_units_to_pixels * pos + offset) / pattern_size; -} // the distance over which the line edge fades out. @@ -88,32 +34,27 @@ varying vec2 v_width2; varying float v_gamma_scale; uniform lowp float a_color_t; -attribute lowp vec4 a_color_min; -attribute lowp vec4 a_color_max; +attribute lowp vec4 a_color; varying lowp vec4 color; uniform lowp float a_blur_t; -attribute lowp float a_blur_min; -attribute lowp float a_blur_max; +attribute lowp vec2 a_blur; varying lowp float blur; uniform lowp float a_opacity_t; -attribute lowp float a_opacity_min; -attribute lowp float a_opacity_max; +attribute lowp vec2 a_opacity; varying lowp float opacity; uniform lowp float a_gapwidth_t; -attribute mediump float a_gapwidth_min; -attribute mediump float a_gapwidth_max; +attribute mediump vec2 a_gapwidth; varying mediump float gapwidth; uniform lowp float a_offset_t; -attribute lowp float a_offset_min; -attribute lowp float a_offset_max; +attribute lowp vec2 a_offset; varying lowp float offset; void main() { - color = mix(a_color_min, a_color_max, a_color_t); - blur = mix(a_blur_min, a_blur_max, a_blur_t); - opacity = mix(a_opacity_min, a_opacity_max, a_opacity_t); - gapwidth = mix(a_gapwidth_min, a_gapwidth_max, a_gapwidth_t); - offset = mix(a_offset_min, a_offset_max, a_offset_t); + color = unpack_mix_vec4(a_color, a_color_t); + blur = unpack_mix_vec2(a_blur, a_blur_t); + opacity = unpack_mix_vec2(a_opacity, a_opacity_t); + gapwidth = unpack_mix_vec2(a_gapwidth, a_gapwidth_t); + offset = unpack_mix_vec2(a_offset, a_offset_t); vec2 a_extrude = a_data.xy - 128.0; float a_direction = mod(a_data.z, 4.0) - 1.0; @@ -164,23 +105,6 @@ void main() { )MBGL_SHADER"; const char* line::fragmentSource = R"MBGL_SHADER( -#ifdef GL_ES -precision mediump float; -#else - -#if !defined(lowp) -#define lowp -#endif - -#if !defined(mediump) -#define mediump -#endif - -#if !defined(highp) -#define highp -#endif - -#endif varying lowp vec4 color; varying lowp float blur; varying lowp float opacity; diff --git a/src/mbgl/shaders/line_pattern.cpp b/src/mbgl/shaders/line_pattern.cpp index 7f2a31ee44..f52a8e2157 100644 --- a/src/mbgl/shaders/line_pattern.cpp +++ b/src/mbgl/shaders/line_pattern.cpp @@ -7,60 +7,6 @@ namespace shaders { const char* line_pattern::name = "line_pattern"; const char* line_pattern::vertexSource = R"MBGL_SHADER( -#ifdef GL_ES -precision highp float; -#else - -#if !defined(lowp) -#define lowp -#endif - -#if !defined(mediump) -#define mediump -#endif - -#if !defined(highp) -#define highp -#endif - -#endif - -float evaluate_zoom_function_1(const vec4 values, const float t) { - if (t < 1.0) { - return mix(values[0], values[1], t); - } else if (t < 2.0) { - return mix(values[1], values[2], t - 1.0); - } else { - return mix(values[2], values[3], t - 2.0); - } -} -vec4 evaluate_zoom_function_4(const vec4 value0, const vec4 value1, const vec4 value2, const vec4 value3, const float t) { - if (t < 1.0) { - return mix(value0, value1, t); - } else if (t < 2.0) { - return mix(value1, value2, t - 1.0); - } else { - return mix(value2, value3, t - 2.0); - } -} - -// The offset depends on how many pixels are between the world origin and the edge of the tile: -// vec2 offset = mod(pixel_coord, size) -// -// At high zoom levels there are a ton of pixels between the world origin and the edge of the tile. -// The glsl spec only guarantees 16 bits of precision for highp floats. We need more than that. -// -// The pixel_coord is passed in as two 16 bit values: -// pixel_coord_upper = floor(pixel_coord / 2^16) -// pixel_coord_lower = mod(pixel_coord, 2^16) -// -// The offset is calculated in a series of steps that should preserve this precision: -vec2 get_pattern_pos(const vec2 pixel_coord_upper, const vec2 pixel_coord_lower, - const vec2 pattern_size, const float tile_units_to_pixels, const vec2 pos) { - - vec2 offset = mod(mod(mod(pixel_coord_upper, pattern_size) * 256.0, pattern_size) * 256.0 + pixel_coord_lower, pattern_size); - return (tile_units_to_pixels * pos + offset) / pattern_size; -} // floor(127 / 2) == 63.0 // the maximum allowed miter limit is 2.0 at the moment. the extrude normal is // stored in a byte (-128..127). we scale regular normals up to length 63, but @@ -91,27 +37,23 @@ varying float v_linesofar; varying float v_gamma_scale; uniform lowp float a_blur_t; -attribute lowp float a_blur_min; -attribute lowp float a_blur_max; +attribute lowp vec2 a_blur; varying lowp float blur; uniform lowp float a_opacity_t; -attribute lowp float a_opacity_min; -attribute lowp float a_opacity_max; +attribute lowp vec2 a_opacity; varying lowp float opacity; uniform lowp float a_offset_t; -attribute lowp float a_offset_min; -attribute lowp float a_offset_max; +attribute lowp vec2 a_offset; varying lowp float offset; uniform lowp float a_gapwidth_t; -attribute mediump float a_gapwidth_min; -attribute mediump float a_gapwidth_max; +attribute mediump vec2 a_gapwidth; varying mediump float gapwidth; void main() { - blur = mix(a_blur_min, a_blur_max, a_blur_t); - opacity = mix(a_opacity_min, a_opacity_max, a_opacity_t); - offset = mix(a_offset_min, a_offset_max, a_offset_t); - gapwidth = mix(a_gapwidth_min, a_gapwidth_max, a_gapwidth_t); + blur = unpack_mix_vec2(a_blur, a_blur_t); + opacity = unpack_mix_vec2(a_opacity, a_opacity_t); + offset = unpack_mix_vec2(a_offset, a_offset_t); + gapwidth = unpack_mix_vec2(a_gapwidth, a_gapwidth_t); vec2 a_extrude = a_data.xy - 128.0; float a_direction = mod(a_data.z, 4.0) - 1.0; @@ -163,23 +105,6 @@ void main() { )MBGL_SHADER"; const char* line_pattern::fragmentSource = R"MBGL_SHADER( -#ifdef GL_ES -precision mediump float; -#else - -#if !defined(lowp) -#define lowp -#endif - -#if !defined(mediump) -#define mediump -#endif - -#if !defined(highp) -#define highp -#endif - -#endif uniform vec2 u_pattern_size_a; uniform vec2 u_pattern_size_b; uniform vec2 u_pattern_tl_a; diff --git a/src/mbgl/shaders/line_sdf.cpp b/src/mbgl/shaders/line_sdf.cpp index 011c1c3738..cd0d4ac318 100644 --- a/src/mbgl/shaders/line_sdf.cpp +++ b/src/mbgl/shaders/line_sdf.cpp @@ -7,60 +7,6 @@ namespace shaders { const char* line_sdf::name = "line_sdf"; const char* line_sdf::vertexSource = R"MBGL_SHADER( -#ifdef GL_ES -precision highp float; -#else - -#if !defined(lowp) -#define lowp -#endif - -#if !defined(mediump) -#define mediump -#endif - -#if !defined(highp) -#define highp -#endif - -#endif - -float evaluate_zoom_function_1(const vec4 values, const float t) { - if (t < 1.0) { - return mix(values[0], values[1], t); - } else if (t < 2.0) { - return mix(values[1], values[2], t - 1.0); - } else { - return mix(values[2], values[3], t - 2.0); - } -} -vec4 evaluate_zoom_function_4(const vec4 value0, const vec4 value1, const vec4 value2, const vec4 value3, const float t) { - if (t < 1.0) { - return mix(value0, value1, t); - } else if (t < 2.0) { - return mix(value1, value2, t - 1.0); - } else { - return mix(value2, value3, t - 2.0); - } -} - -// The offset depends on how many pixels are between the world origin and the edge of the tile: -// vec2 offset = mod(pixel_coord, size) -// -// At high zoom levels there are a ton of pixels between the world origin and the edge of the tile. -// The glsl spec only guarantees 16 bits of precision for highp floats. We need more than that. -// -// The pixel_coord is passed in as two 16 bit values: -// pixel_coord_upper = floor(pixel_coord / 2^16) -// pixel_coord_lower = mod(pixel_coord, 2^16) -// -// The offset is calculated in a series of steps that should preserve this precision: -vec2 get_pattern_pos(const vec2 pixel_coord_upper, const vec2 pixel_coord_lower, - const vec2 pattern_size, const float tile_units_to_pixels, const vec2 pos) { - - vec2 offset = mod(mod(mod(pixel_coord_upper, pattern_size) * 256.0, pattern_size) * 256.0 + pixel_coord_lower, pattern_size); - return (tile_units_to_pixels * pos + offset) / pattern_size; -} // floor(127 / 2) == 63.0 // the maximum allowed miter limit is 2.0 at the moment. the extrude normal is // stored in a byte (-128..127). we scale regular normals up to length 63, but @@ -96,32 +42,27 @@ varying vec2 v_tex_b; varying float v_gamma_scale; uniform lowp float a_color_t; -attribute lowp vec4 a_color_min; -attribute lowp vec4 a_color_max; +attribute lowp vec4 a_color; varying lowp vec4 color; uniform lowp float a_blur_t; -attribute lowp float a_blur_min; -attribute lowp float a_blur_max; +attribute lowp vec2 a_blur; varying lowp float blur; uniform lowp float a_opacity_t; -attribute lowp float a_opacity_min; -attribute lowp float a_opacity_max; +attribute lowp vec2 a_opacity; varying lowp float opacity; uniform lowp float a_gapwidth_t; -attribute mediump float a_gapwidth_min; -attribute mediump float a_gapwidth_max; +attribute mediump vec2 a_gapwidth; varying mediump float gapwidth; uniform lowp float a_offset_t; -attribute lowp float a_offset_min; -attribute lowp float a_offset_max; +attribute lowp vec2 a_offset; varying lowp float offset; void main() { - color = mix(a_color_min, a_color_max, a_color_t); - blur = mix(a_blur_min, a_blur_max, a_blur_t); - opacity = mix(a_opacity_min, a_opacity_max, a_opacity_t); - gapwidth = mix(a_gapwidth_min, a_gapwidth_max, a_gapwidth_t); - offset = mix(a_offset_min, a_offset_max, a_offset_t); + color = unpack_mix_vec4(a_color, a_color_t); + blur = unpack_mix_vec2(a_blur, a_blur_t); + opacity = unpack_mix_vec2(a_opacity, a_opacity_t); + gapwidth = unpack_mix_vec2(a_gapwidth, a_gapwidth_t); + offset = unpack_mix_vec2(a_offset, a_offset_t); vec2 a_extrude = a_data.xy - 128.0; float a_direction = mod(a_data.z, 4.0) - 1.0; @@ -175,23 +116,6 @@ void main() { )MBGL_SHADER"; const char* line_sdf::fragmentSource = R"MBGL_SHADER( -#ifdef GL_ES -precision mediump float; -#else - -#if !defined(lowp) -#define lowp -#endif - -#if !defined(mediump) -#define mediump -#endif - -#if !defined(highp) -#define highp -#endif - -#endif uniform sampler2D u_image; uniform float u_sdfgamma; diff --git a/src/mbgl/shaders/preludes.cpp b/src/mbgl/shaders/preludes.cpp new file mode 100644 index 0000000000..806e655285 --- /dev/null +++ b/src/mbgl/shaders/preludes.cpp @@ -0,0 +1,112 @@ +// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED. + +#include <mbgl/shaders/preludes.hpp> + +namespace mbgl { +namespace shaders { + +const char* vertexPrelude = R"MBGL_SHADER( +#ifdef GL_ES +precision highp float; +#else + +#if !defined(lowp) +#define lowp +#endif + +#if !defined(mediump) +#define mediump +#endif + +#if !defined(highp) +#define highp +#endif + +#endif + +float evaluate_zoom_function_1(const vec4 values, const float t) { + if (t < 1.0) { + return mix(values[0], values[1], t); + } else if (t < 2.0) { + return mix(values[1], values[2], t - 1.0); + } else { + return mix(values[2], values[3], t - 2.0); + } +} +vec4 evaluate_zoom_function_4(const vec4 value0, const vec4 value1, const vec4 value2, const vec4 value3, const float t) { + if (t < 1.0) { + return mix(value0, value1, t); + } else if (t < 2.0) { + return mix(value1, value2, t - 1.0); + } else { + return mix(value2, value3, t - 2.0); + } +} + + +// To minimize the number of attributes needed in the mapbox-gl-native shaders, +// we encode a 4-component color into a pair of floats (i.e. a vec2) as follows: +// [ floor(color.r * 255) * 256 + color.g * 255, +// floor(color.b * 255) * 256 + color.g * 255 ] +vec4 decode_color(const vec2 encodedColor) { + float r = floor(encodedColor[0]/256.0)/255.0; + float g = (encodedColor[0] - r*256.0*255.0)/255.0; + float b = floor(encodedColor[1]/256.0)/255.0; + float a = (encodedColor[1] - b*256.0*255.0)/255.0; + return vec4(r, g, b, a); +} + +// Unpack a pair of paint values and interpolate between them. +float unpack_mix_vec2(const vec2 packedValue, const float t) { + return mix(packedValue[0], packedValue[1], t); +} + +// Unpack a pair of paint values and interpolate between them. +vec4 unpack_mix_vec4(const vec4 packedColors, const float t) { + vec4 minColor = decode_color(vec2(packedColors[0], packedColors[1])); + vec4 maxColor = decode_color(vec2(packedColors[2], packedColors[3])); + return mix(minColor, maxColor, t); +} + +// The offset depends on how many pixels are between the world origin and the edge of the tile: +// vec2 offset = mod(pixel_coord, size) +// +// At high zoom levels there are a ton of pixels between the world origin and the edge of the tile. +// The glsl spec only guarantees 16 bits of precision for highp floats. We need more than that. +// +// The pixel_coord is passed in as two 16 bit values: +// pixel_coord_upper = floor(pixel_coord / 2^16) +// pixel_coord_lower = mod(pixel_coord, 2^16) +// +// The offset is calculated in a series of steps that should preserve this precision: +vec2 get_pattern_pos(const vec2 pixel_coord_upper, const vec2 pixel_coord_lower, + const vec2 pattern_size, const float tile_units_to_pixels, const vec2 pos) { + + vec2 offset = mod(mod(mod(pixel_coord_upper, pattern_size) * 256.0, pattern_size) * 256.0 + pixel_coord_lower, pattern_size); + return (tile_units_to_pixels * pos + offset) / pattern_size; +} + +)MBGL_SHADER"; +const char* fragmentPrelude = R"MBGL_SHADER( +#ifdef GL_ES +precision mediump float; +#else + +#if !defined(lowp) +#define lowp +#endif + +#if !defined(mediump) +#define mediump +#endif + +#if !defined(highp) +#define highp +#endif + +#endif + +)MBGL_SHADER"; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/preludes.hpp b/src/mbgl/shaders/preludes.hpp new file mode 100644 index 0000000000..a3abc9001f --- /dev/null +++ b/src/mbgl/shaders/preludes.hpp @@ -0,0 +1,12 @@ +// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED. + +#pragma once + +namespace mbgl { +namespace shaders { + +extern const char* vertexPrelude; +extern const char* fragmentPrelude; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/raster.cpp b/src/mbgl/shaders/raster.cpp index ba0aa5cd05..eb7a2db240 100644 --- a/src/mbgl/shaders/raster.cpp +++ b/src/mbgl/shaders/raster.cpp @@ -7,60 +7,6 @@ namespace shaders { const char* raster::name = "raster"; const char* raster::vertexSource = R"MBGL_SHADER( -#ifdef GL_ES -precision highp float; -#else - -#if !defined(lowp) -#define lowp -#endif - -#if !defined(mediump) -#define mediump -#endif - -#if !defined(highp) -#define highp -#endif - -#endif - -float evaluate_zoom_function_1(const vec4 values, const float t) { - if (t < 1.0) { - return mix(values[0], values[1], t); - } else if (t < 2.0) { - return mix(values[1], values[2], t - 1.0); - } else { - return mix(values[2], values[3], t - 2.0); - } -} -vec4 evaluate_zoom_function_4(const vec4 value0, const vec4 value1, const vec4 value2, const vec4 value3, const float t) { - if (t < 1.0) { - return mix(value0, value1, t); - } else if (t < 2.0) { - return mix(value1, value2, t - 1.0); - } else { - return mix(value2, value3, t - 2.0); - } -} - -// The offset depends on how many pixels are between the world origin and the edge of the tile: -// vec2 offset = mod(pixel_coord, size) -// -// At high zoom levels there are a ton of pixels between the world origin and the edge of the tile. -// The glsl spec only guarantees 16 bits of precision for highp floats. We need more than that. -// -// The pixel_coord is passed in as two 16 bit values: -// pixel_coord_upper = floor(pixel_coord / 2^16) -// pixel_coord_lower = mod(pixel_coord, 2^16) -// -// The offset is calculated in a series of steps that should preserve this precision: -vec2 get_pattern_pos(const vec2 pixel_coord_upper, const vec2 pixel_coord_lower, - const vec2 pattern_size, const float tile_units_to_pixels, const vec2 pos) { - - vec2 offset = mod(mod(mod(pixel_coord_upper, pattern_size) * 256.0, pattern_size) * 256.0 + pixel_coord_lower, pattern_size); - return (tile_units_to_pixels * pos + offset) / pattern_size; -} uniform mat4 u_matrix; uniform vec2 u_tl_parent; uniform float u_scale_parent; @@ -80,23 +26,6 @@ void main() { )MBGL_SHADER"; const char* raster::fragmentSource = R"MBGL_SHADER( -#ifdef GL_ES -precision mediump float; -#else - -#if !defined(lowp) -#define lowp -#endif - -#if !defined(mediump) -#define mediump -#endif - -#if !defined(highp) -#define highp -#endif - -#endif uniform float u_fade_t; uniform float u_opacity; uniform sampler2D u_image0; diff --git a/src/mbgl/shaders/symbol_icon.cpp b/src/mbgl/shaders/symbol_icon.cpp index e6728e15de..9adda0ba16 100644 --- a/src/mbgl/shaders/symbol_icon.cpp +++ b/src/mbgl/shaders/symbol_icon.cpp @@ -7,68 +7,13 @@ namespace shaders { const char* symbol_icon::name = "symbol_icon"; const char* symbol_icon::vertexSource = R"MBGL_SHADER( -#ifdef GL_ES -precision highp float; -#else -#if !defined(lowp) -#define lowp -#endif - -#if !defined(mediump) -#define mediump -#endif - -#if !defined(highp) -#define highp -#endif - -#endif - -float evaluate_zoom_function_1(const vec4 values, const float t) { - if (t < 1.0) { - return mix(values[0], values[1], t); - } else if (t < 2.0) { - return mix(values[1], values[2], t - 1.0); - } else { - return mix(values[2], values[3], t - 2.0); - } -} -vec4 evaluate_zoom_function_4(const vec4 value0, const vec4 value1, const vec4 value2, const vec4 value3, const float t) { - if (t < 1.0) { - return mix(value0, value1, t); - } else if (t < 2.0) { - return mix(value1, value2, t - 1.0); - } else { - return mix(value2, value3, t - 2.0); - } -} - -// The offset depends on how many pixels are between the world origin and the edge of the tile: -// vec2 offset = mod(pixel_coord, size) -// -// At high zoom levels there are a ton of pixels between the world origin and the edge of the tile. -// The glsl spec only guarantees 16 bits of precision for highp floats. We need more than that. -// -// The pixel_coord is passed in as two 16 bit values: -// pixel_coord_upper = floor(pixel_coord / 2^16) -// pixel_coord_lower = mod(pixel_coord, 2^16) -// -// The offset is calculated in a series of steps that should preserve this precision: -vec2 get_pattern_pos(const vec2 pixel_coord_upper, const vec2 pixel_coord_lower, - const vec2 pattern_size, const float tile_units_to_pixels, const vec2 pos) { - - vec2 offset = mod(mod(mod(pixel_coord_upper, pattern_size) * 256.0, pattern_size) * 256.0 + pixel_coord_lower, pattern_size); - return (tile_units_to_pixels * pos + offset) / pattern_size; -} -attribute vec2 a_pos; -attribute vec2 a_offset; +attribute vec4 a_pos_offset; attribute vec2 a_texture_pos; attribute vec4 a_data; uniform lowp float a_opacity_t; -attribute lowp float a_opacity_min; -attribute lowp float a_opacity_max; +attribute lowp vec2 a_opacity; varying lowp float opacity; // matrix is for the vertex position. @@ -84,7 +29,10 @@ varying vec2 v_tex; varying vec2 v_fade_tex; void main() { - opacity = mix(a_opacity_min, a_opacity_max, a_opacity_t); + opacity = unpack_mix_vec2(a_opacity, a_opacity_t); + + vec2 a_pos = a_pos_offset.xy; + vec2 a_offset = a_pos_offset.zw; vec2 a_tex = a_texture_pos.xy; mediump float a_labelminzoom = a_data[0]; @@ -109,23 +57,6 @@ void main() { )MBGL_SHADER"; const char* symbol_icon::fragmentSource = R"MBGL_SHADER( -#ifdef GL_ES -precision mediump float; -#else - -#if !defined(lowp) -#define lowp -#endif - -#if !defined(mediump) -#define mediump -#endif - -#if !defined(highp) -#define highp -#endif - -#endif uniform sampler2D u_texture; uniform sampler2D u_fadetexture; diff --git a/src/mbgl/shaders/symbol_sdf.cpp b/src/mbgl/shaders/symbol_sdf.cpp index e087242bf8..76399dbb55 100644 --- a/src/mbgl/shaders/symbol_sdf.cpp +++ b/src/mbgl/shaders/symbol_sdf.cpp @@ -7,86 +7,26 @@ namespace shaders { const char* symbol_sdf::name = "symbol_sdf"; const char* symbol_sdf::vertexSource = R"MBGL_SHADER( -#ifdef GL_ES -precision highp float; -#else - -#if !defined(lowp) -#define lowp -#endif - -#if !defined(mediump) -#define mediump -#endif - -#if !defined(highp) -#define highp -#endif - -#endif - -float evaluate_zoom_function_1(const vec4 values, const float t) { - if (t < 1.0) { - return mix(values[0], values[1], t); - } else if (t < 2.0) { - return mix(values[1], values[2], t - 1.0); - } else { - return mix(values[2], values[3], t - 2.0); - } -} -vec4 evaluate_zoom_function_4(const vec4 value0, const vec4 value1, const vec4 value2, const vec4 value3, const float t) { - if (t < 1.0) { - return mix(value0, value1, t); - } else if (t < 2.0) { - return mix(value1, value2, t - 1.0); - } else { - return mix(value2, value3, t - 2.0); - } -} - -// The offset depends on how many pixels are between the world origin and the edge of the tile: -// vec2 offset = mod(pixel_coord, size) -// -// At high zoom levels there are a ton of pixels between the world origin and the edge of the tile. -// The glsl spec only guarantees 16 bits of precision for highp floats. We need more than that. -// -// The pixel_coord is passed in as two 16 bit values: -// pixel_coord_upper = floor(pixel_coord / 2^16) -// pixel_coord_lower = mod(pixel_coord, 2^16) -// -// The offset is calculated in a series of steps that should preserve this precision: -vec2 get_pattern_pos(const vec2 pixel_coord_upper, const vec2 pixel_coord_lower, - const vec2 pattern_size, const float tile_units_to_pixels, const vec2 pos) { - - vec2 offset = mod(mod(mod(pixel_coord_upper, pattern_size) * 256.0, pattern_size) * 256.0 + pixel_coord_lower, pattern_size); - return (tile_units_to_pixels * pos + offset) / pattern_size; -} const float PI = 3.141592653589793; -attribute vec2 a_pos; -attribute vec2 a_offset; +attribute vec4 a_pos_offset; attribute vec2 a_texture_pos; attribute vec4 a_data; uniform lowp float a_fill_color_t; -attribute lowp vec4 a_fill_color_min; -attribute lowp vec4 a_fill_color_max; +attribute lowp vec4 a_fill_color; varying lowp vec4 fill_color; uniform lowp float a_halo_color_t; -attribute lowp vec4 a_halo_color_min; -attribute lowp vec4 a_halo_color_max; +attribute lowp vec4 a_halo_color; varying lowp vec4 halo_color; uniform lowp float a_opacity_t; -attribute lowp float a_opacity_min; -attribute lowp float a_opacity_max; +attribute lowp vec2 a_opacity; varying lowp float opacity; uniform lowp float a_halo_width_t; -attribute lowp float a_halo_width_min; -attribute lowp float a_halo_width_max; +attribute lowp vec2 a_halo_width; varying lowp float halo_width; uniform lowp float a_halo_blur_t; -attribute lowp float a_halo_blur_min; -attribute lowp float a_halo_blur_max; +attribute lowp vec2 a_halo_blur; varying lowp float halo_blur; // matrix is for the vertex position. @@ -107,11 +47,14 @@ varying vec2 v_fade_tex; varying float v_gamma_scale; void main() { - fill_color = mix(a_fill_color_min, a_fill_color_max, a_fill_color_t); - halo_color = mix(a_halo_color_min, a_halo_color_max, a_halo_color_t); - opacity = mix(a_opacity_min, a_opacity_max, a_opacity_t); - halo_width = mix(a_halo_width_min, a_halo_width_max, a_halo_width_t); - halo_blur = mix(a_halo_blur_min, a_halo_blur_max, a_halo_blur_t); + fill_color = unpack_mix_vec4(a_fill_color, a_fill_color_t); + halo_color = unpack_mix_vec4(a_halo_color, a_halo_color_t); + opacity = unpack_mix_vec2(a_opacity, a_opacity_t); + halo_width = unpack_mix_vec2(a_halo_width, a_halo_width_t); + halo_blur = unpack_mix_vec2(a_halo_blur, a_halo_blur_t); + + vec2 a_pos = a_pos_offset.xy; + vec2 a_offset = a_pos_offset.zw; vec2 a_tex = a_texture_pos.xy; mediump float a_labelminzoom = a_data[0]; @@ -172,23 +115,6 @@ void main() { )MBGL_SHADER"; const char* symbol_sdf::fragmentSource = R"MBGL_SHADER( -#ifdef GL_ES -precision mediump float; -#else - -#if !defined(lowp) -#define lowp -#endif - -#if !defined(mediump) -#define mediump -#endif - -#if !defined(highp) -#define highp -#endif - -#endif #define SDF_PX 8.0 #define EDGE_GAMMA 0.105/DEVICE_PIXEL_RATIO diff --git a/src/mbgl/style/paint_property.hpp b/src/mbgl/style/paint_property.hpp index 1fa2390f33..599bbef1f4 100644 --- a/src/mbgl/style/paint_property.hpp +++ b/src/mbgl/style/paint_property.hpp @@ -51,6 +51,12 @@ public: // Transition from prior value is now complete. prior = {}; return finalValue; + } else if (value.isDataDriven()) { + // Transitions to data-driven properties are not supported. + // We snap immediately to the data-driven value so that, when we perform layout, + // we see the data-driven function and can use it to populate vertex buffers. + prior = {}; + return finalValue; } else if (now < begin) { // Transition hasn't started yet. return prior->get().evaluate(evaluator, now); diff --git a/src/mbgl/style/paint_property_binder.hpp b/src/mbgl/style/paint_property_binder.hpp index 79c7692b2f..17c99fe1d9 100644 --- a/src/mbgl/style/paint_property_binder.hpp +++ b/src/mbgl/style/paint_property_binder.hpp @@ -11,8 +11,11 @@ namespace style { template <class T, class A> class ConstantPaintPropertyBinder { public: - using Attribute = A; - using AttributeValue = typename Attribute::Value; + using BaseAttribute = A; + using BaseAttributeValue = typename BaseAttribute::Value; + using BaseAttributeBinding = typename BaseAttribute::Binding; + + using Attribute = attributes::ZoomInterpolatedAttribute<BaseAttribute>; using AttributeBinding = typename Attribute::Binding; ConstantPaintPropertyBinder(T constant_) @@ -22,16 +25,13 @@ public: void populateVertexVector(const GeometryTileFeature&, std::size_t) {} void upload(gl::Context&) {} - AttributeBinding minAttributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const { + AttributeBinding attributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const { + auto val = currentValue.constantOr(constant); return typename Attribute::ConstantBinding { - Attribute::value(currentValue.constantOr(constant)) + Attribute::value(val, val) }; } - AttributeBinding maxAttributeBinding(const PossiblyEvaluatedPropertyValue<T>&) const { - return AttributeBinding(); - } - float interpolationFactor(float) const { return 0.0f; } @@ -43,12 +43,13 @@ private: template <class T, class A> class SourceFunctionPaintPropertyBinder { public: - using Attribute = A; - using AttributeValue = typename Attribute::Value; - using AttributeBinding = typename Attribute::Binding; + using BaseAttribute = A; + using BaseAttributeValue = typename BaseAttribute::Value; + using BaseAttributeBinding = typename BaseAttribute::Binding; + using BaseVertex = typename gl::Attributes<BaseAttribute>::Vertex; - using Attributes = gl::Attributes<Attribute>; - using Vertex = typename Attributes::Vertex; + using Attribute = attributes::ZoomInterpolatedAttribute<BaseAttribute>; + using AttributeBinding = typename Attribute::Binding; SourceFunctionPaintPropertyBinder(SourceFunction<T> function_, T defaultValue_) : function(std::move(function_)), @@ -56,9 +57,10 @@ public: } void populateVertexVector(const GeometryTileFeature& feature, std::size_t length) { - AttributeValue value = Attribute::value(function.evaluate(feature, defaultValue)); + auto val = function.evaluate(feature, defaultValue); + BaseAttributeValue value = BaseAttribute::value(val); for (std::size_t i = vertexVector.vertexSize(); i < length; ++i) { - vertexVector.emplace_back(Vertex { value }); + vertexVector.emplace_back(BaseVertex { value }); } } @@ -66,21 +68,17 @@ public: vertexBuffer = context.createVertexBuffer(std::move(vertexVector)); } - AttributeBinding minAttributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const { + AttributeBinding attributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const { if (currentValue.isConstant()) { + auto val = *currentValue.constant(); return typename Attribute::ConstantBinding { - Attribute::value(*currentValue.constant()) + Attribute::value(val, val) }; } else { - return Attributes::allVariableBindings(*vertexBuffer) - .template get<Attribute>(); + return Attribute::variableBinding(*vertexBuffer, 0, BaseAttribute::Dimensions); } } - AttributeBinding maxAttributeBinding(const PossiblyEvaluatedPropertyValue<T>&) const { - return AttributeBinding(); - } - float interpolationFactor(float) const { return 0.0f; } @@ -88,22 +86,17 @@ public: private: SourceFunction<T> function; T defaultValue; - gl::VertexVector<Vertex> vertexVector; - optional<gl::VertexBuffer<Vertex>> vertexBuffer; + gl::VertexVector<BaseVertex> vertexVector; + optional<gl::VertexBuffer<BaseVertex>> vertexBuffer; }; template <class T, class A> class CompositeFunctionPaintPropertyBinder { public: - using Attribute = A; + using Attribute = attributes::ZoomInterpolatedAttribute<A>; using AttributeValue = typename Attribute::Value; using AttributeBinding = typename Attribute::Binding; - - using MinAttribute = attributes::Min<Attribute>; - using MaxAttribute = attributes::Max<Attribute>; - - using Attributes = gl::Attributes<MinAttribute, MaxAttribute>; - using Vertex = typename Attributes::Vertex; + using Vertex = typename gl::Attributes<Attribute>::Vertex; CompositeFunctionPaintPropertyBinder(CompositeFunction<T> function_, float zoom, T defaultValue_) : function(std::move(function_)), @@ -113,10 +106,9 @@ public: void populateVertexVector(const GeometryTileFeature& feature, std::size_t length) { Range<T> range = function.evaluate(std::get<1>(coveringRanges), feature, defaultValue); - AttributeValue min = Attribute::value(range.min); - AttributeValue max = Attribute::value(range.max); + AttributeValue minMax = Attribute::value(range.min, range.max); for (std::size_t i = vertexVector.vertexSize(); i < length; ++i) { - vertexVector.emplace_back(Vertex { min, max }); + vertexVector.emplace_back(Vertex { minMax }); } } @@ -124,23 +116,14 @@ public: vertexBuffer = context.createVertexBuffer(std::move(vertexVector)); } - AttributeBinding minAttributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const { + AttributeBinding attributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const { if (currentValue.isConstant()) { + auto val = *currentValue.constant(); return typename Attribute::ConstantBinding { - Attribute::value(*currentValue.constant()) + Attribute::value(val, val) }; } else { - return Attributes::allVariableBindings(*vertexBuffer) - .template get<MinAttribute>(); - } - } - - AttributeBinding maxAttributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const { - if (currentValue.isConstant()) { - return AttributeBinding(); - } else { - return Attributes::allVariableBindings(*vertexBuffer) - .template get<MaxAttribute>(); + return Attribute::variableBinding(*vertexBuffer, 0); } } @@ -161,24 +144,27 @@ template <class PaintProperty> class PaintPropertyBinder { public: using Type = typename PaintProperty::Type; - using Attribute = typename PaintProperty::Attribute; using PropertyValue = typename PaintProperty::EvaluatedType; + using BaseAttribute = typename PaintProperty::Attribute; + using Attribute = attributes::ZoomInterpolatedAttribute<BaseAttribute>; + using AttributeBinding = typename Attribute::Binding; + using Binder = variant< - ConstantPaintPropertyBinder<Type, Attribute>, - SourceFunctionPaintPropertyBinder<Type, Attribute>, - CompositeFunctionPaintPropertyBinder<Type, Attribute>>; + ConstantPaintPropertyBinder<Type, BaseAttribute>, + SourceFunctionPaintPropertyBinder<Type, BaseAttribute>, + CompositeFunctionPaintPropertyBinder<Type, BaseAttribute>>; PaintPropertyBinder(const PropertyValue& value, float zoom) : binder(value.match( [&] (const Type& constant) -> Binder { - return ConstantPaintPropertyBinder<Type, Attribute>(constant); + return ConstantPaintPropertyBinder<Type, BaseAttribute>(constant); }, [&] (const SourceFunction<Type>& function) { - return SourceFunctionPaintPropertyBinder<Type, Attribute>(function, PaintProperty::defaultValue()); + return SourceFunctionPaintPropertyBinder<Type, BaseAttribute>(function, PaintProperty::defaultValue()); }, [&] (const CompositeFunction<Type>& function) { - return CompositeFunctionPaintPropertyBinder<Type, Attribute>(function, zoom, PaintProperty::defaultValue()); + return CompositeFunctionPaintPropertyBinder<Type, BaseAttribute>(function, zoom, PaintProperty::defaultValue()); } )) { } @@ -195,19 +181,9 @@ public: }); } - using MinAttribute = attributes::Min<Attribute>; - using MaxAttribute = attributes::Max<Attribute>; - using AttributeBinding = typename Attribute::Binding; - - AttributeBinding minAttributeBinding(const PropertyValue& currentValue) const { - return binder.match([&] (const auto& b) { - return b.minAttributeBinding(currentValue); - }); - } - - AttributeBinding maxAttributeBinding(const PropertyValue& currentValue) const { + AttributeBinding attributeBinding(const PropertyValue& currentValue) const { return binder.match([&] (const auto& b) { - return b.maxAttributeBinding(currentValue); + return b.attributeBinding(currentValue); }); } @@ -252,21 +228,14 @@ public: }); } - using MinAttributes = gl::Attributes<typename PaintPropertyBinder<Ps>::MinAttribute...>; - using MaxAttributes = gl::Attributes<typename PaintPropertyBinder<Ps>::MaxAttribute...>; - - using Attributes = gl::ConcatenateAttributes<MinAttributes, MaxAttributes>; + using Attributes = gl::Attributes<typename PaintPropertyBinder<Ps>::Attribute...>; using AttributeBindings = typename Attributes::Bindings; template <class EvaluatedProperties> AttributeBindings attributeBindings(const EvaluatedProperties& currentProperties) const { - const typename MinAttributes::Bindings min { - binders.template get<Ps>().minAttributeBinding(currentProperties.template get<Ps>())... - }; - const typename MaxAttributes::Bindings max { - binders.template get<Ps>().maxAttributeBinding(currentProperties.template get<Ps>())... + return typename Attributes::Bindings { + binders.template get<Ps>().attributeBinding(currentProperties.template get<Ps>())... }; - return min.concat(max); } using Uniforms = gl::Uniforms<typename PaintPropertyBinder<Ps>::InterpolationUniform...>; diff --git a/src/mbgl/style/query_parameters.hpp b/src/mbgl/style/query_parameters.hpp deleted file mode 100644 index 3c1abf3b70..0000000000 --- a/src/mbgl/style/query_parameters.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include <mbgl/util/geo.hpp> - -#include <vector> - -namespace mbgl { - -class TransformState; - -namespace style { - -class QueryParameters { -public: - const ScreenLineString& geometry; - const TransformState& transformState; - const optional<std::vector<std::string>>& layerIDs; -}; - -} // namespace style -} // namespace mbgl diff --git a/src/mbgl/style/source_impl.cpp b/src/mbgl/style/source_impl.cpp index 003df4f6b1..fdacb00b4c 100644 --- a/src/mbgl/style/source_impl.cpp +++ b/src/mbgl/style/source_impl.cpp @@ -4,12 +4,12 @@ #include <mbgl/renderer/render_tile.hpp> #include <mbgl/renderer/painter.hpp> #include <mbgl/style/update_parameters.hpp> -#include <mbgl/style/query_parameters.hpp> #include <mbgl/text/placement_config.hpp> #include <mbgl/util/logging.hpp> #include <mbgl/math/clamp.hpp> #include <mbgl/util/tile_cover.hpp> #include <mbgl/util/enum.hpp> +#include <mbgl/map/query.hpp> #include <mbgl/algorithm/update_renderables.hpp> #include <mbgl/algorithm/generate_clip_ids.hpp> @@ -44,6 +44,10 @@ bool Source::Impl::isLoaded() const { return true; } + +void Source::Impl::detach() { + invalidateTiles(); +} void Source::Impl::invalidateTiles() { tiles.clear(); @@ -200,17 +204,19 @@ void Source::Impl::reloadTiles() { } } -std::unordered_map<std::string, std::vector<Feature>> Source::Impl::queryRenderedFeatures(const QueryParameters& parameters) const { +std::unordered_map<std::string, std::vector<Feature>> Source::Impl::queryRenderedFeatures(const ScreenLineString& geometry, + const TransformState& transformState, + const QueryOptions& options) const { std::unordered_map<std::string, std::vector<Feature>> result; - if (renderTiles.empty() || parameters.geometry.empty()) { + if (renderTiles.empty() || geometry.empty()) { return result; } LineString<double> queryGeometry; - for (const auto& p : parameters.geometry) { + for (const auto& p : geometry) { queryGeometry.push_back(TileCoordinate::fromScreenCoordinate( - parameters.transformState, 0, { p.x, parameters.transformState.getSize().height - p.y }).p); + transformState, 0, { p.x, transformState.getSize().height - p.y }).p); } mapbox::geometry::box<double> box = mapbox::geometry::envelope(queryGeometry); @@ -245,8 +251,8 @@ std::unordered_map<std::string, std::vector<Feature>> Source::Impl::queryRendere renderTile.tile.queryRenderedFeatures(result, tileSpaceQueryGeometry, - parameters.transformState, - parameters.layerIDs); + transformState, + options); } return result; diff --git a/src/mbgl/style/source_impl.hpp b/src/mbgl/style/source_impl.hpp index e6340ae1cb..54af93c04f 100644 --- a/src/mbgl/style/source_impl.hpp +++ b/src/mbgl/style/source_impl.hpp @@ -66,7 +66,9 @@ public: std::map<UnwrappedTileID, RenderTile>& getRenderTiles(); std::unordered_map<std::string, std::vector<Feature>> - queryRenderedFeatures(const QueryParameters&) const; + queryRenderedFeatures(const ScreenLineString& geometry, + const TransformState& transformState, + const QueryOptions& options) const; void setCacheSize(size_t); void onLowMemory(); @@ -85,6 +87,9 @@ public: // be initialized to true so that Style::isLoaded() does not produce false positives if // called before Style::recalculate(). bool enabled = true; + + // Detaches from the style + void detach(); protected: void invalidateTiles(); diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp index b6f14ecf4b..5b45ca27ef 100644 --- a/src/mbgl/style/style.cpp +++ b/src/mbgl/style/style.cpp @@ -14,7 +14,6 @@ #include <mbgl/style/layers/raster_layer.hpp> #include <mbgl/style/layer_impl.hpp> #include <mbgl/style/parser.hpp> -#include <mbgl/style/query_parameters.hpp> #include <mbgl/style/transition_options.hpp> #include <mbgl/style/class_dictionary.hpp> #include <mbgl/style/update_parameters.hpp> @@ -31,6 +30,7 @@ #include <mbgl/util/logging.hpp> #include <mbgl/util/math.hpp> #include <mbgl/math/minmax.hpp> +#include <mbgl/map/query.hpp> #include <algorithm> @@ -166,6 +166,7 @@ std::unique_ptr<Source> Style::removeSource(const std::string& id) { sources.erase(it); updateBatch.sourceIDs.erase(id); + source->baseImpl->detach(); return source; } @@ -502,11 +503,13 @@ RenderData Style::getRenderData(MapDebugOptions debugOptions, float angle) const return result; } -std::vector<Feature> Style::queryRenderedFeatures(const QueryParameters& parameters) const { +std::vector<Feature> Style::queryRenderedFeatures(const ScreenLineString& geometry, + const TransformState& transformState, + const QueryOptions& options) const { std::unordered_set<std::string> sourceFilter; - if (parameters.layerIDs) { - for (const auto& layerID : *parameters.layerIDs) { + if (options.layerIDs) { + for (const auto& layerID : *options.layerIDs) { auto layer = getLayer(layerID); if (layer) sourceFilter.emplace(layer->baseImpl->source); } @@ -520,7 +523,7 @@ std::vector<Feature> Style::queryRenderedFeatures(const QueryParameters& paramet continue; } - auto sourceResults = source->baseImpl->queryRenderedFeatures(parameters); + auto sourceResults = source->baseImpl->queryRenderedFeatures(geometry, transformState, options); std::move(sourceResults.begin(), sourceResults.end(), std::inserter(resultsByLayer, resultsByLayer.begin())); } diff --git a/src/mbgl/style/style.hpp b/src/mbgl/style/style.hpp index 4c4bcec63a..5246f6877d 100644 --- a/src/mbgl/style/style.hpp +++ b/src/mbgl/style/style.hpp @@ -28,6 +28,8 @@ class GlyphAtlas; class SpriteAtlas; class LineAtlas; class RenderData; +class TransformState; +class QueryOptions; namespace style { @@ -95,8 +97,10 @@ public: RenderData getRenderData(MapDebugOptions, float angle) const; - std::vector<Feature> queryRenderedFeatures(const QueryParameters&) const; - + std::vector<Feature> queryRenderedFeatures(const ScreenLineString& geometry, + const TransformState& transformState, + const QueryOptions& options) const; + float getQueryRadius() const; void setSourceTileCacheSize(size_t); diff --git a/src/mbgl/text/check_max_angle.cpp b/src/mbgl/text/check_max_angle.cpp index 3ef13a0dd7..9109235798 100644 --- a/src/mbgl/text/check_max_angle.cpp +++ b/src/mbgl/text/check_max_angle.cpp @@ -13,9 +13,11 @@ struct Corner { float angleDelta; }; -bool checkMaxAngle(const GeometryCoordinates &line, Anchor &anchor, const float labelLength, - const float windowSize, const float maxAngle) { - +bool checkMaxAngle(const GeometryCoordinates& line, + const Anchor& anchor, + const float labelLength, + const float windowSize, + const float maxAngle) { // horizontal labels always pass if (anchor.segment < 0) return true; @@ -74,8 +76,6 @@ bool checkMaxAngle(const GeometryCoordinates &line, Anchor &anchor, const float // no part of the line had an angle greater than the maximum allowed. check passes. return true; - - } } // namespace mbgl diff --git a/src/mbgl/text/check_max_angle.hpp b/src/mbgl/text/check_max_angle.hpp index 008e70b5da..c95661160c 100644 --- a/src/mbgl/text/check_max_angle.hpp +++ b/src/mbgl/text/check_max_angle.hpp @@ -4,9 +4,12 @@ namespace mbgl { -struct Anchor; +class Anchor; -bool checkMaxAngle(const GeometryCoordinates &line, Anchor &anchor, const float labelLength, - const float windowSize, const float maxAngle); +bool checkMaxAngle(const GeometryCoordinates& line, + const Anchor& anchor, + const float labelLength, + const float windowSize, + const float maxAngle); } // namespace mbgl diff --git a/src/mbgl/text/collision_feature.cpp b/src/mbgl/text/collision_feature.cpp index 661c44891f..67f669ab61 100644 --- a/src/mbgl/text/collision_feature.cpp +++ b/src/mbgl/text/collision_feature.cpp @@ -3,12 +3,18 @@ namespace mbgl { -CollisionFeature::CollisionFeature(const GeometryCoordinates &line, const Anchor &anchor, - const float top, const float bottom, const float left, const float right, - const float boxScale, const float padding, const style::SymbolPlacementType placement, IndexedSubfeature indexedFeature_, - const bool straight) +CollisionFeature::CollisionFeature(const GeometryCoordinates& line, + const Anchor& anchor, + const float top, + const float bottom, + const float left, + const float right, + const float boxScale, + const float padding, + const style::SymbolPlacementType placement, + IndexedSubfeature indexedFeature_, + const bool straight) : indexedFeature(std::move(indexedFeature_)) { - if (top == 0 && bottom == 0 && left == 0 && right == 0) return; const float y1 = top * boxScale - padding; @@ -40,9 +46,8 @@ CollisionFeature::CollisionFeature(const GeometryCoordinates &line, const Anchor } } -void CollisionFeature::bboxifyLabel(const GeometryCoordinates &line, - GeometryCoordinate &anchorPoint, const int segment, const float labelLength, const float boxSize) { - +void CollisionFeature::bboxifyLabel(const GeometryCoordinates& line, GeometryCoordinate& anchorPoint, + const int segment, const float labelLength, const float boxSize) { const float step = boxSize / 2; const unsigned int nBoxes = std::floor(labelLength / step); @@ -101,5 +106,4 @@ void CollisionFeature::bboxifyLabel(const GeometryCoordinates &line, } } - } // namespace mbgl diff --git a/src/mbgl/text/collision_feature.hpp b/src/mbgl/text/collision_feature.hpp index 12c14fe0c1..1436e0815b 100644 --- a/src/mbgl/text/collision_feature.hpp +++ b/src/mbgl/text/collision_feature.hpp @@ -8,57 +8,69 @@ #include <vector> namespace mbgl { - class CollisionBox { - public: - explicit CollisionBox(Point<float> _anchor, float _x1, float _y1, float _x2, float _y2, float _maxScale) : - anchor(std::move(_anchor)), x1(_x1), y1(_y1), x2(_x2), y2(_y2), maxScale(_maxScale) {} - // the box is centered around the anchor point - Point<float> anchor; +class CollisionBox { +public: + CollisionBox(Point<float> _anchor, float _x1, float _y1, float _x2, float _y2, float _maxScale) : + anchor(std::move(_anchor)), x1(_x1), y1(_y1), x2(_x2), y2(_y2), maxScale(_maxScale) {} - // distances to the edges from the anchor - float x1; - float y1; - float x2; - float y2; + // the box is centered around the anchor point + Point<float> anchor; - // the box is only valid for scales < maxScale. - // The box does not block other boxes at scales >= maxScale; - float maxScale; + // distances to the edges from the anchor + float x1; + float y1; + float x2; + float y2; - // the scale at which the label can first be shown - float placementScale = 0.0f; - }; + // the box is only valid for scales < maxScale. + // The box does not block other boxes at scales >= maxScale; + float maxScale; - class CollisionFeature { - public: - // for text - explicit CollisionFeature(const GeometryCoordinates &line, const Anchor &anchor, - const Shaping &shapedText, - const float boxScale, const float padding, const style::SymbolPlacementType placement, const IndexedSubfeature& indexedFeature_) - : CollisionFeature(line, anchor, - shapedText.top, shapedText.bottom, shapedText.left, shapedText.right, - boxScale, padding, placement, indexedFeature_, false) {} + // the scale at which the label can first be shown + float placementScale = 0.0f; +}; - // for icons - explicit CollisionFeature(const GeometryCoordinates &line, const Anchor &anchor, - const PositionedIcon &shapedIcon, - const float boxScale, const float padding, const style::SymbolPlacementType placement, const IndexedSubfeature& indexedFeature_) - : CollisionFeature(line, anchor, - shapedIcon.top, shapedIcon.bottom, shapedIcon.left, shapedIcon.right, - boxScale, padding, placement, indexedFeature_, true) {} +class CollisionFeature { +public: + // for text + CollisionFeature(const GeometryCoordinates& line, + const Anchor& anchor, + const Shaping& shapedText, + const float boxScale, + const float padding, + const style::SymbolPlacementType placement, + const IndexedSubfeature& indexedFeature_) + : CollisionFeature(line, anchor, shapedText.top, shapedText.bottom, shapedText.left, shapedText.right, boxScale, padding, placement, indexedFeature_, false) {} - explicit CollisionFeature(const GeometryCoordinates &line, const Anchor &anchor, - const float top, const float bottom, const float left, const float right, - const float boxScale, const float padding, const style::SymbolPlacementType placement, - IndexedSubfeature, const bool straight); + // for icons + CollisionFeature(const GeometryCoordinates& line, + const Anchor& anchor, + const PositionedIcon& shapedIcon, + const float boxScale, + const float padding, + const style::SymbolPlacementType placement, + const IndexedSubfeature& indexedFeature_) + : CollisionFeature(line, anchor, shapedIcon.top, shapedIcon.bottom, shapedIcon.left, shapedIcon.right, boxScale, padding, placement, indexedFeature_, true) {} + CollisionFeature(const GeometryCoordinates& line, + const Anchor& anchor, + const float top, + const float bottom, + const float left, + const float right, + const float boxScale, + const float padding, + const style::SymbolPlacementType placement, + IndexedSubfeature, + const bool straight); - std::vector<CollisionBox> boxes; - IndexedSubfeature indexedFeature; + std::vector<CollisionBox> boxes; + IndexedSubfeature indexedFeature; + +private: + void bboxifyLabel(const GeometryCoordinates& line, GeometryCoordinate& anchorPoint, + const int segment, const float length, const float height); +}; - private: - void bboxifyLabel(const GeometryCoordinates &line, GeometryCoordinate &anchorPoint, - const int segment, const float length, const float height); - }; } // namespace mbgl diff --git a/src/mbgl/text/get_anchors.cpp b/src/mbgl/text/get_anchors.cpp index b912c7763e..82702b20f0 100644 --- a/src/mbgl/text/get_anchors.cpp +++ b/src/mbgl/text/get_anchors.cpp @@ -8,9 +8,14 @@ namespace mbgl { -Anchors resample(const GeometryCoordinates &line, const float offset, const float spacing, - const float angleWindowSize, const float maxAngle, const float labelLength, const bool continuedLine, const bool placeAtMiddle) { - +static Anchors resample(const GeometryCoordinates& line, + const float offset, + const float spacing, + const float angleWindowSize, + const float maxAngle, + const float labelLength, + const bool continuedLine, + const bool placeAtMiddle) { const float halfLabelLength = labelLength / 2.0f; float lineLength = 0; for (auto it = line.begin(), end = line.end() - 1; it != end; it++) { @@ -26,8 +31,8 @@ Anchors resample(const GeometryCoordinates &line, const float offset, const floa int i = 0; for (auto it = line.begin(), end = line.end() - 1; it != end; it++, i++) { - const GeometryCoordinate &a = *(it); - const GeometryCoordinate &b = *(it + 1); + const GeometryCoordinate& a = *(it); + const GeometryCoordinate& b = *(it + 1); const float segmentDist = util::dist<float>(a, b); const float angle = util::angle_to(b, a); @@ -68,11 +73,19 @@ Anchors resample(const GeometryCoordinates &line, const float offset, const floa return anchors; } -Anchors getAnchors(const GeometryCoordinates &line, float spacing, - const float maxAngle, const float textLeft, const float textRight, - const float iconLeft, const float iconRight, - const float glyphSize, const float boxScale, const float overscaling) { - if (line.empty()) return {}; +Anchors getAnchors(const GeometryCoordinates& line, + float spacing, + const float maxAngle, + const float textLeft, + const float textRight, + const float iconLeft, + const float iconRight, + const float glyphSize, + const float boxScale, + const float overscaling) { + if (line.empty()) { + return {}; + } // Resample a line to get anchor points for labels and check that each // potential label passes text-max-angle check and has enough froom to fit diff --git a/src/mbgl/text/get_anchors.hpp b/src/mbgl/text/get_anchors.hpp index b61f8fe0dc..48f3013093 100644 --- a/src/mbgl/text/get_anchors.hpp +++ b/src/mbgl/text/get_anchors.hpp @@ -6,8 +6,15 @@ namespace mbgl { -Anchors getAnchors(const GeometryCoordinates &line, float spacing, - const float maxAngle, const float textLeft, const float textRight, - const float iconLeft, const float iconRight, - const float glyphSize, const float boxScale, const float overscaling); +Anchors getAnchors(const GeometryCoordinates& line, + float spacing, + const float maxAngle, + const float textLeft, + const float textRight, + const float iconLeft, + const float iconRight, + const float glyphSize, + const float boxScale, + const float overscaling); + } // namespace mbgl diff --git a/src/mbgl/text/quads.cpp b/src/mbgl/text/quads.cpp index 6113d1f5d4..a0742f5a4b 100644 --- a/src/mbgl/text/quads.cpp +++ b/src/mbgl/text/quads.cpp @@ -5,6 +5,7 @@ #include <mbgl/style/layers/symbol_layer_properties.hpp> #include <mbgl/util/math.hpp> #include <mbgl/util/constants.hpp> + #include <cassert> namespace mbgl { @@ -13,10 +14,12 @@ using namespace style; const float globalMinScale = 0.5f; // underscale by 1 zoom level -SymbolQuad getIconQuad(Anchor& anchor, const PositionedIcon& shapedIcon, - const GeometryCoordinates& line, const SymbolLayoutProperties::Evaluated& layout, - const style::SymbolPlacementType placement, const Shaping& shapedText) { - +SymbolQuad getIconQuad(const Anchor& anchor, + const PositionedIcon& shapedIcon, + const GeometryCoordinates& line, + const SymbolLayoutProperties::Evaluated& layout, + const style::SymbolPlacementType placement, + const Shaping& shapedText) { auto image = *(shapedIcon.image); const float border = 1.0; @@ -38,7 +41,7 @@ SymbolQuad getIconQuad(Anchor& anchor, const PositionedIcon& shapedIcon, auto textTop = shapedText.top * size; auto textBottom = shapedText.bottom * size; auto textWidth = textRight - textLeft; - auto textHeight = textBottom - textTop;; + auto textHeight = textBottom - textTop; auto padT = layout.get<IconTextFitPadding>()[0]; auto padR = layout.get<IconTextFitPadding>()[1]; auto padB = layout.get<IconTextFitPadding>()[2]; @@ -75,7 +78,6 @@ SymbolQuad getIconQuad(Anchor& anchor, const PositionedIcon& shapedIcon, } } - if (angle) { // Compute the transformation matrix. float angle_sin = std::sin(angle); @@ -106,9 +108,12 @@ struct GlyphInstance { typedef std::vector<GlyphInstance> GlyphInstances; -void getSegmentGlyphs(std::back_insert_iterator<GlyphInstances> glyphs, Anchor &anchor, - float offset, const GeometryCoordinates &line, int segment, bool forward) { - +void getSegmentGlyphs(std::back_insert_iterator<GlyphInstances> glyphs, + Anchor& anchor, + float offset, + const GeometryCoordinates& line, + int segment, + bool forward) { const bool upsideDown = !forward; if (offset < 0) @@ -162,10 +167,13 @@ void getSegmentGlyphs(std::back_insert_iterator<GlyphInstances> glyphs, Anchor & } } -SymbolQuads getGlyphQuads(Anchor& anchor, const Shaping& shapedText, - const float boxScale, const GeometryCoordinates& line, const SymbolLayoutProperties::Evaluated& layout, - const style::SymbolPlacementType placement, const GlyphPositions& face) { - +SymbolQuads getGlyphQuads(Anchor& anchor, + const Shaping& shapedText, + const float boxScale, + const GeometryCoordinates& line, + const SymbolLayoutProperties::Evaluated& layout, + const style::SymbolPlacementType placement, + const GlyphPositions& face) { const float textRotate = layout.get<TextRotate>() * util::DEG2RAD; const bool keepUpright = layout.get<TextKeepUpright>(); @@ -191,7 +199,6 @@ SymbolQuads getGlyphQuads(Anchor& anchor, const Shaping& shapedText, getSegmentGlyphs(std::back_inserter(glyphInstances), anchor, centerX, line, anchor.segment, true); if (keepUpright) getSegmentGlyphs(std::back_inserter(glyphInstances), anchor, centerX, line, anchor.segment, false); - } else { glyphInstances.emplace_back(GlyphInstance{anchor.point}); } @@ -220,7 +227,6 @@ SymbolQuads getGlyphQuads(Anchor& anchor, const Shaping& shapedText, } for (const GlyphInstance &instance : glyphInstances) { - Point<float> tl = otl; Point<float> tr = otr; Point<float> bl = obl; @@ -244,9 +250,7 @@ SymbolQuads getGlyphQuads(Anchor& anchor, const Shaping& shapedText, const float anchorAngle = std::fmod((anchor.angle + instance.offset + 2 * M_PI), (2 * M_PI)); const float glyphAngle = std::fmod((instance.angle + instance.offset + 2 * M_PI), (2 * M_PI)); quads.emplace_back(tl, tr, bl, br, rect, anchorAngle, glyphAngle, instance.anchorPoint, glyphMinScale, instance.maxScale, shapedText.writingMode); - } - } return quads; diff --git a/src/mbgl/text/quads.hpp b/src/mbgl/text/quads.hpp index 07a94c763b..f1529d8829 100644 --- a/src/mbgl/text/quads.hpp +++ b/src/mbgl/text/quads.hpp @@ -9,13 +9,22 @@ namespace mbgl { -struct Anchor; +class Anchor; class PositionedIcon; -struct SymbolQuad { - explicit SymbolQuad(Point<float> tl_, Point<float> tr_, Point<float> bl_, Point<float> br_, - Rect<uint16_t> tex_, float anchorAngle_, float glyphAngle_, Point<float> anchorPoint_, - float minScale_, float maxScale_, WritingModeType writingMode_) +class SymbolQuad { +public: + SymbolQuad(Point<float> tl_, + Point<float> tr_, + Point<float> bl_, + Point<float> br_, + Rect<uint16_t> tex_, + float anchorAngle_, + float glyphAngle_, + Point<float> anchorPoint_, + float minScale_, + float maxScale_, + WritingModeType writingMode_) : tl(std::move(tl_)), tr(std::move(tr_)), bl(std::move(bl_)), @@ -28,22 +37,33 @@ struct SymbolQuad { maxScale(maxScale_), writingMode(writingMode_) {} - Point<float> tl, tr, bl, br; + Point<float> tl; + Point<float> tr; + Point<float> bl; + Point<float> br; Rect<uint16_t> tex; float anchorAngle, glyphAngle; Point<float> anchorPoint; - float minScale, maxScale; + float minScale; + float maxScale; WritingModeType writingMode; }; typedef std::vector<SymbolQuad> SymbolQuads; -SymbolQuad getIconQuad(Anchor& anchor, const PositionedIcon& shapedIcon, - const GeometryCoordinates& line, const style::SymbolLayoutProperties::Evaluated&, - style::SymbolPlacementType placement, const Shaping& shapedText); +SymbolQuad getIconQuad(const Anchor& anchor, + const PositionedIcon& shapedIcon, + const GeometryCoordinates& line, + const style::SymbolLayoutProperties::Evaluated&, + style::SymbolPlacementType placement, + const Shaping& shapedText); -SymbolQuads getGlyphQuads(Anchor& anchor, const Shaping& shapedText, - const float boxScale, const GeometryCoordinates& line, const style::SymbolLayoutProperties::Evaluated&, - style::SymbolPlacementType placement, const GlyphPositions& face); +SymbolQuads getGlyphQuads(Anchor& anchor, + const Shaping& shapedText, + const float boxScale, + const GeometryCoordinates& line, + const style::SymbolLayoutProperties::Evaluated&, + style::SymbolPlacementType placement, + const GlyphPositions& face); } // namespace mbgl diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp index 9aeb35c821..83d130841d 100644 --- a/src/mbgl/tile/geometry_tile.cpp +++ b/src/mbgl/tile/geometry_tile.cpp @@ -13,6 +13,7 @@ #include <mbgl/text/collision_tile.hpp> #include <mbgl/map/transform_state.hpp> #include <mbgl/util/run_loop.hpp> +#include <mbgl/map/query.hpp> namespace mbgl { @@ -141,7 +142,7 @@ void GeometryTile::queryRenderedFeatures( std::unordered_map<std::string, std::vector<Feature>>& result, const GeometryCoordinates& queryGeometry, const TransformState& transformState, - const optional<std::vector<std::string>>& layerIDs) { + const QueryOptions& options) { if (!featureIndex || !data) return; @@ -150,7 +151,7 @@ void GeometryTile::queryRenderedFeatures( transformState.getAngle(), util::tileSize * id.overscaleFactor(), std::pow(2, transformState.getZoom() - id.overscaledZ), - layerIDs, + options, *data, id.canonical, style, diff --git a/src/mbgl/tile/geometry_tile.hpp b/src/mbgl/tile/geometry_tile.hpp index c61a510311..85a068ee01 100644 --- a/src/mbgl/tile/geometry_tile.hpp +++ b/src/mbgl/tile/geometry_tile.hpp @@ -44,7 +44,7 @@ public: std::unordered_map<std::string, std::vector<Feature>>& result, const GeometryCoordinates& queryGeometry, const TransformState&, - const optional<std::vector<std::string>>& layerIDs) override; + const QueryOptions& options) override; void cancel() override; diff --git a/src/mbgl/tile/tile.cpp b/src/mbgl/tile/tile.cpp index e84eaaf780..4829ac8355 100644 --- a/src/mbgl/tile/tile.cpp +++ b/src/mbgl/tile/tile.cpp @@ -3,6 +3,7 @@ #include <mbgl/renderer/debug_bucket.hpp> #include <mbgl/util/string.hpp> #include <mbgl/util/logging.hpp> +#include <mbgl/map/query.hpp> namespace mbgl { @@ -32,6 +33,6 @@ void Tile::queryRenderedFeatures( std::unordered_map<std::string, std::vector<Feature>>&, const GeometryCoordinates&, const TransformState&, - const optional<std::vector<std::string>>&) {} + const QueryOptions&) {} } // namespace mbgl diff --git a/src/mbgl/tile/tile.hpp b/src/mbgl/tile/tile.hpp index cebf913f56..0f0babf085 100644 --- a/src/mbgl/tile/tile.hpp +++ b/src/mbgl/tile/tile.hpp @@ -21,6 +21,7 @@ class DebugBucket; class TransformState; class TileObserver; class PlacementConfig; +class QueryOptions; namespace style { class Layer; @@ -55,7 +56,7 @@ public: std::unordered_map<std::string, std::vector<Feature>>& result, const GeometryCoordinates& queryGeometry, const TransformState&, - const optional<std::vector<std::string>>& layerIDs); + const QueryOptions& options); void setTriedOptional(); diff --git a/src/mbgl/util/offscreen_texture.cpp b/src/mbgl/util/offscreen_texture.cpp index aad20e59d3..cbe33c8d58 100644 --- a/src/mbgl/util/offscreen_texture.cpp +++ b/src/mbgl/util/offscreen_texture.cpp @@ -1,35 +1,69 @@ -#include <mbgl/util/offscreen_texture.hpp> #include <mbgl/gl/context.hpp> +#include <mbgl/util/offscreen_texture.hpp> -#include <cstring> #include <cassert> +#include <cstring> namespace mbgl { -OffscreenTexture::OffscreenTexture(gl::Context& context_, const Size size_) - : size(std::move(size_)), context(context_) { +class OffscreenTexture::Impl { +public: + Impl(gl::Context& context_, const Size size_) : context(context_), size(std::move(size_)) { + assert(size); + } + + void bind() { + if (!framebuffer) { + texture = context.createTexture(size); + framebuffer = context.createFramebuffer(*texture); + } else { + context.bindFramebuffer = framebuffer->framebuffer; + } + + context.viewport = { 0, 0, size }; + } + + PremultipliedImage readStillImage() { + return context.readFramebuffer<PremultipliedImage>(size); + } + + gl::Texture& getTexture() { + assert(texture); + return *texture; + } + + const Size& getSize() const { + return size; + } + +private: + gl::Context& context; + const Size size; + optional<gl::Framebuffer> framebuffer; + optional<gl::Texture> texture; +}; + +OffscreenTexture::OffscreenTexture(gl::Context& context, const Size size) + : impl(std::make_unique<Impl>(context, std::move(size))) { assert(size); } +OffscreenTexture::~OffscreenTexture() = default; + void OffscreenTexture::bind() { - if (!framebuffer) { - texture = context.createTexture(size); - framebuffer = context.createFramebuffer(*texture); - } else { - context.bindFramebuffer = framebuffer->framebuffer; - } + impl->bind(); +} - context.viewport = { 0, 0, size }; +PremultipliedImage OffscreenTexture::readStillImage() { + return impl->readStillImage(); } gl::Texture& OffscreenTexture::getTexture() { - assert(texture); - return *texture; + return impl->getTexture(); } -PremultipliedImage OffscreenTexture::readStillImage() { - return context.readFramebuffer<PremultipliedImage>(size); +const Size& OffscreenTexture::getSize() const { + return impl->getSize(); } - } // namespace mbgl diff --git a/src/mbgl/util/offscreen_texture.hpp b/src/mbgl/util/offscreen_texture.hpp index 64eb7bc565..b8bfabf7d3 100644 --- a/src/mbgl/util/offscreen_texture.hpp +++ b/src/mbgl/util/offscreen_texture.hpp @@ -1,20 +1,19 @@ #pragma once #include <mbgl/map/view.hpp> -#include <mbgl/gl/framebuffer.hpp> -#include <mbgl/gl/texture.hpp> -#include <mbgl/util/optional.hpp> #include <mbgl/util/image.hpp> namespace mbgl { namespace gl { class Context; +class Texture; } // namespace gl class OffscreenTexture : public View { public: OffscreenTexture(gl::Context&, Size size = { 256, 256 }); + ~OffscreenTexture(); void bind() override; @@ -22,13 +21,11 @@ public: gl::Texture& getTexture(); -public: - const Size size; + const Size& getSize() const; private: - gl::Context& context; - optional<gl::Framebuffer> framebuffer; - optional<gl::Texture> texture; + class Impl; + const std::unique_ptr<Impl> impl; }; } // namespace mbgl diff --git a/test/api/annotations.test.cpp b/test/api/annotations.test.cpp index 6644e9c92c..30027d8610 100644 --- a/test/api/annotations.test.cpp +++ b/test/api/annotations.test.cpp @@ -401,7 +401,7 @@ TEST(Annotations, VisibleFeatures) { test.map.setBearing(45); test::render(test.map, test.view); - auto features = test.map.queryRenderedFeatures(box); + auto features = test.map.queryRenderedFeatures(box, {}); auto sortID = [](const Feature& lhs, const Feature& rhs) { return lhs.id < rhs.id; }; auto sameID = [](const Feature& lhs, const Feature& rhs) { return lhs.id == rhs.id; }; std::sort(features.begin(), features.end(), sortID); diff --git a/test/api/query.test.cpp b/test/api/query.test.cpp index 4d2bf00f67..b42046fb48 100644 --- a/test/api/query.test.cpp +++ b/test/api/query.test.cpp @@ -10,6 +10,7 @@ #include <mbgl/util/run_loop.hpp> using namespace mbgl; +using namespace mbgl::style; namespace { @@ -39,7 +40,7 @@ TEST(Query, QueryRenderedFeatures) { QueryTest test; auto features1 = test.map.queryRenderedFeatures(test.map.pixelForLatLng({ 0, 0 })); - EXPECT_EQ(features1.size(), 3u); + EXPECT_EQ(features1.size(), 4u); auto features2 = test.map.queryRenderedFeatures(test.map.pixelForLatLng({ 9, 9 })); EXPECT_EQ(features2.size(), 0u); @@ -50,15 +51,33 @@ TEST(Query, QueryRenderedFeaturesFilterLayer) { auto zz = test.map.pixelForLatLng({ 0, 0 }); - auto features1 = test.map.queryRenderedFeatures(zz, {{ "layer1"}}); + auto features1 = test.map.queryRenderedFeatures(zz, {{{ "layer1"}}, {}}); EXPECT_EQ(features1.size(), 1u); - auto features2 = test.map.queryRenderedFeatures(zz, {{ "layer1", "layer2" }}); + auto features2 = test.map.queryRenderedFeatures(zz, {{{ "layer1", "layer2" }}, {}}); EXPECT_EQ(features2.size(), 2u); - auto features3 = test.map.queryRenderedFeatures(zz, {{ "foobar" }}); + auto features3 = test.map.queryRenderedFeatures(zz, {{{ "foobar" }}, {}}); EXPECT_EQ(features3.size(), 0u); - auto features4 = test.map.queryRenderedFeatures(zz, {{ "foobar", "layer3" }}); + auto features4 = test.map.queryRenderedFeatures(zz, {{{ "foobar", "layer3" }}, {}}); EXPECT_EQ(features4.size(), 1u); } + +TEST(Query, QueryRenderedFeaturesFilter) { + QueryTest test; + + auto zz = test.map.pixelForLatLng({ 0, 0 }); + + const EqualsFilter eqFilter = { "key1", std::string("value1") }; + auto features1 = test.map.queryRenderedFeatures(zz, {{}, { eqFilter }}); + EXPECT_EQ(features1.size(), 1u); + + const IdentifierNotEqualsFilter idNotEqFilter = { std::string("feature1") }; + auto features2 = test.map.queryRenderedFeatures(zz, {{{ "layer4" }}, { idNotEqFilter }}); + EXPECT_EQ(features2.size(), 0u); + + const GreaterThanFilter gtFilter = { "key2", 1.0 }; + auto features3 = test.map.queryRenderedFeatures(zz, {{ }, { gtFilter }}); + EXPECT_EQ(features3.size(), 1u); +} diff --git a/test/fixtures/api/query_style.json b/test/fixtures/api/query_style.json index 6978e1ba1b..4e11921775 100644 --- a/test/fixtures/api/query_style.json +++ b/test/fixtures/api/query_style.json @@ -30,6 +30,26 @@ 0 ] } + }, + "source4": { + "type": "geojson", + "data": { + "type": "Feature", + "id": "feature1", + "geometry": { + "type": "Point", + "coordinates": [ + 0.0, + 0.0 + ] + }, + "properties": { + "key1": "value1", + "key2": 1.5, + "key3": false, + "key4": 0.5 + } + } } }, "layers": [ @@ -56,6 +76,14 @@ "layout": { "icon-image": "test-icon" } + }, + { + "id": "layer4", + "type": "symbol", + "source": "source4", + "layout": { + "icon-image": "test-icon" + } } ] } diff --git a/test/style/paint_property.test.cpp b/test/style/paint_property.test.cpp index c70fa101ca..39d31068c1 100644 --- a/test/style/paint_property.test.cpp +++ b/test/style/paint_property.test.cpp @@ -22,6 +22,22 @@ float evaluate(UnevaluatedPaintProperty<PropertyValue<float>>& property, Duratio return property.evaluate(evaluator, parameters.now); } +PossiblyEvaluatedPropertyValue<float> evaluate(UnevaluatedPaintProperty<DataDrivenPropertyValue<float>>& property, Duration delta = Duration::zero()) { + PropertyEvaluationParameters parameters { + 0, + TimePoint::min() + delta, + ZoomHistory(), + Duration::zero() + }; + + DataDrivenPropertyEvaluator<float> evaluator { + parameters, + 0.0f + }; + + return property.evaluate(evaluator, parameters.now); +} + TEST(UnevaluatedPaintProperty, EvaluateDefaultValue) { UnevaluatedPaintProperty<PropertyValue<float>> property; ASSERT_EQ(0.0f, evaluate(property)); @@ -86,3 +102,32 @@ TEST(UnevaluatedPaintProperty, EvaluateTransitionedConstantWithDelay) { ASSERT_FLOAT_EQ(0.823099f, evaluate(t1, 1500ms)); ASSERT_FLOAT_EQ(1.0f, evaluate(t1, 2500ms)); } + +TEST(UnevaluatedPaintProperty, EvaluateDataDrivenValue) { + TransitionOptions transition; + transition.delay = { 1000ms }; + transition.duration = { 1000ms }; + + UnevaluatedPaintProperty<DataDrivenPropertyValue<float>> t0 { + DataDrivenPropertyValue<float>(0.0f), + UnevaluatedPaintProperty<DataDrivenPropertyValue<float>>(), + TransitionOptions(), + TimePoint::min() + }; + + SourceFunction<float> sourceFunction = { + "property_name", + IdentityStops<float>() + }; + + UnevaluatedPaintProperty<DataDrivenPropertyValue<float>> t1 { + DataDrivenPropertyValue<float>(sourceFunction), + t0, + transition, + TimePoint::min() + }; + + ASSERT_TRUE(evaluate(t0, 0ms).isConstant()); + ASSERT_FALSE(evaluate(t1, 0ms).isConstant()) << + "A paint property transition to a data-driven evaluates immediately to the final value (see https://github.com/mapbox/mapbox-gl-native/issues/8237)."; +} diff --git a/test/util/memory.test.cpp b/test/util/memory.test.cpp index d49c49018f..79a3c43dbd 100644 --- a/test/util/memory.test.cpp +++ b/test/util/memory.test.cpp @@ -157,8 +157,8 @@ TEST(Memory, Footprint) { RecordProperty("vectorFootprint", vectorFootprint); RecordProperty("rasterFootprint", rasterFootprint); - ASSERT_LT(vectorFootprint, 65 * 1024 * 1024) << "\ - mbgl::Map footprint over 65MB for vector styles."; + ASSERT_LT(vectorFootprint, 65.2 * 1024 * 1024) << "\ + mbgl::Map footprint over 65.2MB for vector styles."; ASSERT_LT(rasterFootprint, 25 * 1024 * 1024) << "\ mbgl::Map footprint over 25MB for raster styles."; |