diff --git a/include/mbgl/style/conversion/make_property_setters.hpp b/include/mbgl/style/conversion/make_property_setters.hpp index 78c2fabebcb..85bcd44cf39 100644 --- a/include/mbgl/style/conversion/make_property_setters.hpp +++ b/include/mbgl/style/conversion/make_property_setters.hpp @@ -40,7 +40,7 @@ auto makeLayoutPropertySetters() { result["icon-size"] = &setLayoutProperty, &SymbolLayer::setIconSize>; result["icon-text-fit"] = &setLayoutProperty, &SymbolLayer::setIconTextFit>; result["icon-text-fit-padding"] = &setLayoutProperty>, &SymbolLayer::setIconTextFitPadding>; - result["icon-image"] = &setLayoutProperty, &SymbolLayer::setIconImage>; + result["icon-image"] = &setLayoutProperty, &SymbolLayer::setIconImage>; result["icon-rotate"] = &setLayoutProperty, &SymbolLayer::setIconRotate>; result["icon-padding"] = &setLayoutProperty, &SymbolLayer::setIconPadding>; result["icon-keep-upright"] = &setLayoutProperty, &SymbolLayer::setIconKeepUpright>; diff --git a/include/mbgl/style/layers/symbol_layer.hpp b/include/mbgl/style/layers/symbol_layer.hpp index 23bdf303b6d..853a71bef2e 100644 --- a/include/mbgl/style/layers/symbol_layer.hpp +++ b/include/mbgl/style/layers/symbol_layer.hpp @@ -71,9 +71,9 @@ class SymbolLayer : public Layer { PropertyValue> getIconTextFitPadding() const; void setIconTextFitPadding(PropertyValue>); - static PropertyValue getDefaultIconImage(); - PropertyValue getIconImage() const; - void setIconImage(PropertyValue); + static DataDrivenPropertyValue getDefaultIconImage(); + DataDrivenPropertyValue getIconImage() const; + void setIconImage(DataDrivenPropertyValue); static DataDrivenPropertyValue getDefaultIconRotate(); DataDrivenPropertyValue getIconRotate() const; diff --git a/mapbox-gl-js b/mapbox-gl-js index fac47099c29..3d8ca27a1bf 160000 --- a/mapbox-gl-js +++ b/mapbox-gl-js @@ -1 +1 @@ -Subproject commit fac47099c295912f3ac1ba422415b1c46ba7340f +Subproject commit 3d8ca27a1bf384142d2322b3b6ca1be176115553 diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java index 7be8e245976..269a7770505 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java @@ -1595,11 +1595,11 @@ public static PropertyValue iconImage(String value) { /** * Name of image in sprite to use for drawing an image background. A string with {tokens} replaced, referencing the data property to pull from. * - * @param the zoom parameter type - * @param function a wrapper {@link CameraFunction} for String + * @param the function input type + * @param function a wrapper function for String * @return property wrapper around a String function */ - public static PropertyValue> iconImage(CameraFunction function) { + public static PropertyValue> iconImage(Function function) { return new LayoutPropertyValue<>("icon-image", function); } 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 4c635097983..e8af375d666 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 @@ -494,6 +494,51 @@ public void testIconImageAsCameraFunction() { } + @Test + public void testIconImageAsIdentitySourceFunction() { + checkViewIsDisplayed(R.id.mapView); + Timber.i("icon-image"); + assertNotNull(layer); + + // Set + layer.setProperties( + iconImage(property("FeaturePropertyA", Stops.identity())) + ); + + // Verify + assertNotNull(layer.getIconImage()); + assertNotNull(layer.getIconImage().getFunction()); + assertEquals(SourceFunction.class, layer.getIconImage().getFunction().getClass()); + assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconImage().getFunction()).getProperty()); + assertEquals(IdentityStops.class, layer.getIconImage().getFunction().getStops().getClass()); + } + + @Test + public void testIconImageAsIntervalSourceFunction() { + checkViewIsDisplayed(R.id.mapView); + Timber.i("icon-image"); + assertNotNull(layer); + + // Set + layer.setProperties( + iconImage( + property( + "FeaturePropertyA", + interval( + stop(1, iconImage("undefined")) + ) + ) + ) + ); + + // Verify + assertNotNull(layer.getIconImage()); + assertNotNull(layer.getIconImage().getFunction()); + assertEquals(SourceFunction.class, layer.getIconImage().getFunction().getClass()); + assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconImage().getFunction()).getProperty()); + assertEquals(IntervalStops.class, layer.getIconImage().getFunction().getStops().getClass()); + } + @Test public void testIconRotateAsConstant() { checkViewIsDisplayed(R.id.mapView); diff --git a/platform/darwin/src/MGLSymbolStyleLayer.h b/platform/darwin/src/MGLSymbolStyleLayer.h index 6d2cb18f50d..2c32b36c315 100644 --- a/platform/darwin/src/MGLSymbolStyleLayer.h +++ b/platform/darwin/src/MGLSymbolStyleLayer.h @@ -344,8 +344,18 @@ MGL_EXPORT You can set this property to an instance of: * `MGLConstantStyleValue` - * `MGLCameraStyleFunction` with an interpolation mode of - `MGLInterpolationModeInterval` + * `MGLCameraStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLSourceStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLInterpolationModeCategorical` + * `MGLInterpolationModeIdentity` + * `MGLCompositeStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLInterpolationModeCategorical` */ @property (nonatomic, null_resettable) MGLStyleValue *iconImageName; diff --git a/platform/darwin/src/MGLSymbolStyleLayer.mm b/platform/darwin/src/MGLSymbolStyleLayer.mm index b5179095742..c01877f8dc5 100644 --- a/platform/darwin/src/MGLSymbolStyleLayer.mm +++ b/platform/darwin/src/MGLSymbolStyleLayer.mm @@ -240,7 +240,7 @@ - (void)setIconIgnorePlacement:(MGLStyleValue *)iconIgnorePlacement - (void)setIconImageName:(MGLStyleValue *)iconImageName { MGLAssertStyleLayerIsValid(); - auto mbglValue = MGLStyleValueTransformer().toPropertyValue(iconImageName); + auto mbglValue = MGLStyleValueTransformer().toDataDrivenPropertyValue(iconImageName); self.rawLayer->setIconImage(mbglValue); } @@ -249,9 +249,9 @@ - (void)setIconImageName:(MGLStyleValue *)iconImageName { auto propertyValue = self.rawLayer->getIconImage(); if (propertyValue.isUndefined()) { - return MGLStyleValueTransformer().toStyleValue(self.rawLayer->getDefaultIconImage()); + return MGLStyleValueTransformer().toDataDrivenStyleValue(self.rawLayer->getDefaultIconImage()); } - return MGLStyleValueTransformer().toStyleValue(propertyValue); + return MGLStyleValueTransformer().toDataDrivenStyleValue(propertyValue); } - (void)setIconImage:(MGLStyleValue *)iconImage { diff --git a/platform/darwin/test/MGLSymbolStyleLayerTests.mm b/platform/darwin/test/MGLSymbolStyleLayerTests.mm index c967be611d6..eee61dd5d79 100644 --- a/platform/darwin/test/MGLSymbolStyleLayerTests.mm +++ b/platform/darwin/test/MGLSymbolStyleLayerTests.mm @@ -134,7 +134,7 @@ - (void)testProperties { MGLStyleValue *constantStyleValue = [MGLStyleValue valueWithRawValue:@"Icon Image"]; layer.iconImageName = constantStyleValue; - mbgl::style::PropertyValue propertyValue = { "Icon Image" }; + mbgl::style::DataDrivenPropertyValue propertyValue = { "Icon Image" }; XCTAssertEqual(rawLayer->getIconImage(), propertyValue, @"Setting iconImageName to a constant value should update icon-image."); XCTAssertEqualObjects(layer.iconImageName, constantStyleValue, @@ -158,11 +158,6 @@ - (void)testProperties { @"Unsetting iconImageName should return icon-image to the default value."); XCTAssertEqualObjects(layer.iconImageName, defaultStyleValue, @"iconImageName should return the default value after being unset."); - - functionStyleValue = [MGLStyleValue valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil]; - XCTAssertThrowsSpecificNamed(layer.iconImageName = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it"); - functionStyleValue = [MGLStyleValue valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil]; - XCTAssertThrowsSpecificNamed(layer.iconImageName = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it"); } // icon-offset diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp index 7b77bdaf6fc..ad58f063118 100644 --- a/src/mbgl/layout/symbol_layout.cpp +++ b/src/mbgl/layout/symbol_layout.cpp @@ -30,6 +30,14 @@ namespace mbgl { using namespace style; +template +static bool has(const style::SymbolLayoutProperties::PossiblyEvaluated& layout) { + return layout.get().match( + [&] (const std::string& s) { return !s.empty(); }, + [&] (const auto&) { return true; } + ); +} + SymbolLayout::SymbolLayout(const BucketParameters& parameters, const std::vector& layers, const GeometryTileLayer& sourceLayer, @@ -72,15 +80,9 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters, layout.get() = leader.layout.evaluate(PropertyEvaluationParameters(zoom + 1)); layout.get() = leader.layout.evaluate(PropertyEvaluationParameters(zoom + 1)); - - const bool hasTextField = layout.get().match( - [&] (const std::string& s) { return !s.empty(); }, - [&] (const auto&) { return true; } - ); - - const bool hasText = !layout.get().empty() && hasTextField; - const bool hasIcon = !layout.get().empty(); + const bool hasText = has(layout) && !layout.get().empty(); + const bool hasIcon = has(layout); if (!hasText && !hasIcon) { return; @@ -147,7 +149,11 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters, } if (hasIcon) { - ft.icon = util::replaceTokens(layout.get(), getValue); + std::string icon = layout.evaluate(zoom, ft); + if (layout.get().isConstant()) { + icon = util::replaceTokens(icon, getValue); + } + ft.icon = icon; } if (ft.text || ft.icon) { @@ -165,16 +171,11 @@ bool SymbolLayout::hasSymbolInstances() const { } bool SymbolLayout::canPrepare(GlyphAtlas& glyphAtlas) { - const bool hasTextField = layout.get().match( - [&] (const std::string& s) { return !s.empty(); }, - [&] (const auto&) { return true; } - ); - - if (hasTextField && !layout.get().empty() && !glyphAtlas.hasGlyphRanges(layout.get(), ranges)) { + if (has(layout) && !layout.get().empty() && !glyphAtlas.hasGlyphRanges(layout.get(), ranges)) { return false; } - if (!layout.get().empty() && !spriteAtlas.isLoaded()) { + if (has(layout) && !spriteAtlas.isLoaded()) { return false; } diff --git a/src/mbgl/style/layers/symbol_layer.cpp b/src/mbgl/style/layers/symbol_layer.cpp index 3a896d4c933..bd5cf30ad67 100644 --- a/src/mbgl/style/layers/symbol_layer.cpp +++ b/src/mbgl/style/layers/symbol_layer.cpp @@ -203,15 +203,15 @@ void SymbolLayer::setIconTextFitPadding(PropertyValue> valu impl->layout.unevaluated.get() = value; impl->observer->onLayerLayoutPropertyChanged(*this, "icon-text-fit-padding"); } -PropertyValue SymbolLayer::getDefaultIconImage() { +DataDrivenPropertyValue SymbolLayer::getDefaultIconImage() { return IconImage::defaultValue(); } -PropertyValue SymbolLayer::getIconImage() const { +DataDrivenPropertyValue SymbolLayer::getIconImage() const { return impl->layout.unevaluated.get(); } -void SymbolLayer::setIconImage(PropertyValue value) { +void SymbolLayer::setIconImage(DataDrivenPropertyValue value) { if (value == getIconImage()) return; impl->layout.unevaluated.get() = value; diff --git a/src/mbgl/style/layers/symbol_layer_properties.hpp b/src/mbgl/style/layers/symbol_layer_properties.hpp index 4e4c64eec9e..4f63ed419aa 100644 --- a/src/mbgl/style/layers/symbol_layer_properties.hpp +++ b/src/mbgl/style/layers/symbol_layer_properties.hpp @@ -60,7 +60,7 @@ struct IconTextFitPadding : LayoutProperty> { static std::array defaultValue() { return {{ 0, 0, 0, 0 }}; } }; -struct IconImage : LayoutProperty { +struct IconImage : DataDrivenLayoutProperty { static constexpr const char * key = "icon-image"; static std::string defaultValue() { return ""; } };