diff options
11 files changed, 158 insertions, 23 deletions
diff --git a/include/mbgl/style/conversion/make_property_setters.hpp b/include/mbgl/style/conversion/make_property_setters.hpp index 2f26fe75c4..78c2fabebc 100644 --- a/include/mbgl/style/conversion/make_property_setters.hpp +++ b/include/mbgl/style/conversion/make_property_setters.hpp @@ -56,7 +56,7 @@ auto makeLayoutPropertySetters() { 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-rotate"] = &setLayoutProperty<V, SymbolLayer, DataDrivenPropertyValue<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>; diff --git a/include/mbgl/style/layers/symbol_layer.hpp b/include/mbgl/style/layers/symbol_layer.hpp index b507c992f5..23bdf303b6 100644 --- a/include/mbgl/style/layers/symbol_layer.hpp +++ b/include/mbgl/style/layers/symbol_layer.hpp @@ -135,9 +135,9 @@ public: PropertyValue<float> getTextMaxAngle() const; void setTextMaxAngle(PropertyValue<float>); - static PropertyValue<float> getDefaultTextRotate(); - PropertyValue<float> getTextRotate() const; - void setTextRotate(PropertyValue<float>); + static DataDrivenPropertyValue<float> getDefaultTextRotate(); + DataDrivenPropertyValue<float> getTextRotate() const; + void setTextRotate(DataDrivenPropertyValue<float>); static PropertyValue<float> getDefaultTextPadding(); PropertyValue<float> getTextPadding() const; diff --git a/mapbox-gl-js b/mapbox-gl-js -Subproject c34b6e9bc4a2672c1046267408f1055271484b2 +Subproject fac47099c295912f3ac1ba422415b1c46ba7340 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 ef0bd38b56..7be8e24597 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 @@ -1963,11 +1963,11 @@ public class PropertyFactory { /** * Rotates the text clockwise. * - * @param <Z> the zoom parameter type - * @param function a wrapper {@link CameraFunction} for Float + * @param <T> the function input type + * @param function a wrapper function for Float * @return property wrapper around a Float function */ - public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> textRotate(CameraFunction<Z, Float> function) { + public static <T> PropertyValue<Function<T, Float>> textRotate(Function<T, Float> function) { return new LayoutPropertyValue<>("text-rotate", 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 5472d32dc6..4c63509798 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 @@ -1294,6 +1294,114 @@ public class SymbolLayerTest extends BaseStyleTest { @Test + public void testTextRotateAsIdentitySourceFunction() { + checkViewIsDisplayed(R.id.mapView); + Timber.i("text-rotate"); + assertNotNull(layer); + + // Set + layer.setProperties( + textRotate(property("FeaturePropertyA", Stops.<Float>identity())) + ); + + // Verify + assertNotNull(layer.getTextRotate()); + assertNotNull(layer.getTextRotate().getFunction()); + assertEquals(SourceFunction.class, layer.getTextRotate().getFunction().getClass()); + assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextRotate().getFunction()).getProperty()); + assertEquals(IdentityStops.class, layer.getTextRotate().getFunction().getStops().getClass()); + } + + @Test + public void testTextRotateAsExponentialSourceFunction() { + checkViewIsDisplayed(R.id.mapView); + Timber.i("text-rotate"); + assertNotNull(layer); + + // Set + layer.setProperties( + textRotate( + property( + "FeaturePropertyA", + exponential( + stop(0.3f, textRotate(0.3f)) + ).withBase(0.5f) + ) + ) + ); + + // Verify + assertNotNull(layer.getTextRotate()); + assertNotNull(layer.getTextRotate().getFunction()); + assertEquals(SourceFunction.class, layer.getTextRotate().getFunction().getClass()); + assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextRotate().getFunction()).getProperty()); + assertEquals(ExponentialStops.class, layer.getTextRotate().getFunction().getStops().getClass()); + } + + @Test + public void testTextRotateAsCategoricalSourceFunction() { + checkViewIsDisplayed(R.id.mapView); + Timber.i("text-rotate"); + assertNotNull(layer); + + // Set + layer.setProperties( + textRotate( + property( + "FeaturePropertyA", + categorical( + stop(1.0f, textRotate(0.3f)) + ) + ).withDefaultValue(textRotate(0.3f)) + ) + ); + + // Verify + assertNotNull(layer.getTextRotate()); + assertNotNull(layer.getTextRotate().getFunction()); + assertEquals(SourceFunction.class, layer.getTextRotate().getFunction().getClass()); + assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextRotate().getFunction()).getProperty()); + assertEquals(CategoricalStops.class, layer.getTextRotate().getFunction().getStops().getClass()); + assertNotNull(((SourceFunction) layer.getTextRotate().getFunction()).getDefaultValue()); + assertNotNull(((SourceFunction) layer.getTextRotate().getFunction()).getDefaultValue().getValue()); + assertEquals(0.3f, ((SourceFunction) layer.getTextRotate().getFunction()).getDefaultValue().getValue()); + } + + @Test + public void testTextRotateAsCompositeFunction() { + checkViewIsDisplayed(R.id.mapView); + Timber.i("text-rotate"); + assertNotNull(layer); + + // Set + layer.setProperties( + textRotate( + composite( + "FeaturePropertyA", + exponential( + stop(0, 0.3f, textRotate(0.9f)) + ).withBase(0.5f) + ).withDefaultValue(textRotate(0.3f)) + ) + ); + + // Verify + assertNotNull(layer.getTextRotate()); + assertNotNull(layer.getTextRotate().getFunction()); + assertEquals(CompositeFunction.class, layer.getTextRotate().getFunction().getClass()); + assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getTextRotate().getFunction()).getProperty()); + assertEquals(ExponentialStops.class, layer.getTextRotate().getFunction().getStops().getClass()); + assertEquals(1, ((ExponentialStops) layer.getTextRotate().getFunction().getStops()).size()); + + ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops = + (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getTextRotate().getFunction().getStops(); + Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next(); + assertEquals(0f, stop.in.zoom, 0.001); + assertEquals(0.3f, stop.in.value, 0.001f); + assertEquals(0.9f, stop.out, 0.001f); + } + + @Test public void testTextPaddingAsConstant() { checkViewIsDisplayed(R.id.mapView); Timber.i("text-padding"); diff --git a/platform/darwin/src/MGLSymbolStyleLayer.h b/platform/darwin/src/MGLSymbolStyleLayer.h index 11dc67b458..6d2cb18f50 100644 --- a/platform/darwin/src/MGLSymbolStyleLayer.h +++ b/platform/darwin/src/MGLSymbolStyleLayer.h @@ -1150,6 +1150,15 @@ MGL_EXPORT * `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<NSNumber *> *textRotation; diff --git a/platform/darwin/src/MGLSymbolStyleLayer.mm b/platform/darwin/src/MGLSymbolStyleLayer.mm index 6e35bf5dd2..b517909574 100644 --- a/platform/darwin/src/MGLSymbolStyleLayer.mm +++ b/platform/darwin/src/MGLSymbolStyleLayer.mm @@ -831,7 +831,7 @@ namespace mbgl { - (void)setTextRotation:(MGLStyleValue<NSNumber *> *)textRotation { MGLAssertStyleLayerIsValid(); - auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(textRotation); + auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenPropertyValue(textRotation); self.rawLayer->setTextRotate(mbglValue); } @@ -840,9 +840,9 @@ namespace mbgl { auto propertyValue = self.rawLayer->getTextRotate(); if (propertyValue.isUndefined()) { - return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultTextRotate()); + return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(self.rawLayer->getDefaultTextRotate()); } - return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue); + return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(propertyValue); } - (void)setTextRotate:(MGLStyleValue<NSNumber *> *)textRotate { diff --git a/platform/darwin/test/MGLSymbolStyleLayerTests.mm b/platform/darwin/test/MGLSymbolStyleLayerTests.mm index 18dfa1366f..c967be611d 100644 --- a/platform/darwin/test/MGLSymbolStyleLayerTests.mm +++ b/platform/darwin/test/MGLSymbolStyleLayerTests.mm @@ -1332,7 +1332,7 @@ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff]; layer.textRotation = constantStyleValue; - mbgl::style::PropertyValue<float> propertyValue = { 0xff }; + mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff }; XCTAssertEqual(rawLayer->getTextRotate(), propertyValue, @"Setting textRotation to a constant value should update text-rotate."); XCTAssertEqualObjects(layer.textRotation, constantStyleValue, @@ -1349,6 +1349,29 @@ XCTAssertEqualObjects(layer.textRotation, functionStyleValue, @"textRotation should round-trip camera functions."); + functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil]; + layer.textRotation = functionStyleValue; + + mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 }; + propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops }; + + XCTAssertEqual(rawLayer->getTextRotate(), propertyValue, + @"Setting textRotation to a source function should update text-rotate."); + XCTAssertEqualObjects(layer.textRotation, functionStyleValue, + @"textRotation should round-trip source functions."); + + functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil]; + layer.textRotation = functionStyleValue; + + std::map<float, float> innerStops { {18, 0xff} }; + mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 }; + + propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops }; + + XCTAssertEqual(rawLayer->getTextRotate(), propertyValue, + @"Setting textRotation to a composite function should update text-rotate."); + XCTAssertEqualObjects(layer.textRotation, functionStyleValue, + @"textRotation should round-trip composite functions."); layer.textRotation = nil; @@ -1356,11 +1379,6 @@ @"Unsetting textRotation should return text-rotate to the default value."); XCTAssertEqualObjects(layer.textRotation, defaultStyleValue, @"textRotation should return the default value after being unset."); - - functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil]; - XCTAssertThrowsSpecificNamed(layer.textRotation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it"); - functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil]; - XCTAssertThrowsSpecificNamed(layer.textRotation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it"); } // text-rotation-alignment diff --git a/src/mbgl/style/layers/symbol_layer.cpp b/src/mbgl/style/layers/symbol_layer.cpp index 02e1e364f1..3a896d4c93 100644 --- a/src/mbgl/style/layers/symbol_layer.cpp +++ b/src/mbgl/style/layers/symbol_layer.cpp @@ -427,15 +427,15 @@ void SymbolLayer::setTextMaxAngle(PropertyValue<float> value) { impl->layout.unevaluated.get<TextMaxAngle>() = value; impl->observer->onLayerLayoutPropertyChanged(*this, "text-max-angle"); } -PropertyValue<float> SymbolLayer::getDefaultTextRotate() { +DataDrivenPropertyValue<float> SymbolLayer::getDefaultTextRotate() { return TextRotate::defaultValue(); } -PropertyValue<float> SymbolLayer::getTextRotate() const { +DataDrivenPropertyValue<float> SymbolLayer::getTextRotate() const { return impl->layout.unevaluated.get<TextRotate>(); } -void SymbolLayer::setTextRotate(PropertyValue<float> value) { +void SymbolLayer::setTextRotate(DataDrivenPropertyValue<float> value) { if (value == getTextRotate()) return; impl->layout.unevaluated.get<TextRotate>() = value; diff --git a/src/mbgl/style/layers/symbol_layer_properties.hpp b/src/mbgl/style/layers/symbol_layer_properties.hpp index e7cfb8d455..4e4c64eec9 100644 --- a/src/mbgl/style/layers/symbol_layer_properties.hpp +++ b/src/mbgl/style/layers/symbol_layer_properties.hpp @@ -140,7 +140,7 @@ struct TextMaxAngle : LayoutProperty<float> { static float defaultValue() { return 45; } }; -struct TextRotate : LayoutProperty<float> { +struct TextRotate : DataDrivenLayoutProperty<float> { static constexpr const char * key = "text-rotate"; static float defaultValue() { return 0; } }; diff --git a/src/mbgl/style/layout_property.hpp b/src/mbgl/style/layout_property.hpp index 624ff2bdc5..e2137deb9f 100644 --- a/src/mbgl/style/layout_property.hpp +++ b/src/mbgl/style/layout_property.hpp @@ -40,14 +40,14 @@ public: /* For layout properties we implement a two step evaluation process: if you have a zoom level, you can evaluate a set of unevaluated property values, producing a set of possibly evaluated - values, where non-data-driven property values have been fully evaluated, and data-driven values - have not. + values, where undefined, constant, or camera function values have been fully evaluated, and + source or composite function values have not. Once you also have a particular feature, you can evaluate that set of possibly evaluated values fully, producing a set of fully evaluated values. This is in theory maximally efficient in terms of avoiding repeated evaluation of camera - functions, though it's more of a historical accident that a purposeful optimization. + functions, though it's more of a historical accident than a purposeful optimization. */ using UnevaluatedTypes = TypeList<typename Ps::UnevaluatedType...>; |