summaryrefslogtreecommitdiff
path: root/platform/darwin/test
diff options
context:
space:
mode:
Diffstat (limited to 'platform/darwin/test')
-rw-r--r--platform/darwin/test/MGLAttributionInfoTests.m10
-rw-r--r--platform/darwin/test/MGLBackgroundStyleLayerTests.mm129
-rw-r--r--platform/darwin/test/MGLCircleStyleLayerTests.mm568
-rw-r--r--platform/darwin/test/MGLComputedShapeSourceTests.m24
-rw-r--r--platform/darwin/test/MGLDocumentationExampleTests.swift157
-rw-r--r--platform/darwin/test/MGLDocumentationGuideTests.swift242
-rw-r--r--platform/darwin/test/MGLExpressionTests.mm955
-rw-r--r--platform/darwin/test/MGLFeatureTests.mm33
-rw-r--r--platform/darwin/test/MGLFillExtrusionStyleLayerTests.mm344
-rw-r--r--platform/darwin/test/MGLFillStyleLayerTests.mm344
-rw-r--r--platform/darwin/test/MGLGeometryTests.mm9
-rw-r--r--platform/darwin/test/MGLHeatmapColorTests.mm62
-rw-r--r--platform/darwin/test/MGLHeatmapStyleLayerTests.mm300
-rw-r--r--platform/darwin/test/MGLHillshadeStyleLayerTests.mm348
-rw-r--r--platform/darwin/test/MGLLightTest.mm49
-rw-r--r--platform/darwin/test/MGLLightTest.mm.ejs17
-rw-r--r--platform/darwin/test/MGLLineStyleLayerTests.mm675
-rw-r--r--platform/darwin/test/MGLNSStringAdditionsTests.m26
-rw-r--r--platform/darwin/test/MGLPredicateTests.mm696
-rw-r--r--platform/darwin/test/MGLRasterStyleLayerTests.mm310
-rw-r--r--platform/darwin/test/MGLSDKTestHelpers.swift18
-rw-r--r--platform/darwin/test/MGLShapeSourceTests.mm3
-rw-r--r--platform/darwin/test/MGLSourceQueryTests.m4
-rw-r--r--platform/darwin/test/MGLStyleLayerTests.h5
-rw-r--r--platform/darwin/test/MGLStyleLayerTests.m4
-rw-r--r--platform/darwin/test/MGLStyleLayerTests.mm.ejs73
-rw-r--r--platform/darwin/test/MGLStyleTests.mm154
-rw-r--r--platform/darwin/test/MGLStyleValueTests.h4
-rw-r--r--platform/darwin/test/MGLStyleValueTests.m113
-rw-r--r--platform/darwin/test/MGLStyleValueTests.swift362
-rw-r--r--platform/darwin/test/MGLSymbolStyleLayerTests.mm2332
-rw-r--r--platform/darwin/test/MGLTileSetTests.mm29
-rw-r--r--platform/darwin/test/test-Bridging-Header.h2
33 files changed, 5170 insertions, 3231 deletions
diff --git a/platform/darwin/test/MGLAttributionInfoTests.m b/platform/darwin/test/MGLAttributionInfoTests.m
index ed4927d44b..5961b61133 100644
--- a/platform/darwin/test/MGLAttributionInfoTests.m
+++ b/platform/darwin/test/MGLAttributionInfoTests.m
@@ -17,7 +17,7 @@
@"<a class=\"mapbox-improve-map\" href=\"https://www.mapbox.com/map-feedback/\" target=\"_blank\">Improve this map</a>",
};
- NS_MUTABLE_ARRAY_OF(MGLAttributionInfo *) *infos = [NSMutableArray array];
+ NSMutableArray<MGLAttributionInfo *> *infos = [NSMutableArray array];
for (NSUInteger i = 0; i < sizeof(htmlStrings) / sizeof(htmlStrings[0]); i++) {
NSArray *subinfos = [MGLAttributionInfo attributionInfosFromHTMLString:htmlStrings[i]
fontSize:0
@@ -51,12 +51,12 @@
XCTAssertEqualObjects([infos[3] feedbackURLAtCenterCoordinate:mapbox zoomLevel:14],
[NSURL URLWithString:@"https://www.mapbox.com/feedback/?referrer=com.mapbox.sdk.ios#/77.63680/12.98108/14.00/0.0/0"]);
XCTAssertEqualObjects([infos[3] feedbackURLForStyleURL:styleURL atCenterCoordinate:mapbox zoomLevel:3.14159 direction:90.9 pitch:12.5],
- [NSURL URLWithString:@"https://www.mapbox.com/feedback/?referrer=com.mapbox.sdk.ios&owner=mapbox&id=satellite-streets-v99&access_token#/77.63680/12.98108/3.14/90.9/13"]);
+ [NSURL URLWithString:@"https://www.mapbox.com/feedback/?referrer=com.mapbox.sdk.ios&owner=mapbox&id=satellite-streets-v99&access_token&map_sdk_version=1.0.0#/77.63680/12.98108/3.14/90.9/13"]);
#else
XCTAssertEqualObjects([infos[3] feedbackURLAtCenterCoordinate:mapbox zoomLevel:14],
[NSURL URLWithString:@"https://www.mapbox.com/feedback/?referrer=com.mapbox.MapboxGL#/77.63680/12.98108/14.00/0.0/0"]);
XCTAssertEqualObjects([infos[3] feedbackURLForStyleURL:styleURL atCenterCoordinate:mapbox zoomLevel:3.14159 direction:90.9 pitch:12.5],
- [NSURL URLWithString:@"https://www.mapbox.com/feedback/?referrer=com.mapbox.MapboxGL&owner=mapbox&id=satellite-streets-v99&access_token#/77.63680/12.98108/3.14/90.9/13"]);
+ [NSURL URLWithString:@"https://www.mapbox.com/feedback/?referrer=com.mapbox.MapboxGL&owner=mapbox&id=satellite-streets-v99&access_token&map_sdk_version=1.0.0#/77.63680/12.98108/3.14/90.9/13"]);
#endif
}
@@ -67,7 +67,7 @@
CGFloat fontSize = 72;
MGLColor *color = [MGLColor redColor];
- NS_MUTABLE_ARRAY_OF(MGLAttributionInfo *) *infos = [NSMutableArray array];
+ NSMutableArray<MGLAttributionInfo *> *infos = [NSMutableArray array];
for (NSUInteger i = 0; i < sizeof(htmlStrings) / sizeof(htmlStrings[0]); i++) {
NSArray *subinfos = [MGLAttributionInfo attributionInfosFromHTMLString:htmlStrings[i]
fontSize:72
@@ -109,7 +109,7 @@
@"Hello World",
};
- NS_MUTABLE_ARRAY_OF(MGLAttributionInfo *) *infos = [NSMutableArray array];
+ NSMutableArray<MGLAttributionInfo *> *infos = [NSMutableArray array];
for (NSUInteger i = 0; i < sizeof(htmlStrings) / sizeof(htmlStrings[0]); i++) {
NSArray *subinfos = [MGLAttributionInfo attributionInfosFromHTMLString:htmlStrings[i]
fontSize:0
diff --git a/platform/darwin/test/MGLBackgroundStyleLayerTests.mm b/platform/darwin/test/MGLBackgroundStyleLayerTests.mm
index c96a4fe7fa..de8080f425 100644
--- a/platform/darwin/test/MGLBackgroundStyleLayerTests.mm
+++ b/platform/darwin/test/MGLBackgroundStyleLayerTests.mm
@@ -31,39 +31,44 @@
{
XCTAssertTrue(rawLayer->getBackgroundColor().isUndefined(),
@"background-color should be unset initially.");
- MGLStyleValue<MGLColor *> *defaultStyleValue = layer.backgroundColor;
+ NSExpression *defaultExpression = layer.backgroundColor;
- MGLStyleValue<MGLColor *> *constantStyleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
- layer.backgroundColor = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ layer.backgroundColor = constantExpression;
mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getBackgroundColor(), propertyValue,
- @"Setting backgroundColor to a constant value should update background-color.");
- XCTAssertEqualObjects(layer.backgroundColor, constantStyleValue,
- @"backgroundColor should round-trip constant values.");
-
- MGLStyleValue<MGLColor *> * functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.backgroundColor = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::Color> intervalStops = { {{18, { 1, 0, 0, 1 }}} };
+ @"Setting backgroundColor to a constant value expression should update background-color.");
+ XCTAssertEqualObjects(layer.backgroundColor, constantExpression,
+ @"backgroundColor should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.backgroundColor = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::Color> intervalStops = {{
+ { -INFINITY, { 1, 0, 0, 1 } },
+ { 18, { 1, 0, 0, 1 } },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::Color> { intervalStops };
XCTAssertEqual(rawLayer->getBackgroundColor(), propertyValue,
- @"Setting backgroundColor to a camera function should update background-color.");
- XCTAssertEqualObjects(layer.backgroundColor, functionStyleValue,
- @"backgroundColor should round-trip camera functions.");
+ @"Setting backgroundColor to a camera expression should update background-color.");
+ XCTAssertEqualObjects(layer.backgroundColor, functionExpression,
+ @"backgroundColor should round-trip camera expressions.");
layer.backgroundColor = nil;
XCTAssertTrue(rawLayer->getBackgroundColor().isUndefined(),
@"Unsetting backgroundColor should return background-color to the default value.");
- XCTAssertEqualObjects(layer.backgroundColor, defaultStyleValue,
+ XCTAssertEqualObjects(layer.backgroundColor, defaultExpression,
@"backgroundColor should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.backgroundColor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.backgroundColor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.backgroundColor = functionExpression, NSException, NSInvalidArgumentException, @"MGLBackgroundLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.backgroundColor = functionExpression, NSException, NSInvalidArgumentException, @"MGLBackgroundLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
// Transition property test
layer.backgroundColorTransition = transitionTest;
auto toptions = rawLayer->getBackgroundColorTransition();
@@ -79,39 +84,44 @@
{
XCTAssertTrue(rawLayer->getBackgroundOpacity().isUndefined(),
@"background-opacity should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.backgroundOpacity;
+ NSExpression *defaultExpression = layer.backgroundOpacity;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.backgroundOpacity = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.backgroundOpacity = constantExpression;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getBackgroundOpacity(), propertyValue,
- @"Setting backgroundOpacity to a constant value should update background-opacity.");
- XCTAssertEqualObjects(layer.backgroundOpacity, constantStyleValue,
- @"backgroundOpacity should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.backgroundOpacity = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting backgroundOpacity to a constant value expression should update background-opacity.");
+ XCTAssertEqualObjects(layer.backgroundOpacity, constantExpression,
+ @"backgroundOpacity should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.backgroundOpacity = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getBackgroundOpacity(), propertyValue,
- @"Setting backgroundOpacity to a camera function should update background-opacity.");
- XCTAssertEqualObjects(layer.backgroundOpacity, functionStyleValue,
- @"backgroundOpacity should round-trip camera functions.");
+ @"Setting backgroundOpacity to a camera expression should update background-opacity.");
+ XCTAssertEqualObjects(layer.backgroundOpacity, functionExpression,
+ @"backgroundOpacity should round-trip camera expressions.");
layer.backgroundOpacity = nil;
XCTAssertTrue(rawLayer->getBackgroundOpacity().isUndefined(),
@"Unsetting backgroundOpacity should return background-opacity to the default value.");
- XCTAssertEqualObjects(layer.backgroundOpacity, defaultStyleValue,
+ XCTAssertEqualObjects(layer.backgroundOpacity, defaultExpression,
@"backgroundOpacity should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.backgroundOpacity = 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.backgroundOpacity = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.backgroundOpacity = functionExpression, NSException, NSInvalidArgumentException, @"MGLBackgroundLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.backgroundOpacity = functionExpression, NSException, NSInvalidArgumentException, @"MGLBackgroundLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
// Transition property test
layer.backgroundOpacityTransition = transitionTest;
auto toptions = rawLayer->getBackgroundOpacityTransition();
@@ -127,39 +137,44 @@
{
XCTAssertTrue(rawLayer->getBackgroundPattern().isUndefined(),
@"background-pattern should be unset initially.");
- MGLStyleValue<NSString *> *defaultStyleValue = layer.backgroundPattern;
+ NSExpression *defaultExpression = layer.backgroundPattern;
- MGLStyleValue<NSString *> *constantStyleValue = [MGLStyleValue<NSString *> valueWithRawValue:@"Background Pattern"];
- layer.backgroundPattern = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'Background Pattern'"];
+ layer.backgroundPattern = constantExpression;
mbgl::style::PropertyValue<std::string> propertyValue = { "Background Pattern" };
XCTAssertEqual(rawLayer->getBackgroundPattern(), propertyValue,
- @"Setting backgroundPattern to a constant value should update background-pattern.");
- XCTAssertEqualObjects(layer.backgroundPattern, constantStyleValue,
- @"backgroundPattern should round-trip constant values.");
-
- MGLStyleValue<NSString *> * functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.backgroundPattern = functionStyleValue;
-
- mbgl::style::IntervalStops<std::string> intervalStops = { {{18, "Background Pattern"}} };
+ @"Setting backgroundPattern to a constant value expression should update background-pattern.");
+ XCTAssertEqualObjects(layer.backgroundPattern, constantExpression,
+ @"backgroundPattern should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"'Background Pattern'"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.backgroundPattern = functionExpression;
+
+ mbgl::style::IntervalStops<std::string> intervalStops = {{
+ { -INFINITY, "Background Pattern" },
+ { 18, "Background Pattern" },
+ }};
propertyValue = mbgl::style::CameraFunction<std::string> { intervalStops };
XCTAssertEqual(rawLayer->getBackgroundPattern(), propertyValue,
- @"Setting backgroundPattern to a camera function should update background-pattern.");
- XCTAssertEqualObjects(layer.backgroundPattern, functionStyleValue,
- @"backgroundPattern should round-trip camera functions.");
+ @"Setting backgroundPattern to a camera expression should update background-pattern.");
+ XCTAssertEqualObjects(layer.backgroundPattern, functionExpression,
+ @"backgroundPattern should round-trip camera expressions.");
layer.backgroundPattern = nil;
XCTAssertTrue(rawLayer->getBackgroundPattern().isUndefined(),
@"Unsetting backgroundPattern should return background-pattern to the default value.");
- XCTAssertEqualObjects(layer.backgroundPattern, defaultStyleValue,
+ XCTAssertEqualObjects(layer.backgroundPattern, defaultExpression,
@"backgroundPattern should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.backgroundPattern = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.backgroundPattern = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.backgroundPattern = functionExpression, NSException, NSInvalidArgumentException, @"MGLBackgroundLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.backgroundPattern = functionExpression, NSException, NSInvalidArgumentException, @"MGLBackgroundLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
// Transition property test
layer.backgroundPatternTransition = transitionTest;
auto toptions = rawLayer->getBackgroundPatternTransition();
diff --git a/platform/darwin/test/MGLCircleStyleLayerTests.mm b/platform/darwin/test/MGLCircleStyleLayerTests.mm
index c0c503153a..d7bf2a5afd 100644
--- a/platform/darwin/test/MGLCircleStyleLayerTests.mm
+++ b/platform/darwin/test/MGLCircleStyleLayerTests.mm
@@ -30,8 +30,8 @@
XCTAssertNil(layer.sourceLayerIdentifier);
XCTAssertNil(layer.predicate);
- layer.predicate = [NSPredicate predicateWithValue:NO];
- XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithValue:NO]);
+ layer.predicate = [NSPredicate predicateWithFormat:@"$featureIdentifier = 1"];
+ XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithFormat:@"$featureIdentifier = 1"]);
layer.predicate = nil;
XCTAssertNil(layer.predicate);
}
@@ -52,40 +52,45 @@
{
XCTAssertTrue(rawLayer->getCircleBlur().isUndefined(),
@"circle-blur should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.circleBlur;
+ NSExpression *defaultExpression = layer.circleBlur;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.circleBlur = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.circleBlur = constantExpression;
mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getCircleBlur(), propertyValue,
- @"Setting circleBlur to a constant value should update circle-blur.");
- XCTAssertEqualObjects(layer.circleBlur, constantStyleValue,
- @"circleBlur should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.circleBlur = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting circleBlur to a constant value expression should update circle-blur.");
+ XCTAssertEqualObjects(layer.circleBlur, constantExpression,
+ @"circleBlur should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.circleBlur = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getCircleBlur(), propertyValue,
- @"Setting circleBlur to a camera function should update circle-blur.");
- XCTAssertEqualObjects(layer.circleBlur, functionStyleValue,
- @"circleBlur should round-trip camera functions.");
+ @"Setting circleBlur to a camera expression should update circle-blur.");
+ XCTAssertEqualObjects(layer.circleBlur, functionExpression,
+ @"circleBlur should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.circleBlur = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.circleBlur = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getCircleBlur(), propertyValue,
- @"Setting circleBlur to a source function should update circle-blur.");
- XCTAssertEqualObjects(layer.circleBlur, functionStyleValue,
- @"circleBlur should round-trip source functions.");
+ @"Setting circleBlur to a data expression should update circle-blur.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.circleBlur, pedanticFunctionExpression,
+ @"circleBlur should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.circleBlur = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.circleBlur = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -93,15 +98,16 @@
propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getCircleBlur(), propertyValue,
- @"Setting circleBlur to a composite function should update circle-blur.");
- XCTAssertEqualObjects(layer.circleBlur, functionStyleValue,
- @"circleBlur should round-trip composite functions.");
+ @"Setting circleBlur to a camera-data expression should update circle-blur.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.circleBlur, pedanticFunctionExpression,
+ @"circleBlur should round-trip camera-data expressions.");
layer.circleBlur = nil;
XCTAssertTrue(rawLayer->getCircleBlur().isUndefined(),
@"Unsetting circleBlur should return circle-blur to the default value.");
- XCTAssertEqualObjects(layer.circleBlur, defaultStyleValue,
+ XCTAssertEqualObjects(layer.circleBlur, defaultExpression,
@"circleBlur should return the default value after being unset.");
// Transition property test
layer.circleBlurTransition = transitionTest;
@@ -118,40 +124,45 @@
{
XCTAssertTrue(rawLayer->getCircleColor().isUndefined(),
@"circle-color should be unset initially.");
- MGLStyleValue<MGLColor *> *defaultStyleValue = layer.circleColor;
+ NSExpression *defaultExpression = layer.circleColor;
- MGLStyleValue<MGLColor *> *constantStyleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
- layer.circleColor = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ layer.circleColor = constantExpression;
mbgl::style::DataDrivenPropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getCircleColor(), propertyValue,
- @"Setting circleColor to a constant value should update circle-color.");
- XCTAssertEqualObjects(layer.circleColor, constantStyleValue,
- @"circleColor should round-trip constant values.");
-
- MGLStyleValue<MGLColor *> * functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.circleColor = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::Color> intervalStops = { {{18, { 1, 0, 0, 1 }}} };
+ @"Setting circleColor to a constant value expression should update circle-color.");
+ XCTAssertEqualObjects(layer.circleColor, constantExpression,
+ @"circleColor should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.circleColor = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::Color> intervalStops = {{
+ { -INFINITY, { 1, 0, 0, 1 } },
+ { 18, { 1, 0, 0, 1 } },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::Color> { intervalStops };
XCTAssertEqual(rawLayer->getCircleColor(), propertyValue,
- @"Setting circleColor to a camera function should update circle-color.");
- XCTAssertEqualObjects(layer.circleColor, functionStyleValue,
- @"circleColor should round-trip camera functions.");
+ @"Setting circleColor to a camera expression should update circle-color.");
+ XCTAssertEqualObjects(layer.circleColor, functionExpression,
+ @"circleColor should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.circleColor = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.circleColor = functionExpression;
mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<mbgl::Color> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getCircleColor(), propertyValue,
- @"Setting circleColor to a source function should update circle-color.");
- XCTAssertEqualObjects(layer.circleColor, functionStyleValue,
- @"circleColor should round-trip source functions.");
+ @"Setting circleColor to a data expression should update circle-color.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.circleColor, pedanticFunctionExpression,
+ @"circleColor should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.circleColor = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.circleColor = functionExpression;
std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
mbgl::style::CompositeExponentialStops<mbgl::Color> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -159,15 +170,16 @@
propertyValue = mbgl::style::CompositeFunction<mbgl::Color> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getCircleColor(), propertyValue,
- @"Setting circleColor to a composite function should update circle-color.");
- XCTAssertEqualObjects(layer.circleColor, functionStyleValue,
- @"circleColor should round-trip composite functions.");
+ @"Setting circleColor to a camera-data expression should update circle-color.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.circleColor, pedanticFunctionExpression,
+ @"circleColor should round-trip camera-data expressions.");
layer.circleColor = nil;
XCTAssertTrue(rawLayer->getCircleColor().isUndefined(),
@"Unsetting circleColor should return circle-color to the default value.");
- XCTAssertEqualObjects(layer.circleColor, defaultStyleValue,
+ XCTAssertEqualObjects(layer.circleColor, defaultExpression,
@"circleColor should return the default value after being unset.");
// Transition property test
layer.circleColorTransition = transitionTest;
@@ -184,40 +196,45 @@
{
XCTAssertTrue(rawLayer->getCircleOpacity().isUndefined(),
@"circle-opacity should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.circleOpacity;
+ NSExpression *defaultExpression = layer.circleOpacity;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.circleOpacity = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.circleOpacity = constantExpression;
mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getCircleOpacity(), propertyValue,
- @"Setting circleOpacity to a constant value should update circle-opacity.");
- XCTAssertEqualObjects(layer.circleOpacity, constantStyleValue,
- @"circleOpacity should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.circleOpacity = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting circleOpacity to a constant value expression should update circle-opacity.");
+ XCTAssertEqualObjects(layer.circleOpacity, constantExpression,
+ @"circleOpacity should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.circleOpacity = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getCircleOpacity(), propertyValue,
- @"Setting circleOpacity to a camera function should update circle-opacity.");
- XCTAssertEqualObjects(layer.circleOpacity, functionStyleValue,
- @"circleOpacity should round-trip camera functions.");
+ @"Setting circleOpacity to a camera expression should update circle-opacity.");
+ XCTAssertEqualObjects(layer.circleOpacity, functionExpression,
+ @"circleOpacity should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.circleOpacity = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.circleOpacity = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getCircleOpacity(), propertyValue,
- @"Setting circleOpacity to a source function should update circle-opacity.");
- XCTAssertEqualObjects(layer.circleOpacity, functionStyleValue,
- @"circleOpacity should round-trip source functions.");
+ @"Setting circleOpacity to a data expression should update circle-opacity.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.circleOpacity, pedanticFunctionExpression,
+ @"circleOpacity should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.circleOpacity = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.circleOpacity = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -225,15 +242,16 @@
propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getCircleOpacity(), propertyValue,
- @"Setting circleOpacity to a composite function should update circle-opacity.");
- XCTAssertEqualObjects(layer.circleOpacity, functionStyleValue,
- @"circleOpacity should round-trip composite functions.");
+ @"Setting circleOpacity to a camera-data expression should update circle-opacity.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.circleOpacity, pedanticFunctionExpression,
+ @"circleOpacity should round-trip camera-data expressions.");
layer.circleOpacity = nil;
XCTAssertTrue(rawLayer->getCircleOpacity().isUndefined(),
@"Unsetting circleOpacity should return circle-opacity to the default value.");
- XCTAssertEqualObjects(layer.circleOpacity, defaultStyleValue,
+ XCTAssertEqualObjects(layer.circleOpacity, defaultExpression,
@"circleOpacity should return the default value after being unset.");
// Transition property test
layer.circleOpacityTransition = transitionTest;
@@ -250,79 +268,89 @@
{
XCTAssertTrue(rawLayer->getCirclePitchAlignment().isUndefined(),
@"circle-pitch-alignment should be unset initially.");
- MGLStyleValue<NSValue *> *defaultStyleValue = layer.circlePitchAlignment;
+ NSExpression *defaultExpression = layer.circlePitchAlignment;
- MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLCirclePitchAlignment:MGLCirclePitchAlignmentViewport]];
- layer.circlePitchAlignment = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'viewport'"];
+ layer.circlePitchAlignment = constantExpression;
mbgl::style::PropertyValue<mbgl::style::AlignmentType> propertyValue = { mbgl::style::AlignmentType::Viewport };
XCTAssertEqual(rawLayer->getCirclePitchAlignment(), propertyValue,
- @"Setting circlePitchAlignment to a constant value should update circle-pitch-alignment.");
- XCTAssertEqualObjects(layer.circlePitchAlignment, constantStyleValue,
- @"circlePitchAlignment should round-trip constant values.");
-
- MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.circlePitchAlignment = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::style::AlignmentType> intervalStops = { {{18, mbgl::style::AlignmentType::Viewport}} };
+ @"Setting circlePitchAlignment to a constant value expression should update circle-pitch-alignment.");
+ XCTAssertEqualObjects(layer.circlePitchAlignment, constantExpression,
+ @"circlePitchAlignment should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"'viewport'"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.circlePitchAlignment = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::style::AlignmentType> intervalStops = {{
+ { -INFINITY, mbgl::style::AlignmentType::Viewport },
+ { 18, mbgl::style::AlignmentType::Viewport },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::style::AlignmentType> { intervalStops };
XCTAssertEqual(rawLayer->getCirclePitchAlignment(), propertyValue,
- @"Setting circlePitchAlignment to a camera function should update circle-pitch-alignment.");
- XCTAssertEqualObjects(layer.circlePitchAlignment, functionStyleValue,
- @"circlePitchAlignment should round-trip camera functions.");
+ @"Setting circlePitchAlignment to a camera expression should update circle-pitch-alignment.");
+ XCTAssertEqualObjects(layer.circlePitchAlignment, functionExpression,
+ @"circlePitchAlignment should round-trip camera expressions.");
layer.circlePitchAlignment = nil;
XCTAssertTrue(rawLayer->getCirclePitchAlignment().isUndefined(),
@"Unsetting circlePitchAlignment should return circle-pitch-alignment to the default value.");
- XCTAssertEqualObjects(layer.circlePitchAlignment, defaultStyleValue,
+ XCTAssertEqualObjects(layer.circlePitchAlignment, defaultExpression,
@"circlePitchAlignment should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.circlePitchAlignment = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.circlePitchAlignment = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.circlePitchAlignment = functionExpression, NSException, NSInvalidArgumentException, @"MGLCircleLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.circlePitchAlignment = functionExpression, NSException, NSInvalidArgumentException, @"MGLCircleLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// circle-radius
{
XCTAssertTrue(rawLayer->getCircleRadius().isUndefined(),
@"circle-radius should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.circleRadius;
+ NSExpression *defaultExpression = layer.circleRadius;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.circleRadius = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.circleRadius = constantExpression;
mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getCircleRadius(), propertyValue,
- @"Setting circleRadius to a constant value should update circle-radius.");
- XCTAssertEqualObjects(layer.circleRadius, constantStyleValue,
- @"circleRadius should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.circleRadius = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting circleRadius to a constant value expression should update circle-radius.");
+ XCTAssertEqualObjects(layer.circleRadius, constantExpression,
+ @"circleRadius should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.circleRadius = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getCircleRadius(), propertyValue,
- @"Setting circleRadius to a camera function should update circle-radius.");
- XCTAssertEqualObjects(layer.circleRadius, functionStyleValue,
- @"circleRadius should round-trip camera functions.");
+ @"Setting circleRadius to a camera expression should update circle-radius.");
+ XCTAssertEqualObjects(layer.circleRadius, functionExpression,
+ @"circleRadius should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.circleRadius = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.circleRadius = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getCircleRadius(), propertyValue,
- @"Setting circleRadius to a source function should update circle-radius.");
- XCTAssertEqualObjects(layer.circleRadius, functionStyleValue,
- @"circleRadius should round-trip source functions.");
+ @"Setting circleRadius to a data expression should update circle-radius.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.circleRadius, pedanticFunctionExpression,
+ @"circleRadius should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.circleRadius = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.circleRadius = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -330,15 +358,16 @@
propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getCircleRadius(), propertyValue,
- @"Setting circleRadius to a composite function should update circle-radius.");
- XCTAssertEqualObjects(layer.circleRadius, functionStyleValue,
- @"circleRadius should round-trip composite functions.");
+ @"Setting circleRadius to a camera-data expression should update circle-radius.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.circleRadius, pedanticFunctionExpression,
+ @"circleRadius should round-trip camera-data expressions.");
layer.circleRadius = nil;
XCTAssertTrue(rawLayer->getCircleRadius().isUndefined(),
@"Unsetting circleRadius should return circle-radius to the default value.");
- XCTAssertEqualObjects(layer.circleRadius, defaultStyleValue,
+ XCTAssertEqualObjects(layer.circleRadius, defaultExpression,
@"circleRadius should return the default value after being unset.");
// Transition property test
layer.circleRadiusTransition = transitionTest;
@@ -355,79 +384,89 @@
{
XCTAssertTrue(rawLayer->getCirclePitchScale().isUndefined(),
@"circle-pitch-scale should be unset initially.");
- MGLStyleValue<NSValue *> *defaultStyleValue = layer.circleScaleAlignment;
+ NSExpression *defaultExpression = layer.circleScaleAlignment;
- MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLCircleScaleAlignment:MGLCircleScaleAlignmentViewport]];
- layer.circleScaleAlignment = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'viewport'"];
+ layer.circleScaleAlignment = constantExpression;
mbgl::style::PropertyValue<mbgl::style::CirclePitchScaleType> propertyValue = { mbgl::style::CirclePitchScaleType::Viewport };
XCTAssertEqual(rawLayer->getCirclePitchScale(), propertyValue,
- @"Setting circleScaleAlignment to a constant value should update circle-pitch-scale.");
- XCTAssertEqualObjects(layer.circleScaleAlignment, constantStyleValue,
- @"circleScaleAlignment should round-trip constant values.");
-
- MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.circleScaleAlignment = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::style::CirclePitchScaleType> intervalStops = { {{18, mbgl::style::CirclePitchScaleType::Viewport}} };
+ @"Setting circleScaleAlignment to a constant value expression should update circle-pitch-scale.");
+ XCTAssertEqualObjects(layer.circleScaleAlignment, constantExpression,
+ @"circleScaleAlignment should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"'viewport'"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.circleScaleAlignment = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::style::CirclePitchScaleType> intervalStops = {{
+ { -INFINITY, mbgl::style::CirclePitchScaleType::Viewport },
+ { 18, mbgl::style::CirclePitchScaleType::Viewport },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::style::CirclePitchScaleType> { intervalStops };
XCTAssertEqual(rawLayer->getCirclePitchScale(), propertyValue,
- @"Setting circleScaleAlignment to a camera function should update circle-pitch-scale.");
- XCTAssertEqualObjects(layer.circleScaleAlignment, functionStyleValue,
- @"circleScaleAlignment should round-trip camera functions.");
+ @"Setting circleScaleAlignment to a camera expression should update circle-pitch-scale.");
+ XCTAssertEqualObjects(layer.circleScaleAlignment, functionExpression,
+ @"circleScaleAlignment should round-trip camera expressions.");
layer.circleScaleAlignment = nil;
XCTAssertTrue(rawLayer->getCirclePitchScale().isUndefined(),
@"Unsetting circleScaleAlignment should return circle-pitch-scale to the default value.");
- XCTAssertEqualObjects(layer.circleScaleAlignment, defaultStyleValue,
+ XCTAssertEqualObjects(layer.circleScaleAlignment, defaultExpression,
@"circleScaleAlignment should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.circleScaleAlignment = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.circleScaleAlignment = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.circleScaleAlignment = functionExpression, NSException, NSInvalidArgumentException, @"MGLCircleLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.circleScaleAlignment = functionExpression, NSException, NSInvalidArgumentException, @"MGLCircleLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// circle-stroke-color
{
XCTAssertTrue(rawLayer->getCircleStrokeColor().isUndefined(),
@"circle-stroke-color should be unset initially.");
- MGLStyleValue<MGLColor *> *defaultStyleValue = layer.circleStrokeColor;
+ NSExpression *defaultExpression = layer.circleStrokeColor;
- MGLStyleValue<MGLColor *> *constantStyleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
- layer.circleStrokeColor = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ layer.circleStrokeColor = constantExpression;
mbgl::style::DataDrivenPropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getCircleStrokeColor(), propertyValue,
- @"Setting circleStrokeColor to a constant value should update circle-stroke-color.");
- XCTAssertEqualObjects(layer.circleStrokeColor, constantStyleValue,
- @"circleStrokeColor should round-trip constant values.");
-
- MGLStyleValue<MGLColor *> * functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.circleStrokeColor = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::Color> intervalStops = { {{18, { 1, 0, 0, 1 }}} };
+ @"Setting circleStrokeColor to a constant value expression should update circle-stroke-color.");
+ XCTAssertEqualObjects(layer.circleStrokeColor, constantExpression,
+ @"circleStrokeColor should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.circleStrokeColor = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::Color> intervalStops = {{
+ { -INFINITY, { 1, 0, 0, 1 } },
+ { 18, { 1, 0, 0, 1 } },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::Color> { intervalStops };
XCTAssertEqual(rawLayer->getCircleStrokeColor(), propertyValue,
- @"Setting circleStrokeColor to a camera function should update circle-stroke-color.");
- XCTAssertEqualObjects(layer.circleStrokeColor, functionStyleValue,
- @"circleStrokeColor should round-trip camera functions.");
+ @"Setting circleStrokeColor to a camera expression should update circle-stroke-color.");
+ XCTAssertEqualObjects(layer.circleStrokeColor, functionExpression,
+ @"circleStrokeColor should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.circleStrokeColor = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.circleStrokeColor = functionExpression;
mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<mbgl::Color> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getCircleStrokeColor(), propertyValue,
- @"Setting circleStrokeColor to a source function should update circle-stroke-color.");
- XCTAssertEqualObjects(layer.circleStrokeColor, functionStyleValue,
- @"circleStrokeColor should round-trip source functions.");
+ @"Setting circleStrokeColor to a data expression should update circle-stroke-color.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.circleStrokeColor, pedanticFunctionExpression,
+ @"circleStrokeColor should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.circleStrokeColor = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.circleStrokeColor = functionExpression;
std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
mbgl::style::CompositeExponentialStops<mbgl::Color> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -435,15 +474,16 @@
propertyValue = mbgl::style::CompositeFunction<mbgl::Color> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getCircleStrokeColor(), propertyValue,
- @"Setting circleStrokeColor to a composite function should update circle-stroke-color.");
- XCTAssertEqualObjects(layer.circleStrokeColor, functionStyleValue,
- @"circleStrokeColor should round-trip composite functions.");
+ @"Setting circleStrokeColor to a camera-data expression should update circle-stroke-color.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.circleStrokeColor, pedanticFunctionExpression,
+ @"circleStrokeColor should round-trip camera-data expressions.");
layer.circleStrokeColor = nil;
XCTAssertTrue(rawLayer->getCircleStrokeColor().isUndefined(),
@"Unsetting circleStrokeColor should return circle-stroke-color to the default value.");
- XCTAssertEqualObjects(layer.circleStrokeColor, defaultStyleValue,
+ XCTAssertEqualObjects(layer.circleStrokeColor, defaultExpression,
@"circleStrokeColor should return the default value after being unset.");
// Transition property test
layer.circleStrokeColorTransition = transitionTest;
@@ -460,40 +500,45 @@
{
XCTAssertTrue(rawLayer->getCircleStrokeOpacity().isUndefined(),
@"circle-stroke-opacity should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.circleStrokeOpacity;
+ NSExpression *defaultExpression = layer.circleStrokeOpacity;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.circleStrokeOpacity = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.circleStrokeOpacity = constantExpression;
mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getCircleStrokeOpacity(), propertyValue,
- @"Setting circleStrokeOpacity to a constant value should update circle-stroke-opacity.");
- XCTAssertEqualObjects(layer.circleStrokeOpacity, constantStyleValue,
- @"circleStrokeOpacity should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.circleStrokeOpacity = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting circleStrokeOpacity to a constant value expression should update circle-stroke-opacity.");
+ XCTAssertEqualObjects(layer.circleStrokeOpacity, constantExpression,
+ @"circleStrokeOpacity should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.circleStrokeOpacity = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getCircleStrokeOpacity(), propertyValue,
- @"Setting circleStrokeOpacity to a camera function should update circle-stroke-opacity.");
- XCTAssertEqualObjects(layer.circleStrokeOpacity, functionStyleValue,
- @"circleStrokeOpacity should round-trip camera functions.");
+ @"Setting circleStrokeOpacity to a camera expression should update circle-stroke-opacity.");
+ XCTAssertEqualObjects(layer.circleStrokeOpacity, functionExpression,
+ @"circleStrokeOpacity should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.circleStrokeOpacity = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.circleStrokeOpacity = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getCircleStrokeOpacity(), propertyValue,
- @"Setting circleStrokeOpacity to a source function should update circle-stroke-opacity.");
- XCTAssertEqualObjects(layer.circleStrokeOpacity, functionStyleValue,
- @"circleStrokeOpacity should round-trip source functions.");
+ @"Setting circleStrokeOpacity to a data expression should update circle-stroke-opacity.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.circleStrokeOpacity, pedanticFunctionExpression,
+ @"circleStrokeOpacity should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.circleStrokeOpacity = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.circleStrokeOpacity = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -501,15 +546,16 @@
propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getCircleStrokeOpacity(), propertyValue,
- @"Setting circleStrokeOpacity to a composite function should update circle-stroke-opacity.");
- XCTAssertEqualObjects(layer.circleStrokeOpacity, functionStyleValue,
- @"circleStrokeOpacity should round-trip composite functions.");
+ @"Setting circleStrokeOpacity to a camera-data expression should update circle-stroke-opacity.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.circleStrokeOpacity, pedanticFunctionExpression,
+ @"circleStrokeOpacity should round-trip camera-data expressions.");
layer.circleStrokeOpacity = nil;
XCTAssertTrue(rawLayer->getCircleStrokeOpacity().isUndefined(),
@"Unsetting circleStrokeOpacity should return circle-stroke-opacity to the default value.");
- XCTAssertEqualObjects(layer.circleStrokeOpacity, defaultStyleValue,
+ XCTAssertEqualObjects(layer.circleStrokeOpacity, defaultExpression,
@"circleStrokeOpacity should return the default value after being unset.");
// Transition property test
layer.circleStrokeOpacityTransition = transitionTest;
@@ -526,40 +572,45 @@
{
XCTAssertTrue(rawLayer->getCircleStrokeWidth().isUndefined(),
@"circle-stroke-width should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.circleStrokeWidth;
+ NSExpression *defaultExpression = layer.circleStrokeWidth;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.circleStrokeWidth = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.circleStrokeWidth = constantExpression;
mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getCircleStrokeWidth(), propertyValue,
- @"Setting circleStrokeWidth to a constant value should update circle-stroke-width.");
- XCTAssertEqualObjects(layer.circleStrokeWidth, constantStyleValue,
- @"circleStrokeWidth should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.circleStrokeWidth = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting circleStrokeWidth to a constant value expression should update circle-stroke-width.");
+ XCTAssertEqualObjects(layer.circleStrokeWidth, constantExpression,
+ @"circleStrokeWidth should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.circleStrokeWidth = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getCircleStrokeWidth(), propertyValue,
- @"Setting circleStrokeWidth to a camera function should update circle-stroke-width.");
- XCTAssertEqualObjects(layer.circleStrokeWidth, functionStyleValue,
- @"circleStrokeWidth should round-trip camera functions.");
+ @"Setting circleStrokeWidth to a camera expression should update circle-stroke-width.");
+ XCTAssertEqualObjects(layer.circleStrokeWidth, functionExpression,
+ @"circleStrokeWidth should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.circleStrokeWidth = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.circleStrokeWidth = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getCircleStrokeWidth(), propertyValue,
- @"Setting circleStrokeWidth to a source function should update circle-stroke-width.");
- XCTAssertEqualObjects(layer.circleStrokeWidth, functionStyleValue,
- @"circleStrokeWidth should round-trip source functions.");
+ @"Setting circleStrokeWidth to a data expression should update circle-stroke-width.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.circleStrokeWidth, pedanticFunctionExpression,
+ @"circleStrokeWidth should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.circleStrokeWidth = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.circleStrokeWidth = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -567,15 +618,16 @@
propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getCircleStrokeWidth(), propertyValue,
- @"Setting circleStrokeWidth to a composite function should update circle-stroke-width.");
- XCTAssertEqualObjects(layer.circleStrokeWidth, functionStyleValue,
- @"circleStrokeWidth should round-trip composite functions.");
+ @"Setting circleStrokeWidth to a camera-data expression should update circle-stroke-width.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.circleStrokeWidth, pedanticFunctionExpression,
+ @"circleStrokeWidth should round-trip camera-data expressions.");
layer.circleStrokeWidth = nil;
XCTAssertTrue(rawLayer->getCircleStrokeWidth().isUndefined(),
@"Unsetting circleStrokeWidth should return circle-stroke-width to the default value.");
- XCTAssertEqualObjects(layer.circleStrokeWidth, defaultStyleValue,
+ XCTAssertEqualObjects(layer.circleStrokeWidth, defaultExpression,
@"circleStrokeWidth should return the default value after being unset.");
// Transition property test
layer.circleStrokeWidthTransition = transitionTest;
@@ -592,84 +644,94 @@
{
XCTAssertTrue(rawLayer->getCircleTranslate().isUndefined(),
@"circle-translate should be unset initially.");
- MGLStyleValue<NSValue *> *defaultStyleValue = layer.circleTranslation;
+ NSExpression *defaultExpression = layer.circleTranslation;
- MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"%@",
#if TARGET_OS_IPHONE
[NSValue valueWithCGVector:CGVectorMake(1, 1)]
#else
[NSValue valueWithMGLVector:CGVectorMake(1, -1)]
#endif
];
- layer.circleTranslation = constantStyleValue;
+ layer.circleTranslation = constantExpression;
mbgl::style::PropertyValue<std::array<float, 2>> propertyValue = { { 1, 1 } };
XCTAssertEqual(rawLayer->getCircleTranslate(), propertyValue,
- @"Setting circleTranslation to a constant value should update circle-translate.");
- XCTAssertEqualObjects(layer.circleTranslation, constantStyleValue,
- @"circleTranslation should round-trip constant values.");
-
- MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.circleTranslation = functionStyleValue;
-
- mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = { {{18, { 1, 1 }}} };
+ @"Setting circleTranslation to a constant value expression should update circle-translate.");
+ XCTAssertEqualObjects(layer.circleTranslation, constantExpression,
+ @"circleTranslation should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"{1, 1}"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.circleTranslation = functionExpression;
+
+ mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = {{
+ { -INFINITY, { 1, 1 } },
+ { 18, { 1, 1 } },
+ }};
propertyValue = mbgl::style::CameraFunction<std::array<float, 2>> { intervalStops };
XCTAssertEqual(rawLayer->getCircleTranslate(), propertyValue,
- @"Setting circleTranslation to a camera function should update circle-translate.");
- XCTAssertEqualObjects(layer.circleTranslation, functionStyleValue,
- @"circleTranslation should round-trip camera functions.");
+ @"Setting circleTranslation to a camera expression should update circle-translate.");
+ XCTAssertEqualObjects(layer.circleTranslation, functionExpression,
+ @"circleTranslation should round-trip camera expressions.");
layer.circleTranslation = nil;
XCTAssertTrue(rawLayer->getCircleTranslate().isUndefined(),
@"Unsetting circleTranslation should return circle-translate to the default value.");
- XCTAssertEqualObjects(layer.circleTranslation, defaultStyleValue,
+ XCTAssertEqualObjects(layer.circleTranslation, defaultExpression,
@"circleTranslation should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.circleTranslation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.circleTranslation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.circleTranslation = functionExpression, NSException, NSInvalidArgumentException, @"MGLCircleLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.circleTranslation = functionExpression, NSException, NSInvalidArgumentException, @"MGLCircleLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// circle-translate-anchor
{
XCTAssertTrue(rawLayer->getCircleTranslateAnchor().isUndefined(),
@"circle-translate-anchor should be unset initially.");
- MGLStyleValue<NSValue *> *defaultStyleValue = layer.circleTranslationAnchor;
+ NSExpression *defaultExpression = layer.circleTranslationAnchor;
- MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLCircleTranslationAnchor:MGLCircleTranslationAnchorViewport]];
- layer.circleTranslationAnchor = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'viewport'"];
+ layer.circleTranslationAnchor = constantExpression;
mbgl::style::PropertyValue<mbgl::style::TranslateAnchorType> propertyValue = { mbgl::style::TranslateAnchorType::Viewport };
XCTAssertEqual(rawLayer->getCircleTranslateAnchor(), propertyValue,
- @"Setting circleTranslationAnchor to a constant value should update circle-translate-anchor.");
- XCTAssertEqualObjects(layer.circleTranslationAnchor, constantStyleValue,
- @"circleTranslationAnchor should round-trip constant values.");
-
- MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.circleTranslationAnchor = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::style::TranslateAnchorType> intervalStops = { {{18, mbgl::style::TranslateAnchorType::Viewport}} };
+ @"Setting circleTranslationAnchor to a constant value expression should update circle-translate-anchor.");
+ XCTAssertEqualObjects(layer.circleTranslationAnchor, constantExpression,
+ @"circleTranslationAnchor should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"'viewport'"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.circleTranslationAnchor = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::style::TranslateAnchorType> intervalStops = {{
+ { -INFINITY, mbgl::style::TranslateAnchorType::Viewport },
+ { 18, mbgl::style::TranslateAnchorType::Viewport },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::style::TranslateAnchorType> { intervalStops };
XCTAssertEqual(rawLayer->getCircleTranslateAnchor(), propertyValue,
- @"Setting circleTranslationAnchor to a camera function should update circle-translate-anchor.");
- XCTAssertEqualObjects(layer.circleTranslationAnchor, functionStyleValue,
- @"circleTranslationAnchor should round-trip camera functions.");
+ @"Setting circleTranslationAnchor to a camera expression should update circle-translate-anchor.");
+ XCTAssertEqualObjects(layer.circleTranslationAnchor, functionExpression,
+ @"circleTranslationAnchor should round-trip camera expressions.");
layer.circleTranslationAnchor = nil;
XCTAssertTrue(rawLayer->getCircleTranslateAnchor().isUndefined(),
@"Unsetting circleTranslationAnchor should return circle-translate-anchor to the default value.");
- XCTAssertEqualObjects(layer.circleTranslationAnchor, defaultStyleValue,
+ XCTAssertEqualObjects(layer.circleTranslationAnchor, defaultExpression,
@"circleTranslationAnchor should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.circleTranslationAnchor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.circleTranslationAnchor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.circleTranslationAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLCircleLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.circleTranslationAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLCircleLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
}
diff --git a/platform/darwin/test/MGLComputedShapeSourceTests.m b/platform/darwin/test/MGLComputedShapeSourceTests.m
new file mode 100644
index 0000000000..6eb45913d6
--- /dev/null
+++ b/platform/darwin/test/MGLComputedShapeSourceTests.m
@@ -0,0 +1,24 @@
+#import <XCTest/XCTest.h>
+
+#import <Mapbox/Mapbox.h>
+
+
+@interface MGLComputedShapeSourceTests : XCTestCase
+@end
+
+@implementation MGLComputedShapeSourceTests
+
+- (void)testInitializer {
+ MGLComputedShapeSource *source = [[MGLComputedShapeSource alloc] initWithIdentifier:@"id" options:@{}];
+ XCTAssertNotNil(source);
+ XCTAssertNotNil(source.requestQueue);
+ XCTAssertNil(source.dataSource);
+}
+
+- (void)testNilOptions {
+ MGLComputedShapeSource *source = [[MGLComputedShapeSource alloc] initWithIdentifier:@"id" options:nil];
+ XCTAssertNotNil(source);
+}
+
+
+@end
diff --git a/platform/darwin/test/MGLDocumentationExampleTests.swift b/platform/darwin/test/MGLDocumentationExampleTests.swift
index 668e5f57f8..9edb33a078 100644
--- a/platform/darwin/test/MGLDocumentationExampleTests.swift
+++ b/platform/darwin/test/MGLDocumentationExampleTests.swift
@@ -73,14 +73,14 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
XCTAssertNotNil(mapView.style?.source(withIdentifier: "lines"))
}
- func testMGLRasterSource() {
+ func testMGLRasterTileSource() {
//#-example-code
- let source = MGLRasterSource(identifier: "clouds", tileURLTemplates: ["https://example.com/raster-tiles/{z}/{x}/{y}.png"], options: [
+ let source = MGLRasterTileSource(identifier: "clouds", tileURLTemplates: ["https://example.com/raster-tiles/{z}/{x}/{y}.png"], options: [
.minimumZoomLevel: 9,
.maximumZoomLevel: 16,
.tileSize: 512,
.attributionInfos: [
- MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "http://mapbox.com"))
+ MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "https://mapbox.com"))
]
])
mapView.style?.addSource(source)
@@ -88,14 +88,34 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
XCTAssertNotNil(mapView.style?.source(withIdentifier: "clouds"))
}
+
+ func testMGLRasterDEMSource() {
+ // We want to use mapbox.terrain-rgb in the example, but using a mapbox:
+ // URL requires setting an access token. So this identically named
+ // subclass of MGLRasterDEMSource swaps in a nonexistent URL.
+ class MGLRasterDEMSource: Mapbox.MGLRasterDEMSource {
+ override init(identifier: String, configurationURL: URL, tileSize: CGFloat = 256) {
+ let bogusURL = URL(string: "https://example.com/raster-rgb.json")!
+ super.init(identifier: identifier, configurationURL: bogusURL, tileSize: tileSize)
+ }
+ }
+
+ //#-example-code
+ let terrainRGBURL = URL(string: "mapbox://mapbox.terrain-rgb")!
+ let source = MGLRasterDEMSource(identifier: "hills", configurationURL: terrainRGBURL)
+ mapView.style?.addSource(source)
+ //#-end-example-code
+
+ XCTAssertNotNil(mapView.style?.source(withIdentifier: "hills"))
+ }
- func testMGLVectorSource() {
+ func testMGLVectorTileSource() {
//#-example-code
- let source = MGLVectorSource(identifier: "pois", tileURLTemplates: ["https://example.com/vector-tiles/{z}/{x}/{y}.mvt"], options: [
+ let source = MGLVectorTileSource(identifier: "pois", tileURLTemplates: ["https://example.com/vector-tiles/{z}/{x}/{y}.mvt"], options: [
.minimumZoomLevel: 9,
.maximumZoomLevel: 16,
.attributionInfos: [
- MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "http://mapbox.com"))
+ MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "https://mapbox.com"))
]
])
mapView.style?.addSource(source)
@@ -131,18 +151,21 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
}
func testMGLCircleStyleLayer() {
- let population = MGLVectorSource(identifier: "population", configurationURL: URL(string: "https://example.com/style.json")!)
+ let population = MGLVectorTileSource(identifier: "population", configurationURL: URL(string: "https://example.com/style.json")!)
mapView.style?.addSource(population)
//#-example-code
let layer = MGLCircleStyleLayer(identifier: "circles", source: population)
layer.sourceLayerIdentifier = "population"
- layer.circleColor = MGLStyleValue(rawValue: .green)
- layer.circleRadius = MGLStyleValue(interpolationMode: .exponential,
- cameraStops: [12: MGLStyleValue(rawValue: 2),
- 22: MGLStyleValue(rawValue: 180)],
- options: [.interpolationBase: 1.75])
- layer.circleOpacity = MGLStyleValue(rawValue: 0.7)
+ #if os(macOS)
+ layer.circleColor = NSExpression(forConstantValue: NSColor.green)
+ #else
+ layer.circleColor = NSExpression(forConstantValue: UIColor.green)
+ #endif
+ layer.circleRadius = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'exponential', 1.75, %@)",
+ [12: 2,
+ 22: 180])
+ layer.circleOpacity = NSExpression(forConstantValue: 0.7)
layer.predicate = NSPredicate(format: "%K == %@", "marital-status", "married")
mapView.style?.addLayer(layer)
//#-end-example-code
@@ -151,18 +174,21 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
}
func testMGLLineStyleLayer() {
- let trails = MGLVectorSource(identifier: "trails", configurationURL: URL(string: "https://example.com/style.json")!)
+ let trails = MGLVectorTileSource(identifier: "trails", configurationURL: URL(string: "https://example.com/style.json")!)
mapView.style?.addSource(trails)
//#-example-code
let layer = MGLLineStyleLayer(identifier: "trails-path", source: trails)
layer.sourceLayerIdentifier = "trails"
- layer.lineWidth = MGLStyleValue(interpolationMode: .exponential,
- cameraStops: [14: MGLStyleValue(rawValue: 2),
- 18: MGLStyleValue(rawValue: 20)],
- options: [.interpolationBase: 1.5])
- layer.lineColor = MGLStyleValue(rawValue: .brown)
- layer.lineCap = MGLStyleValue(rawValue: NSValue(mglLineCap: .round))
+ layer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'exponential', 1.5, %@)",
+ [14: 2,
+ 18: 20])
+ #if os(macOS)
+ layer.lineColor = NSExpression(forConstantValue: NSColor.brown)
+ #else
+ layer.lineColor = NSExpression(forConstantValue: UIColor.brown)
+ #endif
+ layer.lineCap = NSExpression(forConstantValue: "round")
layer.predicate = NSPredicate(format: "%K == %@", "trail-type", "mountain-biking")
mapView.style?.addLayer(layer)
//#-end-example-code
@@ -171,13 +197,17 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
}
func testMGLFillStyleLayer() {
- let parks = MGLVectorSource(identifier: "parks", configurationURL: URL(string: "https://example.com/style.json")!)
+ let parks = MGLVectorTileSource(identifier: "parks", configurationURL: URL(string: "https://example.com/style.json")!)
mapView.style?.addSource(parks)
//#-example-code
let layer = MGLFillStyleLayer(identifier: "parks", source: parks)
layer.sourceLayerIdentifier = "parks"
- layer.fillColor = MGLStyleValue(rawValue: .green)
+ #if os(macOS)
+ layer.fillColor = NSExpression(forConstantValue: NSColor.green)
+ #else
+ layer.fillColor = NSExpression(forConstantValue: UIColor.green)
+ #endif
layer.predicate = NSPredicate(format: "type == %@", "national-park")
mapView.style?.addLayer(layer)
//#-end-example-code
@@ -186,39 +216,57 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
}
func testMGLFillExtrusionStyleLayer() {
- let buildings = MGLVectorSource(identifier: "buildings", configurationURL: URL(string: "https://example.com/style.json")!)
+ let buildings = MGLVectorTileSource(identifier: "buildings", configurationURL: URL(string: "https://example.com/style.json")!)
mapView.style?.addSource(buildings)
//#-example-code
let layer = MGLFillExtrusionStyleLayer(identifier: "buildings", source: buildings)
layer.sourceLayerIdentifier = "building"
- layer.fillExtrusionHeight = MGLStyleValue(interpolationMode: .identity, sourceStops: nil, attributeName: "height", options: nil)
- layer.fillExtrusionBase = MGLStyleValue(interpolationMode: .identity, sourceStops: nil, attributeName: "min_height", options: nil)
+ layer.fillExtrusionHeight = NSExpression(forKeyPath: "height")
+ layer.fillExtrusionBase = NSExpression(forKeyPath: "min_height")
layer.predicate = NSPredicate(format: "extrude == 'true'")
mapView.style?.addLayer(layer)
//#-end-example-code
XCTAssertNotNil(mapView.style?.layer(withIdentifier: "buildings"))
}
+
+ func testMGLHeatmapStyleLayer() {
+ let earthquakes = MGLShapeSource(identifier: "earthquakes", url: URL(string: "https://example.com/earthquakes.json")!, options: [:])
+ mapView.style?.addSource(earthquakes)
+
+ //#-example-code
+ let layer = MGLHeatmapStyleLayer(identifier: "earthquake-heat", source: earthquakes)
+ layer.heatmapWeight = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:(magnitude, 'linear', nil, %@)",
+ [0: 0,
+ 6: 1])
+ layer.heatmapIntensity = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)",
+ [0: 1,
+ 9: 3])
+ mapView.style?.addLayer(layer)
+ //#-end-example-code
+
+ XCTAssertNotNil(mapView.style?.layer(withIdentifier: "earthquake-heat"))
+ }
func testMGLSymbolStyleLayer() {
- let pois = MGLVectorSource(identifier: "pois", configurationURL: URL(string: "https://example.com/style.json")!)
+ let pois = MGLVectorTileSource(identifier: "pois", configurationURL: URL(string: "https://example.com/style.json")!)
mapView.style?.addSource(pois)
//#-example-code
let layer = MGLSymbolStyleLayer(identifier: "coffeeshops", source: pois)
layer.sourceLayerIdentifier = "pois"
- layer.iconImageName = MGLStyleValue(rawValue: "coffee")
- layer.iconScale = MGLStyleValue(rawValue: 0.5)
- layer.text = MGLStyleValue(rawValue: "{name}")
+ layer.iconImageName = NSExpression(forConstantValue: "coffee")
+ layer.iconScale = NSExpression(forConstantValue: 0.5)
+ layer.text = NSExpression(forKeyPath: "name")
#if os(macOS)
var vector = CGVector(dx: 10, dy: 0)
- layer.textTranslation = MGLStyleValue(rawValue: NSValue(bytes: &vector, objCType: "{CGVector=dd}"))
+ layer.textTranslation = NSExpression(forConstantValue: NSValue(bytes: &vector, objCType: "{CGVector=dd}"))
#else
- layer.textTranslation = MGLStyleValue(rawValue: NSValue(cgVector: CGVector(dx: 10, dy: 0)))
+ layer.textTranslation = NSExpression(forConstantValue: NSValue(cgVector: CGVector(dx: 10, dy: 0)))
#endif
- layer.textJustification = MGLStyleValue(rawValue: NSValue(mglTextJustification: .left))
- layer.textAnchor = MGLStyleValue(rawValue: NSValue(mglTextAnchor: .left))
+ layer.textJustification = NSExpression(forConstantValue: "left")
+ layer.textAnchor = NSExpression(forConstantValue: "left")
layer.predicate = NSPredicate(format: "%K == %@", "venue-type", "coffee")
mapView.style?.addLayer(layer)
//#-end-example-code
@@ -227,33 +275,60 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
}
func testMGLRasterStyleLayer() {
- let source = MGLRasterSource(identifier: "clouds", tileURLTemplates: ["https://example.com/raster-tiles/{z}/{x}/{y}.png"], options: [
+ let source = MGLRasterTileSource(identifier: "clouds", tileURLTemplates: ["https://example.com/raster-tiles/{z}/{x}/{y}.png"], options: [
.minimumZoomLevel: 9,
.maximumZoomLevel: 16,
.tileSize: 512,
.attributionInfos: [
- MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "http://mapbox.com"))
+ MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "https://mapbox.com"))
]
])
mapView.style?.addSource(source)
//#-example-code
let layer = MGLRasterStyleLayer(identifier: "clouds", source: source)
- layer.rasterOpacity = MGLStyleValue(rawValue: 0.5)
+ layer.rasterOpacity = NSExpression(forConstantValue: 0.5)
mapView.style?.addLayer(layer)
//#-end-example-code
XCTAssertNotNil(mapView.style?.layer(withIdentifier: "clouds"))
}
+ func testMGLHillshadeStyleLayer() {
+ let source = MGLRasterDEMSource(identifier: "dem", tileURLTemplates: ["https://example.com/raster-rgb/{z}/{x}/{y}.png"], options: [
+ .minimumZoomLevel: 9,
+ .maximumZoomLevel: 16,
+ .tileSize: 256,
+ .attributionInfos: [
+ MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "https://mapbox.com"))
+ ]
+ ])
+ mapView.style?.addSource(source)
+
+ let canals = MGLVectorTileSource(identifier: "canals", configurationURL: URL(string: "https://example.com/style.json")!)
+ mapView.style?.addSource(canals)
+ let canalShadowLayer = MGLLineStyleLayer(identifier: "waterway-river-canal-shadow", source: canals)
+ mapView.style?.addLayer(canalShadowLayer)
+
+ //#-example-code
+ let layer = MGLHillshadeStyleLayer(identifier: "hills", source: source)
+ layer.hillshadeExaggeration = NSExpression(forConstantValue: 0.6)
+ if let canalShadowLayer = mapView.style?.layer(withIdentifier: "waterway-river-canal-shadow") {
+ mapView.style?.insertLayer(layer, below: canalShadowLayer)
+ }
+ //#-end-example-code
+
+ XCTAssertNotNil(mapView.style?.layer(withIdentifier: "hills"))
+ }
+
func testMGLVectorStyleLayer$predicate() {
- let terrain = MGLVectorSource(identifier: "terrain", configurationURL: URL(string: "https://example.com/style.json")!)
+ let terrain = MGLVectorTileSource(identifier: "terrain", configurationURL: URL(string: "https://example.com/style.json")!)
mapView.style?.addSource(terrain)
//#-example-code
let layer = MGLLineStyleLayer(identifier: "contour", source: terrain)
layer.sourceLayerIdentifier = "contours"
- layer.predicate = NSPredicate(format: "(index == 5 || index == 10) && ele >= 1500.0")
+ layer.predicate = NSPredicate(format: "(index == 5 || index == 10) && CAST(ele, 'NSNumber') >= 1500.0")
mapView.style?.addLayer(layer)
//#-end-example-code
@@ -295,7 +370,7 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
#endif
class MGLStyle {
- static func satelliteStreetsStyleURL() -> URL {
+ static var satelliteStreetsStyleURL: URL {
return MGLDocumentationExampleTests.styleURL
}
}
@@ -303,7 +378,7 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
//#-example-code
let camera = MGLMapCamera(lookingAtCenter: CLLocationCoordinate2D(latitude: 37.7184, longitude: -122.4365), fromDistance: 100, pitch: 20, heading: 0)
- let options = MGLMapSnapshotOptions(styleURL: MGLStyle.satelliteStreetsStyleURL(), camera: camera, size: CGSize(width: 320, height: 480))
+ let options = MGLMapSnapshotOptions(styleURL: MGLStyle.satelliteStreetsStyleURL, camera: camera, size: CGSize(width: 320, height: 480))
options.zoomLevel = 10
let snapshotter = MGLMapSnapshotter(options: options)
@@ -316,7 +391,7 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
}
//#-end-example-code
- wait(for: [expectation], timeout: 1)
+ wait(for: [expectation], timeout: 5)
}
// For testMGLMapView().
diff --git a/platform/darwin/test/MGLDocumentationGuideTests.swift b/platform/darwin/test/MGLDocumentationGuideTests.swift
index c71f1b46c7..4de1d81aa9 100644
--- a/platform/darwin/test/MGLDocumentationGuideTests.swift
+++ b/platform/darwin/test/MGLDocumentationGuideTests.swift
@@ -1,3 +1,4 @@
+import XCTest
import Foundation
import Mapbox
#if os(iOS)
@@ -49,31 +50,32 @@ class MGLDocumentationGuideTests: XCTestCase, MGLMapViewDelegate {
styleLoadingExpectation.fulfill()
}
- func testUsingStyleFunctionsAtRuntime$Stops() {
+ func testMigratingToExpressions$Stops() {
//#-example-code
#if os(macOS)
- let stops = [
- 0: MGLStyleValue<NSColor>(rawValue: .yellow),
- 2.5: MGLStyleValue(rawValue: .orange),
- 5: MGLStyleValue(rawValue: .red),
- 7.5: MGLStyleValue(rawValue: .blue),
- 10: MGLStyleValue(rawValue: .white),
+ let stops: [NSNumber: NSColor] = [
+ 0: .yellow,
+ 2.5: .orange,
+ 5: .red,
+ 7.5: .blue,
+ 10: .white,
]
#else
- let stops = [
- 0: MGLStyleValue<UIColor>(rawValue: .yellow),
- 2.5: MGLStyleValue(rawValue: .orange),
- 5: MGLStyleValue(rawValue: .red),
- 7.5: MGLStyleValue(rawValue: .blue),
- 10: MGLStyleValue(rawValue: .white),
+ let stops: [NSNumber: UIColor] = [
+ 0: .yellow,
+ 2.5: .orange,
+ 5: .red,
+ 7.5: .blue,
+ 10: .white,
]
#endif
//#-end-example-code
- let _ = MGLStyleValue(interpolationMode: .exponential, cameraStops: stops, options: nil)
+ let _ = NSExpression(format: "mgl_step:from:stops:(mag, %@, %@)",
+ stops[0]!, stops)
}
- func testUsingStyleFunctionsAtRuntime$Linear() {
+ func testMigratingToExpressions$Linear() {
//#-example-code
let url = URL(string: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson")!
let symbolSource = MGLSource(identifier: "source")
@@ -83,132 +85,192 @@ class MGLDocumentationGuideTests: XCTestCase, MGLMapViewDelegate {
mapView.style?.addSource(source)
#if os(macOS)
- let stops = [
- 0: MGLStyleValue<NSColor>(rawValue: .yellow),
- 2.5: MGLStyleValue(rawValue: .orange),
- 5: MGLStyleValue(rawValue: .red),
- 7.5: MGLStyleValue(rawValue: .blue),
- 10: MGLStyleValue(rawValue: .white),
+ let stops: [NSNumber: NSColor] = [
+ 0: .yellow,
+ 2.5: .orange,
+ 5: .red,
+ 7.5: .blue,
+ 10: .white,
]
#else
- let stops = [
- 0: MGLStyleValue<UIColor>(rawValue: .yellow),
- 2.5: MGLStyleValue(rawValue: .orange),
- 5: MGLStyleValue(rawValue: .red),
- 7.5: MGLStyleValue(rawValue: .blue),
- 10: MGLStyleValue(rawValue: .white),
+ let stops: [NSNumber: UIColor] = [
+ 0: .yellow,
+ 2.5: .orange,
+ 5: .red,
+ 7.5: .blue,
+ 10: .white,
]
#endif
let layer = MGLCircleStyleLayer(identifier: "circles", source: source)
#if os(macOS)
- layer.circleColor = MGLStyleValue(interpolationMode: .exponential,
- sourceStops: stops,
- attributeName: "mag",
- options: [.defaultValue: MGLStyleValue<NSColor>(rawValue: .green)])
+ layer.circleColor = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:(mag, 'linear', nil, %@)",
+ stops)
#else
- layer.circleColor = MGLStyleValue(interpolationMode: .exponential,
- sourceStops: stops,
- attributeName: "mag",
- options: [.defaultValue: MGLStyleValue<UIColor>(rawValue: .green)])
+ layer.circleColor = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:(mag, 'linear', nil, %@)",
+ stops)
#endif
- layer.circleRadius = MGLStyleValue(rawValue: 10)
+ layer.circleRadius = NSExpression(forConstantValue: 10)
mapView.style?.insertLayer(layer, below: symbolLayer)
//#-end-example-code
}
- func testUsingStyleFunctionsAtRuntime$Exponential() {
+ func testMigratingToExpressions$LinearConvenience() {
+ let source = MGLShapeSource(identifier: "circles", shape: nil, options: nil)
+ let layer = MGLCircleStyleLayer(identifier: "circles", source: source)
+
+ #if os(macOS)
+ let stops: [NSNumber: NSColor] = [
+ 0: .yellow,
+ 2.5: .orange,
+ 5: .red,
+ 7.5: .blue,
+ 10: .white,
+ ]
+ #else
+ let stops: [NSNumber: UIColor] = [
+ 0: .yellow,
+ 2.5: .orange,
+ 5: .red,
+ 7.5: .blue,
+ 10: .white,
+ ]
+ #endif
+
+ //#-example-code
+ layer.circleColor = NSExpression(forMGLInterpolating: NSExpression(forKeyPath: "mag"), curveType: .linear, parameters: nil, stops: NSExpression(forConstantValue: stops))
+ //#-end-example-code
+
+ layer.circleRadius = NSExpression(forConstantValue: 10)
+ mapView.style?.addLayer(layer)
+
+ }
+ func testMigratingToExpressions$Exponential() {
let source = MGLShapeSource(identifier: "circles", shape: nil, options: nil)
let layer = MGLCircleStyleLayer(identifier: "circles", source: source)
//#-example-code
let stops = [
- 12: MGLStyleValue<NSNumber>(rawValue: 0.5),
- 14: MGLStyleValue(rawValue: 2),
- 18: MGLStyleValue(rawValue: 18),
+ 12: 0.5,
+ 14: 2,
+ 18: 18,
]
- layer.circleRadius = MGLStyleValue(interpolationMode: .exponential,
- cameraStops: stops,
- options: [.interpolationBase: 1.5])
+ layer.circleRadius = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'exponential', 1.5, %@)",
+ stops)
//#-end-example-code
}
- func testUsingStyleFunctionsAtRuntime$Interval() {
+ func testMigratingToExpressions$ExponentialConvenience() {
+ let source = MGLShapeSource(identifier: "circles", shape: nil, options: nil)
+ let layer = MGLCircleStyleLayer(identifier: "circles", source: source)
+
+ //#-example-code
+ let stops = [
+ 12: 0.5,
+ 14: 2,
+ 18: 18,
+ ]
+
+ layer.circleRadius = NSExpression(forMGLInterpolating: NSExpression.zoomLevelVariable, curveType: MGLExpressionInterpolationMode.exponential, parameters: NSExpression(forConstantValue: 1.5), stops: NSExpression(forConstantValue: stops))
+ //#-end-example-code
+ }
+ func testMigratingToExpressions$Interval() {
let source = MGLShapeSource(identifier: "circles", shape: nil, options: nil)
let layer = MGLCircleStyleLayer(identifier: "circles", source: source)
//#-example-code
#if os(macOS)
- let stops = [
- 0: MGLStyleValue<NSColor>(rawValue: .yellow),
- 2.5: MGLStyleValue(rawValue: .orange),
- 5: MGLStyleValue(rawValue: .red),
- 7.5: MGLStyleValue(rawValue: .blue),
- 10: MGLStyleValue(rawValue: .white),
+ let stops: [NSNumber: NSColor] = [
+ 0: .yellow,
+ 2.5: .orange,
+ 5: .red,
+ 7.5: .blue,
+ 10: .white,
]
- layer.circleColor = MGLStyleValue(interpolationMode: .interval,
- sourceStops: stops,
- attributeName: "mag",
- options: [.defaultValue: MGLStyleValue<NSColor>(rawValue: .green)])
+ layer.circleColor = NSExpression(format: "mgl_step:from:stops:(mag, %@, %@)",
+ NSColor.green, stops)
#else
- let stops = [
- 0: MGLStyleValue<UIColor>(rawValue: .yellow),
- 2.5: MGLStyleValue(rawValue: .orange),
- 5: MGLStyleValue(rawValue: .red),
- 7.5: MGLStyleValue(rawValue: .blue),
- 10: MGLStyleValue(rawValue: .white),
+ let stops: [NSNumber: UIColor] = [
+ 0: .yellow,
+ 2.5: .orange,
+ 5: .red,
+ 7.5: .blue,
+ 10: .white,
]
- layer.circleColor = MGLStyleValue(interpolationMode: .interval,
- sourceStops: stops,
- attributeName: "mag",
- options: [.defaultValue: MGLStyleValue<UIColor>(rawValue: .green)])
+ layer.circleColor = NSExpression(format: "mgl_step:from:stops:(mag, %@, %@)",
+ UIColor.green, stops)
#endif
//#-end-example-code
}
- func testUsingStyleFunctionsAtRuntime$Categorical() {
+ func testMigratingToExpressions$Categorical() {
let source = MGLShapeSource(identifier: "circles", shape: nil, options: nil)
let layer = MGLCircleStyleLayer(identifier: "circles", source: source)
//#-example-code
#if os(macOS)
- let categoricalStops = [
- "earthquake": MGLStyleValue<NSColor>(rawValue: .orange),
- "explosion": MGLStyleValue(rawValue: .red),
- "quarry blast": MGLStyleValue(rawValue: .yellow),
- ]
-
- layer.circleColor = MGLStyleValue(interpolationMode: .categorical,
- sourceStops: categoricalStops,
- attributeName: "type",
- options: [.defaultValue: MGLStyleValue<NSColor>(rawValue: .blue)])
+ let defaultColor = NSColor.blue
+ layer.circleColor = NSExpression(
+ format: "MGL_MATCH(type, 'earthquake', %@, 'explosion', %@, 'quarry blast', %@, %@)",
+ NSColor.orange, NSColor.red, NSColor.yellow, defaultColor)
#else
- let categoricalStops = [
- "earthquake": MGLStyleValue<UIColor>(rawValue: .orange),
- "explosion": MGLStyleValue(rawValue: .red),
- "quarry blast": MGLStyleValue(rawValue: .yellow),
- ]
-
- layer.circleColor = MGLStyleValue(interpolationMode: .categorical,
- sourceStops: categoricalStops,
- attributeName: "type",
- options: [.defaultValue: MGLStyleValue<UIColor>(rawValue: .blue)])
+ let defaultColor = UIColor.blue
+ layer.circleColor = NSExpression(format: "MGL_MATCH(type, 'earthquake', %@, 'explosion', %@, 'quarry blast', %@, %@)",
+ UIColor.orange, UIColor.red, UIColor.yellow, defaultColor)
+ #endif
+ //#-end-example-code
+ }
+
+ func testMigratingToExpressions$CategoricalValue() {
+ let source = MGLShapeSource(identifier: "circles", shape: nil, options: nil)
+ let layer = MGLCircleStyleLayer(identifier: "circles", source: source)
+
+ //#-example-code
+ #if os(macOS)
+ let stops : [String : NSColor] = ["earthquake" : NSColor.orange,
+ "explosion" : NSColor.red,
+ "quarry blast" : NSColor.yellow]
+ layer.circleColor = NSExpression(
+ format: "FUNCTION(%@, 'valueForKeyPath:', type)",
+ stops)
+ #else
+ let stops : [String : UIColor] = ["earthquake" : UIColor.orange,
+ "explosion" : UIColor.red,
+ "quarry blast" : UIColor.yellow]
+ layer.circleColor = NSExpression(
+ format: "FUNCTION(%@, 'valueForKeyPath:', type)",
+ stops)
#endif
//#-end-example-code
}
+ func testMigratingToExpressions$Identity() {
+ let source = MGLShapeSource(identifier: "circles", shape: nil, options: nil)
+ let layer = MGLCircleStyleLayer(identifier: "circles", source: source)
+
+ //#-example-code
+ layer.circleRadius = NSExpression(forKeyPath: "mag")
+ //#-end-example-code
+ }
- func testUsingStyleFunctionsAtRuntime$Identity() {
+ func testMigratingToExpressions$Multiply() {
let source = MGLShapeSource(identifier: "circles", shape: nil, options: nil)
let layer = MGLCircleStyleLayer(identifier: "circles", source: source)
//#-example-code
- layer.circleRadius = MGLStyleValue(interpolationMode: .identity,
- sourceStops: nil,
- attributeName: "mag",
- options: [.defaultValue: MGLStyleValue<NSNumber>(rawValue: 0)])
+ layer.circleRadius = NSExpression(forFunction: "multiply:by:", arguments: [NSExpression(forKeyPath: "mag"), 3])
+ //#-end-example-code
+ }
+
+ func testMigratingToExpressions$Cast() {
+ let source = MGLShapeSource(identifier: "circles", shape: nil, options: nil)
+
+ //#-example-code
+ let magnitudeLayer = MGLSymbolStyleLayer(identifier: "mag-layer", source: source)
+ magnitudeLayer.text = NSExpression(format: "CAST(mag, 'NSString')")
+ mapView.style?.addLayer(magnitudeLayer)
//#-end-example-code
}
}
diff --git a/platform/darwin/test/MGLExpressionTests.mm b/platform/darwin/test/MGLExpressionTests.mm
index ad0833a068..6d710fdcfe 100644
--- a/platform/darwin/test/MGLExpressionTests.mm
+++ b/platform/darwin/test/MGLExpressionTests.mm
@@ -1,9 +1,17 @@
#import <XCTest/XCTest.h>
+#import "MGLStyleLayerTests.h"
+
#import <string>
#import "MGLTypes.h"
-#import "NSExpression+MGLAdditions.h"
+#import "NSExpression+MGLPrivateAdditions.h"
+#import "NSValue+MGLAdditions.h"
+#if TARGET_OS_IPHONE
+#import "UIColor+MGLAdditions.h"
+#else
+#import "NSColor+MGLAdditions.h"
+#endif
#define MGLAssertEqualValues(actual, expected, ...) \
XCTAssertTrue(actual.is<__typeof__(expected)>()); \
@@ -17,11 +25,14 @@
XCTAssertEqualWithAccuracy(actual.get<__typeof__(expected)>(), expected, accuracy, __VA_ARGS__); \
}
+#define MGLConstantExpression(constant) \
+ [NSExpression expressionForConstantValue:constant]
+
#define MGLAssertConstantEqualsValue(constant, value, ...) \
- MGLAssertEqualValues([NSExpression expressionForConstantValue:constant].mgl_constantMBGLValue, value, __VA_ARGS__);
+ MGLAssertEqualValues(MGLConstantExpression(constant).mgl_constantMBGLValue, value, __VA_ARGS__);
#define MGLAssertConstantEqualsValueWithAccuracy(constant, value, accuracy, ...) \
- MGLAssertEqualValuesWithAccuracy([NSExpression expressionForConstantValue:constant].mgl_constantMBGLValue, value, accuracy, __VA_ARGS__);
+ MGLAssertEqualValuesWithAccuracy(MGLConstantExpression(constant).mgl_constantMBGLValue, value, accuracy, __VA_ARGS__);
using namespace std::string_literals;
@@ -140,4 +151,942 @@ using namespace std::string_literals;
XCTAssertEqual([NSExpression expressionForConstantValue:nil].mgl_featureType, mbgl::FeatureType::Unknown);
}
+#pragma mark - JSON expression object tests
+
+- (void)testVariableExpressionObject {
+ {
+ NSExpression *expression = [NSExpression expressionForVariable:@"zoomLevel"];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, @[@"zoom"]);
+ XCTAssertEqualObjects([NSExpression expressionWithFormat:@"$zoomLevel"].mgl_jsonExpressionObject, @[@"zoom"]);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:@[@"zoom"]], expression);
+ NSMutableDictionary *context = [@{@"zoomLevel": @16} mutableCopy];
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:context], @16);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForVariable:@"heatmapDensity"];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, @[@"heatmap-density"]);
+ XCTAssertEqualObjects([NSExpression expressionWithFormat:@"$heatmapDensity"].mgl_jsonExpressionObject, @[@"heatmap-density"]);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:@[@"heatmap-density"]], expression);
+ NSMutableDictionary *context = [@{@"heatmapDensity": @1} mutableCopy];
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:context], @1);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForVariable:@"geometryType"];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, @[@"geometry-type"]);
+ XCTAssertEqualObjects([NSExpression expressionWithFormat:@"$geometryType"].mgl_jsonExpressionObject, @[@"geometry-type"]);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:@[@"geometry-type"]], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForVariable:@"featureIdentifier"];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, @[@"id"]);
+ XCTAssertEqualObjects([NSExpression expressionWithFormat:@"$featureIdentifier"].mgl_jsonExpressionObject, @[@"id"]);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:@[@"id"]], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForVariable:@"featureAttributes"];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, @[@"properties"]);
+ XCTAssertEqualObjects([NSExpression expressionWithFormat:@"$featureAttributes"].mgl_jsonExpressionObject, @[@"properties"]);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:@[@"properties"]], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForVariable:@"loremIpsum"];
+ NSArray *jsonExpression = @[@"var", @"loremIpsum"];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithFormat:@"$loremIpsum"].mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ NSMutableDictionary *context = [@{@"loremIpsum": @"Lorem ipsum dolor sit amet"} mutableCopy];
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:context], @"Lorem ipsum dolor sit amet");
+ }
+ {
+ NSDictionary *context = @{@"loremIpsum": MGLConstantExpression(@"Lorem ipsum dolor sit amet")};
+ NSExpression *expression = [NSExpression expressionWithFormat:@"MGL_LET('loremIpsum', 'Lorem ipsum dolor sit amet', uppercase($loremIpsum))", context];
+ NSExpression *compatibilityExpression = [NSExpression expressionWithFormat:@"FUNCTION(uppercase($loremIpsum), 'mgl_expressionWithContext:', %@)", context];
+ NSArray *jsonExpression = @[@"let", @"loremIpsum", @"Lorem ipsum dolor sit amet", @[@"upcase", @[@"var", @"loremIpsum"]]];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects(compatibilityExpression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+}
+
+- (void)testConstantValueExpressionObject {
+ {
+ NSExpression *expression = [NSExpression expressionForConstantValue:nil];
+ XCTAssert(expression.mgl_jsonExpressionObject == [NSNull null]);
+ XCTAssert([NSExpression expressionWithFormat:@"nil"].mgl_jsonExpressionObject == [NSNull null]);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:[NSNull null]], expression);
+ XCTAssertNil([expression expressionValueWithObject:nil context:nil]);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForConstantValue:@1];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, @1);
+ XCTAssertEqualObjects([NSExpression expressionWithFormat:@"1"].mgl_jsonExpressionObject, @1);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:@1], expression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @1);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForConstantValue:@YES];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, @YES);
+ XCTAssertEqualObjects([NSExpression expressionWithFormat:@"TRUE"].mgl_jsonExpressionObject, @YES);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:@YES], expression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @YES);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForConstantValue:nil];
+ XCTAssert(expression.mgl_jsonExpressionObject == [NSNull null]);
+ XCTAssert([NSExpression expressionWithFormat:@"nil"].mgl_jsonExpressionObject == [NSNull null]);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:[NSNull null]], expression);
+ XCTAssertNil([expression expressionValueWithObject:nil context:nil]);
+ }
+ {
+ CGVector vector = CGVectorMake(1, 2);
+ NSExpression *expression = [NSExpression expressionForConstantValue:@(vector)];
+#if !TARGET_OS_IPHONE
+ NSArray *jsonExpression = @[@"literal", @[@1, @-2]];
+#else
+ NSArray *jsonExpression = @[@"literal", @[@1, @2]];
+#endif
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ // No way to distinguish offsets from ordinary arrays in expressions.
+ XCTAssertEqualObjects([[NSExpression expressionWithMGLJSONObject:jsonExpression].collection valueForKeyPath:@"constantValue"], jsonExpression.lastObject);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @(vector));
+ }
+ {
+#if !TARGET_OS_IPHONE
+ NSEdgeInsets padding = {1, 2, 3, 4};
+ NSValue *value = [NSValue valueWithEdgeInsets:padding];
+#else
+ UIEdgeInsets padding = {1, 2, 3, 4};
+ NSValue *value = [NSValue valueWithUIEdgeInsets:padding];
+#endif
+ NSExpression *expression = [NSExpression expressionForConstantValue:value];
+ NSArray *jsonExpression = @[@"literal", @[@1, @4, @3, @2]];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ // No way to distinguish offsets from ordinary arrays in expressions.
+ XCTAssertEqualObjects([[NSExpression expressionWithMGLJSONObject:jsonExpression].collection valueForKeyPath:@"constantValue"], jsonExpression.lastObject);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], value);
+ }
+ {
+ MGLColor *color = [MGLColor mgl_colorWithColor:{ 255.0/255, 239.0/255, 213.0/255, 1 }]; // papayawhip
+ NSExpression *expression = [NSExpression expressionForConstantValue:color];
+ NSArray *jsonExpression = @[@"rgb", @255, @239, @213];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], color);
+ }
+ {
+ MGLColor *color = [MGLColor mgl_colorWithColor:{ 255.0/255, 239.0/255, 213.0/255, 0.5 }]; // papayawhip
+ NSExpression *expression = [NSExpression expressionForConstantValue:color];
+ NSArray *jsonExpression = @[@"rgba", @255, @239, @213, @0.5];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], color);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionWithFormat:@"noindex(513)"];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, @513);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @513);
+ }
+}
+
+- (void)testKeyPathExpressionObject {
+ {
+ NSExpression *expression = [NSExpression expressionForKeyPath:@"highway"];
+ NSArray *jsonExpression = @[@"get", @"highway"];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithFormat:@"highway"].mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionWithFormat:@"%@.population", @{@"population": MGLConstantExpression(@12000)}];
+ NSArray *jsonExpression = @[@"get", @"population", @[@"literal", @{@"population": @12000}]];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionWithFormat:@"%@.uppercase('population')", @{@"POPULATION": MGLConstantExpression(@12000)}];
+ NSArray *jsonExpression = @[@"get", @[@"upcase", @"population"], @[@"literal", @{@"POPULATION": @12000}]];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+}
+
+- (void)testStatisticalExpressionObject {
+ {
+ NSExpression *expression = [NSExpression expressionWithFormat:@"average({1, 2, 2, 3, 4, 7, 9})"];
+ NSArray *jsonExpression = @[@"/", @[@"+", @1, @2, @2, @3, @4, @7, @9], @[@"length", @[@"literal", @[@1, @2, @2, @3, @4, @7, @9]]]];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @4);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionWithFormat:@"sum({1, 2, 2, 3, 4, 7, 9})"];
+ NSArray *jsonExpression = @[@"+", @1, @2, @2, @3, @4, @7, @9];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @28);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionWithFormat:@"count({1, 2, 2, 3, 4, 7, 9})"];
+ NSArray *jsonExpression = @[@"length", @[@"literal", @[@1, @2, @2, @3, @4, @7, @9]]];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @7);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionWithFormat:@"min({1, 2, 2, 3, 4, 7, 9})"];
+ NSArray *jsonExpression = @[@"min", @1, @2, @2, @3, @4, @7, @9];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @1);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionWithFormat:@"max({1, 2, 2, 3, 4, 7, 9})"];
+ NSArray *jsonExpression = @[@"max", @1, @2, @2, @3, @4, @7, @9];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @9);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+}
+
+- (void)testArithmeticExpressionObject {
+ NSArray *arguments = @[MGLConstantExpression(@1), MGLConstantExpression(@1)];
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"add:to:" arguments:arguments];
+ NSArray *jsonExpression = @[@"+", @1, @1];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithFormat:@"1 + 1"].mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSArray *arguments = @[MGLConstantExpression(@1), MGLConstantExpression(@1), MGLConstantExpression(@1)];
+ NSExpression *expression = [NSExpression expressionForFunction:@"add:to:" arguments:arguments];
+ NSArray *jsonExpression = @[@"+", @1, @1, @1];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ jsonExpression = @[@"+", @[@"+", @1, @1], @1];
+ XCTAssertEqualObjects([NSExpression expressionWithFormat:@"1 + 1 + 1"].mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], [NSExpression expressionWithFormat:@"1 + 1 + 1"]);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"from:subtract:" arguments:arguments];
+ NSArray *jsonExpression = @[@"-", @1, @1];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithFormat:@"1 - 1"].mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"multiply:by:" arguments:arguments];
+ NSArray *jsonExpression = @[@"*", @1, @1];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithFormat:@"1 * 1"].mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"divide:by:" arguments:arguments];
+ NSArray *jsonExpression = @[@"/", @1, @1];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithFormat:@"1 / 1"].mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"modulus:by:" arguments:arguments];
+ NSArray *jsonExpression = @[@"%", @1, @1];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ // NSExpression lacks a shorthand operator for modulus.
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"ceiling:" arguments:@[MGLConstantExpression(@1.5)]];
+ NSArray *jsonExpression = @[@"ceil", @1.5];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @2);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"ceiling:" arguments:@[MGLConstantExpression(@-1.5)]];
+ NSArray *jsonExpression = @[@"ceil", @-1.5];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @-1);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"ceiling:" arguments:@[MGLConstantExpression(@2)]];
+ NSArray *jsonExpression = @[@"ceil", @2];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @2);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"ceiling:" arguments:@[MGLConstantExpression(@-2)]];
+ NSArray *jsonExpression = @[@"ceil", @-2];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @-2);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"trunc:" arguments:@[MGLConstantExpression(@1.5)]];
+ NSArray *jsonExpression = @[@"-", @1.5, @[@"%", @1.5, @1]];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @1);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"trunc:" arguments:@[MGLConstantExpression(@-1.5)]];
+ NSArray *jsonExpression = @[@"-", @-1.5, @[@"%", @-1.5, @1]];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @-1);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"abs:" arguments:@[MGLConstantExpression(@2)]];
+ NSArray *jsonExpression = @[@"abs", @2];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @2);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"abs:" arguments:@[MGLConstantExpression(@-2)]];
+ NSArray *jsonExpression = @[@"abs", @-2];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @2);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"floor:" arguments:@[MGLConstantExpression(@1.5)]];
+ NSArray *jsonExpression = @[@"floor", @1.5];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @1);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"floor:" arguments:@[MGLConstantExpression(@-1.5)]];
+ NSArray *jsonExpression = @[@"floor", @-1.5];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @-2);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"floor:" arguments:@[MGLConstantExpression(@2)]];
+ NSArray *jsonExpression = @[@"floor", @2];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @2);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"floor:" arguments:@[MGLConstantExpression(@-2)]];
+ NSArray *jsonExpression = @[@"floor", @-2];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @-2);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"mgl_round:" arguments:@[MGLConstantExpression(@1.5)]];
+ NSArray *jsonExpression = @[@"round", @1.5];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @2);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"mgl_round:" arguments:@[MGLConstantExpression(@-1.5)]];
+ NSArray *jsonExpression = @[@"round", @-1.5];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @-2);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"mgl_round:" arguments:@[MGLConstantExpression(@2.5)]];
+ NSArray *jsonExpression = @[@"round", @2.5];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @3);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"mgl_round:" arguments:@[MGLConstantExpression(@-2.5)]];
+ NSArray *jsonExpression = @[@"round", @-2.5];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @-3);
+ }
+}
+
+- (void)testTrigonometricExpressionObject {
+ NSArray *arguments = @[MGLConstantExpression(@1), MGLConstantExpression(@1)];
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"sqrt:" arguments:arguments];
+ NSArray *jsonExpression = @[@"sqrt", @1, @1];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"ln:" arguments:arguments];
+ NSArray *jsonExpression = @[@"ln", @1, @1];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"mgl_log2:" arguments:@[MGLConstantExpression(@1024)]];
+ NSArray *jsonExpression = @[@"log2", @1024];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @10);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"raise:toPower:" arguments:arguments];
+ NSArray *jsonExpression = @[@"^", @1, @1];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithFormat:@"1 ** 1"].mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"exp:" arguments:@[MGLConstantExpression(@0)]];
+ NSArray *jsonExpression = @[@"^", @[@"e"], @0];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @1);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForConstantValue:@(M_E)];
+ NSArray *jsonExpression = @[@"e"];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @(M_E));
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForConstantValue:@(M_PI)];
+ NSArray *jsonExpression = @[@"pi"];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @(M_PI));
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"mgl_acos:" arguments:@[MGLConstantExpression(@1)]];
+ NSArray *jsonExpression = @[@"acos", @1];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @0);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"mgl_cos:" arguments:@[MGLConstantExpression(@0)]];
+ NSArray *jsonExpression = @[@"cos", @0];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @1);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"mgl_asin:" arguments:@[MGLConstantExpression(@0)]];
+ NSArray *jsonExpression = @[@"asin", @0];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @0);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"mgl_sin:" arguments:@[MGLConstantExpression(@0)]];
+ NSArray *jsonExpression = @[@"sin", @0];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @0);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"mgl_atan:" arguments:@[MGLConstantExpression(@20)]];
+ NSArray *jsonExpression = @[@"atan", @20];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ NSNumber *value = [expression expressionValueWithObject:nil context:nil];
+ XCTAssertEqualWithAccuracy(value.doubleValue, 1.52, 0.001);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"mgl_tan:" arguments:@[MGLConstantExpression(@0)]];
+ NSArray *jsonExpression = @[@"tan", @0];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @0);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+}
+
+- (void)testStringFormattingExpressionObject {
+ NSArray *arguments = @[MGLConstantExpression(@"MacDonald")];
+ {
+ NSExpression *expression = [NSExpression expressionWithFormat:@"FUNCTION('Old', 'stringByAppendingString:', 'MacDonald')"];
+ NSExpression *aftermarketExpression = [NSExpression expressionWithFormat:@"mgl_join({'Old', 'MacDonald'})"];
+ NSArray *jsonExpression = @[@"concat", @"Old", @"MacDonald"];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects(aftermarketExpression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @"OldMacDonald");
+ XCTAssertEqualObjects([aftermarketExpression expressionValueWithObject:nil context:nil], @"OldMacDonald");
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], aftermarketExpression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"uppercase:" arguments:arguments];
+ NSArray *jsonExpression = @[@"upcase", @"MacDonald"];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"lowercase:" arguments:arguments];
+ NSArray *jsonExpression = @[@"downcase", @"MacDonald"];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"length:" arguments:arguments];
+ NSArray *jsonExpression = @[@"length", @"MacDonald"];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+}
+
+- (void)testTypeConversionExpressionObject {
+ {
+ NSExpression *expression = [NSExpression expressionWithFormat:@"FUNCTION(number, 'boolValue')"];
+ NSArray *jsonExpression = @[@"to-boolean", @[@"get", @"number"]];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ // NSExpression is unable to evaluate -[NSNumber boolValue] by itself
+ // because it returns a primitive instead of an object.
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionWithFormat:@"FUNCTION(postalCode, 'mgl_number')"];
+ NSArray *jsonExpression = @[@"to-number", @[@"get", @"postalCode"]];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithFormat:@"FUNCTION(postalCode, 'doubleValue')"].mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithFormat:@"FUNCTION(postalCode, 'floatValue')"].mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithFormat:@"FUNCTION(postalCode, 'decimalValue')"].mgl_jsonExpressionObject, jsonExpression);
+ // NSExpression is unable to evaluate NSNumber’s -floatValue,
+ // -doubleValue, or -decimalValue by themselves because they each return
+ // a primitive instead of an object.
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression],
+ [NSExpression expressionWithFormat:@"CAST(postalCode, 'NSNumber')"]);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionWithFormat:@"FUNCTION(postalCode, 'mgl_numberWithFallbackValues:', zipCode)"];
+ NSArray *jsonExpression = @[@"to-number", @[@"get", @"postalCode"], @[@"get", @"zipCode"]];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithFormat:@"FUNCTION(postalCode, 'doubleValue', zipCode)"].mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithFormat:@"FUNCTION(postalCode, 'floatValue', zipCode)"].mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithFormat:@"FUNCTION(postalCode, 'decimalValue', zipCode)"].mgl_jsonExpressionObject, jsonExpression);
+ // NSExpression is unable to evaluate NSNumber’s -floatValue,
+ // -doubleValue, or -decimalValue by themselves because they each return
+ // a primitive instead of an object.
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionWithFormat:@"CAST(postalCode, 'NSNumber')"];
+ NSExpression *compatibilityExpression = [NSExpression expressionWithFormat:@"FUNCTION(postalCode, 'mgl_numberWithFallbackValues:')"];
+ NSArray *jsonExpression = @[@"to-number", @[@"get", @"postalCode"]];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects(compatibilityExpression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:@{@"postalCode": @"02134"} context:nil], @02134);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionWithFormat:@"CAST(number, 'NSString')"];
+ NSExpression *compatibilityExpression = [NSExpression expressionWithFormat:@"FUNCTION(number, 'stringValue')"];
+ NSArray *jsonExpression = @[@"to-string", @[@"get", @"number"]];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects(compatibilityExpression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:@{@"number": @1.5} context:nil], @"1.5");
+ XCTAssertEqualObjects([compatibilityExpression expressionValueWithObject:@{@"number": @1.5} context:nil], @"1.5");
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+}
+
+- (void)testInterpolationExpressionObject {
+ {
+ NSDictionary *stops = @{@0: MGLConstantExpression(@100), @10: MGLConstantExpression(@200)};
+ NSExpression *expression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(x, 'linear', nil, %@)", stops];
+ NSExpression *compatibilityExpression = [NSExpression expressionWithFormat:@"FUNCTION(x, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", stops];
+ NSArray *jsonExpression = @[@"interpolate", @[@"linear"], @[@"get", @"x"], @0, @100, @10, @200];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects(compatibilityExpression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSDictionary *stops = @{@1: MGLConstantExpression(@2), @3: MGLConstantExpression(@6)};
+ NSExpression *expression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(x, 'exponential', 2, %@)", stops];
+ NSArray *jsonExpression = @[@"interpolate", @[@"exponential", @2], @[@"get", @"x"], @1, @2, @3, @6];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSDictionary *stops = @{@0: MGLConstantExpression(@0), @100: MGLConstantExpression(@100)};
+ NSExpression *expression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(x, 'cubic-bezier', { 0.42, 0, 0.58, 1 }, %@)", stops];
+ NSArray *jsonExpression = @[@"interpolate", @[@"cubic-bezier", @0.42, @0, @0.58, @1], @[@"get", @"x"], @0, @0, @100, @100];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSDictionary *stops = @{@0: MGLConstantExpression(@111), @1: MGLConstantExpression(@1111)};
+ NSExpression *expression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(x, 11, %@)", stops];
+ NSExpression *compatibilityExpression = [NSExpression expressionWithFormat:@"FUNCTION(x, 'mgl_stepWithMinimum:stops:', 11, %@)", stops];
+ NSArray *jsonExpression = @[@"step", @[@"get", @"x"], @11, @0, @111, @1, @1111];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects(compatibilityExpression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSDictionary *stops = @{@0: MGLConstantExpression(@111), @1: MGLConstantExpression(@1111)};
+ NSExpression *expression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, 11, %@)", stops];
+ NSArray *jsonExpression = @[@"step", @[@"zoom"], @11, @0, @111, @1, @1111];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+}
+
+- (void)testMatchExpressionObject {
+ {
+ NSExpression *expression = [NSExpression expressionWithFormat:@"MGL_MATCH(2 - 1, %@, %@, %@, %@, 'default')", MGLConstantExpression(@1),
+ MGLConstantExpression(@"one"),
+ MGLConstantExpression(@0),
+ MGLConstantExpression(@"zero")];
+ NSExpression *predicate = [NSExpression expressionWithFormat:@"2 - 1"];
+ NSExpression *compatibilityExpression = [NSExpression expressionWithFormat:@"FUNCTION(%@, 'mgl_match:', %@)", predicate, @[MGLConstantExpression(@1),
+ MGLConstantExpression(@"one"),
+ MGLConstantExpression(@0),
+ MGLConstantExpression(@"zero"),
+ MGLConstantExpression(@"default")]];
+ NSArray *jsonExpression = @[@"match", @[@"-", @2, @1], @1, @"one", @0, @"zero", @"default"];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects(compatibilityExpression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionWithFormat:@"MGL_MATCH(2 * 1, %@, %@, 'default')", MGLConstantExpression(@1), MGLConstantExpression(@"one")];
+ NSArray *jsonExpression = @[@"match", @[@"*", @2, @1], @1, @"one", @"default"];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+}
+
+- (void)testCoalesceExpressionObject {
+ {
+ NSExpression *expression = [NSExpression expressionWithFormat:@"mgl_coalesce(%@)",
+ @[[NSExpression expressionForKeyPath:@"x"],
+ [NSExpression expressionForKeyPath:@"y"],
+ [NSExpression expressionForKeyPath:@"z"],
+ [NSExpression expressionForConstantValue:@0]]];
+ NSExpression *compatibilityExpression = [NSExpression expressionWithFormat:@"FUNCTION(%@, 'mgl_coalesce')", @[[NSExpression expressionForKeyPath:@"x"],
+ [NSExpression expressionForKeyPath:@"y"],
+ [NSExpression expressionForKeyPath:@"z"],
+ [NSExpression expressionForConstantValue:@0]]];
+ NSArray *jsonExpression = @[@"coalesce", @[@"get", @"x"], @[@"get", @"y"], @[@"get", @"z"], @0];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects(compatibilityExpression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+
+}
+
+- (void)testConditionalExpressionObject {
+ {
+ NSPredicate *conditional = [NSPredicate predicateWithFormat:@"1 = 2"];
+ NSExpression *trueExpression = [NSExpression expressionForConstantValue:@YES];
+ NSExpression *falseExpression = [NSExpression expressionForConstantValue:@NO];
+ NSExpression *expression = [NSExpression expressionForConditional:conditional trueExpression:trueExpression falseExpression:falseExpression];
+ NSArray *jsonExpression = @[@"case", @[@"==", @1, @2], @YES, @NO];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithFormat:@"TERNARY(1 = 2, TRUE, FALSE)"].mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @NO);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionWithFormat:@"TERNARY(0 = 1, TRUE, TERNARY(1 = 2, TRUE, FALSE))"];
+ NSArray *jsonExpression = @[@"case", @[@"==", @0, @1], @YES, @[@"==", @1, @2], @YES, @NO];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @NO);
+ expression = [NSExpression expressionWithFormat:@"MGL_IF(%@, TRUE, %@, TRUE, FALSE)",
+ MGLConstantExpression([NSPredicate predicateWithFormat:@"0 = 1"]),
+ MGLConstantExpression([NSPredicate predicateWithFormat:@"1 = 2"])];
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionWithFormat:@"MGL_IF(%@, %@, %@)",
+ [NSExpression expressionWithFormat:@"%@", [NSPredicate predicateWithFormat:@"1 = 2"]],
+ MGLConstantExpression(@YES),
+ MGLConstantExpression(@NO)];
+ NSExpression *compatibilityExpression = [NSExpression expressionWithFormat:@"FUNCTION(%@, 'mgl_if:', %@)", [NSPredicate predicateWithFormat:@"1 = 2"], @[MGLConstantExpression(@YES), MGLConstantExpression(@NO)]];
+ NSArray *jsonExpression = @[@"case", @[@"==", @1, @2], @YES, @NO];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects(compatibilityExpression.mgl_jsonExpressionObject, jsonExpression);
+ expression = [NSExpression expressionWithFormat:@"TERNARY(1 = 2, YES, NO)"];
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @NO);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionWithFormat:@"MGL_IF(%@, %@, %@, %@, %@)",
+ [NSExpression expressionWithFormat:@"%@", [NSPredicate predicateWithFormat:@"1 = 2"]],
+ MGLConstantExpression(@YES),
+ [NSExpression expressionWithFormat:@"%@", [NSPredicate predicateWithFormat:@"1 = 1"]],
+ MGLConstantExpression(@YES),
+ MGLConstantExpression(@NO)];
+ NSArray *jsonExpression = @[@"case", @[@"==", @1, @2], @YES, @[@"==", @1, @1], @YES, @NO];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @YES);
+ }
+ {
+ NSArray *jsonExpression = @[
+ @"case",
+ @[
+ @"<",
+ @[@"get", @"area"],
+ @80000
+ ],
+ @[@"get", @"abbr"],
+ @[@"get", @"name_en"]
+ ];
+ NSExpression *expression = [NSExpression expressionWithFormat:@"TERNARY(area < 80000, abbr, name_en)"];
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ }
+}
+
+- (void)testLookupExpressionObject {
+ {
+ NSExpression *array = [NSExpression expressionForAggregate:@[MGLConstantExpression(@9),
+ MGLConstantExpression(@8),
+ MGLConstantExpression(@7)]];
+ NSExpression *expression = [NSExpression expressionForFunction:@"objectFrom:withIndex:"
+ arguments:@[array, MGLConstantExpression(@1)]];
+ NSArray *jsonExpression = @[@"at", @1, @[ @"literal", @[@9, @8, @7]]];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *array = [NSExpression expressionForAggregate:@[MGLConstantExpression(@9),
+ MGLConstantExpression(@8),
+ MGLConstantExpression(@7)]];
+ NSExpression *expression = [NSExpression expressionForFunction:@"objectFrom:withIndex:"
+ arguments:@[array, [NSExpression expressionForKeyPath:@"x"]]];
+ NSArray *jsonExpression = @[@"at", @[@"get", @"x"], @[ @"literal", @[@9, @8, @7]]];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"mgl_does:have:"
+ arguments:@[[NSExpression expressionForEvaluatedObject],
+ [NSExpression expressionForConstantValue:@"x"]]];
+ NSExpression *compatibilityExpression = [NSExpression expressionWithFormat:@"FUNCTION(self, 'mgl_has:', 'x')"];
+ NSArray *jsonExpression = @[@"has", @"x"];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects(compatibilityExpression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"mgl_does:have:"
+ arguments:@[MGLConstantExpression(@{@"x": MGLConstantExpression(@0)}),
+ MGLConstantExpression(@"x")]];
+ NSArray *jsonExpression = @[@"has", @"x", @[@"literal", @{@"x": @0}]];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"mgl_does:have:"
+ arguments:@[[NSExpression expressionForVariable:@"featureAttributes"],
+ [NSExpression expressionForConstantValue:@"x"]]];
+ NSArray *jsonExpression = @[@"has", @"x", @[@"properties"]];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression;
+ expression = [NSExpression expressionWithFormat:@"TERNARY(key != nil, 1, 0)"];
+ NSArray *jsonExpression = @[@"case", @[@"!=", @[@"get", @"key"], [NSNull null]], @1, @0];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:@{} context:nil], @NO);
+ XCTAssertEqualObjects([expression expressionValueWithObject:@{@"key": @"🗝"} context:nil], @YES);
+ }
+ {
+ NSDictionary *dictionary = @{@"key": @"🔑"};
+ NSExpression *expression;
+ expression = [NSExpression expressionWithFormat:@"TERNARY(%@.key != nil, 1, 0)", dictionary];
+ NSArray *jsonExpression = @[@"case", @[@"!=", @[@"get", @"key", @[@"literal", dictionary]], [NSNull null]], @1, @0];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ // The dictionary isn’t equal enough.
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression].description, expression.description);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @YES);
+ }
+}
+
+- (void)testGenericExpressionObject {
+ {
+ NSExpression *expression = [NSExpression expressionWithFormat:@"MGL_FUNCTION('random', 1, 2, 3, 4, 5)"];
+ NSArray *jsonExpression = @[@"random", @1, @2, @3, @4, @5];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ expression = [NSExpression expressionWithFormat:@"MGL_FUNCTION('random', 1, 2, 3, 4)"];
+ XCTAssertThrowsSpecificNamed([expression expressionValueWithObject:nil context:nil], NSException, NSInvalidArgumentException);
+ }
+}
+
+#pragma mark - Localization tests
+
+- (void)testTokenReplacement {
+ {
+ NSExpression *original = MGLConstantExpression(@"");
+ NSExpression *expected = original;
+ XCTAssertEqualObjects(original.mgl_expressionByReplacingTokensWithKeyPaths, expected);
+ }
+ {
+ NSExpression *original = MGLConstantExpression(@"{");
+ NSExpression *expected = original;
+ XCTAssertEqualObjects(original.mgl_expressionByReplacingTokensWithKeyPaths, expected);
+ }
+ {
+ NSExpression *original = MGLConstantExpression(@"{token");
+ NSExpression *expected = original;
+ XCTAssertEqualObjects(original.mgl_expressionByReplacingTokensWithKeyPaths, expected);
+ }
+ {
+ NSExpression *original = MGLConstantExpression(@"{token}");
+ NSExpression *expected = [NSExpression expressionForKeyPath:@"token"];
+ XCTAssertEqualObjects(original.mgl_expressionByReplacingTokensWithKeyPaths, expected);
+ }
+ {
+ NSExpression *original = MGLConstantExpression(@"{token} {token}");
+ NSExpression *expected = [NSExpression expressionWithFormat:@"mgl_join({token, ' ', token})"];
+ XCTAssertEqualObjects(original.mgl_expressionByReplacingTokensWithKeyPaths, expected);
+ }
+ {
+ NSExpression *original = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, '{short}', %@)", @{
+ @1: MGLConstantExpression(@"{short}"),
+ @2: @"…",
+ @3: @"{long}",
+ }];
+ NSExpression *expected = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, short, %@)", @{
+ @1: [NSExpression expressionForKeyPath:@"short"],
+ @2: @"…",
+ @3: [NSExpression expressionForKeyPath:@"long"],
+ }];
+ XCTAssertEqualObjects(original.mgl_expressionByReplacingTokensWithKeyPaths, expected);
+ }
+}
+
+- (void)testLocalization {
+ {
+ NSExpression *original = MGLConstantExpression(@"");
+ NSExpression *expected = original;
+ XCTAssertEqualObjects([original mgl_expressionLocalizedIntoLocale:nil], expected);
+ }
+ {
+ NSExpression *original = MGLConstantExpression(@"Old MacDonald");
+ NSExpression *expected = original;
+ XCTAssertEqualObjects([original mgl_expressionLocalizedIntoLocale:nil], expected);
+ }
+ {
+ NSExpression *original = MGLConstantExpression(@"{name_en}");
+ NSExpression *expected = original;
+ XCTAssertEqualObjects([original mgl_expressionLocalizedIntoLocale:nil], expected);
+ }
+ {
+ NSExpression *original = [NSExpression expressionForKeyPath:@"name_en"];
+ NSExpression *expected = original;
+ XCTAssertEqualObjects([original mgl_expressionLocalizedIntoLocale:nil], expected);
+ }
+ {
+ NSExpression *original = [NSExpression expressionForKeyPath:@"name_en"];
+ NSExpression *expected = [NSExpression expressionForKeyPath:@"name"];
+ XCTAssertEqualObjects([original mgl_expressionLocalizedIntoLocale:[NSLocale localeWithLocaleIdentifier:@"mul"]], expected);
+ }
+ {
+ NSExpression *original = [NSExpression expressionForKeyPath:@"name_en"];
+ NSExpression *expected = [NSExpression expressionForKeyPath:@"name_fr"];
+ XCTAssertEqualObjects([original mgl_expressionLocalizedIntoLocale:[NSLocale localeWithLocaleIdentifier:@"fr-CA"]], expected);
+ }
+ {
+ NSExpression *original = [NSExpression expressionForKeyPath:@"name_en"];
+ NSExpression *expected = [NSExpression expressionForKeyPath:@"name_zh-Hans"];
+ XCTAssertEqualObjects([original mgl_expressionLocalizedIntoLocale:[NSLocale localeWithLocaleIdentifier:@"zh-Hans"]], expected);
+ }
+ {
+ NSExpression *original = [NSExpression expressionForKeyPath:@"name_en"];
+ NSExpression *expected = [NSExpression expressionForKeyPath:@"name"];
+ XCTAssertEqualObjects([original mgl_expressionLocalizedIntoLocale:[NSLocale localeWithLocaleIdentifier:@"tlh"]], expected);
+ }
+ {
+ NSExpression *original = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, short, %@)", @{
+ @1: [NSExpression expressionForKeyPath:@"abbr"],
+ @2: @"…",
+ @3: [NSExpression expressionForKeyPath:@"name_fr"],
+ }];
+ NSExpression *expected = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, short, %@)", @{
+ @1: [NSExpression expressionForKeyPath:@"abbr"],
+ @2: @"…",
+ @3: [NSExpression expressionForKeyPath:@"name_es"],
+ }];
+ XCTAssertEqualObjects([original mgl_expressionLocalizedIntoLocale:[NSLocale localeWithLocaleIdentifier:@"es-PR"]], expected);
+ }
+ {
+ NSArray *jsonExpression = @[
+ @"step",
+ @[@"zoom"],
+ @[
+ @"case",
+ @[
+ @"<",
+ @[
+ @"to-number",
+ @[@"get", @"area"]
+ ],
+ @80000
+ ],
+ @[@"get", @"abbr"],
+ @[@"get", @"name_en"]
+ ],
+ @5, @[@"get", @"name_en"]
+ ];
+ NSArray *localizedJSONExpression = @[
+ @"step",
+ @[@"zoom"],
+ @[
+ @"case",
+ @[
+ @"<",
+ @[
+ @"to-number",
+ @[@"get", @"area"]
+ ],
+ @80000
+ ],
+ @[@"get", @"abbr"],
+ @[@"get", @"name"]
+ ],
+ @5, @[@"get", @"name"]
+ ];
+ NSExpression *expression = [NSExpression expressionWithMGLJSONObject:jsonExpression];
+ NSExpression *localizedExpression = [expression mgl_expressionLocalizedIntoLocale:[NSLocale localeWithLocaleIdentifier:@"mul"]];
+ XCTAssertEqualObjects(localizedExpression.mgl_jsonExpressionObject, localizedJSONExpression);
+ }
+}
+
+- (void)testConvenienceInitializers {
+ {
+ NSExpression *expression = [NSExpression mgl_expressionForConditional:[NSPredicate predicateWithFormat:@"1 = 2"]
+ trueExpression:MGLConstantExpression(@YES)
+ falseExpresssion:MGLConstantExpression(@NO)];
+
+ NSArray *jsonExpression = @[@"case", @[@"==", @1, @2], @YES, @NO];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @NO);
+ }
+ {
+ NSDictionary *stops = @{@0: MGLConstantExpression(@111), @1: MGLConstantExpression(@1111)};
+ NSExpression *expression = [NSExpression mgl_expressionForSteppingExpression:[NSExpression expressionForKeyPath:@"x"]
+ fromExpression:[NSExpression expressionForConstantValue:@11]
+ stops:[NSExpression expressionForConstantValue:stops]];
+ NSArray *jsonExpression = @[@"step", @[@"get", @"x"], @11, @0, @111, @1, @1111];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSDictionary *stops = @{@0: MGLConstantExpression(@100), @10: MGLConstantExpression(@200)};
+ NSExpression *expression = [NSExpression mgl_expressionForInterpolatingExpression:[NSExpression expressionForKeyPath:@"x"]
+ withCurveType:MGLExpressionInterpolationModeLinear
+ parameters:nil
+ stops:[NSExpression expressionForConstantValue:stops]];
+ NSArray *jsonExpression = @[@"interpolate", @[@"linear"], @[@"get", @"x"], @0, @100, @10, @200];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [[NSExpression expressionForConstantValue:@"Old"] mgl_expressionByAppendingExpression:[NSExpression expressionForConstantValue:@"MacDonald"]];
+
+ NSArray *jsonExpression = @[@"concat", @"Old", @"MacDonald"];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @"OldMacDonald");
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSDictionary *values = @{ MGLConstantExpression(@1): MGLConstantExpression(@"one") };
+ NSExpression *expression = [NSExpression mgl_expressionForMatchingExpression:[NSExpression expressionWithFormat:@"2 * 1"]
+ inDictionary:values
+ defaultExpression:[NSExpression expressionForConstantValue:@"default"]];
+ NSArray *jsonExpression = @[@"match", @[@"*", @2, @1], @1, @"one", @"default"];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+}
+
+
@end
diff --git a/platform/darwin/test/MGLFeatureTests.mm b/platform/darwin/test/MGLFeatureTests.mm
index 818ad8200e..d135b018f4 100644
--- a/platform/darwin/test/MGLFeatureTests.mm
+++ b/platform/darwin/test/MGLFeatureTests.mm
@@ -38,7 +38,7 @@
};
features.push_back(mbgl::Feature { polygon });
- NS_ARRAY_OF(MGLShape <MGLFeature> *) *shapes = MGLFeaturesFromMBGLFeatures(features);
+ NSArray<MGLShape <MGLFeature> *> *shapes = MGLFeaturesFromMBGLFeatures(features);
XCTAssertEqual(shapes.count, 3, @"All features should be converted into shapes");
MGLPointFeature *pointShape = (MGLPointFeature *)shapes[0];
@@ -69,7 +69,7 @@
[NSValue valueWithMGLCoordinate:CLLocationCoordinate2DMake(4, 4)]);
XCTAssertEqualObjects([NSValue valueWithMGLCoordinate:polygonCoordinates[3]],
[NSValue valueWithMGLCoordinate:CLLocationCoordinate2DMake(4, 1)]);
- NS_ARRAY_OF(MGLPolygon *) *interiorPolygons = polygonShape.interiorPolygons;
+ NSArray<MGLPolygon *> *interiorPolygons = polygonShape.interiorPolygons;
XCTAssertEqual(interiorPolygons.count, 1);
MGLPolygon *interiorPolygon = interiorPolygons.firstObject;
XCTAssertEqual(interiorPolygon.pointCount, 4);
@@ -103,7 +103,7 @@
vector.push_back(true);
features.push_back(pointFeature);
- NS_ARRAY_OF(MGLShape <MGLFeature> *) *shapes = MGLFeaturesFromMBGLFeatures(features);
+ NSArray<MGLShape <MGLFeature> *> *shapes = MGLFeaturesFromMBGLFeatures(features);
XCTAssertEqual(shapes.count, 1, @"All features should be converted into shapes");
MGLShape <MGLFeature> *shape = shapes.firstObject;
@@ -298,29 +298,36 @@
}
- (void)testShapeCollectionFeatureGeoJSONDictionary {
- MGLPointAnnotation *pointFeature = [[MGLPointAnnotation alloc] init];
+ MGLPointFeature *pointFeature = [[MGLPointFeature alloc] init];
CLLocationCoordinate2D pointCoordinate = { 10, 10 };
pointFeature.coordinate = pointCoordinate;
CLLocationCoordinate2D coord1 = { 0, 0 };
CLLocationCoordinate2D coord2 = { 10, 10 };
CLLocationCoordinate2D coords[] = { coord1, coord2 };
- MGLPolyline *polyline = [MGLPolyline polylineWithCoordinates:coords count:2];
+ MGLPolylineFeature *polylineFeature = [MGLPolylineFeature polylineWithCoordinates:coords count:2];
+
+ MGLShapeCollectionFeature *shapeCollectionFeature = [MGLShapeCollectionFeature shapeCollectionWithShapes:@[pointFeature, polylineFeature]];
- MGLShapeCollectionFeature *shapeCollectionFeature = [MGLShapeCollectionFeature shapeCollectionWithShapes:@[pointFeature,
- polyline]];
// A GeoJSON feature
NSDictionary *geoJSONFeature = [shapeCollectionFeature geoJSONDictionary];
// it has the correct geometry
NSDictionary *expectedGeometry = @{@"type": @"GeometryCollection",
@"geometries": @[
- @{@"type": @"Point",
- @"coordinates": @[@(pointCoordinate.longitude), @(pointCoordinate.latitude)]},
- @{@"type": @"LineString",
- @"coordinates": @[@[@(coord1.longitude), @(coord1.latitude)],
- @[@(coord2.longitude), @(coord2.latitude)]]}
- ]};
+ @{ @"geometry": @{@"type": @"Point",
+ @"coordinates": @[@(pointCoordinate.longitude), @(pointCoordinate.latitude)]},
+ @"properties": [NSNull null],
+ @"type": @"Feature",
+ },
+ @{ @"geometry": @{@"type": @"LineString",
+ @"coordinates": @[@[@(coord1.longitude), @(coord1.latitude)],
+ @[@(coord2.longitude), @(coord2.latitude)]]},
+ @"properties": [NSNull null],
+ @"type": @"Feature",
+ }
+ ]
+ };
XCTAssertEqualObjects(geoJSONFeature[@"geometry"], expectedGeometry);
// When the shape collection is created with an empty array of shapes
diff --git a/platform/darwin/test/MGLFillExtrusionStyleLayerTests.mm b/platform/darwin/test/MGLFillExtrusionStyleLayerTests.mm
index 5d99c815ea..6081d104e1 100644
--- a/platform/darwin/test/MGLFillExtrusionStyleLayerTests.mm
+++ b/platform/darwin/test/MGLFillExtrusionStyleLayerTests.mm
@@ -30,8 +30,8 @@
XCTAssertNil(layer.sourceLayerIdentifier);
XCTAssertNil(layer.predicate);
- layer.predicate = [NSPredicate predicateWithValue:NO];
- XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithValue:NO]);
+ layer.predicate = [NSPredicate predicateWithFormat:@"$featureIdentifier = 1"];
+ XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithFormat:@"$featureIdentifier = 1"]);
layer.predicate = nil;
XCTAssertNil(layer.predicate);
}
@@ -52,40 +52,45 @@
{
XCTAssertTrue(rawLayer->getFillExtrusionBase().isUndefined(),
@"fill-extrusion-base should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.fillExtrusionBase;
+ NSExpression *defaultExpression = layer.fillExtrusionBase;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.fillExtrusionBase = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.fillExtrusionBase = constantExpression;
mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getFillExtrusionBase(), propertyValue,
- @"Setting fillExtrusionBase to a constant value should update fill-extrusion-base.");
- XCTAssertEqualObjects(layer.fillExtrusionBase, constantStyleValue,
- @"fillExtrusionBase should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.fillExtrusionBase = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting fillExtrusionBase to a constant value expression should update fill-extrusion-base.");
+ XCTAssertEqualObjects(layer.fillExtrusionBase, constantExpression,
+ @"fillExtrusionBase should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.fillExtrusionBase = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getFillExtrusionBase(), propertyValue,
- @"Setting fillExtrusionBase to a camera function should update fill-extrusion-base.");
- XCTAssertEqualObjects(layer.fillExtrusionBase, functionStyleValue,
- @"fillExtrusionBase should round-trip camera functions.");
+ @"Setting fillExtrusionBase to a camera expression should update fill-extrusion-base.");
+ XCTAssertEqualObjects(layer.fillExtrusionBase, functionExpression,
+ @"fillExtrusionBase should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.fillExtrusionBase = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.fillExtrusionBase = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getFillExtrusionBase(), propertyValue,
- @"Setting fillExtrusionBase to a source function should update fill-extrusion-base.");
- XCTAssertEqualObjects(layer.fillExtrusionBase, functionStyleValue,
- @"fillExtrusionBase should round-trip source functions.");
+ @"Setting fillExtrusionBase to a data expression should update fill-extrusion-base.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.fillExtrusionBase, pedanticFunctionExpression,
+ @"fillExtrusionBase should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.fillExtrusionBase = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.fillExtrusionBase = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -93,15 +98,16 @@
propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getFillExtrusionBase(), propertyValue,
- @"Setting fillExtrusionBase to a composite function should update fill-extrusion-base.");
- XCTAssertEqualObjects(layer.fillExtrusionBase, functionStyleValue,
- @"fillExtrusionBase should round-trip composite functions.");
+ @"Setting fillExtrusionBase to a camera-data expression should update fill-extrusion-base.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.fillExtrusionBase, pedanticFunctionExpression,
+ @"fillExtrusionBase should round-trip camera-data expressions.");
layer.fillExtrusionBase = nil;
XCTAssertTrue(rawLayer->getFillExtrusionBase().isUndefined(),
@"Unsetting fillExtrusionBase should return fill-extrusion-base to the default value.");
- XCTAssertEqualObjects(layer.fillExtrusionBase, defaultStyleValue,
+ XCTAssertEqualObjects(layer.fillExtrusionBase, defaultExpression,
@"fillExtrusionBase should return the default value after being unset.");
// Transition property test
layer.fillExtrusionBaseTransition = transitionTest;
@@ -118,40 +124,45 @@
{
XCTAssertTrue(rawLayer->getFillExtrusionColor().isUndefined(),
@"fill-extrusion-color should be unset initially.");
- MGLStyleValue<MGLColor *> *defaultStyleValue = layer.fillExtrusionColor;
+ NSExpression *defaultExpression = layer.fillExtrusionColor;
- MGLStyleValue<MGLColor *> *constantStyleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
- layer.fillExtrusionColor = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ layer.fillExtrusionColor = constantExpression;
mbgl::style::DataDrivenPropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getFillExtrusionColor(), propertyValue,
- @"Setting fillExtrusionColor to a constant value should update fill-extrusion-color.");
- XCTAssertEqualObjects(layer.fillExtrusionColor, constantStyleValue,
- @"fillExtrusionColor should round-trip constant values.");
-
- MGLStyleValue<MGLColor *> * functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.fillExtrusionColor = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::Color> intervalStops = { {{18, { 1, 0, 0, 1 }}} };
+ @"Setting fillExtrusionColor to a constant value expression should update fill-extrusion-color.");
+ XCTAssertEqualObjects(layer.fillExtrusionColor, constantExpression,
+ @"fillExtrusionColor should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.fillExtrusionColor = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::Color> intervalStops = {{
+ { -INFINITY, { 1, 0, 0, 1 } },
+ { 18, { 1, 0, 0, 1 } },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::Color> { intervalStops };
XCTAssertEqual(rawLayer->getFillExtrusionColor(), propertyValue,
- @"Setting fillExtrusionColor to a camera function should update fill-extrusion-color.");
- XCTAssertEqualObjects(layer.fillExtrusionColor, functionStyleValue,
- @"fillExtrusionColor should round-trip camera functions.");
+ @"Setting fillExtrusionColor to a camera expression should update fill-extrusion-color.");
+ XCTAssertEqualObjects(layer.fillExtrusionColor, functionExpression,
+ @"fillExtrusionColor should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.fillExtrusionColor = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.fillExtrusionColor = functionExpression;
mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<mbgl::Color> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getFillExtrusionColor(), propertyValue,
- @"Setting fillExtrusionColor to a source function should update fill-extrusion-color.");
- XCTAssertEqualObjects(layer.fillExtrusionColor, functionStyleValue,
- @"fillExtrusionColor should round-trip source functions.");
+ @"Setting fillExtrusionColor to a data expression should update fill-extrusion-color.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.fillExtrusionColor, pedanticFunctionExpression,
+ @"fillExtrusionColor should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.fillExtrusionColor = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.fillExtrusionColor = functionExpression;
std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
mbgl::style::CompositeExponentialStops<mbgl::Color> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -159,15 +170,16 @@
propertyValue = mbgl::style::CompositeFunction<mbgl::Color> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getFillExtrusionColor(), propertyValue,
- @"Setting fillExtrusionColor to a composite function should update fill-extrusion-color.");
- XCTAssertEqualObjects(layer.fillExtrusionColor, functionStyleValue,
- @"fillExtrusionColor should round-trip composite functions.");
+ @"Setting fillExtrusionColor to a camera-data expression should update fill-extrusion-color.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.fillExtrusionColor, pedanticFunctionExpression,
+ @"fillExtrusionColor should round-trip camera-data expressions.");
layer.fillExtrusionColor = nil;
XCTAssertTrue(rawLayer->getFillExtrusionColor().isUndefined(),
@"Unsetting fillExtrusionColor should return fill-extrusion-color to the default value.");
- XCTAssertEqualObjects(layer.fillExtrusionColor, defaultStyleValue,
+ XCTAssertEqualObjects(layer.fillExtrusionColor, defaultExpression,
@"fillExtrusionColor should return the default value after being unset.");
// Transition property test
layer.fillExtrusionColorTransition = transitionTest;
@@ -184,40 +196,45 @@
{
XCTAssertTrue(rawLayer->getFillExtrusionHeight().isUndefined(),
@"fill-extrusion-height should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.fillExtrusionHeight;
+ NSExpression *defaultExpression = layer.fillExtrusionHeight;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.fillExtrusionHeight = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.fillExtrusionHeight = constantExpression;
mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getFillExtrusionHeight(), propertyValue,
- @"Setting fillExtrusionHeight to a constant value should update fill-extrusion-height.");
- XCTAssertEqualObjects(layer.fillExtrusionHeight, constantStyleValue,
- @"fillExtrusionHeight should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.fillExtrusionHeight = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting fillExtrusionHeight to a constant value expression should update fill-extrusion-height.");
+ XCTAssertEqualObjects(layer.fillExtrusionHeight, constantExpression,
+ @"fillExtrusionHeight should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.fillExtrusionHeight = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getFillExtrusionHeight(), propertyValue,
- @"Setting fillExtrusionHeight to a camera function should update fill-extrusion-height.");
- XCTAssertEqualObjects(layer.fillExtrusionHeight, functionStyleValue,
- @"fillExtrusionHeight should round-trip camera functions.");
+ @"Setting fillExtrusionHeight to a camera expression should update fill-extrusion-height.");
+ XCTAssertEqualObjects(layer.fillExtrusionHeight, functionExpression,
+ @"fillExtrusionHeight should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.fillExtrusionHeight = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.fillExtrusionHeight = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getFillExtrusionHeight(), propertyValue,
- @"Setting fillExtrusionHeight to a source function should update fill-extrusion-height.");
- XCTAssertEqualObjects(layer.fillExtrusionHeight, functionStyleValue,
- @"fillExtrusionHeight should round-trip source functions.");
+ @"Setting fillExtrusionHeight to a data expression should update fill-extrusion-height.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.fillExtrusionHeight, pedanticFunctionExpression,
+ @"fillExtrusionHeight should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.fillExtrusionHeight = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.fillExtrusionHeight = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -225,15 +242,16 @@
propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getFillExtrusionHeight(), propertyValue,
- @"Setting fillExtrusionHeight to a composite function should update fill-extrusion-height.");
- XCTAssertEqualObjects(layer.fillExtrusionHeight, functionStyleValue,
- @"fillExtrusionHeight should round-trip composite functions.");
+ @"Setting fillExtrusionHeight to a camera-data expression should update fill-extrusion-height.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.fillExtrusionHeight, pedanticFunctionExpression,
+ @"fillExtrusionHeight should round-trip camera-data expressions.");
layer.fillExtrusionHeight = nil;
XCTAssertTrue(rawLayer->getFillExtrusionHeight().isUndefined(),
@"Unsetting fillExtrusionHeight should return fill-extrusion-height to the default value.");
- XCTAssertEqualObjects(layer.fillExtrusionHeight, defaultStyleValue,
+ XCTAssertEqualObjects(layer.fillExtrusionHeight, defaultExpression,
@"fillExtrusionHeight should return the default value after being unset.");
// Transition property test
layer.fillExtrusionHeightTransition = transitionTest;
@@ -250,39 +268,44 @@
{
XCTAssertTrue(rawLayer->getFillExtrusionOpacity().isUndefined(),
@"fill-extrusion-opacity should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.fillExtrusionOpacity;
+ NSExpression *defaultExpression = layer.fillExtrusionOpacity;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.fillExtrusionOpacity = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.fillExtrusionOpacity = constantExpression;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getFillExtrusionOpacity(), propertyValue,
- @"Setting fillExtrusionOpacity to a constant value should update fill-extrusion-opacity.");
- XCTAssertEqualObjects(layer.fillExtrusionOpacity, constantStyleValue,
- @"fillExtrusionOpacity should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.fillExtrusionOpacity = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting fillExtrusionOpacity to a constant value expression should update fill-extrusion-opacity.");
+ XCTAssertEqualObjects(layer.fillExtrusionOpacity, constantExpression,
+ @"fillExtrusionOpacity should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.fillExtrusionOpacity = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getFillExtrusionOpacity(), propertyValue,
- @"Setting fillExtrusionOpacity to a camera function should update fill-extrusion-opacity.");
- XCTAssertEqualObjects(layer.fillExtrusionOpacity, functionStyleValue,
- @"fillExtrusionOpacity should round-trip camera functions.");
+ @"Setting fillExtrusionOpacity to a camera expression should update fill-extrusion-opacity.");
+ XCTAssertEqualObjects(layer.fillExtrusionOpacity, functionExpression,
+ @"fillExtrusionOpacity should round-trip camera expressions.");
layer.fillExtrusionOpacity = nil;
XCTAssertTrue(rawLayer->getFillExtrusionOpacity().isUndefined(),
@"Unsetting fillExtrusionOpacity should return fill-extrusion-opacity to the default value.");
- XCTAssertEqualObjects(layer.fillExtrusionOpacity, defaultStyleValue,
+ XCTAssertEqualObjects(layer.fillExtrusionOpacity, defaultExpression,
@"fillExtrusionOpacity should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.fillExtrusionOpacity = 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.fillExtrusionOpacity = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.fillExtrusionOpacity = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillExtrusionLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.fillExtrusionOpacity = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillExtrusionLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
// Transition property test
layer.fillExtrusionOpacityTransition = transitionTest;
auto toptions = rawLayer->getFillExtrusionOpacityTransition();
@@ -298,39 +321,44 @@
{
XCTAssertTrue(rawLayer->getFillExtrusionPattern().isUndefined(),
@"fill-extrusion-pattern should be unset initially.");
- MGLStyleValue<NSString *> *defaultStyleValue = layer.fillExtrusionPattern;
+ NSExpression *defaultExpression = layer.fillExtrusionPattern;
- MGLStyleValue<NSString *> *constantStyleValue = [MGLStyleValue<NSString *> valueWithRawValue:@"Fill Extrusion Pattern"];
- layer.fillExtrusionPattern = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'Fill Extrusion Pattern'"];
+ layer.fillExtrusionPattern = constantExpression;
mbgl::style::PropertyValue<std::string> propertyValue = { "Fill Extrusion Pattern" };
XCTAssertEqual(rawLayer->getFillExtrusionPattern(), propertyValue,
- @"Setting fillExtrusionPattern to a constant value should update fill-extrusion-pattern.");
- XCTAssertEqualObjects(layer.fillExtrusionPattern, constantStyleValue,
- @"fillExtrusionPattern should round-trip constant values.");
-
- MGLStyleValue<NSString *> * functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.fillExtrusionPattern = functionStyleValue;
-
- mbgl::style::IntervalStops<std::string> intervalStops = { {{18, "Fill Extrusion Pattern"}} };
+ @"Setting fillExtrusionPattern to a constant value expression should update fill-extrusion-pattern.");
+ XCTAssertEqualObjects(layer.fillExtrusionPattern, constantExpression,
+ @"fillExtrusionPattern should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"'Fill Extrusion Pattern'"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.fillExtrusionPattern = functionExpression;
+
+ mbgl::style::IntervalStops<std::string> intervalStops = {{
+ { -INFINITY, "Fill Extrusion Pattern" },
+ { 18, "Fill Extrusion Pattern" },
+ }};
propertyValue = mbgl::style::CameraFunction<std::string> { intervalStops };
XCTAssertEqual(rawLayer->getFillExtrusionPattern(), propertyValue,
- @"Setting fillExtrusionPattern to a camera function should update fill-extrusion-pattern.");
- XCTAssertEqualObjects(layer.fillExtrusionPattern, functionStyleValue,
- @"fillExtrusionPattern should round-trip camera functions.");
+ @"Setting fillExtrusionPattern to a camera expression should update fill-extrusion-pattern.");
+ XCTAssertEqualObjects(layer.fillExtrusionPattern, functionExpression,
+ @"fillExtrusionPattern should round-trip camera expressions.");
layer.fillExtrusionPattern = nil;
XCTAssertTrue(rawLayer->getFillExtrusionPattern().isUndefined(),
@"Unsetting fillExtrusionPattern should return fill-extrusion-pattern to the default value.");
- XCTAssertEqualObjects(layer.fillExtrusionPattern, defaultStyleValue,
+ XCTAssertEqualObjects(layer.fillExtrusionPattern, defaultExpression,
@"fillExtrusionPattern should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.fillExtrusionPattern = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.fillExtrusionPattern = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.fillExtrusionPattern = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillExtrusionLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.fillExtrusionPattern = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillExtrusionLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
// Transition property test
layer.fillExtrusionPatternTransition = transitionTest;
auto toptions = rawLayer->getFillExtrusionPatternTransition();
@@ -346,84 +374,94 @@
{
XCTAssertTrue(rawLayer->getFillExtrusionTranslate().isUndefined(),
@"fill-extrusion-translate should be unset initially.");
- MGLStyleValue<NSValue *> *defaultStyleValue = layer.fillExtrusionTranslation;
+ NSExpression *defaultExpression = layer.fillExtrusionTranslation;
- MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"%@",
#if TARGET_OS_IPHONE
[NSValue valueWithCGVector:CGVectorMake(1, 1)]
#else
[NSValue valueWithMGLVector:CGVectorMake(1, -1)]
#endif
];
- layer.fillExtrusionTranslation = constantStyleValue;
+ layer.fillExtrusionTranslation = constantExpression;
mbgl::style::PropertyValue<std::array<float, 2>> propertyValue = { { 1, 1 } };
XCTAssertEqual(rawLayer->getFillExtrusionTranslate(), propertyValue,
- @"Setting fillExtrusionTranslation to a constant value should update fill-extrusion-translate.");
- XCTAssertEqualObjects(layer.fillExtrusionTranslation, constantStyleValue,
- @"fillExtrusionTranslation should round-trip constant values.");
-
- MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.fillExtrusionTranslation = functionStyleValue;
-
- mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = { {{18, { 1, 1 }}} };
+ @"Setting fillExtrusionTranslation to a constant value expression should update fill-extrusion-translate.");
+ XCTAssertEqualObjects(layer.fillExtrusionTranslation, constantExpression,
+ @"fillExtrusionTranslation should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"{1, 1}"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.fillExtrusionTranslation = functionExpression;
+
+ mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = {{
+ { -INFINITY, { 1, 1 } },
+ { 18, { 1, 1 } },
+ }};
propertyValue = mbgl::style::CameraFunction<std::array<float, 2>> { intervalStops };
XCTAssertEqual(rawLayer->getFillExtrusionTranslate(), propertyValue,
- @"Setting fillExtrusionTranslation to a camera function should update fill-extrusion-translate.");
- XCTAssertEqualObjects(layer.fillExtrusionTranslation, functionStyleValue,
- @"fillExtrusionTranslation should round-trip camera functions.");
+ @"Setting fillExtrusionTranslation to a camera expression should update fill-extrusion-translate.");
+ XCTAssertEqualObjects(layer.fillExtrusionTranslation, functionExpression,
+ @"fillExtrusionTranslation should round-trip camera expressions.");
layer.fillExtrusionTranslation = nil;
XCTAssertTrue(rawLayer->getFillExtrusionTranslate().isUndefined(),
@"Unsetting fillExtrusionTranslation should return fill-extrusion-translate to the default value.");
- XCTAssertEqualObjects(layer.fillExtrusionTranslation, defaultStyleValue,
+ XCTAssertEqualObjects(layer.fillExtrusionTranslation, defaultExpression,
@"fillExtrusionTranslation should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.fillExtrusionTranslation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.fillExtrusionTranslation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.fillExtrusionTranslation = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillExtrusionLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.fillExtrusionTranslation = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillExtrusionLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// fill-extrusion-translate-anchor
{
XCTAssertTrue(rawLayer->getFillExtrusionTranslateAnchor().isUndefined(),
@"fill-extrusion-translate-anchor should be unset initially.");
- MGLStyleValue<NSValue *> *defaultStyleValue = layer.fillExtrusionTranslationAnchor;
+ NSExpression *defaultExpression = layer.fillExtrusionTranslationAnchor;
- MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLFillExtrusionTranslationAnchor:MGLFillExtrusionTranslationAnchorViewport]];
- layer.fillExtrusionTranslationAnchor = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'viewport'"];
+ layer.fillExtrusionTranslationAnchor = constantExpression;
mbgl::style::PropertyValue<mbgl::style::TranslateAnchorType> propertyValue = { mbgl::style::TranslateAnchorType::Viewport };
XCTAssertEqual(rawLayer->getFillExtrusionTranslateAnchor(), propertyValue,
- @"Setting fillExtrusionTranslationAnchor to a constant value should update fill-extrusion-translate-anchor.");
- XCTAssertEqualObjects(layer.fillExtrusionTranslationAnchor, constantStyleValue,
- @"fillExtrusionTranslationAnchor should round-trip constant values.");
-
- MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.fillExtrusionTranslationAnchor = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::style::TranslateAnchorType> intervalStops = { {{18, mbgl::style::TranslateAnchorType::Viewport}} };
+ @"Setting fillExtrusionTranslationAnchor to a constant value expression should update fill-extrusion-translate-anchor.");
+ XCTAssertEqualObjects(layer.fillExtrusionTranslationAnchor, constantExpression,
+ @"fillExtrusionTranslationAnchor should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"'viewport'"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.fillExtrusionTranslationAnchor = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::style::TranslateAnchorType> intervalStops = {{
+ { -INFINITY, mbgl::style::TranslateAnchorType::Viewport },
+ { 18, mbgl::style::TranslateAnchorType::Viewport },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::style::TranslateAnchorType> { intervalStops };
XCTAssertEqual(rawLayer->getFillExtrusionTranslateAnchor(), propertyValue,
- @"Setting fillExtrusionTranslationAnchor to a camera function should update fill-extrusion-translate-anchor.");
- XCTAssertEqualObjects(layer.fillExtrusionTranslationAnchor, functionStyleValue,
- @"fillExtrusionTranslationAnchor should round-trip camera functions.");
+ @"Setting fillExtrusionTranslationAnchor to a camera expression should update fill-extrusion-translate-anchor.");
+ XCTAssertEqualObjects(layer.fillExtrusionTranslationAnchor, functionExpression,
+ @"fillExtrusionTranslationAnchor should round-trip camera expressions.");
layer.fillExtrusionTranslationAnchor = nil;
XCTAssertTrue(rawLayer->getFillExtrusionTranslateAnchor().isUndefined(),
@"Unsetting fillExtrusionTranslationAnchor should return fill-extrusion-translate-anchor to the default value.");
- XCTAssertEqualObjects(layer.fillExtrusionTranslationAnchor, defaultStyleValue,
+ XCTAssertEqualObjects(layer.fillExtrusionTranslationAnchor, defaultExpression,
@"fillExtrusionTranslationAnchor should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.fillExtrusionTranslationAnchor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.fillExtrusionTranslationAnchor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.fillExtrusionTranslationAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillExtrusionLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.fillExtrusionTranslationAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillExtrusionLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
}
diff --git a/platform/darwin/test/MGLFillStyleLayerTests.mm b/platform/darwin/test/MGLFillStyleLayerTests.mm
index 85f0b24fa7..a5019f1032 100644
--- a/platform/darwin/test/MGLFillStyleLayerTests.mm
+++ b/platform/darwin/test/MGLFillStyleLayerTests.mm
@@ -30,8 +30,8 @@
XCTAssertNil(layer.sourceLayerIdentifier);
XCTAssertNil(layer.predicate);
- layer.predicate = [NSPredicate predicateWithValue:NO];
- XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithValue:NO]);
+ layer.predicate = [NSPredicate predicateWithFormat:@"$featureIdentifier = 1"];
+ XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithFormat:@"$featureIdentifier = 1"]);
layer.predicate = nil;
XCTAssertNil(layer.predicate);
}
@@ -52,79 +52,89 @@
{
XCTAssertTrue(rawLayer->getFillAntialias().isUndefined(),
@"fill-antialias should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.fillAntialiased;
+ NSExpression *defaultExpression = layer.fillAntialiased;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@NO];
- layer.fillAntialiased = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"false"];
+ layer.fillAntialiased = constantExpression;
mbgl::style::PropertyValue<bool> propertyValue = { false };
XCTAssertEqual(rawLayer->getFillAntialias(), propertyValue,
- @"Setting fillAntialiased to a constant value should update fill-antialias.");
- XCTAssertEqualObjects(layer.fillAntialiased, constantStyleValue,
- @"fillAntialiased should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.fillAntialiased = functionStyleValue;
-
- mbgl::style::IntervalStops<bool> intervalStops = { {{18, false}} };
+ @"Setting fillAntialiased to a constant value expression should update fill-antialias.");
+ XCTAssertEqualObjects(layer.fillAntialiased, constantExpression,
+ @"fillAntialiased should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"false"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.fillAntialiased = functionExpression;
+
+ mbgl::style::IntervalStops<bool> intervalStops = {{
+ { -INFINITY, false },
+ { 18, false },
+ }};
propertyValue = mbgl::style::CameraFunction<bool> { intervalStops };
XCTAssertEqual(rawLayer->getFillAntialias(), propertyValue,
- @"Setting fillAntialiased to a camera function should update fill-antialias.");
- XCTAssertEqualObjects(layer.fillAntialiased, functionStyleValue,
- @"fillAntialiased should round-trip camera functions.");
+ @"Setting fillAntialiased to a camera expression should update fill-antialias.");
+ XCTAssertEqualObjects(layer.fillAntialiased, functionExpression,
+ @"fillAntialiased should round-trip camera expressions.");
layer.fillAntialiased = nil;
XCTAssertTrue(rawLayer->getFillAntialias().isUndefined(),
@"Unsetting fillAntialiased should return fill-antialias to the default value.");
- XCTAssertEqualObjects(layer.fillAntialiased, defaultStyleValue,
+ XCTAssertEqualObjects(layer.fillAntialiased, defaultExpression,
@"fillAntialiased should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.fillAntialiased = 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.fillAntialiased = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.fillAntialiased = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.fillAntialiased = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// fill-color
{
XCTAssertTrue(rawLayer->getFillColor().isUndefined(),
@"fill-color should be unset initially.");
- MGLStyleValue<MGLColor *> *defaultStyleValue = layer.fillColor;
+ NSExpression *defaultExpression = layer.fillColor;
- MGLStyleValue<MGLColor *> *constantStyleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
- layer.fillColor = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ layer.fillColor = constantExpression;
mbgl::style::DataDrivenPropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getFillColor(), propertyValue,
- @"Setting fillColor to a constant value should update fill-color.");
- XCTAssertEqualObjects(layer.fillColor, constantStyleValue,
- @"fillColor should round-trip constant values.");
-
- MGLStyleValue<MGLColor *> * functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.fillColor = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::Color> intervalStops = { {{18, { 1, 0, 0, 1 }}} };
+ @"Setting fillColor to a constant value expression should update fill-color.");
+ XCTAssertEqualObjects(layer.fillColor, constantExpression,
+ @"fillColor should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.fillColor = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::Color> intervalStops = {{
+ { -INFINITY, { 1, 0, 0, 1 } },
+ { 18, { 1, 0, 0, 1 } },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::Color> { intervalStops };
XCTAssertEqual(rawLayer->getFillColor(), propertyValue,
- @"Setting fillColor to a camera function should update fill-color.");
- XCTAssertEqualObjects(layer.fillColor, functionStyleValue,
- @"fillColor should round-trip camera functions.");
+ @"Setting fillColor to a camera expression should update fill-color.");
+ XCTAssertEqualObjects(layer.fillColor, functionExpression,
+ @"fillColor should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.fillColor = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.fillColor = functionExpression;
mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<mbgl::Color> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getFillColor(), propertyValue,
- @"Setting fillColor to a source function should update fill-color.");
- XCTAssertEqualObjects(layer.fillColor, functionStyleValue,
- @"fillColor should round-trip source functions.");
+ @"Setting fillColor to a data expression should update fill-color.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.fillColor, pedanticFunctionExpression,
+ @"fillColor should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.fillColor = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.fillColor = functionExpression;
std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
mbgl::style::CompositeExponentialStops<mbgl::Color> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -132,15 +142,16 @@
propertyValue = mbgl::style::CompositeFunction<mbgl::Color> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getFillColor(), propertyValue,
- @"Setting fillColor to a composite function should update fill-color.");
- XCTAssertEqualObjects(layer.fillColor, functionStyleValue,
- @"fillColor should round-trip composite functions.");
+ @"Setting fillColor to a camera-data expression should update fill-color.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.fillColor, pedanticFunctionExpression,
+ @"fillColor should round-trip camera-data expressions.");
layer.fillColor = nil;
XCTAssertTrue(rawLayer->getFillColor().isUndefined(),
@"Unsetting fillColor should return fill-color to the default value.");
- XCTAssertEqualObjects(layer.fillColor, defaultStyleValue,
+ XCTAssertEqualObjects(layer.fillColor, defaultExpression,
@"fillColor should return the default value after being unset.");
// Transition property test
layer.fillColorTransition = transitionTest;
@@ -157,40 +168,45 @@
{
XCTAssertTrue(rawLayer->getFillOpacity().isUndefined(),
@"fill-opacity should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.fillOpacity;
+ NSExpression *defaultExpression = layer.fillOpacity;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.fillOpacity = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.fillOpacity = constantExpression;
mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getFillOpacity(), propertyValue,
- @"Setting fillOpacity to a constant value should update fill-opacity.");
- XCTAssertEqualObjects(layer.fillOpacity, constantStyleValue,
- @"fillOpacity should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.fillOpacity = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting fillOpacity to a constant value expression should update fill-opacity.");
+ XCTAssertEqualObjects(layer.fillOpacity, constantExpression,
+ @"fillOpacity should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.fillOpacity = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getFillOpacity(), propertyValue,
- @"Setting fillOpacity to a camera function should update fill-opacity.");
- XCTAssertEqualObjects(layer.fillOpacity, functionStyleValue,
- @"fillOpacity should round-trip camera functions.");
+ @"Setting fillOpacity to a camera expression should update fill-opacity.");
+ XCTAssertEqualObjects(layer.fillOpacity, functionExpression,
+ @"fillOpacity should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.fillOpacity = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.fillOpacity = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getFillOpacity(), propertyValue,
- @"Setting fillOpacity to a source function should update fill-opacity.");
- XCTAssertEqualObjects(layer.fillOpacity, functionStyleValue,
- @"fillOpacity should round-trip source functions.");
+ @"Setting fillOpacity to a data expression should update fill-opacity.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.fillOpacity, pedanticFunctionExpression,
+ @"fillOpacity should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.fillOpacity = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.fillOpacity = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -198,15 +214,16 @@
propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getFillOpacity(), propertyValue,
- @"Setting fillOpacity to a composite function should update fill-opacity.");
- XCTAssertEqualObjects(layer.fillOpacity, functionStyleValue,
- @"fillOpacity should round-trip composite functions.");
+ @"Setting fillOpacity to a camera-data expression should update fill-opacity.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.fillOpacity, pedanticFunctionExpression,
+ @"fillOpacity should round-trip camera-data expressions.");
layer.fillOpacity = nil;
XCTAssertTrue(rawLayer->getFillOpacity().isUndefined(),
@"Unsetting fillOpacity should return fill-opacity to the default value.");
- XCTAssertEqualObjects(layer.fillOpacity, defaultStyleValue,
+ XCTAssertEqualObjects(layer.fillOpacity, defaultExpression,
@"fillOpacity should return the default value after being unset.");
// Transition property test
layer.fillOpacityTransition = transitionTest;
@@ -223,40 +240,45 @@
{
XCTAssertTrue(rawLayer->getFillOutlineColor().isUndefined(),
@"fill-outline-color should be unset initially.");
- MGLStyleValue<MGLColor *> *defaultStyleValue = layer.fillOutlineColor;
+ NSExpression *defaultExpression = layer.fillOutlineColor;
- MGLStyleValue<MGLColor *> *constantStyleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
- layer.fillOutlineColor = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ layer.fillOutlineColor = constantExpression;
mbgl::style::DataDrivenPropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getFillOutlineColor(), propertyValue,
- @"Setting fillOutlineColor to a constant value should update fill-outline-color.");
- XCTAssertEqualObjects(layer.fillOutlineColor, constantStyleValue,
- @"fillOutlineColor should round-trip constant values.");
-
- MGLStyleValue<MGLColor *> * functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.fillOutlineColor = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::Color> intervalStops = { {{18, { 1, 0, 0, 1 }}} };
+ @"Setting fillOutlineColor to a constant value expression should update fill-outline-color.");
+ XCTAssertEqualObjects(layer.fillOutlineColor, constantExpression,
+ @"fillOutlineColor should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.fillOutlineColor = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::Color> intervalStops = {{
+ { -INFINITY, { 1, 0, 0, 1 } },
+ { 18, { 1, 0, 0, 1 } },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::Color> { intervalStops };
XCTAssertEqual(rawLayer->getFillOutlineColor(), propertyValue,
- @"Setting fillOutlineColor to a camera function should update fill-outline-color.");
- XCTAssertEqualObjects(layer.fillOutlineColor, functionStyleValue,
- @"fillOutlineColor should round-trip camera functions.");
+ @"Setting fillOutlineColor to a camera expression should update fill-outline-color.");
+ XCTAssertEqualObjects(layer.fillOutlineColor, functionExpression,
+ @"fillOutlineColor should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.fillOutlineColor = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.fillOutlineColor = functionExpression;
mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<mbgl::Color> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getFillOutlineColor(), propertyValue,
- @"Setting fillOutlineColor to a source function should update fill-outline-color.");
- XCTAssertEqualObjects(layer.fillOutlineColor, functionStyleValue,
- @"fillOutlineColor should round-trip source functions.");
+ @"Setting fillOutlineColor to a data expression should update fill-outline-color.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.fillOutlineColor, pedanticFunctionExpression,
+ @"fillOutlineColor should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.fillOutlineColor = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.fillOutlineColor = functionExpression;
std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
mbgl::style::CompositeExponentialStops<mbgl::Color> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -264,15 +286,16 @@
propertyValue = mbgl::style::CompositeFunction<mbgl::Color> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getFillOutlineColor(), propertyValue,
- @"Setting fillOutlineColor to a composite function should update fill-outline-color.");
- XCTAssertEqualObjects(layer.fillOutlineColor, functionStyleValue,
- @"fillOutlineColor should round-trip composite functions.");
+ @"Setting fillOutlineColor to a camera-data expression should update fill-outline-color.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.fillOutlineColor, pedanticFunctionExpression,
+ @"fillOutlineColor should round-trip camera-data expressions.");
layer.fillOutlineColor = nil;
XCTAssertTrue(rawLayer->getFillOutlineColor().isUndefined(),
@"Unsetting fillOutlineColor should return fill-outline-color to the default value.");
- XCTAssertEqualObjects(layer.fillOutlineColor, defaultStyleValue,
+ XCTAssertEqualObjects(layer.fillOutlineColor, defaultExpression,
@"fillOutlineColor should return the default value after being unset.");
// Transition property test
layer.fillOutlineColorTransition = transitionTest;
@@ -289,39 +312,44 @@
{
XCTAssertTrue(rawLayer->getFillPattern().isUndefined(),
@"fill-pattern should be unset initially.");
- MGLStyleValue<NSString *> *defaultStyleValue = layer.fillPattern;
+ NSExpression *defaultExpression = layer.fillPattern;
- MGLStyleValue<NSString *> *constantStyleValue = [MGLStyleValue<NSString *> valueWithRawValue:@"Fill Pattern"];
- layer.fillPattern = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'Fill Pattern'"];
+ layer.fillPattern = constantExpression;
mbgl::style::PropertyValue<std::string> propertyValue = { "Fill Pattern" };
XCTAssertEqual(rawLayer->getFillPattern(), propertyValue,
- @"Setting fillPattern to a constant value should update fill-pattern.");
- XCTAssertEqualObjects(layer.fillPattern, constantStyleValue,
- @"fillPattern should round-trip constant values.");
-
- MGLStyleValue<NSString *> * functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.fillPattern = functionStyleValue;
-
- mbgl::style::IntervalStops<std::string> intervalStops = { {{18, "Fill Pattern"}} };
+ @"Setting fillPattern to a constant value expression should update fill-pattern.");
+ XCTAssertEqualObjects(layer.fillPattern, constantExpression,
+ @"fillPattern should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"'Fill Pattern'"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.fillPattern = functionExpression;
+
+ mbgl::style::IntervalStops<std::string> intervalStops = {{
+ { -INFINITY, "Fill Pattern" },
+ { 18, "Fill Pattern" },
+ }};
propertyValue = mbgl::style::CameraFunction<std::string> { intervalStops };
XCTAssertEqual(rawLayer->getFillPattern(), propertyValue,
- @"Setting fillPattern to a camera function should update fill-pattern.");
- XCTAssertEqualObjects(layer.fillPattern, functionStyleValue,
- @"fillPattern should round-trip camera functions.");
+ @"Setting fillPattern to a camera expression should update fill-pattern.");
+ XCTAssertEqualObjects(layer.fillPattern, functionExpression,
+ @"fillPattern should round-trip camera expressions.");
layer.fillPattern = nil;
XCTAssertTrue(rawLayer->getFillPattern().isUndefined(),
@"Unsetting fillPattern should return fill-pattern to the default value.");
- XCTAssertEqualObjects(layer.fillPattern, defaultStyleValue,
+ XCTAssertEqualObjects(layer.fillPattern, defaultExpression,
@"fillPattern should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.fillPattern = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.fillPattern = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.fillPattern = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.fillPattern = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
// Transition property test
layer.fillPatternTransition = transitionTest;
auto toptions = rawLayer->getFillPatternTransition();
@@ -337,84 +365,94 @@
{
XCTAssertTrue(rawLayer->getFillTranslate().isUndefined(),
@"fill-translate should be unset initially.");
- MGLStyleValue<NSValue *> *defaultStyleValue = layer.fillTranslation;
+ NSExpression *defaultExpression = layer.fillTranslation;
- MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"%@",
#if TARGET_OS_IPHONE
[NSValue valueWithCGVector:CGVectorMake(1, 1)]
#else
[NSValue valueWithMGLVector:CGVectorMake(1, -1)]
#endif
];
- layer.fillTranslation = constantStyleValue;
+ layer.fillTranslation = constantExpression;
mbgl::style::PropertyValue<std::array<float, 2>> propertyValue = { { 1, 1 } };
XCTAssertEqual(rawLayer->getFillTranslate(), propertyValue,
- @"Setting fillTranslation to a constant value should update fill-translate.");
- XCTAssertEqualObjects(layer.fillTranslation, constantStyleValue,
- @"fillTranslation should round-trip constant values.");
-
- MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.fillTranslation = functionStyleValue;
-
- mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = { {{18, { 1, 1 }}} };
+ @"Setting fillTranslation to a constant value expression should update fill-translate.");
+ XCTAssertEqualObjects(layer.fillTranslation, constantExpression,
+ @"fillTranslation should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"{1, 1}"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.fillTranslation = functionExpression;
+
+ mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = {{
+ { -INFINITY, { 1, 1 } },
+ { 18, { 1, 1 } },
+ }};
propertyValue = mbgl::style::CameraFunction<std::array<float, 2>> { intervalStops };
XCTAssertEqual(rawLayer->getFillTranslate(), propertyValue,
- @"Setting fillTranslation to a camera function should update fill-translate.");
- XCTAssertEqualObjects(layer.fillTranslation, functionStyleValue,
- @"fillTranslation should round-trip camera functions.");
+ @"Setting fillTranslation to a camera expression should update fill-translate.");
+ XCTAssertEqualObjects(layer.fillTranslation, functionExpression,
+ @"fillTranslation should round-trip camera expressions.");
layer.fillTranslation = nil;
XCTAssertTrue(rawLayer->getFillTranslate().isUndefined(),
@"Unsetting fillTranslation should return fill-translate to the default value.");
- XCTAssertEqualObjects(layer.fillTranslation, defaultStyleValue,
+ XCTAssertEqualObjects(layer.fillTranslation, defaultExpression,
@"fillTranslation should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.fillTranslation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.fillTranslation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.fillTranslation = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.fillTranslation = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// fill-translate-anchor
{
XCTAssertTrue(rawLayer->getFillTranslateAnchor().isUndefined(),
@"fill-translate-anchor should be unset initially.");
- MGLStyleValue<NSValue *> *defaultStyleValue = layer.fillTranslationAnchor;
+ NSExpression *defaultExpression = layer.fillTranslationAnchor;
- MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLFillTranslationAnchor:MGLFillTranslationAnchorViewport]];
- layer.fillTranslationAnchor = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'viewport'"];
+ layer.fillTranslationAnchor = constantExpression;
mbgl::style::PropertyValue<mbgl::style::TranslateAnchorType> propertyValue = { mbgl::style::TranslateAnchorType::Viewport };
XCTAssertEqual(rawLayer->getFillTranslateAnchor(), propertyValue,
- @"Setting fillTranslationAnchor to a constant value should update fill-translate-anchor.");
- XCTAssertEqualObjects(layer.fillTranslationAnchor, constantStyleValue,
- @"fillTranslationAnchor should round-trip constant values.");
-
- MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.fillTranslationAnchor = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::style::TranslateAnchorType> intervalStops = { {{18, mbgl::style::TranslateAnchorType::Viewport}} };
+ @"Setting fillTranslationAnchor to a constant value expression should update fill-translate-anchor.");
+ XCTAssertEqualObjects(layer.fillTranslationAnchor, constantExpression,
+ @"fillTranslationAnchor should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"'viewport'"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.fillTranslationAnchor = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::style::TranslateAnchorType> intervalStops = {{
+ { -INFINITY, mbgl::style::TranslateAnchorType::Viewport },
+ { 18, mbgl::style::TranslateAnchorType::Viewport },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::style::TranslateAnchorType> { intervalStops };
XCTAssertEqual(rawLayer->getFillTranslateAnchor(), propertyValue,
- @"Setting fillTranslationAnchor to a camera function should update fill-translate-anchor.");
- XCTAssertEqualObjects(layer.fillTranslationAnchor, functionStyleValue,
- @"fillTranslationAnchor should round-trip camera functions.");
+ @"Setting fillTranslationAnchor to a camera expression should update fill-translate-anchor.");
+ XCTAssertEqualObjects(layer.fillTranslationAnchor, functionExpression,
+ @"fillTranslationAnchor should round-trip camera expressions.");
layer.fillTranslationAnchor = nil;
XCTAssertTrue(rawLayer->getFillTranslateAnchor().isUndefined(),
@"Unsetting fillTranslationAnchor should return fill-translate-anchor to the default value.");
- XCTAssertEqualObjects(layer.fillTranslationAnchor, defaultStyleValue,
+ XCTAssertEqualObjects(layer.fillTranslationAnchor, defaultExpression,
@"fillTranslationAnchor should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.fillTranslationAnchor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.fillTranslationAnchor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.fillTranslationAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.fillTranslationAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
}
diff --git a/platform/darwin/test/MGLGeometryTests.mm b/platform/darwin/test/MGLGeometryTests.mm
index 1c85470188..a0ddecf77e 100644
--- a/platform/darwin/test/MGLGeometryTests.mm
+++ b/platform/darwin/test/MGLGeometryTests.mm
@@ -163,4 +163,13 @@
[NSValue valueWithMGLCoordinate:quad.bottomRight],
@"Quad bottom right should be computed correctly.");
}
+
+- (void)testMGLMapPoint {
+ MGLMapPoint point = MGLMapPointForCoordinate(CLLocationCoordinate2DMake(37.936, -80.425), 0.0);
+
+ MGLMapPoint roundTrippedPoint = [NSValue valueWithMGLMapPoint:point].MGLMapPointValue;
+ XCTAssertEqual(point.x, roundTrippedPoint.x);
+ XCTAssertEqual(point.y, roundTrippedPoint.y);
+ XCTAssertEqual(point.zoomLevel, roundTrippedPoint.zoomLevel);
+}
@end
diff --git a/platform/darwin/test/MGLHeatmapColorTests.mm b/platform/darwin/test/MGLHeatmapColorTests.mm
new file mode 100644
index 0000000000..bed777ae05
--- /dev/null
+++ b/platform/darwin/test/MGLHeatmapColorTests.mm
@@ -0,0 +1,62 @@
+#import <Mapbox/Mapbox.h>
+#import <XCTest/XCTest.h>
+
+#import "MGLStyleLayer_Private.h"
+
+#include <mbgl/style/layers/heatmap_layer.hpp>
+
+@interface MGLHeatmapColorTests : XCTestCase <MGLMapViewDelegate>
+@end
+
+@implementation MGLHeatmapColorTests
+
+- (void)testProperties {
+ MGLPointFeature *feature = [[MGLPointFeature alloc] init];
+ MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" shape:feature options:nil];
+ MGLHeatmapStyleLayer *layer = [[MGLHeatmapStyleLayer alloc] initWithIdentifier:@"layerID" source:source];
+
+ auto rawLayer = layer.rawLayer->as<mbgl::style::HeatmapLayer>();
+
+ XCTAssertTrue(rawLayer->getHeatmapColor().isUndefined(),
+ @"heatmap-color should be unset initially.");
+ NSExpression *defaultExpression = layer.heatmapColor;
+
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ layer.heatmapColor = constantExpression;
+
+
+ mbgl::style::PropertyValue<float> propertyValue = { 0xff };
+ XCTAssertEqual(rawLayer->getHeatmapColor().evaluate(0.0), mbgl::Color::red(),
+ @"Setting heatmapColor to a constant value expression should update heatmap-color.");
+ XCTAssertEqualObjects(layer.heatmapColor, constantExpression,
+ @"heatmapColor should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ NSExpression *constantExpression2 = [NSExpression expressionWithFormat:@"%@", [MGLColor blueColor]];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($heatmapDensity, %@, %@)", constantExpression, @{@12: constantExpression2}];
+ layer.heatmapColor = functionExpression;
+
+ XCTAssertEqual(rawLayer->getHeatmapColor().evaluate(11.0), mbgl::Color::red(),
+ @"Setting heatmapColor to an expression depending on $heatmapDensity should update heatmap-color.");
+ XCTAssertEqual(rawLayer->getHeatmapColor().evaluate(12.0), mbgl::Color::blue(),
+ @"Setting heatmapColor to an expression depending on $heatmapDensity should update heatmap-color.");
+ XCTAssertEqualObjects(layer.heatmapColor, functionExpression,
+ @"heatmapColor should round-trip expressions depending on $heatmapDensity.");
+
+ layer.heatmapColor = nil;
+ XCTAssertTrue(rawLayer->getHeatmapColor().isUndefined(),
+ @"Unsetting heatmapColor should return heatmap-color to the default value.");
+ // The contained colors aren’t object equal, even though their descriptions are.
+ XCTAssertEqualObjects(layer.heatmapColor.description, defaultExpression.description,
+ @"heatmapColor should return the default value after being unset.");
+
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ XCTAssertThrowsSpecificNamed(layer.heatmapColor = functionExpression, NSException, NSInvalidArgumentException, @"MGLHeatmapLayer should raise an exception if a camera expression is applied to heatmapColor.");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.heatmapColor = functionExpression, NSException, NSInvalidArgumentException, @"MGLHeatmapLayer should raise an exception if a data expression is applied to heatmapColor.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.heatmapColor = functionExpression, NSException, NSInvalidArgumentException, @"MGLHeatmapLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+}
+
+@end
diff --git a/platform/darwin/test/MGLHeatmapStyleLayerTests.mm b/platform/darwin/test/MGLHeatmapStyleLayerTests.mm
new file mode 100644
index 0000000000..e4b1917257
--- /dev/null
+++ b/platform/darwin/test/MGLHeatmapStyleLayerTests.mm
@@ -0,0 +1,300 @@
+// This file is generated.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
+
+#import "MGLStyleLayerTests.h"
+#import "../../darwin/src/NSDate+MGLAdditions.h"
+
+#import "MGLStyleLayer_Private.h"
+
+#include <mbgl/style/layers/heatmap_layer.hpp>
+#include <mbgl/style/transition_options.hpp>
+
+@interface MGLHeatmapLayerTests : MGLStyleLayerTests
+@end
+
+@implementation MGLHeatmapLayerTests
+
++ (NSString *)layerType {
+ return @"heatmap";
+}
+
+- (void)testPredicates {
+ MGLPointFeature *feature = [[MGLPointFeature alloc] init];
+ MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" shape:feature options:nil];
+ MGLHeatmapStyleLayer *layer = [[MGLHeatmapStyleLayer alloc] initWithIdentifier:@"layerID" source:source];
+
+ XCTAssertNil(layer.sourceLayerIdentifier);
+ layer.sourceLayerIdentifier = @"layerID";
+ XCTAssertEqualObjects(layer.sourceLayerIdentifier, @"layerID");
+ layer.sourceLayerIdentifier = nil;
+ XCTAssertNil(layer.sourceLayerIdentifier);
+
+ XCTAssertNil(layer.predicate);
+ layer.predicate = [NSPredicate predicateWithFormat:@"$featureIdentifier = 1"];
+ XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithFormat:@"$featureIdentifier = 1"]);
+ layer.predicate = nil;
+ XCTAssertNil(layer.predicate);
+}
+
+- (void)testProperties {
+ MGLPointFeature *feature = [[MGLPointFeature alloc] init];
+ MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" shape:feature options:nil];
+
+ MGLHeatmapStyleLayer *layer = [[MGLHeatmapStyleLayer alloc] initWithIdentifier:@"layerID" source:source];
+ XCTAssertNotEqual(layer.rawLayer, nullptr);
+ XCTAssertTrue(layer.rawLayer->is<mbgl::style::HeatmapLayer>());
+ auto rawLayer = layer.rawLayer->as<mbgl::style::HeatmapLayer>();
+
+ MGLTransition transitionTest = MGLTransitionMake(5, 4);
+
+
+ // heatmap-intensity
+ {
+ XCTAssertTrue(rawLayer->getHeatmapIntensity().isUndefined(),
+ @"heatmap-intensity should be unset initially.");
+ NSExpression *defaultExpression = layer.heatmapIntensity;
+
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.heatmapIntensity = constantExpression;
+ mbgl::style::PropertyValue<float> propertyValue = { 0xff };
+ XCTAssertEqual(rawLayer->getHeatmapIntensity(), propertyValue,
+ @"Setting heatmapIntensity to a constant value expression should update heatmap-intensity.");
+ XCTAssertEqualObjects(layer.heatmapIntensity, constantExpression,
+ @"heatmapIntensity should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.heatmapIntensity = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
+
+ XCTAssertEqual(rawLayer->getHeatmapIntensity(), propertyValue,
+ @"Setting heatmapIntensity to a camera expression should update heatmap-intensity.");
+ XCTAssertEqualObjects(layer.heatmapIntensity, functionExpression,
+ @"heatmapIntensity should round-trip camera expressions.");
+
+
+
+ layer.heatmapIntensity = nil;
+ XCTAssertTrue(rawLayer->getHeatmapIntensity().isUndefined(),
+ @"Unsetting heatmapIntensity should return heatmap-intensity to the default value.");
+ XCTAssertEqualObjects(layer.heatmapIntensity, defaultExpression,
+ @"heatmapIntensity should return the default value after being unset.");
+
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.heatmapIntensity = functionExpression, NSException, NSInvalidArgumentException, @"MGLHeatmapLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.heatmapIntensity = functionExpression, NSException, NSInvalidArgumentException, @"MGLHeatmapLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ // Transition property test
+ layer.heatmapIntensityTransition = transitionTest;
+ auto toptions = rawLayer->getHeatmapIntensityTransition();
+ XCTAssert(toptions.delay && MGLTimeIntervalFromDuration(*toptions.delay) == transitionTest.delay);
+ XCTAssert(toptions.duration && MGLTimeIntervalFromDuration(*toptions.duration) == transitionTest.duration);
+
+ MGLTransition heatmapIntensityTransition = layer.heatmapIntensityTransition;
+ XCTAssertEqual(heatmapIntensityTransition.delay, transitionTest.delay);
+ XCTAssertEqual(heatmapIntensityTransition.duration, transitionTest.duration);
+ }
+
+ // heatmap-opacity
+ {
+ XCTAssertTrue(rawLayer->getHeatmapOpacity().isUndefined(),
+ @"heatmap-opacity should be unset initially.");
+ NSExpression *defaultExpression = layer.heatmapOpacity;
+
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.heatmapOpacity = constantExpression;
+ mbgl::style::PropertyValue<float> propertyValue = { 0xff };
+ XCTAssertEqual(rawLayer->getHeatmapOpacity(), propertyValue,
+ @"Setting heatmapOpacity to a constant value expression should update heatmap-opacity.");
+ XCTAssertEqualObjects(layer.heatmapOpacity, constantExpression,
+ @"heatmapOpacity should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.heatmapOpacity = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
+
+ XCTAssertEqual(rawLayer->getHeatmapOpacity(), propertyValue,
+ @"Setting heatmapOpacity to a camera expression should update heatmap-opacity.");
+ XCTAssertEqualObjects(layer.heatmapOpacity, functionExpression,
+ @"heatmapOpacity should round-trip camera expressions.");
+
+
+
+ layer.heatmapOpacity = nil;
+ XCTAssertTrue(rawLayer->getHeatmapOpacity().isUndefined(),
+ @"Unsetting heatmapOpacity should return heatmap-opacity to the default value.");
+ XCTAssertEqualObjects(layer.heatmapOpacity, defaultExpression,
+ @"heatmapOpacity should return the default value after being unset.");
+
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.heatmapOpacity = functionExpression, NSException, NSInvalidArgumentException, @"MGLHeatmapLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.heatmapOpacity = functionExpression, NSException, NSInvalidArgumentException, @"MGLHeatmapLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ // Transition property test
+ layer.heatmapOpacityTransition = transitionTest;
+ auto toptions = rawLayer->getHeatmapOpacityTransition();
+ XCTAssert(toptions.delay && MGLTimeIntervalFromDuration(*toptions.delay) == transitionTest.delay);
+ XCTAssert(toptions.duration && MGLTimeIntervalFromDuration(*toptions.duration) == transitionTest.duration);
+
+ MGLTransition heatmapOpacityTransition = layer.heatmapOpacityTransition;
+ XCTAssertEqual(heatmapOpacityTransition.delay, transitionTest.delay);
+ XCTAssertEqual(heatmapOpacityTransition.duration, transitionTest.duration);
+ }
+
+ // heatmap-radius
+ {
+ XCTAssertTrue(rawLayer->getHeatmapRadius().isUndefined(),
+ @"heatmap-radius should be unset initially.");
+ NSExpression *defaultExpression = layer.heatmapRadius;
+
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.heatmapRadius = constantExpression;
+ mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
+ XCTAssertEqual(rawLayer->getHeatmapRadius(), propertyValue,
+ @"Setting heatmapRadius to a constant value expression should update heatmap-radius.");
+ XCTAssertEqualObjects(layer.heatmapRadius, constantExpression,
+ @"heatmapRadius should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.heatmapRadius = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
+
+ XCTAssertEqual(rawLayer->getHeatmapRadius(), propertyValue,
+ @"Setting heatmapRadius to a camera expression should update heatmap-radius.");
+ XCTAssertEqualObjects(layer.heatmapRadius, functionExpression,
+ @"heatmapRadius should round-trip camera expressions.");
+
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.heatmapRadius = functionExpression;
+
+ mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getHeatmapRadius(), propertyValue,
+ @"Setting heatmapRadius to a data expression should update heatmap-radius.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.heatmapRadius, pedanticFunctionExpression,
+ @"heatmapRadius should round-trip data expressions.");
+
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.heatmapRadius = functionExpression;
+
+ 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->getHeatmapRadius(), propertyValue,
+ @"Setting heatmapRadius to a camera-data expression should update heatmap-radius.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.heatmapRadius, pedanticFunctionExpression,
+ @"heatmapRadius should round-trip camera-data expressions.");
+
+
+ layer.heatmapRadius = nil;
+ XCTAssertTrue(rawLayer->getHeatmapRadius().isUndefined(),
+ @"Unsetting heatmapRadius should return heatmap-radius to the default value.");
+ XCTAssertEqualObjects(layer.heatmapRadius, defaultExpression,
+ @"heatmapRadius should return the default value after being unset.");
+ // Transition property test
+ layer.heatmapRadiusTransition = transitionTest;
+ auto toptions = rawLayer->getHeatmapRadiusTransition();
+ XCTAssert(toptions.delay && MGLTimeIntervalFromDuration(*toptions.delay) == transitionTest.delay);
+ XCTAssert(toptions.duration && MGLTimeIntervalFromDuration(*toptions.duration) == transitionTest.duration);
+
+ MGLTransition heatmapRadiusTransition = layer.heatmapRadiusTransition;
+ XCTAssertEqual(heatmapRadiusTransition.delay, transitionTest.delay);
+ XCTAssertEqual(heatmapRadiusTransition.duration, transitionTest.duration);
+ }
+
+ // heatmap-weight
+ {
+ XCTAssertTrue(rawLayer->getHeatmapWeight().isUndefined(),
+ @"heatmap-weight should be unset initially.");
+ NSExpression *defaultExpression = layer.heatmapWeight;
+
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.heatmapWeight = constantExpression;
+ mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
+ XCTAssertEqual(rawLayer->getHeatmapWeight(), propertyValue,
+ @"Setting heatmapWeight to a constant value expression should update heatmap-weight.");
+ XCTAssertEqualObjects(layer.heatmapWeight, constantExpression,
+ @"heatmapWeight should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.heatmapWeight = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
+
+ XCTAssertEqual(rawLayer->getHeatmapWeight(), propertyValue,
+ @"Setting heatmapWeight to a camera expression should update heatmap-weight.");
+ XCTAssertEqualObjects(layer.heatmapWeight, functionExpression,
+ @"heatmapWeight should round-trip camera expressions.");
+
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.heatmapWeight = functionExpression;
+
+ mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getHeatmapWeight(), propertyValue,
+ @"Setting heatmapWeight to a data expression should update heatmap-weight.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.heatmapWeight, pedanticFunctionExpression,
+ @"heatmapWeight should round-trip data expressions.");
+
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.heatmapWeight = functionExpression;
+
+ 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->getHeatmapWeight(), propertyValue,
+ @"Setting heatmapWeight to a camera-data expression should update heatmap-weight.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.heatmapWeight, pedanticFunctionExpression,
+ @"heatmapWeight should round-trip camera-data expressions.");
+
+
+ layer.heatmapWeight = nil;
+ XCTAssertTrue(rawLayer->getHeatmapWeight().isUndefined(),
+ @"Unsetting heatmapWeight should return heatmap-weight to the default value.");
+ XCTAssertEqualObjects(layer.heatmapWeight, defaultExpression,
+ @"heatmapWeight should return the default value after being unset.");
+ }
+}
+
+- (void)testPropertyNames {
+ [self testPropertyName:@"heatmap-intensity" isBoolean:NO];
+ [self testPropertyName:@"heatmap-opacity" isBoolean:NO];
+ [self testPropertyName:@"heatmap-radius" isBoolean:NO];
+ [self testPropertyName:@"heatmap-weight" isBoolean:NO];
+}
+
+@end
diff --git a/platform/darwin/test/MGLHillshadeStyleLayerTests.mm b/platform/darwin/test/MGLHillshadeStyleLayerTests.mm
new file mode 100644
index 0000000000..34937d1674
--- /dev/null
+++ b/platform/darwin/test/MGLHillshadeStyleLayerTests.mm
@@ -0,0 +1,348 @@
+// This file is generated.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
+
+#import "MGLStyleLayerTests.h"
+#import "../../darwin/src/NSDate+MGLAdditions.h"
+
+#import "MGLStyleLayer_Private.h"
+
+#include <mbgl/style/layers/hillshade_layer.hpp>
+#include <mbgl/style/transition_options.hpp>
+
+@interface MGLHillshadeLayerTests : MGLStyleLayerTests
+@end
+
+@implementation MGLHillshadeLayerTests
+
++ (NSString *)layerType {
+ return @"hillshade";
+}
+
+- (void)testProperties {
+ MGLPointFeature *feature = [[MGLPointFeature alloc] init];
+ MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" shape:feature options:nil];
+
+ MGLHillshadeStyleLayer *layer = [[MGLHillshadeStyleLayer alloc] initWithIdentifier:@"layerID" source:source];
+ XCTAssertNotEqual(layer.rawLayer, nullptr);
+ XCTAssertTrue(layer.rawLayer->is<mbgl::style::HillshadeLayer>());
+ auto rawLayer = layer.rawLayer->as<mbgl::style::HillshadeLayer>();
+
+ MGLTransition transitionTest = MGLTransitionMake(5, 4);
+
+
+ // hillshade-accent-color
+ {
+ XCTAssertTrue(rawLayer->getHillshadeAccentColor().isUndefined(),
+ @"hillshade-accent-color should be unset initially.");
+ NSExpression *defaultExpression = layer.hillshadeAccentColor;
+
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ layer.hillshadeAccentColor = constantExpression;
+ mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
+ XCTAssertEqual(rawLayer->getHillshadeAccentColor(), propertyValue,
+ @"Setting hillshadeAccentColor to a constant value expression should update hillshade-accent-color.");
+ XCTAssertEqualObjects(layer.hillshadeAccentColor, constantExpression,
+ @"hillshadeAccentColor should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.hillshadeAccentColor = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::Color> intervalStops = {{
+ { -INFINITY, { 1, 0, 0, 1 } },
+ { 18, { 1, 0, 0, 1 } },
+ }};
+ propertyValue = mbgl::style::CameraFunction<mbgl::Color> { intervalStops };
+
+ XCTAssertEqual(rawLayer->getHillshadeAccentColor(), propertyValue,
+ @"Setting hillshadeAccentColor to a camera expression should update hillshade-accent-color.");
+ XCTAssertEqualObjects(layer.hillshadeAccentColor, functionExpression,
+ @"hillshadeAccentColor should round-trip camera expressions.");
+
+
+
+ layer.hillshadeAccentColor = nil;
+ XCTAssertTrue(rawLayer->getHillshadeAccentColor().isUndefined(),
+ @"Unsetting hillshadeAccentColor should return hillshade-accent-color to the default value.");
+ XCTAssertEqualObjects(layer.hillshadeAccentColor, defaultExpression,
+ @"hillshadeAccentColor should return the default value after being unset.");
+
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.hillshadeAccentColor = functionExpression, NSException, NSInvalidArgumentException, @"MGLHillshadeLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.hillshadeAccentColor = functionExpression, NSException, NSInvalidArgumentException, @"MGLHillshadeLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ // Transition property test
+ layer.hillshadeAccentColorTransition = transitionTest;
+ auto toptions = rawLayer->getHillshadeAccentColorTransition();
+ XCTAssert(toptions.delay && MGLTimeIntervalFromDuration(*toptions.delay) == transitionTest.delay);
+ XCTAssert(toptions.duration && MGLTimeIntervalFromDuration(*toptions.duration) == transitionTest.duration);
+
+ MGLTransition hillshadeAccentColorTransition = layer.hillshadeAccentColorTransition;
+ XCTAssertEqual(hillshadeAccentColorTransition.delay, transitionTest.delay);
+ XCTAssertEqual(hillshadeAccentColorTransition.duration, transitionTest.duration);
+ }
+
+ // hillshade-exaggeration
+ {
+ XCTAssertTrue(rawLayer->getHillshadeExaggeration().isUndefined(),
+ @"hillshade-exaggeration should be unset initially.");
+ NSExpression *defaultExpression = layer.hillshadeExaggeration;
+
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.hillshadeExaggeration = constantExpression;
+ mbgl::style::PropertyValue<float> propertyValue = { 0xff };
+ XCTAssertEqual(rawLayer->getHillshadeExaggeration(), propertyValue,
+ @"Setting hillshadeExaggeration to a constant value expression should update hillshade-exaggeration.");
+ XCTAssertEqualObjects(layer.hillshadeExaggeration, constantExpression,
+ @"hillshadeExaggeration should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.hillshadeExaggeration = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
+
+ XCTAssertEqual(rawLayer->getHillshadeExaggeration(), propertyValue,
+ @"Setting hillshadeExaggeration to a camera expression should update hillshade-exaggeration.");
+ XCTAssertEqualObjects(layer.hillshadeExaggeration, functionExpression,
+ @"hillshadeExaggeration should round-trip camera expressions.");
+
+
+
+ layer.hillshadeExaggeration = nil;
+ XCTAssertTrue(rawLayer->getHillshadeExaggeration().isUndefined(),
+ @"Unsetting hillshadeExaggeration should return hillshade-exaggeration to the default value.");
+ XCTAssertEqualObjects(layer.hillshadeExaggeration, defaultExpression,
+ @"hillshadeExaggeration should return the default value after being unset.");
+
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.hillshadeExaggeration = functionExpression, NSException, NSInvalidArgumentException, @"MGLHillshadeLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.hillshadeExaggeration = functionExpression, NSException, NSInvalidArgumentException, @"MGLHillshadeLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ // Transition property test
+ layer.hillshadeExaggerationTransition = transitionTest;
+ auto toptions = rawLayer->getHillshadeExaggerationTransition();
+ XCTAssert(toptions.delay && MGLTimeIntervalFromDuration(*toptions.delay) == transitionTest.delay);
+ XCTAssert(toptions.duration && MGLTimeIntervalFromDuration(*toptions.duration) == transitionTest.duration);
+
+ MGLTransition hillshadeExaggerationTransition = layer.hillshadeExaggerationTransition;
+ XCTAssertEqual(hillshadeExaggerationTransition.delay, transitionTest.delay);
+ XCTAssertEqual(hillshadeExaggerationTransition.duration, transitionTest.duration);
+ }
+
+ // hillshade-highlight-color
+ {
+ XCTAssertTrue(rawLayer->getHillshadeHighlightColor().isUndefined(),
+ @"hillshade-highlight-color should be unset initially.");
+ NSExpression *defaultExpression = layer.hillshadeHighlightColor;
+
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ layer.hillshadeHighlightColor = constantExpression;
+ mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
+ XCTAssertEqual(rawLayer->getHillshadeHighlightColor(), propertyValue,
+ @"Setting hillshadeHighlightColor to a constant value expression should update hillshade-highlight-color.");
+ XCTAssertEqualObjects(layer.hillshadeHighlightColor, constantExpression,
+ @"hillshadeHighlightColor should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.hillshadeHighlightColor = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::Color> intervalStops = {{
+ { -INFINITY, { 1, 0, 0, 1 } },
+ { 18, { 1, 0, 0, 1 } },
+ }};
+ propertyValue = mbgl::style::CameraFunction<mbgl::Color> { intervalStops };
+
+ XCTAssertEqual(rawLayer->getHillshadeHighlightColor(), propertyValue,
+ @"Setting hillshadeHighlightColor to a camera expression should update hillshade-highlight-color.");
+ XCTAssertEqualObjects(layer.hillshadeHighlightColor, functionExpression,
+ @"hillshadeHighlightColor should round-trip camera expressions.");
+
+
+
+ layer.hillshadeHighlightColor = nil;
+ XCTAssertTrue(rawLayer->getHillshadeHighlightColor().isUndefined(),
+ @"Unsetting hillshadeHighlightColor should return hillshade-highlight-color to the default value.");
+ XCTAssertEqualObjects(layer.hillshadeHighlightColor, defaultExpression,
+ @"hillshadeHighlightColor should return the default value after being unset.");
+
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.hillshadeHighlightColor = functionExpression, NSException, NSInvalidArgumentException, @"MGLHillshadeLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.hillshadeHighlightColor = functionExpression, NSException, NSInvalidArgumentException, @"MGLHillshadeLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ // Transition property test
+ layer.hillshadeHighlightColorTransition = transitionTest;
+ auto toptions = rawLayer->getHillshadeHighlightColorTransition();
+ XCTAssert(toptions.delay && MGLTimeIntervalFromDuration(*toptions.delay) == transitionTest.delay);
+ XCTAssert(toptions.duration && MGLTimeIntervalFromDuration(*toptions.duration) == transitionTest.duration);
+
+ MGLTransition hillshadeHighlightColorTransition = layer.hillshadeHighlightColorTransition;
+ XCTAssertEqual(hillshadeHighlightColorTransition.delay, transitionTest.delay);
+ XCTAssertEqual(hillshadeHighlightColorTransition.duration, transitionTest.duration);
+ }
+
+ // hillshade-illumination-anchor
+ {
+ XCTAssertTrue(rawLayer->getHillshadeIlluminationAnchor().isUndefined(),
+ @"hillshade-illumination-anchor should be unset initially.");
+ NSExpression *defaultExpression = layer.hillshadeIlluminationAnchor;
+
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'viewport'"];
+ layer.hillshadeIlluminationAnchor = constantExpression;
+ mbgl::style::PropertyValue<mbgl::style::HillshadeIlluminationAnchorType> propertyValue = { mbgl::style::HillshadeIlluminationAnchorType::Viewport };
+ XCTAssertEqual(rawLayer->getHillshadeIlluminationAnchor(), propertyValue,
+ @"Setting hillshadeIlluminationAnchor to a constant value expression should update hillshade-illumination-anchor.");
+ XCTAssertEqualObjects(layer.hillshadeIlluminationAnchor, constantExpression,
+ @"hillshadeIlluminationAnchor should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"'viewport'"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.hillshadeIlluminationAnchor = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::style::HillshadeIlluminationAnchorType> intervalStops = {{
+ { -INFINITY, mbgl::style::HillshadeIlluminationAnchorType::Viewport },
+ { 18, mbgl::style::HillshadeIlluminationAnchorType::Viewport },
+ }};
+ propertyValue = mbgl::style::CameraFunction<mbgl::style::HillshadeIlluminationAnchorType> { intervalStops };
+
+ XCTAssertEqual(rawLayer->getHillshadeIlluminationAnchor(), propertyValue,
+ @"Setting hillshadeIlluminationAnchor to a camera expression should update hillshade-illumination-anchor.");
+ XCTAssertEqualObjects(layer.hillshadeIlluminationAnchor, functionExpression,
+ @"hillshadeIlluminationAnchor should round-trip camera expressions.");
+
+
+
+ layer.hillshadeIlluminationAnchor = nil;
+ XCTAssertTrue(rawLayer->getHillshadeIlluminationAnchor().isUndefined(),
+ @"Unsetting hillshadeIlluminationAnchor should return hillshade-illumination-anchor to the default value.");
+ XCTAssertEqualObjects(layer.hillshadeIlluminationAnchor, defaultExpression,
+ @"hillshadeIlluminationAnchor should return the default value after being unset.");
+
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.hillshadeIlluminationAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLHillshadeLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.hillshadeIlluminationAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLHillshadeLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ }
+
+ // hillshade-illumination-direction
+ {
+ XCTAssertTrue(rawLayer->getHillshadeIlluminationDirection().isUndefined(),
+ @"hillshade-illumination-direction should be unset initially.");
+ NSExpression *defaultExpression = layer.hillshadeIlluminationDirection;
+
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.hillshadeIlluminationDirection = constantExpression;
+ mbgl::style::PropertyValue<float> propertyValue = { 0xff };
+ XCTAssertEqual(rawLayer->getHillshadeIlluminationDirection(), propertyValue,
+ @"Setting hillshadeIlluminationDirection to a constant value expression should update hillshade-illumination-direction.");
+ XCTAssertEqualObjects(layer.hillshadeIlluminationDirection, constantExpression,
+ @"hillshadeIlluminationDirection should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.hillshadeIlluminationDirection = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
+
+ XCTAssertEqual(rawLayer->getHillshadeIlluminationDirection(), propertyValue,
+ @"Setting hillshadeIlluminationDirection to a camera expression should update hillshade-illumination-direction.");
+ XCTAssertEqualObjects(layer.hillshadeIlluminationDirection, functionExpression,
+ @"hillshadeIlluminationDirection should round-trip camera expressions.");
+
+
+
+ layer.hillshadeIlluminationDirection = nil;
+ XCTAssertTrue(rawLayer->getHillshadeIlluminationDirection().isUndefined(),
+ @"Unsetting hillshadeIlluminationDirection should return hillshade-illumination-direction to the default value.");
+ XCTAssertEqualObjects(layer.hillshadeIlluminationDirection, defaultExpression,
+ @"hillshadeIlluminationDirection should return the default value after being unset.");
+
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.hillshadeIlluminationDirection = functionExpression, NSException, NSInvalidArgumentException, @"MGLHillshadeLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.hillshadeIlluminationDirection = functionExpression, NSException, NSInvalidArgumentException, @"MGLHillshadeLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ }
+
+ // hillshade-shadow-color
+ {
+ XCTAssertTrue(rawLayer->getHillshadeShadowColor().isUndefined(),
+ @"hillshade-shadow-color should be unset initially.");
+ NSExpression *defaultExpression = layer.hillshadeShadowColor;
+
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ layer.hillshadeShadowColor = constantExpression;
+ mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
+ XCTAssertEqual(rawLayer->getHillshadeShadowColor(), propertyValue,
+ @"Setting hillshadeShadowColor to a constant value expression should update hillshade-shadow-color.");
+ XCTAssertEqualObjects(layer.hillshadeShadowColor, constantExpression,
+ @"hillshadeShadowColor should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.hillshadeShadowColor = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::Color> intervalStops = {{
+ { -INFINITY, { 1, 0, 0, 1 } },
+ { 18, { 1, 0, 0, 1 } },
+ }};
+ propertyValue = mbgl::style::CameraFunction<mbgl::Color> { intervalStops };
+
+ XCTAssertEqual(rawLayer->getHillshadeShadowColor(), propertyValue,
+ @"Setting hillshadeShadowColor to a camera expression should update hillshade-shadow-color.");
+ XCTAssertEqualObjects(layer.hillshadeShadowColor, functionExpression,
+ @"hillshadeShadowColor should round-trip camera expressions.");
+
+
+
+ layer.hillshadeShadowColor = nil;
+ XCTAssertTrue(rawLayer->getHillshadeShadowColor().isUndefined(),
+ @"Unsetting hillshadeShadowColor should return hillshade-shadow-color to the default value.");
+ XCTAssertEqualObjects(layer.hillshadeShadowColor, defaultExpression,
+ @"hillshadeShadowColor should return the default value after being unset.");
+
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.hillshadeShadowColor = functionExpression, NSException, NSInvalidArgumentException, @"MGLHillshadeLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.hillshadeShadowColor = functionExpression, NSException, NSInvalidArgumentException, @"MGLHillshadeLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ // Transition property test
+ layer.hillshadeShadowColorTransition = transitionTest;
+ auto toptions = rawLayer->getHillshadeShadowColorTransition();
+ XCTAssert(toptions.delay && MGLTimeIntervalFromDuration(*toptions.delay) == transitionTest.delay);
+ XCTAssert(toptions.duration && MGLTimeIntervalFromDuration(*toptions.duration) == transitionTest.duration);
+
+ MGLTransition hillshadeShadowColorTransition = layer.hillshadeShadowColorTransition;
+ XCTAssertEqual(hillshadeShadowColorTransition.delay, transitionTest.delay);
+ XCTAssertEqual(hillshadeShadowColorTransition.duration, transitionTest.duration);
+ }
+}
+
+- (void)testPropertyNames {
+ [self testPropertyName:@"hillshade-accent-color" isBoolean:NO];
+ [self testPropertyName:@"hillshade-exaggeration" isBoolean:NO];
+ [self testPropertyName:@"hillshade-highlight-color" isBoolean:NO];
+ [self testPropertyName:@"hillshade-illumination-anchor" isBoolean:NO];
+ [self testPropertyName:@"hillshade-illumination-direction" isBoolean:NO];
+ [self testPropertyName:@"hillshade-shadow-color" isBoolean:NO];
+}
+
+- (void)testValueAdditions {
+ XCTAssertEqual([NSValue valueWithMGLHillshadeIlluminationAnchor:MGLHillshadeIlluminationAnchorMap].MGLHillshadeIlluminationAnchorValue, MGLHillshadeIlluminationAnchorMap);
+ XCTAssertEqual([NSValue valueWithMGLHillshadeIlluminationAnchor:MGLHillshadeIlluminationAnchorViewport].MGLHillshadeIlluminationAnchorValue, MGLHillshadeIlluminationAnchorViewport);
+}
+
+@end
diff --git a/platform/darwin/test/MGLLightTest.mm b/platform/darwin/test/MGLLightTest.mm
index de64d57851..a51c59c725 100644
--- a/platform/darwin/test/MGLLightTest.mm
+++ b/platform/darwin/test/MGLLightTest.mm
@@ -27,29 +27,28 @@
{
mbgl::style::Light light;
MGLLight *mglLight = [[MGLLight alloc] initWithMBGLLight:&light];
- auto lightFromMGLlight = [mglLight mbglLight];
+ auto lightFromMGLLight = mglLight.mbglLight;
- XCTAssertEqual(light.getDefaultAnchor(), lightFromMGLlight.getAnchor());
- XCTAssert([mglLight.anchor isKindOfClass:[MGLConstantStyleValue class]], @"mglLight.anchor isn’t a MGLConstantStyleValue.");
- NSValue *anchorValue = ((MGLConstantStyleValue *)mglLight.anchor).rawValue;
- XCTAssertEqual(anchorValue.MGLLightAnchorValue, MGLLightAnchorViewport);
+ XCTAssertEqual(light.getDefaultAnchor(), lightFromMGLLight.getAnchor());
+ XCTAssertEqual(mglLight.anchor.expressionType, NSConstantValueExpressionType, @"mglLight.anchor isn’t a constant value expression.");
+ XCTAssertEqualObjects(mglLight.anchor.constantValue, @"viewport");
mbgl::style::PropertyValue<mbgl::style::LightAnchorType> propertyValue = { mbgl::style::LightAnchorType::Viewport };
light.setAnchor(propertyValue);
mglLight = [[MGLLight alloc] initWithMBGLLight:&light];
- lightFromMGLlight = [mglLight mbglLight];
+ lightFromMGLLight = mglLight.mbglLight;
- XCTAssertEqual(light.getAnchor(), lightFromMGLlight.getAnchor());
+ XCTAssertEqual(light.getAnchor(), lightFromMGLLight.getAnchor());
}
// position
{
mbgl::style::Light light;
MGLLight *mglLight = [[MGLLight alloc] initWithMBGLLight:&light];
- auto lightFromMGLlight = [mglLight mbglLight];
+ auto lightFromMGLLight = mglLight.mbglLight;
- XCTAssertEqual(light.getDefaultPosition(), lightFromMGLlight.getPosition());
- auto positionTransition = lightFromMGLlight.getPositionTransition();
+ XCTAssertEqual(light.getDefaultPosition(), lightFromMGLLight.getPosition());
+ auto positionTransition = lightFromMGLLight.getPositionTransition();
XCTAssert(positionTransition.delay && MGLTimeIntervalFromDuration(*positionTransition.delay) == defaultTransition.delay);
XCTAssert(positionTransition.duration && MGLTimeIntervalFromDuration(*positionTransition.duration) == defaultTransition.duration);
@@ -60,10 +59,10 @@
light.setPositionTransition(transitionOptions);
mglLight = [[MGLLight alloc] initWithMBGLLight:&light];
- lightFromMGLlight = [mglLight mbglLight];
+ lightFromMGLLight = mglLight.mbglLight;
- XCTAssertEqual(light.getPosition(), lightFromMGLlight.getPosition());
- positionTransition = lightFromMGLlight.getPositionTransition();
+ XCTAssertEqual(light.getPosition(), lightFromMGLLight.getPosition());
+ positionTransition = lightFromMGLLight.getPositionTransition();
XCTAssert(positionTransition.delay && MGLTimeIntervalFromDuration(*positionTransition.delay) == transition.delay);
XCTAssert(positionTransition.duration && MGLTimeIntervalFromDuration(*positionTransition.duration) == transition.duration);
@@ -73,10 +72,10 @@
{
mbgl::style::Light light;
MGLLight *mglLight = [[MGLLight alloc] initWithMBGLLight:&light];
- auto lightFromMGLlight = [mglLight mbglLight];
+ auto lightFromMGLLight = mglLight.mbglLight;
- XCTAssertEqual(light.getDefaultColor(), lightFromMGLlight.getColor());
- auto colorTransition = lightFromMGLlight.getColorTransition();
+ XCTAssertEqual(light.getDefaultColor(), lightFromMGLLight.getColor());
+ auto colorTransition = lightFromMGLLight.getColorTransition();
XCTAssert(colorTransition.delay && MGLTimeIntervalFromDuration(*colorTransition.delay) == defaultTransition.delay);
XCTAssert(colorTransition.duration && MGLTimeIntervalFromDuration(*colorTransition.duration) == defaultTransition.duration);
@@ -85,10 +84,10 @@
light.setColorTransition(transitionOptions);
mglLight = [[MGLLight alloc] initWithMBGLLight:&light];
- lightFromMGLlight = [mglLight mbglLight];
+ lightFromMGLLight = mglLight.mbglLight;
- XCTAssertEqual(light.getColor(), lightFromMGLlight.getColor());
- colorTransition = lightFromMGLlight.getColorTransition();
+ XCTAssertEqual(light.getColor(), lightFromMGLLight.getColor());
+ colorTransition = lightFromMGLLight.getColorTransition();
XCTAssert(colorTransition.delay && MGLTimeIntervalFromDuration(*colorTransition.delay) == transition.delay);
XCTAssert(colorTransition.duration && MGLTimeIntervalFromDuration(*colorTransition.duration) == transition.duration);
@@ -98,10 +97,10 @@
{
mbgl::style::Light light;
MGLLight *mglLight = [[MGLLight alloc] initWithMBGLLight:&light];
- auto lightFromMGLlight = [mglLight mbglLight];
+ auto lightFromMGLLight = mglLight.mbglLight;
- XCTAssertEqual(light.getDefaultIntensity(), lightFromMGLlight.getIntensity());
- auto intensityTransition = lightFromMGLlight.getIntensityTransition();
+ XCTAssertEqual(light.getDefaultIntensity(), lightFromMGLLight.getIntensity());
+ auto intensityTransition = lightFromMGLLight.getIntensityTransition();
XCTAssert(intensityTransition.delay && MGLTimeIntervalFromDuration(*intensityTransition.delay) == defaultTransition.delay);
XCTAssert(intensityTransition.duration && MGLTimeIntervalFromDuration(*intensityTransition.duration) == defaultTransition.duration);
@@ -110,10 +109,10 @@
light.setIntensityTransition(transitionOptions);
mglLight = [[MGLLight alloc] initWithMBGLLight:&light];
- lightFromMGLlight = [mglLight mbglLight];
+ lightFromMGLLight = mglLight.mbglLight;
- XCTAssertEqual(light.getIntensity(), lightFromMGLlight.getIntensity());
- intensityTransition = lightFromMGLlight.getIntensityTransition();
+ XCTAssertEqual(light.getIntensity(), lightFromMGLLight.getIntensity());
+ intensityTransition = lightFromMGLLight.getIntensityTransition();
XCTAssert(intensityTransition.delay && MGLTimeIntervalFromDuration(*intensityTransition.delay) == transition.delay);
XCTAssert(intensityTransition.duration && MGLTimeIntervalFromDuration(*intensityTransition.duration) == transition.duration);
diff --git a/platform/darwin/test/MGLLightTest.mm.ejs b/platform/darwin/test/MGLLightTest.mm.ejs
index 5b1f27d8d1..35ff58b6d5 100644
--- a/platform/darwin/test/MGLLightTest.mm.ejs
+++ b/platform/darwin/test/MGLLightTest.mm.ejs
@@ -32,19 +32,18 @@
{
mbgl::style::Light light;
MGLLight *mglLight = [[MGLLight alloc] initWithMBGLLight:&light];
- auto lightFromMGLlight = [mglLight mbglLight];
+ auto lightFromMGLLight = mglLight.mbglLight;
- XCTAssertEqual(light.getDefault<%- camelize(property.name) -%>(), lightFromMGLlight.get<%- camelize(property.name) -%>());
+ XCTAssertEqual(light.getDefault<%- camelize(property.name) -%>(), lightFromMGLLight.get<%- camelize(property.name) -%>());
<% if (property.transition) { -%>
- auto <%- camelizeWithLeadingLowercase(property.name) -%>Transition = lightFromMGLlight.get<%- camelize(property.name) -%>Transition();
+ auto <%- camelizeWithLeadingLowercase(property.name) -%>Transition = lightFromMGLLight.get<%- camelize(property.name) -%>Transition();
XCTAssert(<%- camelizeWithLeadingLowercase(property.name) -%>Transition.delay && MGLTimeIntervalFromDuration(*<%- camelizeWithLeadingLowercase(property.name) -%>Transition.delay) == defaultTransition.delay);
XCTAssert(<%- camelizeWithLeadingLowercase(property.name) -%>Transition.duration && MGLTimeIntervalFromDuration(*<%- camelizeWithLeadingLowercase(property.name) -%>Transition.duration) == defaultTransition.duration);
<% } -%>
<% if (property.type == "enum" && property.default) { -%>
- XCTAssert([mglLight.<%- camelizeWithLeadingLowercase(property.name) -%> isKindOfClass:[MGLConstantStyleValue class]], @"mglLight.<%- camelizeWithLeadingLowercase(property.name) -%> isn’t a MGLConstantStyleValue.");
- NSValue *<%- camelizeWithLeadingLowercase(property.name) -%>Value = ((MGLConstantStyleValue *)mglLight.<%- camelizeWithLeadingLowercase(property.name) -%>).rawValue;
- XCTAssertEqual(<%- camelizeWithLeadingLowercase(property.name) -%>Value.MGLLight<%- camelize(property.name) -%>Value, MGLLight<%- camelize(property.name) -%><%- camelize(property.default) -%>);
+ XCTAssertEqual(mglLight.<%- camelizeWithLeadingLowercase(property.name) -%>.expressionType, NSConstantValueExpressionType, @"mglLight.<%- camelizeWithLeadingLowercase(property.name) -%> isn’t a constant value expression.");
+ XCTAssertEqualObjects(mglLight.<%- camelizeWithLeadingLowercase(property.name) -%>.constantValue, @"<%- property.default -%>");
<% } -%>
<% if (property.type == "array") { -%>
@@ -60,11 +59,11 @@
<% } -%>
mglLight = [[MGLLight alloc] initWithMBGLLight:&light];
- lightFromMGLlight = [mglLight mbglLight];
+ lightFromMGLLight = mglLight.mbglLight;
- XCTAssertEqual(light.get<%- camelize(property.name) -%>(), lightFromMGLlight.get<%- camelize(property.name) -%>());
+ XCTAssertEqual(light.get<%- camelize(property.name) -%>(), lightFromMGLLight.get<%- camelize(property.name) -%>());
<% if (property.transition) { -%>
- <%- camelizeWithLeadingLowercase(property.name) -%>Transition = lightFromMGLlight.get<%- camelize(property.name) -%>Transition();
+ <%- camelizeWithLeadingLowercase(property.name) -%>Transition = lightFromMGLLight.get<%- camelize(property.name) -%>Transition();
XCTAssert(<%- camelizeWithLeadingLowercase(property.name) -%>Transition.delay && MGLTimeIntervalFromDuration(*<%- camelizeWithLeadingLowercase(property.name) -%>Transition.delay) == transition.delay);
XCTAssert(<%- camelizeWithLeadingLowercase(property.name) -%>Transition.duration && MGLTimeIntervalFromDuration(*<%- camelizeWithLeadingLowercase(property.name) -%>Transition.duration) == transition.duration);
diff --git a/platform/darwin/test/MGLLineStyleLayerTests.mm b/platform/darwin/test/MGLLineStyleLayerTests.mm
index 7e7926e22e..5490278e98 100644
--- a/platform/darwin/test/MGLLineStyleLayerTests.mm
+++ b/platform/darwin/test/MGLLineStyleLayerTests.mm
@@ -30,8 +30,8 @@
XCTAssertNil(layer.sourceLayerIdentifier);
XCTAssertNil(layer.predicate);
- layer.predicate = [NSPredicate predicateWithValue:NO];
- XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithValue:NO]);
+ layer.predicate = [NSPredicate predicateWithFormat:@"$featureIdentifier = 1"];
+ XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithFormat:@"$featureIdentifier = 1"]);
layer.predicate = nil;
XCTAssertNil(layer.predicate);
}
@@ -52,72 +52,81 @@
{
XCTAssertTrue(rawLayer->getLineCap().isUndefined(),
@"line-cap should be unset initially.");
- MGLStyleValue<NSValue *> *defaultStyleValue = layer.lineCap;
+ NSExpression *defaultExpression = layer.lineCap;
- MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLLineCap:MGLLineCapSquare]];
- layer.lineCap = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'square'"];
+ layer.lineCap = constantExpression;
mbgl::style::PropertyValue<mbgl::style::LineCapType> propertyValue = { mbgl::style::LineCapType::Square };
XCTAssertEqual(rawLayer->getLineCap(), propertyValue,
- @"Setting lineCap to a constant value should update line-cap.");
- XCTAssertEqualObjects(layer.lineCap, constantStyleValue,
- @"lineCap should round-trip constant values.");
-
- MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.lineCap = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::style::LineCapType> intervalStops = { {{18, mbgl::style::LineCapType::Square}} };
+ @"Setting lineCap to a constant value expression should update line-cap.");
+ XCTAssertEqualObjects(layer.lineCap, constantExpression,
+ @"lineCap should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"'square'"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.lineCap = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::style::LineCapType> intervalStops = {{
+ { -INFINITY, mbgl::style::LineCapType::Square },
+ { 18, mbgl::style::LineCapType::Square },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::style::LineCapType> { intervalStops };
XCTAssertEqual(rawLayer->getLineCap(), propertyValue,
- @"Setting lineCap to a camera function should update line-cap.");
- XCTAssertEqualObjects(layer.lineCap, functionStyleValue,
- @"lineCap should round-trip camera functions.");
+ @"Setting lineCap to a camera expression should update line-cap.");
+ XCTAssertEqualObjects(layer.lineCap, functionExpression,
+ @"lineCap should round-trip camera expressions.");
layer.lineCap = nil;
XCTAssertTrue(rawLayer->getLineCap().isUndefined(),
@"Unsetting lineCap should return line-cap to the default value.");
- XCTAssertEqualObjects(layer.lineCap, defaultStyleValue,
+ XCTAssertEqualObjects(layer.lineCap, defaultExpression,
@"lineCap should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.lineCap = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.lineCap = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.lineCap = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.lineCap = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// line-join
{
XCTAssertTrue(rawLayer->getLineJoin().isUndefined(),
@"line-join should be unset initially.");
- MGLStyleValue<NSValue *> *defaultStyleValue = layer.lineJoin;
+ NSExpression *defaultExpression = layer.lineJoin;
- MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLLineJoin:MGLLineJoinMiter]];
- layer.lineJoin = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'miter'"];
+ layer.lineJoin = constantExpression;
mbgl::style::DataDrivenPropertyValue<mbgl::style::LineJoinType> propertyValue = { mbgl::style::LineJoinType::Miter };
XCTAssertEqual(rawLayer->getLineJoin(), propertyValue,
- @"Setting lineJoin to a constant value should update line-join.");
- XCTAssertEqualObjects(layer.lineJoin, constantStyleValue,
- @"lineJoin should round-trip constant values.");
-
- MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.lineJoin = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::style::LineJoinType> intervalStops = { {{18, mbgl::style::LineJoinType::Miter}} };
+ @"Setting lineJoin to a constant value expression should update line-join.");
+ XCTAssertEqualObjects(layer.lineJoin, constantExpression,
+ @"lineJoin should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"'miter'"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.lineJoin = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::style::LineJoinType> intervalStops = {{
+ { -INFINITY, mbgl::style::LineJoinType::Miter },
+ { 18, mbgl::style::LineJoinType::Miter },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::style::LineJoinType> { intervalStops };
XCTAssertEqual(rawLayer->getLineJoin(), propertyValue,
- @"Setting lineJoin to a camera function should update line-join.");
- XCTAssertEqualObjects(layer.lineJoin, functionStyleValue,
- @"lineJoin should round-trip camera functions.");
+ @"Setting lineJoin to a camera expression should update line-join.");
+ XCTAssertEqualObjects(layer.lineJoin, functionExpression,
+ @"lineJoin should round-trip camera expressions.");
layer.lineJoin = nil;
XCTAssertTrue(rawLayer->getLineJoin().isUndefined(),
@"Unsetting lineJoin should return line-join to the default value.");
- XCTAssertEqualObjects(layer.lineJoin, defaultStyleValue,
+ XCTAssertEqualObjects(layer.lineJoin, defaultExpression,
@"lineJoin should return the default value after being unset.");
}
@@ -125,118 +134,133 @@
{
XCTAssertTrue(rawLayer->getLineMiterLimit().isUndefined(),
@"line-miter-limit should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.lineMiterLimit;
+ NSExpression *defaultExpression = layer.lineMiterLimit;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.lineMiterLimit = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.lineMiterLimit = constantExpression;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getLineMiterLimit(), propertyValue,
- @"Setting lineMiterLimit to a constant value should update line-miter-limit.");
- XCTAssertEqualObjects(layer.lineMiterLimit, constantStyleValue,
- @"lineMiterLimit should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.lineMiterLimit = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting lineMiterLimit to a constant value expression should update line-miter-limit.");
+ XCTAssertEqualObjects(layer.lineMiterLimit, constantExpression,
+ @"lineMiterLimit should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.lineMiterLimit = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getLineMiterLimit(), propertyValue,
- @"Setting lineMiterLimit to a camera function should update line-miter-limit.");
- XCTAssertEqualObjects(layer.lineMiterLimit, functionStyleValue,
- @"lineMiterLimit should round-trip camera functions.");
+ @"Setting lineMiterLimit to a camera expression should update line-miter-limit.");
+ XCTAssertEqualObjects(layer.lineMiterLimit, functionExpression,
+ @"lineMiterLimit should round-trip camera expressions.");
layer.lineMiterLimit = nil;
XCTAssertTrue(rawLayer->getLineMiterLimit().isUndefined(),
@"Unsetting lineMiterLimit should return line-miter-limit to the default value.");
- XCTAssertEqualObjects(layer.lineMiterLimit, defaultStyleValue,
+ XCTAssertEqualObjects(layer.lineMiterLimit, defaultExpression,
@"lineMiterLimit should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.lineMiterLimit = 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.lineMiterLimit = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.lineMiterLimit = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.lineMiterLimit = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// line-round-limit
{
XCTAssertTrue(rawLayer->getLineRoundLimit().isUndefined(),
@"line-round-limit should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.lineRoundLimit;
+ NSExpression *defaultExpression = layer.lineRoundLimit;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.lineRoundLimit = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.lineRoundLimit = constantExpression;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getLineRoundLimit(), propertyValue,
- @"Setting lineRoundLimit to a constant value should update line-round-limit.");
- XCTAssertEqualObjects(layer.lineRoundLimit, constantStyleValue,
- @"lineRoundLimit should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.lineRoundLimit = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting lineRoundLimit to a constant value expression should update line-round-limit.");
+ XCTAssertEqualObjects(layer.lineRoundLimit, constantExpression,
+ @"lineRoundLimit should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.lineRoundLimit = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getLineRoundLimit(), propertyValue,
- @"Setting lineRoundLimit to a camera function should update line-round-limit.");
- XCTAssertEqualObjects(layer.lineRoundLimit, functionStyleValue,
- @"lineRoundLimit should round-trip camera functions.");
+ @"Setting lineRoundLimit to a camera expression should update line-round-limit.");
+ XCTAssertEqualObjects(layer.lineRoundLimit, functionExpression,
+ @"lineRoundLimit should round-trip camera expressions.");
layer.lineRoundLimit = nil;
XCTAssertTrue(rawLayer->getLineRoundLimit().isUndefined(),
@"Unsetting lineRoundLimit should return line-round-limit to the default value.");
- XCTAssertEqualObjects(layer.lineRoundLimit, defaultStyleValue,
+ XCTAssertEqualObjects(layer.lineRoundLimit, defaultExpression,
@"lineRoundLimit should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.lineRoundLimit = 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.lineRoundLimit = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.lineRoundLimit = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.lineRoundLimit = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// line-blur
{
XCTAssertTrue(rawLayer->getLineBlur().isUndefined(),
@"line-blur should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.lineBlur;
+ NSExpression *defaultExpression = layer.lineBlur;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.lineBlur = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.lineBlur = constantExpression;
mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getLineBlur(), propertyValue,
- @"Setting lineBlur to a constant value should update line-blur.");
- XCTAssertEqualObjects(layer.lineBlur, constantStyleValue,
- @"lineBlur should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.lineBlur = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting lineBlur to a constant value expression should update line-blur.");
+ XCTAssertEqualObjects(layer.lineBlur, constantExpression,
+ @"lineBlur should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.lineBlur = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getLineBlur(), propertyValue,
- @"Setting lineBlur to a camera function should update line-blur.");
- XCTAssertEqualObjects(layer.lineBlur, functionStyleValue,
- @"lineBlur should round-trip camera functions.");
+ @"Setting lineBlur to a camera expression should update line-blur.");
+ XCTAssertEqualObjects(layer.lineBlur, functionExpression,
+ @"lineBlur should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.lineBlur = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.lineBlur = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getLineBlur(), propertyValue,
- @"Setting lineBlur to a source function should update line-blur.");
- XCTAssertEqualObjects(layer.lineBlur, functionStyleValue,
- @"lineBlur should round-trip source functions.");
+ @"Setting lineBlur to a data expression should update line-blur.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.lineBlur, pedanticFunctionExpression,
+ @"lineBlur should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.lineBlur = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.lineBlur = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -244,15 +268,16 @@
propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getLineBlur(), propertyValue,
- @"Setting lineBlur to a composite function should update line-blur.");
- XCTAssertEqualObjects(layer.lineBlur, functionStyleValue,
- @"lineBlur should round-trip composite functions.");
+ @"Setting lineBlur to a camera-data expression should update line-blur.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.lineBlur, pedanticFunctionExpression,
+ @"lineBlur should round-trip camera-data expressions.");
layer.lineBlur = nil;
XCTAssertTrue(rawLayer->getLineBlur().isUndefined(),
@"Unsetting lineBlur should return line-blur to the default value.");
- XCTAssertEqualObjects(layer.lineBlur, defaultStyleValue,
+ XCTAssertEqualObjects(layer.lineBlur, defaultExpression,
@"lineBlur should return the default value after being unset.");
// Transition property test
layer.lineBlurTransition = transitionTest;
@@ -269,40 +294,45 @@
{
XCTAssertTrue(rawLayer->getLineColor().isUndefined(),
@"line-color should be unset initially.");
- MGLStyleValue<MGLColor *> *defaultStyleValue = layer.lineColor;
+ NSExpression *defaultExpression = layer.lineColor;
- MGLStyleValue<MGLColor *> *constantStyleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
- layer.lineColor = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ layer.lineColor = constantExpression;
mbgl::style::DataDrivenPropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getLineColor(), propertyValue,
- @"Setting lineColor to a constant value should update line-color.");
- XCTAssertEqualObjects(layer.lineColor, constantStyleValue,
- @"lineColor should round-trip constant values.");
-
- MGLStyleValue<MGLColor *> * functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.lineColor = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::Color> intervalStops = { {{18, { 1, 0, 0, 1 }}} };
+ @"Setting lineColor to a constant value expression should update line-color.");
+ XCTAssertEqualObjects(layer.lineColor, constantExpression,
+ @"lineColor should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.lineColor = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::Color> intervalStops = {{
+ { -INFINITY, { 1, 0, 0, 1 } },
+ { 18, { 1, 0, 0, 1 } },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::Color> { intervalStops };
XCTAssertEqual(rawLayer->getLineColor(), propertyValue,
- @"Setting lineColor to a camera function should update line-color.");
- XCTAssertEqualObjects(layer.lineColor, functionStyleValue,
- @"lineColor should round-trip camera functions.");
+ @"Setting lineColor to a camera expression should update line-color.");
+ XCTAssertEqualObjects(layer.lineColor, functionExpression,
+ @"lineColor should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.lineColor = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.lineColor = functionExpression;
mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<mbgl::Color> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getLineColor(), propertyValue,
- @"Setting lineColor to a source function should update line-color.");
- XCTAssertEqualObjects(layer.lineColor, functionStyleValue,
- @"lineColor should round-trip source functions.");
+ @"Setting lineColor to a data expression should update line-color.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.lineColor, pedanticFunctionExpression,
+ @"lineColor should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.lineColor = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.lineColor = functionExpression;
std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
mbgl::style::CompositeExponentialStops<mbgl::Color> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -310,15 +340,16 @@
propertyValue = mbgl::style::CompositeFunction<mbgl::Color> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getLineColor(), propertyValue,
- @"Setting lineColor to a composite function should update line-color.");
- XCTAssertEqualObjects(layer.lineColor, functionStyleValue,
- @"lineColor should round-trip composite functions.");
+ @"Setting lineColor to a camera-data expression should update line-color.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.lineColor, pedanticFunctionExpression,
+ @"lineColor should round-trip camera-data expressions.");
layer.lineColor = nil;
XCTAssertTrue(rawLayer->getLineColor().isUndefined(),
@"Unsetting lineColor should return line-color to the default value.");
- XCTAssertEqualObjects(layer.lineColor, defaultStyleValue,
+ XCTAssertEqualObjects(layer.lineColor, defaultExpression,
@"lineColor should return the default value after being unset.");
// Transition property test
layer.lineColorTransition = transitionTest;
@@ -335,79 +366,89 @@
{
XCTAssertTrue(rawLayer->getLineDasharray().isUndefined(),
@"line-dasharray should be unset initially.");
- MGLStyleValue<NSArray<NSNumber *> *> *defaultStyleValue = layer.lineDashPattern;
+ NSExpression *defaultExpression = layer.lineDashPattern;
- MGLStyleValue<NSArray<NSNumber *> *> *constantStyleValue = [MGLStyleValue<NSArray<NSNumber *> *> valueWithRawValue:@[@1, @2]];
- layer.lineDashPattern = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"{1, 2}"];
+ layer.lineDashPattern = constantExpression;
mbgl::style::PropertyValue<std::vector<float>> propertyValue = { {1, 2} };
XCTAssertEqual(rawLayer->getLineDasharray(), propertyValue,
- @"Setting lineDashPattern to a constant value should update line-dasharray.");
- XCTAssertEqualObjects(layer.lineDashPattern, constantStyleValue,
- @"lineDashPattern should round-trip constant values.");
-
- MGLStyleValue<NSArray<NSNumber *> *> * functionStyleValue = [MGLStyleValue<NSArray<NSNumber *> *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.lineDashPattern = functionStyleValue;
-
- mbgl::style::IntervalStops<std::vector<float>> intervalStops = { {{18, {1, 2}}} };
+ @"Setting lineDashPattern to a constant value expression should update line-dasharray.");
+ XCTAssertEqualObjects(layer.lineDashPattern, constantExpression,
+ @"lineDashPattern should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"{1, 2}"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.lineDashPattern = functionExpression;
+
+ mbgl::style::IntervalStops<std::vector<float>> intervalStops = {{
+ { -INFINITY, {1, 2} },
+ { 18, {1, 2} },
+ }};
propertyValue = mbgl::style::CameraFunction<std::vector<float>> { intervalStops };
XCTAssertEqual(rawLayer->getLineDasharray(), propertyValue,
- @"Setting lineDashPattern to a camera function should update line-dasharray.");
- XCTAssertEqualObjects(layer.lineDashPattern, functionStyleValue,
- @"lineDashPattern should round-trip camera functions.");
+ @"Setting lineDashPattern to a camera expression should update line-dasharray.");
+ XCTAssertEqualObjects(layer.lineDashPattern, functionExpression,
+ @"lineDashPattern should round-trip camera expressions.");
layer.lineDashPattern = nil;
XCTAssertTrue(rawLayer->getLineDasharray().isUndefined(),
@"Unsetting lineDashPattern should return line-dasharray to the default value.");
- XCTAssertEqualObjects(layer.lineDashPattern, defaultStyleValue,
+ XCTAssertEqualObjects(layer.lineDashPattern, defaultExpression,
@"lineDashPattern should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSArray<NSNumber *> *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.lineDashPattern = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSArray<NSNumber *> *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.lineDashPattern = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.lineDashPattern = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.lineDashPattern = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// line-gap-width
{
XCTAssertTrue(rawLayer->getLineGapWidth().isUndefined(),
@"line-gap-width should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.lineGapWidth;
+ NSExpression *defaultExpression = layer.lineGapWidth;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.lineGapWidth = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.lineGapWidth = constantExpression;
mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getLineGapWidth(), propertyValue,
- @"Setting lineGapWidth to a constant value should update line-gap-width.");
- XCTAssertEqualObjects(layer.lineGapWidth, constantStyleValue,
- @"lineGapWidth should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.lineGapWidth = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting lineGapWidth to a constant value expression should update line-gap-width.");
+ XCTAssertEqualObjects(layer.lineGapWidth, constantExpression,
+ @"lineGapWidth should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.lineGapWidth = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getLineGapWidth(), propertyValue,
- @"Setting lineGapWidth to a camera function should update line-gap-width.");
- XCTAssertEqualObjects(layer.lineGapWidth, functionStyleValue,
- @"lineGapWidth should round-trip camera functions.");
+ @"Setting lineGapWidth to a camera expression should update line-gap-width.");
+ XCTAssertEqualObjects(layer.lineGapWidth, functionExpression,
+ @"lineGapWidth should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.lineGapWidth = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.lineGapWidth = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getLineGapWidth(), propertyValue,
- @"Setting lineGapWidth to a source function should update line-gap-width.");
- XCTAssertEqualObjects(layer.lineGapWidth, functionStyleValue,
- @"lineGapWidth should round-trip source functions.");
+ @"Setting lineGapWidth to a data expression should update line-gap-width.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.lineGapWidth, pedanticFunctionExpression,
+ @"lineGapWidth should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.lineGapWidth = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.lineGapWidth = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -415,15 +456,16 @@
propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getLineGapWidth(), propertyValue,
- @"Setting lineGapWidth to a composite function should update line-gap-width.");
- XCTAssertEqualObjects(layer.lineGapWidth, functionStyleValue,
- @"lineGapWidth should round-trip composite functions.");
+ @"Setting lineGapWidth to a camera-data expression should update line-gap-width.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.lineGapWidth, pedanticFunctionExpression,
+ @"lineGapWidth should round-trip camera-data expressions.");
layer.lineGapWidth = nil;
XCTAssertTrue(rawLayer->getLineGapWidth().isUndefined(),
@"Unsetting lineGapWidth should return line-gap-width to the default value.");
- XCTAssertEqualObjects(layer.lineGapWidth, defaultStyleValue,
+ XCTAssertEqualObjects(layer.lineGapWidth, defaultExpression,
@"lineGapWidth should return the default value after being unset.");
// Transition property test
layer.lineGapWidthTransition = transitionTest;
@@ -440,40 +482,45 @@
{
XCTAssertTrue(rawLayer->getLineOffset().isUndefined(),
@"line-offset should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.lineOffset;
+ NSExpression *defaultExpression = layer.lineOffset;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.lineOffset = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.lineOffset = constantExpression;
mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getLineOffset(), propertyValue,
- @"Setting lineOffset to a constant value should update line-offset.");
- XCTAssertEqualObjects(layer.lineOffset, constantStyleValue,
- @"lineOffset should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.lineOffset = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting lineOffset to a constant value expression should update line-offset.");
+ XCTAssertEqualObjects(layer.lineOffset, constantExpression,
+ @"lineOffset should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.lineOffset = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getLineOffset(), propertyValue,
- @"Setting lineOffset to a camera function should update line-offset.");
- XCTAssertEqualObjects(layer.lineOffset, functionStyleValue,
- @"lineOffset should round-trip camera functions.");
+ @"Setting lineOffset to a camera expression should update line-offset.");
+ XCTAssertEqualObjects(layer.lineOffset, functionExpression,
+ @"lineOffset should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.lineOffset = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.lineOffset = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getLineOffset(), propertyValue,
- @"Setting lineOffset to a source function should update line-offset.");
- XCTAssertEqualObjects(layer.lineOffset, functionStyleValue,
- @"lineOffset should round-trip source functions.");
+ @"Setting lineOffset to a data expression should update line-offset.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.lineOffset, pedanticFunctionExpression,
+ @"lineOffset should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.lineOffset = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.lineOffset = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -481,15 +528,16 @@
propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getLineOffset(), propertyValue,
- @"Setting lineOffset to a composite function should update line-offset.");
- XCTAssertEqualObjects(layer.lineOffset, functionStyleValue,
- @"lineOffset should round-trip composite functions.");
+ @"Setting lineOffset to a camera-data expression should update line-offset.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.lineOffset, pedanticFunctionExpression,
+ @"lineOffset should round-trip camera-data expressions.");
layer.lineOffset = nil;
XCTAssertTrue(rawLayer->getLineOffset().isUndefined(),
@"Unsetting lineOffset should return line-offset to the default value.");
- XCTAssertEqualObjects(layer.lineOffset, defaultStyleValue,
+ XCTAssertEqualObjects(layer.lineOffset, defaultExpression,
@"lineOffset should return the default value after being unset.");
// Transition property test
layer.lineOffsetTransition = transitionTest;
@@ -506,40 +554,45 @@
{
XCTAssertTrue(rawLayer->getLineOpacity().isUndefined(),
@"line-opacity should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.lineOpacity;
+ NSExpression *defaultExpression = layer.lineOpacity;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.lineOpacity = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.lineOpacity = constantExpression;
mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getLineOpacity(), propertyValue,
- @"Setting lineOpacity to a constant value should update line-opacity.");
- XCTAssertEqualObjects(layer.lineOpacity, constantStyleValue,
- @"lineOpacity should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.lineOpacity = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting lineOpacity to a constant value expression should update line-opacity.");
+ XCTAssertEqualObjects(layer.lineOpacity, constantExpression,
+ @"lineOpacity should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.lineOpacity = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getLineOpacity(), propertyValue,
- @"Setting lineOpacity to a camera function should update line-opacity.");
- XCTAssertEqualObjects(layer.lineOpacity, functionStyleValue,
- @"lineOpacity should round-trip camera functions.");
+ @"Setting lineOpacity to a camera expression should update line-opacity.");
+ XCTAssertEqualObjects(layer.lineOpacity, functionExpression,
+ @"lineOpacity should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.lineOpacity = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.lineOpacity = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getLineOpacity(), propertyValue,
- @"Setting lineOpacity to a source function should update line-opacity.");
- XCTAssertEqualObjects(layer.lineOpacity, functionStyleValue,
- @"lineOpacity should round-trip source functions.");
+ @"Setting lineOpacity to a data expression should update line-opacity.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.lineOpacity, pedanticFunctionExpression,
+ @"lineOpacity should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.lineOpacity = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.lineOpacity = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -547,15 +600,16 @@
propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getLineOpacity(), propertyValue,
- @"Setting lineOpacity to a composite function should update line-opacity.");
- XCTAssertEqualObjects(layer.lineOpacity, functionStyleValue,
- @"lineOpacity should round-trip composite functions.");
+ @"Setting lineOpacity to a camera-data expression should update line-opacity.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.lineOpacity, pedanticFunctionExpression,
+ @"lineOpacity should round-trip camera-data expressions.");
layer.lineOpacity = nil;
XCTAssertTrue(rawLayer->getLineOpacity().isUndefined(),
@"Unsetting lineOpacity should return line-opacity to the default value.");
- XCTAssertEqualObjects(layer.lineOpacity, defaultStyleValue,
+ XCTAssertEqualObjects(layer.lineOpacity, defaultExpression,
@"lineOpacity should return the default value after being unset.");
// Transition property test
layer.lineOpacityTransition = transitionTest;
@@ -572,39 +626,44 @@
{
XCTAssertTrue(rawLayer->getLinePattern().isUndefined(),
@"line-pattern should be unset initially.");
- MGLStyleValue<NSString *> *defaultStyleValue = layer.linePattern;
+ NSExpression *defaultExpression = layer.linePattern;
- MGLStyleValue<NSString *> *constantStyleValue = [MGLStyleValue<NSString *> valueWithRawValue:@"Line Pattern"];
- layer.linePattern = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'Line Pattern'"];
+ layer.linePattern = constantExpression;
mbgl::style::PropertyValue<std::string> propertyValue = { "Line Pattern" };
XCTAssertEqual(rawLayer->getLinePattern(), propertyValue,
- @"Setting linePattern to a constant value should update line-pattern.");
- XCTAssertEqualObjects(layer.linePattern, constantStyleValue,
- @"linePattern should round-trip constant values.");
-
- MGLStyleValue<NSString *> * functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.linePattern = functionStyleValue;
-
- mbgl::style::IntervalStops<std::string> intervalStops = { {{18, "Line Pattern"}} };
+ @"Setting linePattern to a constant value expression should update line-pattern.");
+ XCTAssertEqualObjects(layer.linePattern, constantExpression,
+ @"linePattern should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"'Line Pattern'"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.linePattern = functionExpression;
+
+ mbgl::style::IntervalStops<std::string> intervalStops = {{
+ { -INFINITY, "Line Pattern" },
+ { 18, "Line Pattern" },
+ }};
propertyValue = mbgl::style::CameraFunction<std::string> { intervalStops };
XCTAssertEqual(rawLayer->getLinePattern(), propertyValue,
- @"Setting linePattern to a camera function should update line-pattern.");
- XCTAssertEqualObjects(layer.linePattern, functionStyleValue,
- @"linePattern should round-trip camera functions.");
+ @"Setting linePattern to a camera expression should update line-pattern.");
+ XCTAssertEqualObjects(layer.linePattern, functionExpression,
+ @"linePattern should round-trip camera expressions.");
layer.linePattern = nil;
XCTAssertTrue(rawLayer->getLinePattern().isUndefined(),
@"Unsetting linePattern should return line-pattern to the default value.");
- XCTAssertEqualObjects(layer.linePattern, defaultStyleValue,
+ XCTAssertEqualObjects(layer.linePattern, defaultExpression,
@"linePattern should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.linePattern = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.linePattern = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.linePattern = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.linePattern = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
// Transition property test
layer.linePatternTransition = transitionTest;
auto toptions = rawLayer->getLinePatternTransition();
@@ -620,124 +679,139 @@
{
XCTAssertTrue(rawLayer->getLineTranslate().isUndefined(),
@"line-translate should be unset initially.");
- MGLStyleValue<NSValue *> *defaultStyleValue = layer.lineTranslation;
+ NSExpression *defaultExpression = layer.lineTranslation;
- MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"%@",
#if TARGET_OS_IPHONE
[NSValue valueWithCGVector:CGVectorMake(1, 1)]
#else
[NSValue valueWithMGLVector:CGVectorMake(1, -1)]
#endif
];
- layer.lineTranslation = constantStyleValue;
+ layer.lineTranslation = constantExpression;
mbgl::style::PropertyValue<std::array<float, 2>> propertyValue = { { 1, 1 } };
XCTAssertEqual(rawLayer->getLineTranslate(), propertyValue,
- @"Setting lineTranslation to a constant value should update line-translate.");
- XCTAssertEqualObjects(layer.lineTranslation, constantStyleValue,
- @"lineTranslation should round-trip constant values.");
-
- MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.lineTranslation = functionStyleValue;
-
- mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = { {{18, { 1, 1 }}} };
+ @"Setting lineTranslation to a constant value expression should update line-translate.");
+ XCTAssertEqualObjects(layer.lineTranslation, constantExpression,
+ @"lineTranslation should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"{1, 1}"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.lineTranslation = functionExpression;
+
+ mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = {{
+ { -INFINITY, { 1, 1 } },
+ { 18, { 1, 1 } },
+ }};
propertyValue = mbgl::style::CameraFunction<std::array<float, 2>> { intervalStops };
XCTAssertEqual(rawLayer->getLineTranslate(), propertyValue,
- @"Setting lineTranslation to a camera function should update line-translate.");
- XCTAssertEqualObjects(layer.lineTranslation, functionStyleValue,
- @"lineTranslation should round-trip camera functions.");
+ @"Setting lineTranslation to a camera expression should update line-translate.");
+ XCTAssertEqualObjects(layer.lineTranslation, functionExpression,
+ @"lineTranslation should round-trip camera expressions.");
layer.lineTranslation = nil;
XCTAssertTrue(rawLayer->getLineTranslate().isUndefined(),
@"Unsetting lineTranslation should return line-translate to the default value.");
- XCTAssertEqualObjects(layer.lineTranslation, defaultStyleValue,
+ XCTAssertEqualObjects(layer.lineTranslation, defaultExpression,
@"lineTranslation should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.lineTranslation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.lineTranslation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.lineTranslation = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.lineTranslation = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// line-translate-anchor
{
XCTAssertTrue(rawLayer->getLineTranslateAnchor().isUndefined(),
@"line-translate-anchor should be unset initially.");
- MGLStyleValue<NSValue *> *defaultStyleValue = layer.lineTranslationAnchor;
+ NSExpression *defaultExpression = layer.lineTranslationAnchor;
- MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLLineTranslationAnchor:MGLLineTranslationAnchorViewport]];
- layer.lineTranslationAnchor = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'viewport'"];
+ layer.lineTranslationAnchor = constantExpression;
mbgl::style::PropertyValue<mbgl::style::TranslateAnchorType> propertyValue = { mbgl::style::TranslateAnchorType::Viewport };
XCTAssertEqual(rawLayer->getLineTranslateAnchor(), propertyValue,
- @"Setting lineTranslationAnchor to a constant value should update line-translate-anchor.");
- XCTAssertEqualObjects(layer.lineTranslationAnchor, constantStyleValue,
- @"lineTranslationAnchor should round-trip constant values.");
-
- MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.lineTranslationAnchor = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::style::TranslateAnchorType> intervalStops = { {{18, mbgl::style::TranslateAnchorType::Viewport}} };
+ @"Setting lineTranslationAnchor to a constant value expression should update line-translate-anchor.");
+ XCTAssertEqualObjects(layer.lineTranslationAnchor, constantExpression,
+ @"lineTranslationAnchor should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"'viewport'"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.lineTranslationAnchor = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::style::TranslateAnchorType> intervalStops = {{
+ { -INFINITY, mbgl::style::TranslateAnchorType::Viewport },
+ { 18, mbgl::style::TranslateAnchorType::Viewport },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::style::TranslateAnchorType> { intervalStops };
XCTAssertEqual(rawLayer->getLineTranslateAnchor(), propertyValue,
- @"Setting lineTranslationAnchor to a camera function should update line-translate-anchor.");
- XCTAssertEqualObjects(layer.lineTranslationAnchor, functionStyleValue,
- @"lineTranslationAnchor should round-trip camera functions.");
+ @"Setting lineTranslationAnchor to a camera expression should update line-translate-anchor.");
+ XCTAssertEqualObjects(layer.lineTranslationAnchor, functionExpression,
+ @"lineTranslationAnchor should round-trip camera expressions.");
layer.lineTranslationAnchor = nil;
XCTAssertTrue(rawLayer->getLineTranslateAnchor().isUndefined(),
@"Unsetting lineTranslationAnchor should return line-translate-anchor to the default value.");
- XCTAssertEqualObjects(layer.lineTranslationAnchor, defaultStyleValue,
+ XCTAssertEqualObjects(layer.lineTranslationAnchor, defaultExpression,
@"lineTranslationAnchor should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.lineTranslationAnchor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.lineTranslationAnchor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.lineTranslationAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.lineTranslationAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// line-width
{
XCTAssertTrue(rawLayer->getLineWidth().isUndefined(),
@"line-width should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.lineWidth;
+ NSExpression *defaultExpression = layer.lineWidth;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.lineWidth = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.lineWidth = constantExpression;
mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getLineWidth(), propertyValue,
- @"Setting lineWidth to a constant value should update line-width.");
- XCTAssertEqualObjects(layer.lineWidth, constantStyleValue,
- @"lineWidth should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.lineWidth = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting lineWidth to a constant value expression should update line-width.");
+ XCTAssertEqualObjects(layer.lineWidth, constantExpression,
+ @"lineWidth should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.lineWidth = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getLineWidth(), propertyValue,
- @"Setting lineWidth to a camera function should update line-width.");
- XCTAssertEqualObjects(layer.lineWidth, functionStyleValue,
- @"lineWidth should round-trip camera functions.");
+ @"Setting lineWidth to a camera expression should update line-width.");
+ XCTAssertEqualObjects(layer.lineWidth, functionExpression,
+ @"lineWidth should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.lineWidth = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.lineWidth = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getLineWidth(), propertyValue,
- @"Setting lineWidth to a source function should update line-width.");
- XCTAssertEqualObjects(layer.lineWidth, functionStyleValue,
- @"lineWidth should round-trip source functions.");
+ @"Setting lineWidth to a data expression should update line-width.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.lineWidth, pedanticFunctionExpression,
+ @"lineWidth should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.lineWidth = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.lineWidth = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -745,15 +819,16 @@
propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getLineWidth(), propertyValue,
- @"Setting lineWidth to a composite function should update line-width.");
- XCTAssertEqualObjects(layer.lineWidth, functionStyleValue,
- @"lineWidth should round-trip composite functions.");
+ @"Setting lineWidth to a camera-data expression should update line-width.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.lineWidth, pedanticFunctionExpression,
+ @"lineWidth should round-trip camera-data expressions.");
layer.lineWidth = nil;
XCTAssertTrue(rawLayer->getLineWidth().isUndefined(),
@"Unsetting lineWidth should return line-width to the default value.");
- XCTAssertEqualObjects(layer.lineWidth, defaultStyleValue,
+ XCTAssertEqualObjects(layer.lineWidth, defaultExpression,
@"lineWidth should return the default value after being unset.");
// Transition property test
layer.lineWidthTransition = transitionTest;
diff --git a/platform/darwin/test/MGLNSStringAdditionsTests.m b/platform/darwin/test/MGLNSStringAdditionsTests.m
index 03503b7f8a..a3ee7e3433 100644
--- a/platform/darwin/test/MGLNSStringAdditionsTests.m
+++ b/platform/darwin/test/MGLNSStringAdditionsTests.m
@@ -39,4 +39,30 @@
XCTAssertEqualObjects([@"Improve This iPhone" mgl_titleCasedStringWithLocale:locale], @"Improve This iPhone");
}
+- (void)testTransliteratedString {
+ XCTAssertEqualObjects([@"Portland" mgl_stringByTransliteratingIntoScript:@"Latn"], @"Portland");
+ XCTAssertEqualObjects([@"Portland" mgl_stringByTransliteratingIntoScript:@"Hans"], @"Portland");
+ XCTAssertEqualObjects([@"Portland" mgl_stringByTransliteratingIntoScript:@"Cyrl"], @"Портланд");
+ XCTAssertEqualObjects([@"Portland" mgl_stringByTransliteratingIntoScript:@"Arab"], @"پُرتلَند");
+ XCTAssertEqualObjects([@"Portland" mgl_stringByTransliteratingIntoScript:@"Fake"], @"Portland");
+
+ XCTAssertEqualObjects([@"北京" mgl_stringByTransliteratingIntoScript:@"Latn"], @"běi jīng");
+ XCTAssertEqualObjects([@"北京" mgl_stringByTransliteratingIntoScript:@"Hans"], @"北京");
+ XCTAssertEqualObjects([@"北京" mgl_stringByTransliteratingIntoScript:@"Cyrl"], @"бе̌и йӣнг");
+ XCTAssertEqualObjects([@"北京" mgl_stringByTransliteratingIntoScript:@"Arab"], @"بِِ̌ جِينگ");
+ XCTAssertEqualObjects([@"北京" mgl_stringByTransliteratingIntoScript:@"Fake"], @"北京");
+
+ XCTAssertEqualObjects([@"Mосква" mgl_stringByTransliteratingIntoScript:@"Latn"], @"Moskva");
+ XCTAssertEqualObjects([@"Mосква" mgl_stringByTransliteratingIntoScript:@"Hans"], @"Mосква");
+ XCTAssertEqualObjects([@"Mосква" mgl_stringByTransliteratingIntoScript:@"Cyrl"], @"Москва");
+ XCTAssertEqualObjects([@"Mосква" mgl_stringByTransliteratingIntoScript:@"Arab"], @"مُسكڤَ");
+ XCTAssertEqualObjects([@"Mосква" mgl_stringByTransliteratingIntoScript:@"Fake"], @"Mосква");
+
+ XCTAssertEqualObjects([@"ロンドン" mgl_stringByTransliteratingIntoScript:@"Latn"], @"rondon");
+ XCTAssertEqualObjects([@"ロンドン" mgl_stringByTransliteratingIntoScript:@"Hans"], @"ロンドン");
+ XCTAssertEqualObjects([@"ロンドン" mgl_stringByTransliteratingIntoScript:@"Cyrl"], @"рондон");
+ XCTAssertEqualObjects([@"ロンドン" mgl_stringByTransliteratingIntoScript:@"Arab"], @"رُندُن");
+ XCTAssertEqualObjects([@"ロンドン" mgl_stringByTransliteratingIntoScript:@"Fake"], @"ロンドン");
+}
+
@end
diff --git a/platform/darwin/test/MGLPredicateTests.mm b/platform/darwin/test/MGLPredicateTests.mm
index 6e6951dcdd..ab4a7e2d88 100644
--- a/platform/darwin/test/MGLPredicateTests.mm
+++ b/platform/darwin/test/MGLPredicateTests.mm
@@ -23,295 +23,9 @@ namespace mbgl {
@implementation MGLPredicateTests
-- (void)testFilterization {
- {
- auto actual = [NSPredicate predicateWithValue:YES].mgl_filter;
- mbgl::style::AllFilter expected;
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithValue:NO].mgl_filter;
- mbgl::style::AnyFilter expected;
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"a = 'b'"].mgl_filter;
- mbgl::style::EqualsFilter expected = { .key = "a", .value = std::string("b") };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"%K = 'Point'", @"$type"].mgl_filter;
- mbgl::style::TypeEqualsFilter expected = { .value = mbgl::FeatureType::Point };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"%K = 67086180", @"$id"].mgl_filter;
- mbgl::style::IdentifierEqualsFilter expected = { .value = UINT64_C(67086180) };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"%K = nil", @"$id"].mgl_filter;
- mbgl::style::NotHasIdentifierFilter expected;
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"a = nil"].mgl_filter;
- mbgl::style::NotHasFilter expected = { .key = "a" };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"%K != 'Point'", @"$type"].mgl_filter;
- mbgl::style::TypeNotEqualsFilter expected = { .value = mbgl::FeatureType::Point };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"%K != 67086180", @"$id"].mgl_filter;
- mbgl::style::IdentifierNotEqualsFilter expected = { .value = UINT64_C(67086180) };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"%K != nil", @"$id"].mgl_filter;
- mbgl::style::HasIdentifierFilter expected;
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"a != 'b'"].mgl_filter;
- mbgl::style::NotEqualsFilter expected = { .key = "a", .value = std::string("b") };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"a != nil"].mgl_filter;
- mbgl::style::HasFilter expected = { .key = "a" };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"a < 'b'"].mgl_filter;
- mbgl::style::LessThanFilter expected = { .key = "a", .value = std::string("b") };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"a <= 'b'"].mgl_filter;
- mbgl::style::LessThanEqualsFilter expected = { .key = "a", .value = std::string("b") };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"a > 'b'"].mgl_filter;
- mbgl::style::GreaterThanFilter expected = { .key = "a", .value = std::string("b") };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"a >= 'b'"].mgl_filter;
- mbgl::style::GreaterThanEqualsFilter expected = { .key = "a", .value = std::string("b") };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"a BETWEEN {'b', 'z'}"].mgl_filter;
- mbgl::style::AllFilter expected = {
- .filters = {
- mbgl::style::GreaterThanEqualsFilter { .key = "a", .value = std::string("b") },
- mbgl::style::LessThanEqualsFilter { .key = "a", .value = std::string("z") },
- },
- };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"a BETWEEN %@", @[@"b", @"z"]].mgl_filter;
- mbgl::style::AllFilter expected = {
- .filters = {
- mbgl::style::GreaterThanEqualsFilter { .key = "a", .value = std::string("b") },
- mbgl::style::LessThanEqualsFilter { .key = "a", .value = std::string("z") },
- },
- };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"a IN {'b', 'c'}"].mgl_filter;
- mbgl::style::InFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"a IN %@", @[@"b", @"c"]].mgl_filter;
- mbgl::style::InFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"%K IN {'LineString', 'Polygon'}", @"$type"].mgl_filter;
- mbgl::style::TypeInFilter expected = { .values = { mbgl::FeatureType::LineString, mbgl::FeatureType::Polygon } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"%K IN %@", @"$type", @[@"LineString", @"Polygon"]].mgl_filter;
- mbgl::style::TypeInFilter expected = { .values = { mbgl::FeatureType::LineString, mbgl::FeatureType::Polygon } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"%K IN {67086180, 3709678893, 3352016856, 4189833989}", @"$id"].mgl_filter;
- mbgl::style::IdentifierInFilter expected = { .values = { UINT64_C(67086180), UINT64_C(3709678893), UINT64_C(3352016856), UINT64_C(4189833989) } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"%K IN %@", @"$id", @[@67086180, @3709678893, @3352016856, @4189833989]].mgl_filter;
- mbgl::style::IdentifierInFilter expected = { .values = { UINT64_C(67086180), UINT64_C(3709678893), UINT64_C(3352016856), UINT64_C(4189833989) } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"'Mapbox' IN a"].mgl_filter, NSException, NSInvalidArgumentException);
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"{'b', 'c'} CONTAINS a"].mgl_filter;
- mbgl::style::InFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"%@ CONTAINS a", @[@"b", @"c"]].mgl_filter;
- mbgl::style::InFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"%@ CONTAINS %K", @[@"LineString", @"Polygon"], @"$type"].mgl_filter;
- mbgl::style::TypeInFilter expected = { .values = { mbgl::FeatureType::LineString, mbgl::FeatureType::Polygon } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"{67086180, 3709678893, 3352016856, 4189833989} CONTAINS %K", @"$id"].mgl_filter;
- mbgl::style::IdentifierInFilter expected = { .values = { UINT64_C(67086180), UINT64_C(3709678893), UINT64_C(3352016856), UINT64_C(4189833989) } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"%@ CONTAINS %K", @[@67086180, @3709678893, @3352016856, @4189833989], @"$id"].mgl_filter;
- mbgl::style::IdentifierInFilter expected = { .values = { UINT64_C(67086180), UINT64_C(3709678893), UINT64_C(3352016856), UINT64_C(4189833989) } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a CONTAINS 'Mapbox'"].mgl_filter, NSException, NSInvalidArgumentException);
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"a == 'b' AND c == 'd'"].mgl_filter;
- mbgl::style::AllFilter expected = {
- .filters = {
- mbgl::style::EqualsFilter { .key = "a", .value = std::string("b") },
- mbgl::style::EqualsFilter { .key = "c", .value = std::string("d") },
- },
- };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"a == 'b' OR c == 'd'"].mgl_filter;
- mbgl::style::AnyFilter expected = {
- .filters = {
- mbgl::style::EqualsFilter { .key = "a", .value = std::string("b") },
- mbgl::style::EqualsFilter { .key = "c", .value = std::string("d") },
- },
- };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"NOT(a == 'b' AND c == 'd')"].mgl_filter;
- mbgl::style::NoneFilter expected = {
- .filters = {
- mbgl::style::AllFilter {
- .filters = {
- mbgl::style::EqualsFilter { .key = "a", .value = std::string("b") },
- mbgl::style::EqualsFilter { .key = "c", .value = std::string("d") },
- },
- },
- },
- };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"NOT(a == 'b' OR c == 'd')"].mgl_filter;
- mbgl::style::NoneFilter expected = {
- .filters = {
- mbgl::style::EqualsFilter { .key = "a", .value = std::string("b") },
- mbgl::style::EqualsFilter { .key = "c", .value = std::string("d") },
- },
- };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"NOT a == nil"].mgl_filter;
- mbgl::style::HasFilter expected = { .key = "a" };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"NOT a != nil"].mgl_filter;
- mbgl::style::NotHasFilter expected = { .key = "a" };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"NOT a IN {'b', 'c'}"].mgl_filter;
- mbgl::style::NotInFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"NOT a IN %@", @[@"b", @"c"]].mgl_filter;
- mbgl::style::NotInFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"NOT {'b', 'c'} CONTAINS a"].mgl_filter;
- mbgl::style::NotInFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"NOT %@ CONTAINS a", @[@"b", @"c"]].mgl_filter;
- mbgl::style::NotInFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a BEGINSWITH 'L'"].mgl_filter, NSException, NSInvalidArgumentException);
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a ENDSWITH 'itude'"].mgl_filter, NSException, NSInvalidArgumentException);
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a LIKE 'glob?trotter'"].mgl_filter, NSException, NSInvalidArgumentException);
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a MATCHES 'i\\w{18}n'"].mgl_filter, NSException, NSInvalidArgumentException);
- NSPredicate *selectorPredicate = [NSPredicate predicateWithFormat:@"(SELF isKindOfClass: %@)", [MGLPolyline class]];
- XCTAssertThrowsSpecificNamed(selectorPredicate.mgl_filter, NSException, NSInvalidArgumentException);
-
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary<NSString *, id> * _Nullable bindings) {
- XCTAssertTrue(NO, @"Predicate block should not be evaluated.");
- return NO;
- }].mgl_filter, NSException, NSInvalidArgumentException);
-}
-
- (void)testPredication {
XCTAssertNil([NSPredicate mgl_predicateWithFilter:mbgl::style::NullFilter()]);
-
+
{
mbgl::style::EqualsFilter filter = { .key = "a", .value = std::string("b") };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a = 'b'"]);
@@ -351,12 +65,12 @@ namespace mbgl {
mbgl::style::TypeEqualsFilter filter = { .value = mbgl::FeatureType::Unknown };
XCTAssertThrowsSpecificNamed([NSPredicate mgl_predicateWithFilter:filter], NSException, NSInternalInconsistencyException);
}
-
+
{
mbgl::style::NotHasFilter filter = { .key = "a" };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a = nil"]);
}
-
+
{
mbgl::style::NotEqualsFilter filter = { .key = "a", .value = std::string("b") };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a != 'b'"]);
@@ -379,32 +93,32 @@ namespace mbgl {
NSPredicate *expected = [NSPredicate predicateWithFormat:@"%K != nil", @"$id"];
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], expected);
}
-
+
{
mbgl::style::HasFilter filter = { .key = "a" };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a != nil"]);
}
-
+
{
mbgl::style::LessThanFilter filter = { .key = "a", .value = std::string("b") };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a < 'b'"]);
}
-
+
{
mbgl::style::LessThanEqualsFilter filter = { .key = "a", .value = std::string("b") };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a <= 'b'"]);
}
-
+
{
mbgl::style::GreaterThanFilter filter = { .key = "a", .value = std::string("b") };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a > 'b'"]);
}
-
+
{
mbgl::style::GreaterThanEqualsFilter filter = { .key = "a", .value = std::string("b") };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a >= 'b'"]);
}
-
+
{
mbgl::style::AllFilter filter = {
.filters = {
@@ -414,7 +128,7 @@ namespace mbgl {
};
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a BETWEEN {'b', 'z'}"]);
}
-
+
{
mbgl::style::AllFilter filter = {
.filters = {
@@ -424,7 +138,7 @@ namespace mbgl {
};
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a BETWEEN {'b', 'z'}"]);
}
-
+
{
mbgl::style::InFilter filter = { .key = "a", .values = { std::string("b"), std::string("c") } };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter].predicateFormat, [NSPredicate predicateWithFormat:@"a IN {'b', 'c'}"].predicateFormat);
@@ -441,7 +155,7 @@ namespace mbgl {
NSPredicate *expected = [NSPredicate predicateWithFormat:@"%K IN {67086180, 3709678893, 3352016856, 4189833989}", @"$id"];
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], expected);
}
-
+
{
mbgl::style::NotInFilter filter = { .key = "a", .values = { std::string("b"), std::string("c") } };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter].predicateFormat, [NSPredicate predicateWithFormat:@"NOT a IN {'b', 'c'}"].predicateFormat);
@@ -458,12 +172,12 @@ namespace mbgl {
NSPredicate *expected = [NSPredicate predicateWithFormat:@"NOT %K IN {67086180, 3709678893, 3352016856, 4189833989}", @"$id"];
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], expected);
}
-
+
{
mbgl::style::AllFilter filter;
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithValue:YES]);
}
-
+
{
mbgl::style::AllFilter filter = {
.filters = {
@@ -473,12 +187,12 @@ namespace mbgl {
};
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a == 'b' AND c == 'd'"]);
}
-
+
{
mbgl::style::AnyFilter filter;
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithValue:NO]);
}
-
+
{
mbgl::style::AnyFilter filter = {
.filters = {
@@ -488,12 +202,12 @@ namespace mbgl {
};
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a == 'b' OR c == 'd'"]);
}
-
+
{
mbgl::style::NoneFilter filter;
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithValue:YES]);
}
-
+
{
mbgl::style::NoneFilter filter = {
.filters = {
@@ -505,69 +219,339 @@ namespace mbgl {
}
}
-- (void)testSymmetry {
- [self testSymmetryWithFormat:@"a = 1" reverseFormat:@"1 = a" mustRoundTrip:YES];
- [self testSymmetryWithFormat:@"a != 1" reverseFormat:@"1 != a" mustRoundTrip:YES];
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a = b"].mgl_filter, NSException, NSInvalidArgumentException);
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"1 = 1"].mgl_filter, NSException, NSInvalidArgumentException);
-
- // In the predicate format language, $ is a special character denoting a
- // variable. Use %K to escape the special feature attribute $id.
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"$id == 670861802"].mgl_filter, NSException, NSInvalidArgumentException);
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a = $id"].mgl_filter, NSException, NSInvalidArgumentException);
-
- [self testSymmetryWithFormat:@"a = nil" reverseFormat:@"nil = a" mustRoundTrip:YES];
- [self testSymmetryWithFormat:@"a != nil" reverseFormat:@"nil != a" mustRoundTrip:YES];
-
- [self testSymmetryWithFormat:@"a < 1" reverseFormat:@"1 > a" mustRoundTrip:YES];
- [self testSymmetryWithFormat:@"a <= 1" reverseFormat:@"1 >= a" mustRoundTrip:YES];
- [self testSymmetryWithFormat:@"a > 1" reverseFormat:@"1 < a" mustRoundTrip:YES];
- [self testSymmetryWithFormat:@"a >= 1" reverseFormat:@"1 <= a" mustRoundTrip:YES];
-
- [self testSymmetryWithFormat:@"a BETWEEN {1, 2}" reverseFormat:@"1 <= a && 2 >= a" mustRoundTrip:YES];
- [self testSymmetryWithPredicate:[NSPredicate predicateWithFormat:@"a BETWEEN %@", @[@1, @2]]
- reversePredicate:[NSPredicate predicateWithFormat:@"1 <= a && 2 >= a"]
- mustRoundTrip:YES];
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"{1, 2} BETWEEN a"].mgl_filter, NSException, NSInvalidArgumentException);
- NSPredicate *betweenSetPredicate = [NSPredicate predicateWithFormat:@"a BETWEEN %@", [NSSet setWithObjects:@1, @2, nil]];
- XCTAssertThrowsSpecificNamed(betweenSetPredicate.mgl_filter, NSException, NSInvalidArgumentException);
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a BETWEEN {1}"].mgl_filter, NSException, NSInvalidArgumentException);
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a BETWEEN {1, 2, 3}"].mgl_filter, NSException, NSInvalidArgumentException);
-
- [self testSymmetryWithFormat:@"a IN {1, 2}" reverseFormat:@"{1, 2} CONTAINS a" mustRoundTrip:NO];
- [self testSymmetryWithPredicate:[NSPredicate predicateWithFormat:@"a IN %@", @[@1, @2]]
- reversePredicate:[NSPredicate predicateWithFormat:@"%@ CONTAINS a", @[@1, @2]]
- mustRoundTrip:YES];
+- (void)testUnsupportedFilterPredicates {
+ XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"1 == 2"].mgl_filter, NSException, NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"1 == 1"].mgl_filter, NSException, NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([NSPredicate predicateWithValue:YES].mgl_filter, NSException, NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([NSPredicate predicateWithValue:NO].mgl_filter, NSException, NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a BEGINSWITH 'L'"].mgl_filter, NSException, NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a ENDSWITH 'itude'"].mgl_filter, NSException, NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a LIKE 'glob?trotter'"].mgl_filter, NSException, NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a MATCHES 'i\\w{18}n'"].mgl_filter, NSException, NSInvalidArgumentException);
+ NSPredicate *selectorPredicate = [NSPredicate predicateWithFormat:@"(SELF isKindOfClass: %@)", [MGLPolyline class]];
+ XCTAssertThrowsSpecificNamed(selectorPredicate.mgl_filter, NSException, NSInvalidArgumentException);
+
+ XCTAssertThrowsSpecificNamed([NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary<NSString *, id> * _Nullable bindings) {
+ XCTAssertTrue(NO, @"Predicate block should not be evaluated.");
+ return NO;
+ }].mgl_filter, NSException, NSInvalidArgumentException);
+}
- // The reverse formats here are a bit backwards because we canonicalize
- // a reverse CONTAINS to a forward IN.
- [self testSymmetryWithFormat:@"{1, 2} CONTAINS a" reverseFormat:@"{1, 2} CONTAINS a" mustRoundTrip:NO];
- [self testSymmetryWithPredicate:[NSPredicate predicateWithFormat:@"%@ CONTAINS a", @[@1, @2]]
- reversePredicate:[NSPredicate predicateWithFormat:@"%@ CONTAINS a", @[@1, @2]]
- mustRoundTrip:NO];
+- (void)testComparisonPredicates {
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"x == YES"];
+ NSArray *jsonExpression = @[@"==", @[@"get", @"x"], @YES];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"CAST(x, 'NSNumber') < 5"];
+ NSArray *jsonExpression = @[@"<", @[@"to-number", @[@"get", @"x"]], @5];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"CAST(x, 'NSNumber') > 5"];
+ NSArray *jsonExpression = @[@">", @[@"to-number", @[@"get", @"x"]], @5];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"CAST(x, 'NSNumber') <= 5"];
+ NSArray *jsonExpression = @[@"<=", @[@"to-number", @[@"get", @"x"]], @5];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"CAST(x, 'NSNumber') >= 5"];
+ NSArray *jsonExpression = @[@">=", @[@"to-number", @[@"get", @"x"]], @5];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"CAST(x, 'NSString') > 'value'"];
+ NSArray *jsonExpression = @[@">", @[@"to-string", @[@"get", @"x"]], @"value"];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"a = 'b'"];
+ NSArray *jsonExpression = @[@"==", @[@"get", @"a"], @"b"];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ [self testSymmetryWithPredicate:predicate
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"$geometryType = 'Point'"];
+ NSArray *jsonExpression = @[@"==", @[@"geometry-type"], @"Point"];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ [self testSymmetryWithPredicate:predicate
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"$featureIdentifier = 67086180"];
+ NSArray *jsonExpression = @[@"==", @[@"id"], @67086180];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ [self testSymmetryWithPredicate:predicate
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"$featureIdentifier = nil"];
+ NSArray *jsonExpression = @[@"==", @[@"id"], [NSNull null]];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ [self testSymmetryWithPredicate:predicate
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"a = nil"];
+ NSArray *jsonExpression = @[@"==", @[@"get", @"a"], [NSNull null]];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ [self testSymmetryWithPredicate:predicate
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"$geometryType != 'Point'"];
+ NSArray *jsonExpression = @[@"!=", @[@"geometry-type"], @"Point"];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ [self testSymmetryWithPredicate:predicate
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"$featureIdentifier != 67086180"];
+ NSArray *jsonExpression = @[@"!=", @[@"id"], @67086180];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ [self testSymmetryWithPredicate:predicate
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"$featureIdentifier != nil"];
+ NSArray *jsonExpression = @[@"!=", @[@"id"], [NSNull null]];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ [self testSymmetryWithPredicate:predicate
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"a != 'b'"];
+ NSArray *jsonExpression = @[@"!=", @[@"get", @"a"], @"b"];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ [self testSymmetryWithPredicate:predicate
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"a != nil"];
+ NSArray *jsonExpression = @[@"!=", @[@"get", @"a"], [NSNull null]];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ [self testSymmetryWithPredicate:predicate
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"CAST(a, 'NSString') < 'b'"];
+ NSArray *jsonExpression = @[@"<", @[@"to-string", @[@"get", @"a"]], @"b"];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"CAST(a, 'NSString') <= 'b'"];
+ NSArray *jsonExpression = @[@"<=", @[@"to-string", @[@"get", @"a"]], @"b"];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"CAST(a, 'NSString') > 'b'"];
+ NSArray *jsonExpression = @[@">", @[@"to-string", @[@"get", @"a"]], @"b"];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"CAST(a, 'NSString') >= 'b'"];
+ NSArray *jsonExpression = @[@">=", @[@"to-string", @[@"get", @"a"]], @"b"];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"CAST(a, 'NSString') BETWEEN {'b', 'z'}"];
+ NSArray *jsonExpression =@[@"all", @[@"<=", @"b", @[@"to-string", @[@"get", @"a"]]], @[@"<=", @[@"to-string", @[@"get", @"a"]], @"z"]];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSExpression *limits = [NSExpression expressionForAggregate:@[[NSExpression expressionForConstantValue:@10], [NSExpression expressionForConstantValue:@100]]];
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"CAST(x, 'NSNumber') BETWEEN %@", limits];
+ NSArray *jsonExpression = @[@"all", @[@">=", @[@"to-number", @[@"get", @"x"]], @10], @[@"<=", @[@"to-number", @[@"get", @"x"]], @100]];
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSArray *expected = @[@"all", @[@"<=", @10, @[@"to-number", @[@"get", @"x"]]], @[@"<=", @[@"to-number", @[@"get", @"x"]], @100]];
+ NSExpression *limits = [NSExpression expressionForAggregate:@[[NSExpression expressionForConstantValue:@10], [NSExpression expressionForConstantValue:@100]]];
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"CAST(x, 'NSNumber') BETWEEN %@", limits];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, expected);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:expected], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:expected]
+ mustRoundTrip:NO];
+ }
+ {
+ NSArray *expected = @[@"all", @[@"<=", @10, @[@"to-number", @[@"get", @"x"]]], @[@">=", @100, @[@"to-number", @[@"get", @"x"]]]];
+ NSExpression *limits = [NSExpression expressionForAggregate:@[[NSExpression expressionForConstantValue:@10], [NSExpression expressionForConstantValue:@100]]];
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"CAST(x, 'NSNumber') BETWEEN %@", limits];
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:expected], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:expected]
+ mustRoundTrip:NO];
+ }
+ {
+ NSArray *expected = @[@"all", @[@">=", @[@"to-number", @[@"get", @"x"]], @10], @[@">=", @100, @[@"to-number", @[@"get", @"x"]]]];
+ NSExpression *limits = [NSExpression expressionForAggregate:@[[NSExpression expressionForConstantValue:@10], [NSExpression expressionForConstantValue:@100]]];
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"CAST(x, 'NSNumber') BETWEEN %@", limits];
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:expected], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:expected]
+ mustRoundTrip:NO];
+ }
+ {
+ NSArray *expected = @[@"match", @[@"id"], @6, @YES, @5, @YES, @4, @YES, @3, @YES, @NO];
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"$featureIdentifier IN { 6, 5, 4, 3}"];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, expected);
+ NSPredicate *predicateAfter = [NSPredicate predicateWithFormat:@"MGL_MATCH(CAST($featureIdentifier, 'NSNumber'), 3, YES, 4, YES, 5, YES, 6, YES, NO) == YES"];
+ auto forwardFilter = [NSPredicate mgl_predicateWithJSONObject:expected].mgl_filter;
+ NSPredicate *forwardPredicateAfter = [NSPredicate mgl_predicateWithFilter:forwardFilter];
+ XCTAssertEqualObjects(predicateAfter, forwardPredicateAfter);
+ }
+ {
+ NSArray *expected = @[@"!", @[@"match", @[@"get", @"x"], @6, @YES, @5, @YES, @4, @YES, @3, @YES, @NO]];
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT x IN { 6, 5, 4, 3}"];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, expected);
+ NSPredicate *predicateAfter = [NSPredicate predicateWithFormat:@"NOT MGL_MATCH(CAST(x, 'NSNumber'), 3, YES, 4, YES, 5, YES, 6, YES, NO) == YES"];
+ auto forwardFilter = [NSPredicate mgl_predicateWithJSONObject:expected].mgl_filter;
+ NSPredicate *forwardPredicateAfter = [NSPredicate mgl_predicateWithFilter:forwardFilter];
+ XCTAssertEqualObjects(predicateAfter, forwardPredicateAfter);
+ }
+ {
+ NSArray *expected = @[@"match", @[@"get", @"a"], @"b", @YES, @"c", @YES, @NO];
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"a IN { 'b', 'c' }"];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, expected);
+ NSPredicate *predicateAfter = [NSPredicate predicateWithFormat:@"MGL_MATCH(CAST(a, 'NSString'), 'b', YES, 'c', YES, NO) == YES"];
+ auto forwardFilter = [NSPredicate mgl_predicateWithJSONObject:expected].mgl_filter;
+ NSPredicate *forwardPredicateAfter = [NSPredicate mgl_predicateWithFilter:forwardFilter];
+ XCTAssertEqualObjects(predicateAfter, forwardPredicateAfter);
+ }
+ {
+ NSArray *expected = @[@"match", @[@"geometry-type"], @"LineString", @YES, @"Polygon", @YES, @NO];
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%@ IN %@", [NSExpression expressionForVariable:@"geometryType"], @[@"LineString", @"Polygon"]];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, expected);
+ NSPredicate *predicateAfter = [NSPredicate predicateWithFormat:@"MGL_MATCH($geometryType, 'LineString', YES, 'Polygon', YES, NO) == YES"];
+ auto forwardFilter = [NSPredicate mgl_predicateWithJSONObject:expected].mgl_filter;
+ NSPredicate *forwardPredicateAfter = [NSPredicate mgl_predicateWithFilter:forwardFilter];
+ XCTAssertEqualObjects(predicateAfter, forwardPredicateAfter);
+ }
+ {
+ NSArray *expected = @[@"match", @[@"get", @"x"], @6, @YES, @5, @YES, @4, @YES, @3, @YES, @NO];
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"{ 6, 5, 4, 3} CONTAINS x"];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, expected);
+ NSPredicate *predicateAfter = [NSPredicate predicateWithFormat:@"MGL_MATCH(CAST(x, 'NSNumber'), 3, YES, 4, YES, 5, YES, 6, YES, NO) == YES"];
+ auto forwardFilter = [NSPredicate mgl_predicateWithJSONObject:expected].mgl_filter;
+ NSPredicate *forwardPredicateAfter = [NSPredicate mgl_predicateWithFilter:forwardFilter];
+ XCTAssertEqualObjects(predicateAfter, forwardPredicateAfter);
+ }
+ {
+ NSArray *expected = @[@"match", @[@"geometry-type"], @"LineString", @YES, @"Polygon", @YES, @NO];
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%@ CONTAINS %@", @[@"LineString", @"Polygon"], [NSExpression expressionForVariable:@"geometryType"]];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, expected);
+ NSPredicate *predicateAfter = [NSPredicate predicateWithFormat:@"MGL_MATCH($geometryType, 'LineString', YES, 'Polygon', YES, NO) == YES"];
+ auto forwardFilter = [NSPredicate mgl_predicateWithJSONObject:expected].mgl_filter;
+ NSPredicate *forwardPredicateAfter = [NSPredicate mgl_predicateWithFilter:forwardFilter];
+ XCTAssertEqualObjects(predicateAfter, forwardPredicateAfter);
+ }
+ {
+ NSArray *expected = @[@"match", @[@"id"], @6, @YES, @5, @YES, @4, @YES, @3, @YES, @NO];
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"{ 6, 5, 4, 3} CONTAINS $featureIdentifier"];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, expected);
+ NSPredicate *predicateAfter = [NSPredicate predicateWithFormat:@"MGL_MATCH(CAST($featureIdentifier, 'NSNumber'), 3, YES, 4, YES, 5, YES, 6, YES, NO) == YES"];
+ auto forwardFilter = [NSPredicate mgl_predicateWithJSONObject:expected].mgl_filter;
+ NSPredicate *forwardPredicateAfter = [NSPredicate mgl_predicateWithFilter:forwardFilter];
+ XCTAssertEqualObjects(predicateAfter, forwardPredicateAfter);
+ }
}
-- (void)testSymmetryWithFormat:(NSString *)forwardFormat reverseFormat:(NSString *)reverseFormat mustRoundTrip:(BOOL)mustRoundTrip {
- NSPredicate *forwardPredicate = [NSPredicate predicateWithFormat:forwardFormat];
- NSPredicate *reversePredicate = reverseFormat ? [NSPredicate predicateWithFormat:reverseFormat] : nil;
- [self testSymmetryWithPredicate:forwardPredicate reversePredicate:reversePredicate mustRoundTrip:mustRoundTrip];
+- (void)testCompoundPredicates {
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"a == 'b' AND c == 'd'"];
+ NSArray *jsonExpression = @[@"all", @[@"==", @[@"get", @"a"], @"b"], @[@"==", @[@"get", @"c"], @"d"]];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"a == 'b' OR c == 'd'"];
+ NSArray *jsonExpression = @[@"any", @[@"==", @[@"get", @"a"], @"b"], @[@"==", @[@"get", @"c"], @"d"]];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT(a == 'b' AND c == 'd')"];
+ NSArray *jsonExpression = @[@"!", @[@"all", @[@"==", @[@"get", @"a"], @"b"], @[@"==", @[@"get", @"c"], @"d"]]];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT(a == 'b' OR c == 'd')"];
+ NSArray *jsonExpression = @[@"!", @[@"any", @[@"==", @[@"get", @"a"], @"b"], @[@"==", @[@"get", @"c"], @"d"]]];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT a == nil"];
+ NSArray *jsonExpression = @[@"!", @[@"==", @[@"get", @"a"], [NSNull null]]];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ [self testSymmetryWithPredicate:predicate
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT a != nil"];
+ NSArray *jsonExpression = @[@"!", @[@"!=", @[@"get", @"a"], [NSNull null]]];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ [self testSymmetryWithPredicate:predicate
+ mustRoundTrip:NO];
+ }
}
-- (void)testSymmetryWithPredicate:(NSPredicate *)forwardPredicate reversePredicate:(NSPredicate *)reversePredicate mustRoundTrip:(BOOL)mustRoundTrip {
+- (void)testSymmetryWithPredicate:(NSPredicate *)forwardPredicate mustRoundTrip:(BOOL)mustRoundTrip {
auto forwardFilter = forwardPredicate.mgl_filter;
NSPredicate *forwardPredicateAfter = [NSPredicate mgl_predicateWithFilter:forwardFilter];
if (mustRoundTrip) {
// A collection of ints may turn into an aggregate of longs, for
// example, so compare formats instead of the predicates themselves.
XCTAssertEqualObjects(forwardPredicate.predicateFormat, forwardPredicateAfter.predicateFormat);
- }
-
- if (reversePredicate) {
- auto reverseFilter = reversePredicate.mgl_filter;
- NSPredicate *reversePredicateAfter = [NSPredicate mgl_predicateWithFilter:reverseFilter];
- XCTAssertNotEqualObjects(reversePredicate, reversePredicateAfter);
-
- XCTAssertEqualObjects(forwardPredicateAfter, reversePredicateAfter);
+ } else {
+ XCTAssertEqualObjects(forwardPredicate, forwardPredicateAfter);
}
}
diff --git a/platform/darwin/test/MGLRasterStyleLayerTests.mm b/platform/darwin/test/MGLRasterStyleLayerTests.mm
index 7b0757eeb6..c8e454743e 100644
--- a/platform/darwin/test/MGLRasterStyleLayerTests.mm
+++ b/platform/darwin/test/MGLRasterStyleLayerTests.mm
@@ -34,117 +34,132 @@
{
XCTAssertTrue(rawLayer->getRasterBrightnessMax().isUndefined(),
@"raster-brightness-max should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.maximumRasterBrightness;
+ NSExpression *defaultExpression = layer.maximumRasterBrightness;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.maximumRasterBrightness = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.maximumRasterBrightness = constantExpression;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getRasterBrightnessMax(), propertyValue,
- @"Setting maximumRasterBrightness to a constant value should update raster-brightness-max.");
- XCTAssertEqualObjects(layer.maximumRasterBrightness, constantStyleValue,
- @"maximumRasterBrightness should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.maximumRasterBrightness = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting maximumRasterBrightness to a constant value expression should update raster-brightness-max.");
+ XCTAssertEqualObjects(layer.maximumRasterBrightness, constantExpression,
+ @"maximumRasterBrightness should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.maximumRasterBrightness = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getRasterBrightnessMax(), propertyValue,
- @"Setting maximumRasterBrightness to a camera function should update raster-brightness-max.");
- XCTAssertEqualObjects(layer.maximumRasterBrightness, functionStyleValue,
- @"maximumRasterBrightness should round-trip camera functions.");
+ @"Setting maximumRasterBrightness to a camera expression should update raster-brightness-max.");
+ XCTAssertEqualObjects(layer.maximumRasterBrightness, functionExpression,
+ @"maximumRasterBrightness should round-trip camera expressions.");
layer.maximumRasterBrightness = nil;
XCTAssertTrue(rawLayer->getRasterBrightnessMax().isUndefined(),
@"Unsetting maximumRasterBrightness should return raster-brightness-max to the default value.");
- XCTAssertEqualObjects(layer.maximumRasterBrightness, defaultStyleValue,
+ XCTAssertEqualObjects(layer.maximumRasterBrightness, defaultExpression,
@"maximumRasterBrightness should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.maximumRasterBrightness = 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.maximumRasterBrightness = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.maximumRasterBrightness = functionExpression, NSException, NSInvalidArgumentException, @"MGLRasterLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.maximumRasterBrightness = functionExpression, NSException, NSInvalidArgumentException, @"MGLRasterLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// raster-brightness-min
{
XCTAssertTrue(rawLayer->getRasterBrightnessMin().isUndefined(),
@"raster-brightness-min should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.minimumRasterBrightness;
+ NSExpression *defaultExpression = layer.minimumRasterBrightness;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.minimumRasterBrightness = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.minimumRasterBrightness = constantExpression;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getRasterBrightnessMin(), propertyValue,
- @"Setting minimumRasterBrightness to a constant value should update raster-brightness-min.");
- XCTAssertEqualObjects(layer.minimumRasterBrightness, constantStyleValue,
- @"minimumRasterBrightness should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.minimumRasterBrightness = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting minimumRasterBrightness to a constant value expression should update raster-brightness-min.");
+ XCTAssertEqualObjects(layer.minimumRasterBrightness, constantExpression,
+ @"minimumRasterBrightness should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.minimumRasterBrightness = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getRasterBrightnessMin(), propertyValue,
- @"Setting minimumRasterBrightness to a camera function should update raster-brightness-min.");
- XCTAssertEqualObjects(layer.minimumRasterBrightness, functionStyleValue,
- @"minimumRasterBrightness should round-trip camera functions.");
+ @"Setting minimumRasterBrightness to a camera expression should update raster-brightness-min.");
+ XCTAssertEqualObjects(layer.minimumRasterBrightness, functionExpression,
+ @"minimumRasterBrightness should round-trip camera expressions.");
layer.minimumRasterBrightness = nil;
XCTAssertTrue(rawLayer->getRasterBrightnessMin().isUndefined(),
@"Unsetting minimumRasterBrightness should return raster-brightness-min to the default value.");
- XCTAssertEqualObjects(layer.minimumRasterBrightness, defaultStyleValue,
+ XCTAssertEqualObjects(layer.minimumRasterBrightness, defaultExpression,
@"minimumRasterBrightness should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.minimumRasterBrightness = 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.minimumRasterBrightness = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.minimumRasterBrightness = functionExpression, NSException, NSInvalidArgumentException, @"MGLRasterLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.minimumRasterBrightness = functionExpression, NSException, NSInvalidArgumentException, @"MGLRasterLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// raster-contrast
{
XCTAssertTrue(rawLayer->getRasterContrast().isUndefined(),
@"raster-contrast should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.rasterContrast;
+ NSExpression *defaultExpression = layer.rasterContrast;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.rasterContrast = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.rasterContrast = constantExpression;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getRasterContrast(), propertyValue,
- @"Setting rasterContrast to a constant value should update raster-contrast.");
- XCTAssertEqualObjects(layer.rasterContrast, constantStyleValue,
- @"rasterContrast should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.rasterContrast = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting rasterContrast to a constant value expression should update raster-contrast.");
+ XCTAssertEqualObjects(layer.rasterContrast, constantExpression,
+ @"rasterContrast should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.rasterContrast = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getRasterContrast(), propertyValue,
- @"Setting rasterContrast to a camera function should update raster-contrast.");
- XCTAssertEqualObjects(layer.rasterContrast, functionStyleValue,
- @"rasterContrast should round-trip camera functions.");
+ @"Setting rasterContrast to a camera expression should update raster-contrast.");
+ XCTAssertEqualObjects(layer.rasterContrast, functionExpression,
+ @"rasterContrast should round-trip camera expressions.");
layer.rasterContrast = nil;
XCTAssertTrue(rawLayer->getRasterContrast().isUndefined(),
@"Unsetting rasterContrast should return raster-contrast to the default value.");
- XCTAssertEqualObjects(layer.rasterContrast, defaultStyleValue,
+ XCTAssertEqualObjects(layer.rasterContrast, defaultExpression,
@"rasterContrast should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.rasterContrast = 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.rasterContrast = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.rasterContrast = functionExpression, NSException, NSInvalidArgumentException, @"MGLRasterLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.rasterContrast = functionExpression, NSException, NSInvalidArgumentException, @"MGLRasterLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
// Transition property test
layer.rasterContrastTransition = transitionTest;
auto toptions = rawLayer->getRasterContrastTransition();
@@ -160,126 +175,132 @@
{
XCTAssertTrue(rawLayer->getRasterFadeDuration().isUndefined(),
@"raster-fade-duration should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.rasterFadeDuration;
+ NSExpression *defaultExpression = layer.rasterFadeDuration;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.rasterFadeDuration = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.rasterFadeDuration = constantExpression;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getRasterFadeDuration(), propertyValue,
- @"Setting rasterFadeDuration to a constant value should update raster-fade-duration.");
- XCTAssertEqualObjects(layer.rasterFadeDuration, constantStyleValue,
- @"rasterFadeDuration should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.rasterFadeDuration = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting rasterFadeDuration to a constant value expression should update raster-fade-duration.");
+ XCTAssertEqualObjects(layer.rasterFadeDuration, constantExpression,
+ @"rasterFadeDuration should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.rasterFadeDuration = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getRasterFadeDuration(), propertyValue,
- @"Setting rasterFadeDuration to a camera function should update raster-fade-duration.");
- XCTAssertEqualObjects(layer.rasterFadeDuration, functionStyleValue,
- @"rasterFadeDuration should round-trip camera functions.");
+ @"Setting rasterFadeDuration to a camera expression should update raster-fade-duration.");
+ XCTAssertEqualObjects(layer.rasterFadeDuration, functionExpression,
+ @"rasterFadeDuration should round-trip camera expressions.");
layer.rasterFadeDuration = nil;
XCTAssertTrue(rawLayer->getRasterFadeDuration().isUndefined(),
@"Unsetting rasterFadeDuration should return raster-fade-duration to the default value.");
- XCTAssertEqualObjects(layer.rasterFadeDuration, defaultStyleValue,
+ XCTAssertEqualObjects(layer.rasterFadeDuration, defaultExpression,
@"rasterFadeDuration should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.rasterFadeDuration = 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.rasterFadeDuration = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- // Transition property test
- layer.rasterFadeDurationTransition = transitionTest;
- auto toptions = rawLayer->getRasterFadeDurationTransition();
- XCTAssert(toptions.delay && MGLTimeIntervalFromDuration(*toptions.delay) == transitionTest.delay);
- XCTAssert(toptions.duration && MGLTimeIntervalFromDuration(*toptions.duration) == transitionTest.duration);
-
- MGLTransition rasterFadeDurationTransition = layer.rasterFadeDurationTransition;
- XCTAssertEqual(rasterFadeDurationTransition.delay, transitionTest.delay);
- XCTAssertEqual(rasterFadeDurationTransition.duration, transitionTest.duration);
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.rasterFadeDuration = functionExpression, NSException, NSInvalidArgumentException, @"MGLRasterLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.rasterFadeDuration = functionExpression, NSException, NSInvalidArgumentException, @"MGLRasterLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// raster-hue-rotate
{
XCTAssertTrue(rawLayer->getRasterHueRotate().isUndefined(),
@"raster-hue-rotate should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.rasterHueRotation;
+ NSExpression *defaultExpression = layer.rasterHueRotation;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.rasterHueRotation = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.rasterHueRotation = constantExpression;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getRasterHueRotate(), propertyValue,
- @"Setting rasterHueRotation to a constant value should update raster-hue-rotate.");
- XCTAssertEqualObjects(layer.rasterHueRotation, constantStyleValue,
- @"rasterHueRotation should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.rasterHueRotation = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting rasterHueRotation to a constant value expression should update raster-hue-rotate.");
+ XCTAssertEqualObjects(layer.rasterHueRotation, constantExpression,
+ @"rasterHueRotation should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.rasterHueRotation = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getRasterHueRotate(), propertyValue,
- @"Setting rasterHueRotation to a camera function should update raster-hue-rotate.");
- XCTAssertEqualObjects(layer.rasterHueRotation, functionStyleValue,
- @"rasterHueRotation should round-trip camera functions.");
+ @"Setting rasterHueRotation to a camera expression should update raster-hue-rotate.");
+ XCTAssertEqualObjects(layer.rasterHueRotation, functionExpression,
+ @"rasterHueRotation should round-trip camera expressions.");
layer.rasterHueRotation = nil;
XCTAssertTrue(rawLayer->getRasterHueRotate().isUndefined(),
@"Unsetting rasterHueRotation should return raster-hue-rotate to the default value.");
- XCTAssertEqualObjects(layer.rasterHueRotation, defaultStyleValue,
+ XCTAssertEqualObjects(layer.rasterHueRotation, defaultExpression,
@"rasterHueRotation should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.rasterHueRotation = 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.rasterHueRotation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.rasterHueRotation = functionExpression, NSException, NSInvalidArgumentException, @"MGLRasterLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.rasterHueRotation = functionExpression, NSException, NSInvalidArgumentException, @"MGLRasterLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// raster-opacity
{
XCTAssertTrue(rawLayer->getRasterOpacity().isUndefined(),
@"raster-opacity should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.rasterOpacity;
+ NSExpression *defaultExpression = layer.rasterOpacity;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.rasterOpacity = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.rasterOpacity = constantExpression;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getRasterOpacity(), propertyValue,
- @"Setting rasterOpacity to a constant value should update raster-opacity.");
- XCTAssertEqualObjects(layer.rasterOpacity, constantStyleValue,
- @"rasterOpacity should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.rasterOpacity = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting rasterOpacity to a constant value expression should update raster-opacity.");
+ XCTAssertEqualObjects(layer.rasterOpacity, constantExpression,
+ @"rasterOpacity should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.rasterOpacity = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getRasterOpacity(), propertyValue,
- @"Setting rasterOpacity to a camera function should update raster-opacity.");
- XCTAssertEqualObjects(layer.rasterOpacity, functionStyleValue,
- @"rasterOpacity should round-trip camera functions.");
+ @"Setting rasterOpacity to a camera expression should update raster-opacity.");
+ XCTAssertEqualObjects(layer.rasterOpacity, functionExpression,
+ @"rasterOpacity should round-trip camera expressions.");
layer.rasterOpacity = nil;
XCTAssertTrue(rawLayer->getRasterOpacity().isUndefined(),
@"Unsetting rasterOpacity should return raster-opacity to the default value.");
- XCTAssertEqualObjects(layer.rasterOpacity, defaultStyleValue,
+ XCTAssertEqualObjects(layer.rasterOpacity, defaultExpression,
@"rasterOpacity should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.rasterOpacity = 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.rasterOpacity = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.rasterOpacity = functionExpression, NSException, NSInvalidArgumentException, @"MGLRasterLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.rasterOpacity = functionExpression, NSException, NSInvalidArgumentException, @"MGLRasterLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
// Transition property test
layer.rasterOpacityTransition = transitionTest;
auto toptions = rawLayer->getRasterOpacityTransition();
@@ -295,39 +316,44 @@
{
XCTAssertTrue(rawLayer->getRasterSaturation().isUndefined(),
@"raster-saturation should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.rasterSaturation;
+ NSExpression *defaultExpression = layer.rasterSaturation;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.rasterSaturation = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.rasterSaturation = constantExpression;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getRasterSaturation(), propertyValue,
- @"Setting rasterSaturation to a constant value should update raster-saturation.");
- XCTAssertEqualObjects(layer.rasterSaturation, constantStyleValue,
- @"rasterSaturation should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.rasterSaturation = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting rasterSaturation to a constant value expression should update raster-saturation.");
+ XCTAssertEqualObjects(layer.rasterSaturation, constantExpression,
+ @"rasterSaturation should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.rasterSaturation = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getRasterSaturation(), propertyValue,
- @"Setting rasterSaturation to a camera function should update raster-saturation.");
- XCTAssertEqualObjects(layer.rasterSaturation, functionStyleValue,
- @"rasterSaturation should round-trip camera functions.");
+ @"Setting rasterSaturation to a camera expression should update raster-saturation.");
+ XCTAssertEqualObjects(layer.rasterSaturation, functionExpression,
+ @"rasterSaturation should round-trip camera expressions.");
layer.rasterSaturation = nil;
XCTAssertTrue(rawLayer->getRasterSaturation().isUndefined(),
@"Unsetting rasterSaturation should return raster-saturation to the default value.");
- XCTAssertEqualObjects(layer.rasterSaturation, defaultStyleValue,
+ XCTAssertEqualObjects(layer.rasterSaturation, defaultExpression,
@"rasterSaturation should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.rasterSaturation = 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.rasterSaturation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.rasterSaturation = functionExpression, NSException, NSInvalidArgumentException, @"MGLRasterLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.rasterSaturation = functionExpression, NSException, NSInvalidArgumentException, @"MGLRasterLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
// Transition property test
layer.rasterSaturationTransition = transitionTest;
auto toptions = rawLayer->getRasterSaturationTransition();
diff --git a/platform/darwin/test/MGLSDKTestHelpers.swift b/platform/darwin/test/MGLSDKTestHelpers.swift
index f21041782e..727d8bf0c6 100644
--- a/platform/darwin/test/MGLSDKTestHelpers.swift
+++ b/platform/darwin/test/MGLSDKTestHelpers.swift
@@ -1,3 +1,4 @@
+import XCTest
import Foundation
class MGLSDKTestHelpers {
@@ -22,9 +23,9 @@ extension MGLSDKTestHelpers {
class func protocolMethodDescriptions(_ p: Protocol) -> Set<String> {
var methods = Set<String>()
var methodCount = UInt32()
- let methodDescriptionList: UnsafeMutablePointer<objc_method_description>! = protocol_copyMethodDescriptionList(p, false, true, &methodCount)
+ let methodDescriptionList = protocol_copyMethodDescriptionList(p, false, true, &methodCount)
for i in 0..<Int(methodCount) {
- let description: objc_method_description = methodDescriptionList[i]
+ let description = methodDescriptionList![i]
XCTAssertNotNil(description.name?.description)
methods.insert(description.name!.description)
}
@@ -35,11 +36,16 @@ extension MGLSDKTestHelpers {
class func classMethodDescriptions(_ cls: Swift.AnyClass) -> Set<String> {
var methods = Set<String>()
var methodCount = UInt32()
- let methodList: UnsafeMutablePointer<Method?>! = class_copyMethodList(cls, &methodCount)
+ let methodList = class_copyMethodList(cls, &methodCount)
for i in 0..<Int(methodCount) {
- let method = methodList[i]
- let selector : Selector = method_getName(method)
- methods.insert(selector.description)
+ let method = methodList![i]
+ let selector = method_getName(method)
+ #if os(macOS)
+ methods.insert(selector.description)
+ #else
+ XCTAssertNotNil(selector)
+ methods.insert(selector!.description)
+ #endif
}
free(methodList)
return methods
diff --git a/platform/darwin/test/MGLShapeSourceTests.mm b/platform/darwin/test/MGLShapeSourceTests.mm
index 561af7f3d0..d3f9a599e2 100644
--- a/platform/darwin/test/MGLShapeSourceTests.mm
+++ b/platform/darwin/test/MGLShapeSourceTests.mm
@@ -297,7 +297,10 @@
// when a shape is included in the features array
MGLPolygon *polygon = [MGLPolygon polygonWithCoordinates:coordinates count:sizeof(coordinates)/sizeof(coordinates[0]) interiorPolygons:nil];
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wobjc-literal-conversion"
XCTAssertThrowsSpecificNamed([[MGLShapeSource alloc] initWithIdentifier:@"source-id-invalid" features:@[polygon] options:nil], NSException, NSInvalidArgumentException, @"Shape source should raise an exception if a shape is sent to the features initializer");
+#pragma clang diagnostic pop
}
- (void)testMGLShapeSourceWithShapesConvenienceInitializer {
diff --git a/platform/darwin/test/MGLSourceQueryTests.m b/platform/darwin/test/MGLSourceQueryTests.m
index d1ef180a52..b321da1ea4 100644
--- a/platform/darwin/test/MGLSourceQueryTests.m
+++ b/platform/darwin/test/MGLSourceQueryTests.m
@@ -7,8 +7,8 @@
@implementation MGLSourceQueryTests
-- (void) testQueryVectorSource {
- MGLVectorSource *source = [[MGLVectorSource alloc] initWithIdentifier:@"vector" tileURLTemplates:@[@"fake"] options:nil];
+- (void) testQueryVectorTileSource {
+ MGLVectorTileSource *source = [[MGLVectorTileSource alloc] initWithIdentifier:@"vector" tileURLTemplates:@[@"fake"] options:nil];
NSSet *sourceLayers = [NSSet setWithObjects:@"buildings", @"water", nil];
NSArray* features = [source featuresInSourceLayersWithIdentifiers:sourceLayers predicate:nil];
// Source not added yet, so features is 0
diff --git a/platform/darwin/test/MGLStyleLayerTests.h b/platform/darwin/test/MGLStyleLayerTests.h
index f0b889f022..c7577819b8 100644
--- a/platform/darwin/test/MGLStyleLayerTests.h
+++ b/platform/darwin/test/MGLStyleLayerTests.h
@@ -1,6 +1,9 @@
#import <Mapbox/Mapbox.h>
#import <XCTest/XCTest.h>
+#define MGLConstantExpression(constant) \
+ [NSExpression expressionForConstantValue:constant]
+
@interface MGLStyleLayerTests : XCTestCase <MGLMapViewDelegate>
@property (nonatomic, copy, readonly, class) NSString *layerType;
@@ -11,7 +14,7 @@
@interface NSString (MGLStyleLayerTestAdditions)
-@property (nonatomic, readonly, copy) NS_ARRAY_OF(NSString *) *lexicalClasses;
+@property (nonatomic, readonly, copy) NSArray<NSString *> *lexicalClasses;
@property (nonatomic, readonly, copy) NSString *lemma;
@end
diff --git a/platform/darwin/test/MGLStyleLayerTests.m b/platform/darwin/test/MGLStyleLayerTests.m
index b51fa02af4..52b36dba00 100644
--- a/platform/darwin/test/MGLStyleLayerTests.m
+++ b/platform/darwin/test/MGLStyleLayerTests.m
@@ -33,7 +33,7 @@
}
- (void)testPropertyName:(NSString *)name isBoolean:(BOOL)isBoolean {
- NS_MUTABLE_ARRAY_OF(NSString *) *components = [name componentsSeparatedByString:@"-"].mutableCopy;
+ NSMutableArray<NSString *> *components = [name componentsSeparatedByString:@"-"].mutableCopy;
if (isBoolean) {
if ([components.firstObject isEqualToString:@"is"]) {
[components removeObjectAtIndex:0];
@@ -67,7 +67,7 @@
@implementation NSString (MGLStyleLayerTestAdditions)
-- (NS_ARRAY_OF(NSString *) *)lexicalClasses {
+- (NSArray<NSString *> *)lexicalClasses {
NSOrthography *orthography = [NSOrthography orthographyWithDominantScript:@"Latn"
languageMap:@{@"Latn": @[@"en"]}];
NSLinguisticTaggerOptions options = (NSLinguisticTaggerOmitPunctuation
diff --git a/platform/darwin/test/MGLStyleLayerTests.mm.ejs b/platform/darwin/test/MGLStyleLayerTests.mm.ejs
index 5fdfc3d44e..f70f0bba23 100644
--- a/platform/darwin/test/MGLStyleLayerTests.mm.ejs
+++ b/platform/darwin/test/MGLStyleLayerTests.mm.ejs
@@ -23,7 +23,7 @@
return @"<%- type %>";
}
-<% if (type !== 'background' && type !== 'raster') { -%>
+<% if (type !== 'background' && type !== 'raster' && type !== 'hillshade') { -%>
- (void)testPredicates {
MGLPointFeature *feature = [[MGLPointFeature alloc] init];
MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" shape:feature options:nil];
@@ -36,8 +36,8 @@
XCTAssertNil(layer.sourceLayerIdentifier);
XCTAssertNil(layer.predicate);
- layer.predicate = [NSPredicate predicateWithValue:NO];
- XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithValue:NO]);
+ layer.predicate = [NSPredicate predicateWithFormat:@"$featureIdentifier = 1"];
+ XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithFormat:@"$featureIdentifier = 1"]);
layer.predicate = nil;
XCTAssertNil(layer.predicate);
}
@@ -59,50 +59,56 @@
MGLTransition transitionTest = MGLTransitionMake(5, 4);
<% for (const property of properties) { -%>
+<% if (property.name === 'heatmap-color') continue; -%>
// <%- originalPropertyName(property) %>
{
XCTAssertTrue(rawLayer->get<%- camelize(originalPropertyName(property)) %>().isUndefined(),
@"<%- originalPropertyName(property) %> should be unset initially.");
- MGLStyleValue<<%- propertyType(property) %>> *defaultStyleValue = layer.<%- objCName(property) %>;
+ NSExpression *defaultExpression = layer.<%- objCName(property) %>;
- MGLStyleValue<<%- propertyType(property) %>> *constantStyleValue = [MGLStyleValue<<%- propertyType(property) %>> valueWithRawValue:<%- objCTestValue(property, type, 3) %>];
- layer.<%- objCName(property) %> = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:<%- objCTestValue(property, type, true, 3) %>];
+ layer.<%- objCName(property) %> = constantExpression;
<% if (property["property-function"]) { -%>
mbgl::style::DataDrivenPropertyValue<<%- mbglType(property) %>> propertyValue = { <%- mbglTestValue(property, type) %> };
<% } else { -%>
mbgl::style::PropertyValue<<%- mbglType(property) %>> propertyValue = { <%- mbglTestValue(property, type) %> };
<% } -%>
XCTAssertEqual(rawLayer->get<%- camelize(originalPropertyName(property)) %>(), propertyValue,
- @"Setting <%- objCName(property) %> to a constant value should update <%- originalPropertyName(property) %>.");
- XCTAssertEqualObjects(layer.<%- objCName(property) %>, constantStyleValue,
- @"<%- objCName(property) %> should round-trip constant values.");
-
- MGLStyleValue<<%- propertyType(property) %>> * functionStyleValue = [MGLStyleValue<<%- propertyType(property) %>> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.<%- objCName(property) %> = functionStyleValue;
-
- mbgl::style::IntervalStops<<%- mbglType(property) %>> intervalStops = { {{18, <%- mbglTestValue(property, type) %>}} };
+ @"Setting <%- objCName(property) %> to a constant value expression should update <%- originalPropertyName(property) %>.");
+ XCTAssertEqualObjects(layer.<%- objCName(property) %>, constantExpression,
+ @"<%- objCName(property) %> should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:<%- objCTestValue(property, type, false, 3) %>];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.<%- objCName(property) %> = functionExpression;
+
+ mbgl::style::IntervalStops<<%- mbglType(property) %>> intervalStops = {{
+ { -INFINITY, <%- mbglTestValue(property, type) %> },
+ { 18, <%- mbglTestValue(property, type) %> },
+ }};
propertyValue = mbgl::style::CameraFunction<<%- mbglType(property) %>> { intervalStops };
XCTAssertEqual(rawLayer->get<%- camelize(originalPropertyName(property)) %>(), propertyValue,
- @"Setting <%- objCName(property) %> to a camera function should update <%- originalPropertyName(property) %>.");
- XCTAssertEqualObjects(layer.<%- objCName(property) %>, functionStyleValue,
- @"<%- objCName(property) %> should round-trip camera functions.");
+ @"Setting <%- objCName(property) %> to a camera expression should update <%- originalPropertyName(property) %>.");
+ XCTAssertEqualObjects(layer.<%- objCName(property) %>, functionExpression,
+ @"<%- objCName(property) %> should round-trip camera expressions.");
<% if (property["property-function"] && isInterpolatable(property)) { -%>
- functionStyleValue = [MGLStyleValue<<%- propertyType(property) %>> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.<%- objCName(property) %> = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.<%- objCName(property) %> = functionExpression;
mbgl::style::ExponentialStops<<%- mbglType(property) %>> exponentialStops = { {{18, <%- mbglTestValue(property, type) %>}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<<%- mbglType(property) %>> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->get<%- camelize(originalPropertyName(property)) %>(), propertyValue,
- @"Setting <%- objCName(property) %> to a source function should update <%- originalPropertyName(property) %>.");
- XCTAssertEqualObjects(layer.<%- objCName(property) %>, functionStyleValue,
- @"<%- objCName(property) %> should round-trip source functions.");
+ @"Setting <%- objCName(property) %> to a data expression should update <%- originalPropertyName(property) %>.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.<%- objCName(property) %>, pedanticFunctionExpression,
+ @"<%- objCName(property) %> should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<<%- propertyType(property) %>> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.<%- objCName(property) %> = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.<%- objCName(property) %> = functionExpression;
std::map<float, <%- mbglType(property) %>> innerStops { {18, <%- mbglTestValue(property, type) %>} };
mbgl::style::CompositeExponentialStops<<%- mbglType(property) %>> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -110,24 +116,26 @@
propertyValue = mbgl::style::CompositeFunction<<%- mbglType(property) %>> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->get<%- camelize(originalPropertyName(property)) %>(), propertyValue,
- @"Setting <%- objCName(property) %> to a composite function should update <%- originalPropertyName(property) %>.");
- XCTAssertEqualObjects(layer.<%- objCName(property) %>, functionStyleValue,
- @"<%- objCName(property) %> should round-trip composite functions.");
+ @"Setting <%- objCName(property) %> to a camera-data expression should update <%- originalPropertyName(property) %>.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.<%- objCName(property) %>, pedanticFunctionExpression,
+ @"<%- objCName(property) %> should round-trip camera-data expressions.");
<% } -%>
<% if (!property.required) { -%>
layer.<%- objCName(property) %> = nil;
XCTAssertTrue(rawLayer->get<%- camelize(originalPropertyName(property)) %>().isUndefined(),
@"Unsetting <%- objCName(property) %> should return <%- originalPropertyName(property) %> to the default value.");
- XCTAssertEqualObjects(layer.<%- objCName(property) %>, defaultStyleValue,
+ XCTAssertEqualObjects(layer.<%- objCName(property) %>, defaultExpression,
@"<%- objCName(property) %> should return the default value after being unset.");
<% } -%>
<% if (!property["property-function"]) { -%>
- functionStyleValue = [MGLStyleValue<<%- propertyType(property) %>> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.<%- objCName(property) %> = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<<%- propertyType(property) %>> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.<%- objCName(property) %> = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.<%- objCName(property) %> = functionExpression, NSException, NSInvalidArgumentException, @"MGL<%- camelize(type) %>Layer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.<%- objCName(property) %> = functionExpression, NSException, NSInvalidArgumentException, @"MGL<%- camelize(type) %>Layer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
<% } -%>
<% if (property["transition"] && !property.original) { -%>
// Transition property test
@@ -146,6 +154,7 @@
- (void)testPropertyNames {
<% for (const property of properties) { -%>
+<% if (property.name === 'heatmap-color') continue; -%>
[self testPropertyName:@"<%- property.getter || property.name %>" isBoolean:<%- property.type === 'boolean' ? 'YES' : 'NO' %>];
<% } -%>
}
diff --git a/platform/darwin/test/MGLStyleTests.mm b/platform/darwin/test/MGLStyleTests.mm
index 8f610e338c..6048f39ea3 100644
--- a/platform/darwin/test/MGLStyleTests.mm
+++ b/platform/darwin/test/MGLStyleTests.mm
@@ -1,6 +1,7 @@
#import <Mapbox/Mapbox.h>
#import "NSBundle+MGLAdditions.h"
+#import "MGLVectorTileSource_Private.h"
#import <mbgl/util/default_styles.hpp>
@@ -64,12 +65,6 @@
XCTAssertEqualObjects([MGLStyle darkStyleURL].absoluteString, @(mbgl::util::default_styles::dark.url));
XCTAssertEqualObjects([MGLStyle satelliteStyleURL].absoluteString, @(mbgl::util::default_styles::satellite.url));
XCTAssertEqualObjects([MGLStyle satelliteStreetsStyleURL].absoluteString, @(mbgl::util::default_styles::satelliteStreets.url));
-
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- XCTAssertEqualObjects([MGLStyle emeraldStyleURL].absoluteString, @"mapbox://styles/mapbox/emerald-v8");
- XCTAssertEqualObjects([MGLStyle hybridStyleURL].absoluteString, @"mapbox://styles/mapbox/satellite-hybrid-v8");
-#pragma clang diagnostic pop
}
- (void)testVersionedStyleURLs {
@@ -99,19 +94,8 @@
@(mbgl::util::default_styles::satelliteStreets.url));
XCTAssertEqualObjects([MGLStyle satelliteStreetsStyleURLWithVersion:99].absoluteString,
@"mapbox://styles/mapbox/satellite-streets-v99");
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- XCTAssertEqualObjects([MGLStyle trafficDayStyleURLWithVersion:mbgl::util::default_styles::trafficDay.currentVersion].absoluteString,
- @(mbgl::util::default_styles::trafficDay.url));
- XCTAssertEqualObjects([MGLStyle trafficDayStyleURLWithVersion:99].absoluteString,
- @"mapbox://styles/mapbox/traffic-day-v99");
- XCTAssertEqualObjects([MGLStyle trafficNightStyleURLWithVersion:mbgl::util::default_styles::trafficNight.currentVersion].absoluteString,
- @(mbgl::util::default_styles::trafficNight.url));
- XCTAssertEqualObjects([MGLStyle trafficNightStyleURLWithVersion:99].absoluteString,
- @"mapbox://styles/mapbox/traffic-night-v99");
-#pragma clang diagnostic pop
-
- static_assert(8 == mbgl::util::default_styles::numOrderedStyles,
+
+ static_assert(6 == mbgl::util::default_styles::numOrderedStyles,
"MGLStyleTests isn’t testing all the styles in mbgl::util::default_styles.");
}
@@ -143,7 +127,7 @@
NSString *styleHeader = self.stringWithContentsOfStyleHeader;
NSError *versionedMethodError;
- NSString *versionedMethodExpressionString = @(R"RE(^\+\s*\(NSURL\s*\*\s*\)\s*\w+StyleURLWithVersion\s*:\s*\(\s*NSInteger\s*\)\s*version\s*\b)RE");
+ NSString *versionedMethodExpressionString = @(R"RE(^\+\s*\(NSURL\s*\*\s*\)\s*(?!traffic)\w+StyleURLWithVersion\s*:\s*\(\s*NSInteger\s*\)\s*version\s*\b)RE");
NSRegularExpression *versionedMethodExpression = [NSRegularExpression regularExpressionWithPattern:versionedMethodExpressionString options:NSRegularExpressionAnchorsMatchLines error:&versionedMethodError];
XCTAssertNil(versionedMethodError, @"Error compiling regular expression to search for versioned methods.");
NSUInteger numVersionedMethodDeclarations = [versionedMethodExpression numberOfMatchesInString:styleHeader options:0 range:NSMakeRange(0, styleHeader.length)];
@@ -174,89 +158,89 @@
[self.style addSource:shapeSource];
XCTAssertThrowsSpecificNamed([self.style addSource:shapeSource], NSException, @"MGLRedundantSourceException");
- MGLRasterSource *rasterSource = [[MGLRasterSource alloc] initWithIdentifier:@"rasterSource" configurationURL:[NSURL URLWithString:@".json"] tileSize:42];
- [self.style addSource:rasterSource];
- XCTAssertThrowsSpecificNamed([self.style addSource:rasterSource], NSException, @"MGLRedundantSourceException");
+ MGLRasterTileSource *rasterTileSource = [[MGLRasterTileSource alloc] initWithIdentifier:@"rasterTileSource" configurationURL:[NSURL URLWithString:@".json"] tileSize:42];
+ [self.style addSource:rasterTileSource];
+ XCTAssertThrowsSpecificNamed([self.style addSource:rasterTileSource], NSException, @"MGLRedundantSourceException");
- MGLVectorSource *vectorSource = [[MGLVectorSource alloc] initWithIdentifier:@"vectorSource" configurationURL:[NSURL URLWithString:@".json"]];
- [self.style addSource:vectorSource];
- XCTAssertThrowsSpecificNamed([self.style addSource:vectorSource], NSException, @"MGLRedundantSourceException");
+ MGLVectorTileSource *vectorTileSource = [[MGLVectorTileSource alloc] initWithIdentifier:@"vectorTileSource" configurationURL:[NSURL URLWithString:@".json"]];
+ [self.style addSource:vectorTileSource];
+ XCTAssertThrowsSpecificNamed([self.style addSource:vectorTileSource], NSException, @"MGLRedundantSourceException");
}
- (void)testAddingSourcesWithDuplicateIdentifiers {
- MGLVectorSource *source1 = [[MGLVectorSource alloc] initWithIdentifier:@"my-source" configurationURL:[NSURL URLWithString:@"mapbox://mapbox.mapbox-terrain-v2"]];
- MGLVectorSource *source2 = [[MGLVectorSource alloc] initWithIdentifier:@"my-source" configurationURL:[NSURL URLWithString:@"mapbox://mapbox.mapbox-terrain-v2"]];
+ MGLVectorTileSource *source1 = [[MGLVectorTileSource alloc] initWithIdentifier:@"my-source" configurationURL:[NSURL URLWithString:@"mapbox://mapbox.mapbox-terrain-v2"]];
+ MGLVectorTileSource *source2 = [[MGLVectorTileSource alloc] initWithIdentifier:@"my-source" configurationURL:[NSURL URLWithString:@"mapbox://mapbox.mapbox-terrain-v2"]];
[self.style addSource: source1];
XCTAssertThrowsSpecificNamed([self.style addSource: source2], NSException, @"MGLRedundantSourceIdentifierException");
}
- (void)testRemovingSourcesBeforeAddingThem {
- MGLRasterSource *rasterSource = [[MGLRasterSource alloc] initWithIdentifier:@"raster-source" tileURLTemplates:@[] options:nil];
- [self.style removeSource:rasterSource];
- [self.style addSource:rasterSource];
- XCTAssertNotNil([self.style sourceWithIdentifier:rasterSource.identifier]);
+ MGLRasterTileSource *rasterTileSource = [[MGLRasterTileSource alloc] initWithIdentifier:@"raster-tile-source" tileURLTemplates:@[] options:nil];
+ [self.style removeSource:rasterTileSource];
+ [self.style addSource:rasterTileSource];
+ XCTAssertNotNil([self.style sourceWithIdentifier:rasterTileSource.identifier]);
MGLShapeSource *shapeSource = [[MGLShapeSource alloc] initWithIdentifier:@"shape-source" shape:nil options:nil];
[self.style removeSource:shapeSource];
[self.style addSource:shapeSource];
XCTAssertNotNil([self.style sourceWithIdentifier:shapeSource.identifier]);
- MGLVectorSource *vectorSource = [[MGLVectorSource alloc] initWithIdentifier:@"vector-source" tileURLTemplates:@[] options:nil];
- [self.style removeSource:vectorSource];
- [self.style addSource:vectorSource];
- XCTAssertNotNil([self.style sourceWithIdentifier:vectorSource.identifier]);
+ MGLVectorTileSource *vectorTileSource = [[MGLVectorTileSource alloc] initWithIdentifier:@"vector-tile-source" tileURLTemplates:@[] options:nil];
+ [self.style removeSource:vectorTileSource];
+ [self.style addSource:vectorTileSource];
+ XCTAssertNotNil([self.style sourceWithIdentifier:vectorTileSource.identifier]);
}
- (void)testAddingSourceOfTypeABeforeSourceOfTypeBWithSameIdentifier {
- // Add a raster source
- MGLRasterSource *rasterSource = [[MGLRasterSource alloc] initWithIdentifier:@"some-identifier" tileURLTemplates:@[] options:nil];
- [self.style addSource:rasterSource];
+ // Add a raster tile source
+ MGLRasterTileSource *rasterTileSource = [[MGLRasterTileSource alloc] initWithIdentifier:@"some-identifier" tileURLTemplates:@[] options:nil];
+ [self.style addSource:rasterTileSource];
- // Attempt to remove an image source with the same identifier as the raster source
+ // Attempt to remove an image source with the same identifier as the raster tile source
MGLImageSource *imageSource = [[MGLImageSource alloc] initWithIdentifier:@"some-identifier" coordinateQuad: { } URL:[NSURL URLWithString:@"http://host/image.png"]];
[self.style removeSource:imageSource];
- // The raster source should still be added
- XCTAssertTrue([[self.style sourceWithIdentifier:rasterSource.identifier] isMemberOfClass:[MGLRasterSource class]]);
+ // The raster tile source should still be added
+ XCTAssertTrue([[self.style sourceWithIdentifier:rasterTileSource.identifier] isMemberOfClass:[MGLRasterTileSource class]]);
- // Remove the raster source
- [self.style removeSource:rasterSource];
+ // Remove the raster tile source
+ [self.style removeSource:rasterTileSource];
// Add the shape source
[self.style addSource:imageSource];
- // Attempt to remove a vector source with the same identifer as the shape source
- MGLVectorSource *vectorSource = [[MGLVectorSource alloc] initWithIdentifier:@"some-identifier" tileURLTemplates:@[] options:nil];
- [self.style removeSource:vectorSource];
+ // Attempt to remove a vector tile source with the same identifer as the shape source
+ MGLVectorTileSource *vectorTileSource = [[MGLVectorTileSource alloc] initWithIdentifier:@"some-identifier" tileURLTemplates:@[] options:nil];
+ [self.style removeSource:vectorTileSource];
// The image source should still be added
XCTAssertTrue([[self.style sourceWithIdentifier:imageSource.identifier] isMemberOfClass:[MGLImageSource class]]);
// Remove the image source
[self.style removeSource:imageSource];
- // Add the vector source
- [self.style addSource:vectorSource];
+ // Add the vector tile source
+ [self.style addSource:vectorTileSource];
- // Attempt to remove the previously created raster source that has the same identifer as the shape source
- [self.style removeSource:rasterSource];
- // The vector source should still be added
- XCTAssertTrue([[self.style sourceWithIdentifier:imageSource.identifier] isMemberOfClass:[MGLVectorSource class]]);
+ // Attempt to remove the previously created raster tile source that has the same identifer as the shape source
+ [self.style removeSource:rasterTileSource];
+ // The vector tile source should still be added
+ XCTAssertTrue([[self.style sourceWithIdentifier:imageSource.identifier] isMemberOfClass:[MGLVectorTileSource class]]);
}
- (void)testRemovingSourceInUse {
- // Add a raster source
- MGLRasterSource *rasterSource = [[MGLRasterSource alloc] initWithIdentifier:@"some-identifier" tileURLTemplates:@[] options:nil];
- [self.style addSource:rasterSource];
+ // Add a raster tile source
+ MGLRasterTileSource *rasterTileSource = [[MGLRasterTileSource alloc] initWithIdentifier:@"some-identifier" tileURLTemplates:@[] options:nil];
+ [self.style addSource:rasterTileSource];
// Add a layer using it
- MGLFillStyleLayer *fillLayer = [[MGLFillStyleLayer alloc] initWithIdentifier:@"fillLayer" source:rasterSource];
+ MGLFillStyleLayer *fillLayer = [[MGLFillStyleLayer alloc] initWithIdentifier:@"fillLayer" source:rasterTileSource];
[self.style addLayer:fillLayer];
- // Attempt to remove the raster source
- [self.style removeSource:rasterSource];
+ // Attempt to remove the raster tile source
+ [self.style removeSource:rasterTileSource];
// Ensure it is still there
- XCTAssertTrue([[self.style sourceWithIdentifier:rasterSource.identifier] isMemberOfClass:[MGLRasterSource class]]);
+ XCTAssertTrue([[self.style sourceWithIdentifier:rasterTileSource.identifier] isMemberOfClass:[MGLRasterTileSource class]]);
}
- (void)testLayers {
@@ -306,7 +290,7 @@
- (void)testAddingLayersWithDuplicateIdentifiers {
// Just some source
- MGLVectorSource *source = [[MGLVectorSource alloc] initWithIdentifier:@"my-source" configurationURL:[NSURL URLWithString:@"mapbox://mapbox.mapbox-terrain-v2"]];
+ MGLVectorTileSource *source = [[MGLVectorTileSource alloc] initWithIdentifier:@"my-source" configurationURL:[NSURL URLWithString:@"mapbox://mapbox.mapbox-terrain-v2"]];
[self.style addSource: source];
// Add initial layer
@@ -383,13 +367,6 @@
return styleHeader;
}
-- (void)testClasses {
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- XCTAssertEqual(self.style.styleClasses.count, 0);
-#pragma clang diagnostic pop
-}
-
- (void)testImages {
NSString *imageName = @"TrackingLocationMask";
#if TARGET_OS_IPHONE
@@ -443,4 +420,45 @@
XCTAssertEqualObjects(layers[startIndex++].identifier, layer4.identifier);
}
+#pragma mark Localization tests
+
+- (void)testLanguageMatching {
+ {
+ NSArray *preferences = @[@"en"];
+ XCTAssertEqualObjects([MGLVectorTileSource preferredMapboxStreetsLanguageForPreferences:preferences], @"en");
+ }
+ {
+ NSArray *preferences = @[@"en-US"];
+ XCTAssertEqualObjects([MGLVectorTileSource preferredMapboxStreetsLanguageForPreferences:preferences], @"en");
+ }
+ {
+ NSArray *preferences = @[@"fr"];
+ XCTAssertEqualObjects([MGLVectorTileSource preferredMapboxStreetsLanguageForPreferences:preferences], @"fr");
+ }
+ {
+ NSArray *preferences = @[@"zh-Hans"];
+ XCTAssertEqualObjects([MGLVectorTileSource preferredMapboxStreetsLanguageForPreferences:preferences], @"zh-Hans");
+ }
+ {
+ NSArray *preferences = @[@"zh-Hans", @"en"];
+ XCTAssertEqualObjects([MGLVectorTileSource preferredMapboxStreetsLanguageForPreferences:preferences], @"zh-Hans");
+ }
+ {
+ NSArray *preferences = @[@"zh-Hant"];
+ XCTAssertNil([MGLVectorTileSource preferredMapboxStreetsLanguageForPreferences:preferences]);
+ }
+ {
+ NSArray *preferences = @[@"tlh"];
+ XCTAssertNil([MGLVectorTileSource preferredMapboxStreetsLanguageForPreferences:preferences]);
+ }
+ {
+ NSArray *preferences = @[@"tlh", @"en"];
+ XCTAssertEqualObjects([MGLVectorTileSource preferredMapboxStreetsLanguageForPreferences:preferences], @"en");
+ }
+ {
+ NSArray *preferences = @[@"mul"];
+ XCTAssertNil([MGLVectorTileSource preferredMapboxStreetsLanguageForPreferences:preferences]);
+ }
+}
+
@end
diff --git a/platform/darwin/test/MGLStyleValueTests.h b/platform/darwin/test/MGLStyleValueTests.h
deleted file mode 100644
index a563de39f0..0000000000
--- a/platform/darwin/test/MGLStyleValueTests.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#import <XCTest/XCTest.h>
-
-@interface MGLStyleValueTests : XCTestCase
-@end
diff --git a/platform/darwin/test/MGLStyleValueTests.m b/platform/darwin/test/MGLStyleValueTests.m
deleted file mode 100644
index cd6eec8324..0000000000
--- a/platform/darwin/test/MGLStyleValueTests.m
+++ /dev/null
@@ -1,113 +0,0 @@
-#import <XCTest/XCTest.h>
-#import <Mapbox/Mapbox.h>
-
-@interface MGLStyleValueTests : XCTestCase
-@end
-
-@implementation MGLStyleValueTests
-
-- (void)testStoplessFunction {
- XCTAssertThrowsSpecificNamed([MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential cameraStops:@{} options:nil], NSException, NSInvalidArgumentException, @"Stopless function should raise an exception");
-}
-
-- (void)testDeprecatedFunctions {
- MGLShapeSource *shapeSource = [[MGLShapeSource alloc] initWithIdentifier:@"test"
- shape:nil
- options:nil];
- MGLSymbolStyleLayer *symbolStyleLayer = [[MGLSymbolStyleLayer alloc] initWithIdentifier:@"symbolLayer"
- source:shapeSource];
- MGLCircleStyleLayer *circleStyleLayer = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"circleLayer"
- source:shapeSource];
-
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- // deprecated function, stops with float values
- NSDictionary<NSNumber *, MGLStyleValue<NSNumber *> *> *stops = @{
- @1: [MGLStyleValue<NSNumber *> valueWithRawValue:@0],
- @2: [MGLStyleValue<NSNumber *> valueWithRawValue:@1],
- @3: [MGLStyleValue<NSNumber *> valueWithRawValue:@2],
- @4: [MGLStyleValue<NSNumber *> valueWithRawValue:@0],
- };
- MGLStyleValue<NSNumber *> *iconHaloBlurStyleValue =
- [MGLStyleValue<NSNumber *> valueWithInterpolationBase:1.0 stops:stops];
- symbolStyleLayer.iconHaloBlur = iconHaloBlurStyleValue;
- XCTAssertEqualObjects(symbolStyleLayer.iconHaloBlur, iconHaloBlurStyleValue);
-
- // deprecated function, stops with boolean values
- stops = @{
- @1: [MGLStyleValue<NSNumber *> valueWithRawValue:@YES],
- @2: [MGLStyleValue<NSNumber *> valueWithRawValue:@NO],
- @3: [MGLStyleValue<NSNumber *> valueWithRawValue:@YES],
- @4: [MGLStyleValue<NSNumber *> valueWithRawValue:@NO],
- };
- MGLStyleValue<NSNumber *> *iconAllowsOverlapStyleValue =
- [MGLStyleValue<NSNumber *> valueWithInterpolationBase:1.0 stops:stops];
- symbolStyleLayer.iconAllowsOverlap = iconAllowsOverlapStyleValue;
- // iconAllowsOverlap is boolean so mgl and mbgl conversions will coerce the developers stops into interval stops
- MGLStyleValue<NSNumber *> *expectedIconAllowsOverlapStyleValue =
- [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval
- cameraStops:stops
- options:nil];
- XCTAssertEqualObjects(symbolStyleLayer.iconAllowsOverlap, expectedIconAllowsOverlapStyleValue);
-
- ///
- // creating and using MGLStyleFunctions directly
- ///
-
- NSDictionary<NSNumber *, MGLStyleValue<NSNumber *> *> *circleRadiusStops = @{
- @0: [MGLStyleValue<NSNumber *> valueWithRawValue:@10],
- @20: [MGLStyleValue<NSNumber *> valueWithRawValue:@5],
- };
- MGLStyleFunction<NSNumber *> *circleRadiusFunction =
- [MGLStyleFunction<NSNumber *> functionWithInterpolationBase:1.0
- stops:circleRadiusStops];
- circleStyleLayer.circleRadius = circleRadiusFunction;
- MGLStyleValue<NSNumber *> *expectedCircleRadiusFunction =
- [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential
- cameraStops:circleRadiusStops
- options:nil];
- // setting a data driven property to an MGLStyleFunction should return an exponential camera function
- XCTAssertEqualObjects(circleStyleLayer.circleRadius, expectedCircleRadiusFunction);
-
- CGVector circleTranslationOne = CGVectorMake(100, 0);
- CGVector circleTranslationTwo = CGVectorMake(0, 0);
-#if TARGET_OS_IPHONE
- NSValue *circleTranslationValueOne = [NSValue valueWithCGVector:circleTranslationOne];
- NSValue *circleTranslationValueTwo = [NSValue valueWithCGVector:circleTranslationTwo];
-#else
- NSValue *circleTranslationValueOne = [NSValue value:&circleTranslationOne withObjCType:@encode(CGVector)];
- NSValue *circleTranslationValueTwo = [NSValue value:&circleTranslationTwo withObjCType:@encode(CGVector)];
-#endif
-
- NSDictionary<NSNumber *, MGLStyleValue<NSValue *> *> *circleTranslationStops = @{
- @0: [MGLStyleValue<NSValue *> valueWithRawValue:circleTranslationValueOne],
- @10: [MGLStyleValue<NSValue *> valueWithRawValue:circleTranslationValueTwo],
- };
- MGLStyleFunction<NSValue *> *circleTranslationFunction =
- [MGLStyleFunction<NSValue *> functionWithInterpolationBase:1.0
- stops:circleTranslationStops];
- circleStyleLayer.circleTranslation = circleTranslationFunction;
- MGLStyleValue<NSValue *> *expectedCircleTranslationFunction =
- [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeExponential
- cameraStops:circleTranslationStops
- options:nil];
- // setting a non-data driven, interpolatable property to an MGLStyleFunction should return an exponential camera function
- XCTAssertEqualObjects(circleStyleLayer.circleTranslation, expectedCircleTranslationFunction);
-
- NSDictionary<NSNumber *, MGLStyleValue<NSNumber *> *> *iconOptionalStops = @{
- @0: [MGLStyleValue<NSNumber *> valueWithRawValue:@NO],
- @20: [MGLStyleValue<NSNumber *> valueWithRawValue:@YES],
- };
- MGLStyleFunction<NSNumber *> *iconOptionalFunction =
- [MGLStyleFunction<NSNumber *> valueWithInterpolationBase:1.0
- stops:iconOptionalStops];
- symbolStyleLayer.iconOptional = iconOptionalFunction;
- MGLStyleValue<NSNumber *> *expectedIconOptionalFunction =
- [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval
- cameraStops:iconOptionalStops
- options:nil];
- XCTAssertEqualObjects(symbolStyleLayer.iconOptional, expectedIconOptionalFunction);
-#pragma clang diagnostic pop
-}
-
-@end
diff --git a/platform/darwin/test/MGLStyleValueTests.swift b/platform/darwin/test/MGLStyleValueTests.swift
deleted file mode 100644
index c559037588..0000000000
--- a/platform/darwin/test/MGLStyleValueTests.swift
+++ /dev/null
@@ -1,362 +0,0 @@
-import XCTest
-import Mapbox
-
-#if os(iOS) || os(watchOS) || os(tvOS)
-typealias MGLColor = UIColor
-#elseif os(macOS)
-typealias MGLColor = NSColor
-#endif
-
-#if swift(>=3.2)
-#else
-func XCTAssertEqual<T: FloatingPoint>(_ lhs: @autoclosure () throws -> T, _ rhs: @autoclosure () throws -> T, accuracy: T) {
- XCTAssertEqualWithAccuracy(lhs, rhs, accuracy: accuracy)
-}
-#endif
-
-extension MGLStyleValueTests {
-
- struct Color {
- var red: CGFloat = 0
- var green: CGFloat = 0
- var blue: CGFloat = 0
- var alpha: CGFloat = 0
- }
-
- func assertColorsEqualWithAccuracy(_ actual: MGLColor, _ expected: MGLColor, accuracy: Float = 1/255) {
- var actualColor = Color()
- var expectedColor = Color()
-
- actual.getRed(&actualColor.red, green: &actualColor.green, blue: &actualColor.blue, alpha: &actualColor.alpha)
- expected.getRed(&expectedColor.red, green: &expectedColor.green, blue: &expectedColor.blue, alpha: &expectedColor.alpha)
-
- XCTAssertEqual(Float(actualColor.red), Float(expectedColor.red), accuracy: accuracy)
- XCTAssertEqual(Float(actualColor.green), Float(expectedColor.green), accuracy: accuracy)
- XCTAssertEqual(Float(actualColor.blue), Float(expectedColor.blue), accuracy: accuracy)
- XCTAssertEqual(Float(actualColor.alpha), Float(expectedColor.alpha), accuracy: accuracy)
- }
-
- func assertColorValuesEqual(_ actual: MGLStyleValue<MGLColor>, _ expected: MGLStyleValue<MGLColor>) {
- guard type(of: actual) == type(of: expected) else {
- XCTFail("Expected \(type(of: expected)), but found \(type(of: actual)) instead.")
- return
- }
-
- if let actualConstant = actual as? MGLConstantStyleValue<MGLColor> {
- assertColorsEqualWithAccuracy(actualConstant.rawValue, (expected as! MGLConstantStyleValue<MGLColor>).rawValue)
- } else if let actualFunction = actual as? MGLStyleFunction<MGLColor>,
- let expectedFunction = expected as? MGLStyleFunction<MGLColor> {
-
- // unless we have stops, there's no need for a custom comparison - default to plain == assertion
- guard let actualStops = actualFunction.stops, let expectedStops = expectedFunction.stops else {
- XCTAssertEqual(actualFunction, expectedFunction)
- return
- }
-
- guard expectedStops is [String: Any] || expectedStops is [Float:Any] else {
- XCTFail("Stop levels must be String or Float.")
- return
- }
-
- XCTAssertEqual(actualFunction.interpolationBase, expectedFunction.interpolationBase)
- XCTAssertEqual(actualFunction.interpolationMode, expectedFunction.interpolationMode)
- if let actualFunction = actualFunction as? MGLSourceStyleFunction<MGLColor>,
- let expectedFunction = expectedFunction as? MGLSourceStyleFunction<MGLColor> {
- XCTAssertEqual(actualFunction.defaultValue, expectedFunction.defaultValue)
- } else if let actualFunction = actualFunction as? MGLCompositeStyleFunction<MGLColor>,
- let expectedFunction = expectedFunction as? MGLCompositeStyleFunction<MGLColor> {
- XCTAssertEqual(actualFunction.defaultValue, expectedFunction.defaultValue)
- }
-
- func assertStopEqual (_ actualValue: Any?, _ expectedValue: Any?) {
- guard type(of: actualValue) == type(of: expectedValue) else {
- XCTFail("Expected stop value of type \(type(of: expectedValue)), but found \(type(of: actualValue)) instead.")
- return
- }
- if let actualValue = actualValue as? MGLConstantStyleValue<MGLColor>,
- let expectedValue = expectedValue as? MGLConstantStyleValue<MGLColor> {
- assertColorsEqualWithAccuracy(actualValue.rawValue, expectedValue.rawValue)
- } else if let actualValue = actualValue as? MGLConstantStyleValue<AnyObject>,
- let expectedValue = expectedValue as? MGLConstantStyleValue<AnyObject> {
- XCTAssertEqual(actualValue, expectedValue)
- } else {
- XCTFail("Unsupported stop value type \(type(of: actualValue)).")
- }
- }
-
- XCTAssertEqual(actualStops.count, expectedStops.count)
- if let actualStops = actualStops as? [String:Any], let expectedStops = expectedStops as? [String: Any] {
- for (key, value) in actualStops {
- assertStopEqual(value, expectedStops[key])
- }
- } else if let actualStops = actualStops as? [Float:Any], let expectedStops = expectedStops as? [Float:Any] {
- for (key, value) in actualStops {
- assertStopEqual(value, expectedStops[key])
- }
- } else {
- XCTFail("Expected stops of type \(type(of: Array(expectedStops.keys)).Index.self), but found \(type(of: Array(actualStops.keys)).Index.self) instead.")
- return
- }
- } else {
- XCTFail("MGLStyleValue<MGLColor> must be either a constant or a style function.")
- }
- }
-
- func testConstantValues() {
- let shapeSource = MGLShapeSource(identifier: "source", shape: nil, options: nil)
- let symbolStyleLayer = MGLSymbolStyleLayer(identifier: "symbolLayer", source: shapeSource)
- let circleStyleLayer = MGLCircleStyleLayer(identifier: "circleLayer", source: shapeSource)
-
- // Boolean
- symbolStyleLayer.iconAllowsOverlap = MGLConstantStyleValue(rawValue: true)
- XCTAssertEqual((symbolStyleLayer.iconAllowsOverlap as! MGLConstantStyleValue<NSNumber>).rawValue, true)
-
- // Number
- symbolStyleLayer.iconHaloWidth = MGLConstantStyleValue(rawValue: 3)
- XCTAssertEqual((symbolStyleLayer.iconHaloWidth as! MGLConstantStyleValue<NSNumber>).rawValue, 3)
-
- // String
- symbolStyleLayer.text = MGLConstantStyleValue(rawValue: "{name}")
- XCTAssertEqual((symbolStyleLayer.text as! MGLConstantStyleValue<NSString>).rawValue, "{name}")
-
- var circleTranslationOne = CGVector(dx: 100, dy: 0)
- let circleTranslationValueOne = NSValue(bytes: &circleTranslationOne, objCType: "{CGVector=dd}")
-
- // non-data-driven (interpolatable property value), set to constant style value
- let expectedCircleTranslationValue = MGLStyleValue<NSValue>(rawValue: circleTranslationValueOne)
- circleStyleLayer.circleTranslation = expectedCircleTranslationValue
- XCTAssertEqual(circleStyleLayer.circleTranslation, expectedCircleTranslationValue)
-
- // non-data-driven (enumeration property value), set to constant style value
- let expectedCircleScaleAlignmentValue = MGLStyleValue<NSValue>(rawValue: NSValue(mglCircleScaleAlignment: .map))
- circleStyleLayer.circleScaleAlignment = expectedCircleScaleAlignmentValue
- XCTAssertEqual(circleStyleLayer.circleScaleAlignment, expectedCircleScaleAlignmentValue)
- }
-
- func testFunctionsWithNonDataDrivenProperties() {
- let shapeSource = MGLShapeSource(identifier: "test", shape: nil, options: nil)
- let circleStyleLayer = MGLCircleStyleLayer(identifier: "circleLayer", source: shapeSource)
-
- var circleTranslationOne = CGVector(dx: 100, dy: 0)
- let circleTranslationValueOne = NSValue(bytes: &circleTranslationOne, objCType: "{CGVector=dd}")
- var circleTranslationTwo = CGVector(dx: 0, dy: 0)
- let circleTranslationValueTwo = NSValue(bytes: &circleTranslationTwo, objCType: "{CGVector=dd}")
-
- let circleTranslationStops : [Float:MGLStyleValue<NSValue>] = [
- 0: MGLStyleValue<NSValue>(rawValue: circleTranslationValueOne),
- 10: MGLStyleValue<NSValue>(rawValue: circleTranslationValueTwo)
- ]
-
- // non-data-driven (interpolatable property value), camera function with CGVector (NSValue) stop values
- let expectedCircleTranslationValue = MGLStyleValue<NSValue>(
- interpolationMode: .interval,
- cameraStops: circleTranslationStops,
- options: nil
- )
- circleStyleLayer.circleTranslation = expectedCircleTranslationValue
- XCTAssertEqual(circleStyleLayer.circleTranslation, expectedCircleTranslationValue)
-
- // non-data-driven (enumeration property value), camera function with MGLCircleScaleAlignment enum (NSValue) stop values
- let scaleAlignmentStops : [Float:MGLStyleValue<NSValue>] = [
- 0: MGLStyleValue(rawValue: NSValue(mglCircleScaleAlignment: .map)),
- 10: MGLStyleValue(rawValue: NSValue(mglCircleScaleAlignment: .viewport))
- ]
- let expectedCircleScaleAlignmentValue = MGLStyleValue<NSValue>(
- interpolationMode: .interval,
- cameraStops: scaleAlignmentStops,
- options: nil
- )
- circleStyleLayer.circleScaleAlignment = expectedCircleScaleAlignmentValue
- XCTAssertEqual(circleStyleLayer.circleScaleAlignment, expectedCircleScaleAlignmentValue)
- }
-
- func testFunctionsWithDataDrivenProperties() {
- let shapeSource = MGLShapeSource(identifier: "test", shape: nil, options: nil)
- let circleStyleLayer = MGLCircleStyleLayer(identifier: "circleLayer", source: shapeSource)
-
- // data-driven, camera function with exponential color stop values
- let redGreenStops : [Float:MGLStyleValue<MGLColor>] = [
- 0: MGLStyleValue<MGLColor>(rawValue: .red),
- 10: MGLStyleValue<MGLColor>(rawValue: .red),
- 15: MGLStyleValue<MGLColor>(rawValue: .green)
- ]
- let expectedCircleColorValue = MGLStyleValue<MGLColor>(
- interpolationMode: .exponential,
- cameraStops: redGreenStops,
- options: [.interpolationBase: 10.0]
- )
- circleStyleLayer.circleColor = expectedCircleColorValue
- assertColorValuesEqual(circleStyleLayer.circleColor as! MGLStyleFunction<MGLColor>, expectedCircleColorValue as! MGLStyleFunction<MGLColor>)
-
- // data-driven, source function with categorical color stop values with string attribute keys
- let redOnlyStops = [
- "red": MGLStyleValue<MGLColor>(rawValue: .red)
- ]
- let expectedRedCategoricalValue = MGLStyleValue<MGLColor>(
- interpolationMode: .categorical,
- sourceStops: redOnlyStops,
- attributeName: "red",
- options: [.defaultValue: MGLStyleValue<MGLColor>(rawValue: .cyan)]
- )
- circleStyleLayer.circleColor = expectedRedCategoricalValue
- assertColorValuesEqual(circleStyleLayer.circleColor, expectedRedCategoricalValue)
-
- // data-driven, source function with categorical color stop values with integer attribute keys
- let greenOrangeStops : [Float:MGLStyleValue<MGLColor>] = [
- 0: MGLStyleValue<MGLColor>(rawValue: .green),
- 100: MGLStyleValue<MGLColor>(rawValue: .orange)
- ]
- let expectedGreenOrangeCategoricalValue = MGLStyleValue<MGLColor>(
- interpolationMode: .categorical,
- sourceStops: greenOrangeStops,
- attributeName: "temp",
- options: [.defaultValue: MGLStyleValue<MGLColor>(rawValue: .red)]
- )
- circleStyleLayer.circleColor = expectedGreenOrangeCategoricalValue
- assertColorValuesEqual(circleStyleLayer.circleColor, expectedGreenOrangeCategoricalValue)
-
- // data-driven, source function with exponential color stop values
- let expectedRedGreenSourceExponentialValue = MGLStyleValue<MGLColor>(
- interpolationMode: .exponential,
- sourceStops: redGreenStops,
- attributeName: "temp",
- options: nil
- )
- circleStyleLayer.circleColor = expectedRedGreenSourceExponentialValue
- assertColorValuesEqual(circleStyleLayer.circleColor, expectedRedGreenSourceExponentialValue)
-
- // data-driven, identity source function
- let expectedSourceIdentityValue = MGLStyleValue<MGLColor>(
- interpolationMode: .identity,
- sourceStops: nil,
- attributeName: "size",
- options: [.defaultValue: MGLStyleValue<MGLColor>(rawValue: .green)]
- )
- circleStyleLayer.circleColor = expectedSourceIdentityValue
- assertColorValuesEqual(circleStyleLayer.circleColor, expectedSourceIdentityValue)
-
- // data-driven, source function with categorical color stop values with boolean attribute keys
- let booleanCategoricalStops = [
- false: MGLStyleValue<NSNumber>(rawValue: 0),
- true: MGLStyleValue<NSNumber>(rawValue: 2)
- ]
- let expectedCircleBlurCategoricalValue = MGLStyleValue<NSNumber>(
- interpolationMode: .categorical,
- sourceStops: booleanCategoricalStops,
- attributeName: "fuzzy",
- options: [.defaultValue: MGLStyleValue<NSNumber>(rawValue: 42)]
- )
- circleStyleLayer.circleBlur = expectedCircleBlurCategoricalValue
- XCTAssertEqual(circleStyleLayer.circleBlur, expectedCircleBlurCategoricalValue)
-
- // data-driven, composite function with inner categorical color stop values with string attribute keys nested in outer camera stops
- let smallRadius = MGLStyleValue<NSNumber>(rawValue: 5)
- let mediumRadius = MGLStyleValue<NSNumber>(rawValue: 10)
- let largeRadius = MGLStyleValue<NSNumber>(rawValue: 20)
- let radiusCompositeCategoricalStops: [Float: [String: MGLStyleValue<NSNumber>]] = [
- 0: ["green": smallRadius],
- 10: ["green": smallRadius],
- 15: ["green": largeRadius],
- 20: ["green": largeRadius]
- ]
- let defaultRadius = MGLStyleValue<NSNumber>(rawValue: 2)
- let expectedCompositeCategoricalValue = MGLStyleValue<NSNumber>(
- interpolationMode: .categorical,
- compositeStops: radiusCompositeCategoricalStops,
- attributeName: "color",
- options: [.defaultValue: defaultRadius]
- )
- circleStyleLayer.circleRadius = expectedCompositeCategoricalValue
-
- var compositeValue = circleStyleLayer.circleRadius as! MGLCompositeStyleFunction
- var expectedCompositeValue = expectedCompositeCategoricalValue as! MGLCompositeStyleFunction
- XCTAssertEqual(compositeValue.attributeName, expectedCompositeValue.attributeName)
- XCTAssertEqual(compositeValue.stops as NSDictionary, radiusCompositeCategoricalStops as NSDictionary)
- XCTAssertEqual(compositeValue.interpolationMode, expectedCompositeValue.interpolationMode)
- XCTAssertEqual(compositeValue.defaultValue, expectedCompositeValue.defaultValue)
-
- // data-driven, composite function with inner exponential color stop values nested in outer camera stops
- let radiusCompositeExponentialOrIntervalStops: [Float: [Float: MGLStyleValue<NSNumber>]] = [
- 0: [0: MGLStyleValue<NSNumber>(rawValue: 5)],
- 10: [200: MGLStyleValue<NSNumber>(rawValue: 5)],
- 20: [200: MGLStyleValue<NSNumber>(rawValue: 20)]
- ]
-
- let expectedStops = [
- 0: [0: MGLStyleValue<NSNumber>(rawValue: 5)],
- 10: [200: MGLStyleValue<NSNumber>(rawValue: 5)],
- 20: [200: MGLStyleValue<NSNumber>(rawValue: 20)]
- ]
- circleStyleLayer.circleRadius = MGLStyleValue<NSNumber>(
- interpolationMode: .exponential,
- compositeStops: [
- 0: [0: MGLStyleValue<NSNumber>(rawValue: 5)],
- 10: [200: MGLStyleValue<NSNumber>(rawValue: 5)],
- 20: [200: MGLStyleValue<NSNumber>(rawValue: 20)]
- ],
- attributeName: "temp",
- options: [.defaultValue: mediumRadius]
- )
-
- let expectedCompositeExponentialValue = MGLStyleValue<NSNumber>(
- interpolationMode: .exponential,
- compositeStops: radiusCompositeExponentialOrIntervalStops,
- attributeName: "temp",
- options: [.defaultValue: mediumRadius]
- )
-
- compositeValue = circleStyleLayer.circleRadius as! MGLCompositeStyleFunction
- expectedCompositeValue = expectedCompositeExponentialValue as! MGLCompositeStyleFunction
- XCTAssertEqual(compositeValue.attributeName, expectedCompositeValue.attributeName)
- XCTAssertEqual(compositeValue.stops as NSDictionary, expectedStops as NSDictionary)
- XCTAssertEqual(compositeValue.interpolationMode, expectedCompositeValue.interpolationMode)
- XCTAssertEqual(compositeValue.defaultValue, expectedCompositeValue.defaultValue)
-
- // get a value back
- if let returnedCircleRadius = circleStyleLayer.circleRadius as? MGLCompositeStyleFunction<NSNumber> {
- if let returnedStops = returnedCircleRadius.stops as NSDictionary? as? [NSNumber: [NSNumber: MGLStyleValue<NSNumber>]] {
- let lhs: MGLStyleValue<NSNumber> = returnedStops[0]!.values.first!
- let rhs: MGLStyleValue<NSNumber> = radiusCompositeExponentialOrIntervalStops[0]!.values.first!
- XCTAssertEqual(lhs, rhs)
- }
- }
-
- // get value back as base class
- if let returnedCircleRadius = circleStyleLayer.circleRadius as? MGLStyleFunction<NSNumber> {
- if let returnedStops = returnedCircleRadius.stops as NSDictionary? as? [NSNumber: [NSNumber: MGLStyleValue<NSNumber>]] {
- let lhs: MGLStyleValue<NSNumber> = returnedStops[0]!.values.first!
- let rhs: MGLStyleValue<NSNumber> = radiusCompositeExponentialOrIntervalStops[0]!.values.first!
- XCTAssertEqual(lhs, rhs)
- }
- }
-
- // data-driven, composite function with inner interval color stop values nested in outer camera stops
- let expectedCompositeIntervalValue = MGLStyleValue<NSNumber>(
- interpolationMode: .interval,
- compositeStops: [
-
- 10: [200: MGLStyleValue<NSNumber>(rawValue: 5)],
- 20: [200: MGLStyleValue<NSNumber>(rawValue: 20)]
- ],
- attributeName: "temp",
- options: nil
- )
- circleStyleLayer.circleRadius = MGLStyleValue<NSNumber>(
- interpolationMode: .interval,
- compositeStops: [
- 0: [0: MGLStyleValue<NSNumber>(rawValue: 5)],
- 10: [200: MGLStyleValue<NSNumber>(rawValue: 5)],
- 20: [200: MGLStyleValue<NSNumber>(rawValue: 20)]
- ],
- attributeName: "temp",
- options: nil
- )
-
- compositeValue = circleStyleLayer.circleRadius as! MGLCompositeStyleFunction
- expectedCompositeValue = expectedCompositeIntervalValue as! MGLCompositeStyleFunction
- XCTAssertEqual(compositeValue.attributeName, expectedCompositeValue.attributeName)
- XCTAssertEqual(compositeValue.stops as NSDictionary, expectedStops as NSDictionary)
- XCTAssertEqual(compositeValue.interpolationMode, expectedCompositeValue.interpolationMode)
- XCTAssertEqual(compositeValue.defaultValue, expectedCompositeValue.defaultValue)
- }
-}
diff --git a/platform/darwin/test/MGLSymbolStyleLayerTests.mm b/platform/darwin/test/MGLSymbolStyleLayerTests.mm
index 1ac86dd402..cf2f80125a 100644
--- a/platform/darwin/test/MGLSymbolStyleLayerTests.mm
+++ b/platform/darwin/test/MGLSymbolStyleLayerTests.mm
@@ -30,8 +30,8 @@
XCTAssertNil(layer.sourceLayerIdentifier);
XCTAssertNil(layer.predicate);
- layer.predicate = [NSPredicate predicateWithValue:NO];
- XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithValue:NO]);
+ layer.predicate = [NSPredicate predicateWithFormat:@"$featureIdentifier = 1"];
+ XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithFormat:@"$featureIdentifier = 1"]);
layer.predicate = nil;
XCTAssertNil(layer.predicate);
}
@@ -52,72 +52,81 @@
{
XCTAssertTrue(rawLayer->getIconAllowOverlap().isUndefined(),
@"icon-allow-overlap should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.iconAllowsOverlap;
+ NSExpression *defaultExpression = layer.iconAllowsOverlap;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@YES];
- layer.iconAllowsOverlap = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"true"];
+ layer.iconAllowsOverlap = constantExpression;
mbgl::style::PropertyValue<bool> propertyValue = { true };
XCTAssertEqual(rawLayer->getIconAllowOverlap(), propertyValue,
- @"Setting iconAllowsOverlap to a constant value should update icon-allow-overlap.");
- XCTAssertEqualObjects(layer.iconAllowsOverlap, constantStyleValue,
- @"iconAllowsOverlap should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.iconAllowsOverlap = functionStyleValue;
-
- mbgl::style::IntervalStops<bool> intervalStops = { {{18, true}} };
+ @"Setting iconAllowsOverlap to a constant value expression should update icon-allow-overlap.");
+ XCTAssertEqualObjects(layer.iconAllowsOverlap, constantExpression,
+ @"iconAllowsOverlap should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"true"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.iconAllowsOverlap = functionExpression;
+
+ mbgl::style::IntervalStops<bool> intervalStops = {{
+ { -INFINITY, true },
+ { 18, true },
+ }};
propertyValue = mbgl::style::CameraFunction<bool> { intervalStops };
XCTAssertEqual(rawLayer->getIconAllowOverlap(), propertyValue,
- @"Setting iconAllowsOverlap to a camera function should update icon-allow-overlap.");
- XCTAssertEqualObjects(layer.iconAllowsOverlap, functionStyleValue,
- @"iconAllowsOverlap should round-trip camera functions.");
+ @"Setting iconAllowsOverlap to a camera expression should update icon-allow-overlap.");
+ XCTAssertEqualObjects(layer.iconAllowsOverlap, functionExpression,
+ @"iconAllowsOverlap should round-trip camera expressions.");
layer.iconAllowsOverlap = nil;
XCTAssertTrue(rawLayer->getIconAllowOverlap().isUndefined(),
@"Unsetting iconAllowsOverlap should return icon-allow-overlap to the default value.");
- XCTAssertEqualObjects(layer.iconAllowsOverlap, defaultStyleValue,
+ XCTAssertEqualObjects(layer.iconAllowsOverlap, defaultExpression,
@"iconAllowsOverlap should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.iconAllowsOverlap = 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.iconAllowsOverlap = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.iconAllowsOverlap = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.iconAllowsOverlap = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// icon-anchor
{
XCTAssertTrue(rawLayer->getIconAnchor().isUndefined(),
@"icon-anchor should be unset initially.");
- MGLStyleValue<NSValue *> *defaultStyleValue = layer.iconAnchor;
+ NSExpression *defaultExpression = layer.iconAnchor;
- MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLIconAnchor:MGLIconAnchorBottomRight]];
- layer.iconAnchor = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'bottom-right'"];
+ layer.iconAnchor = constantExpression;
mbgl::style::DataDrivenPropertyValue<mbgl::style::SymbolAnchorType> propertyValue = { mbgl::style::SymbolAnchorType::BottomRight };
XCTAssertEqual(rawLayer->getIconAnchor(), propertyValue,
- @"Setting iconAnchor to a constant value should update icon-anchor.");
- XCTAssertEqualObjects(layer.iconAnchor, constantStyleValue,
- @"iconAnchor should round-trip constant values.");
-
- MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.iconAnchor = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::style::SymbolAnchorType> intervalStops = { {{18, mbgl::style::SymbolAnchorType::BottomRight}} };
+ @"Setting iconAnchor to a constant value expression should update icon-anchor.");
+ XCTAssertEqualObjects(layer.iconAnchor, constantExpression,
+ @"iconAnchor should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"'bottom-right'"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.iconAnchor = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::style::SymbolAnchorType> intervalStops = {{
+ { -INFINITY, mbgl::style::SymbolAnchorType::BottomRight },
+ { 18, mbgl::style::SymbolAnchorType::BottomRight },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::style::SymbolAnchorType> { intervalStops };
XCTAssertEqual(rawLayer->getIconAnchor(), propertyValue,
- @"Setting iconAnchor to a camera function should update icon-anchor.");
- XCTAssertEqualObjects(layer.iconAnchor, functionStyleValue,
- @"iconAnchor should round-trip camera functions.");
+ @"Setting iconAnchor to a camera expression should update icon-anchor.");
+ XCTAssertEqualObjects(layer.iconAnchor, functionExpression,
+ @"iconAnchor should round-trip camera expressions.");
layer.iconAnchor = nil;
XCTAssertTrue(rawLayer->getIconAnchor().isUndefined(),
@"Unsetting iconAnchor should return icon-anchor to the default value.");
- XCTAssertEqualObjects(layer.iconAnchor, defaultStyleValue,
+ XCTAssertEqualObjects(layer.iconAnchor, defaultExpression,
@"iconAnchor should return the default value after being unset.");
}
@@ -125,72 +134,81 @@
{
XCTAssertTrue(rawLayer->getIconIgnorePlacement().isUndefined(),
@"icon-ignore-placement should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.iconIgnoresPlacement;
+ NSExpression *defaultExpression = layer.iconIgnoresPlacement;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@YES];
- layer.iconIgnoresPlacement = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"true"];
+ layer.iconIgnoresPlacement = constantExpression;
mbgl::style::PropertyValue<bool> propertyValue = { true };
XCTAssertEqual(rawLayer->getIconIgnorePlacement(), propertyValue,
- @"Setting iconIgnoresPlacement to a constant value should update icon-ignore-placement.");
- XCTAssertEqualObjects(layer.iconIgnoresPlacement, constantStyleValue,
- @"iconIgnoresPlacement should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.iconIgnoresPlacement = functionStyleValue;
-
- mbgl::style::IntervalStops<bool> intervalStops = { {{18, true}} };
+ @"Setting iconIgnoresPlacement to a constant value expression should update icon-ignore-placement.");
+ XCTAssertEqualObjects(layer.iconIgnoresPlacement, constantExpression,
+ @"iconIgnoresPlacement should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"true"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.iconIgnoresPlacement = functionExpression;
+
+ mbgl::style::IntervalStops<bool> intervalStops = {{
+ { -INFINITY, true },
+ { 18, true },
+ }};
propertyValue = mbgl::style::CameraFunction<bool> { intervalStops };
XCTAssertEqual(rawLayer->getIconIgnorePlacement(), propertyValue,
- @"Setting iconIgnoresPlacement to a camera function should update icon-ignore-placement.");
- XCTAssertEqualObjects(layer.iconIgnoresPlacement, functionStyleValue,
- @"iconIgnoresPlacement should round-trip camera functions.");
+ @"Setting iconIgnoresPlacement to a camera expression should update icon-ignore-placement.");
+ XCTAssertEqualObjects(layer.iconIgnoresPlacement, functionExpression,
+ @"iconIgnoresPlacement should round-trip camera expressions.");
layer.iconIgnoresPlacement = nil;
XCTAssertTrue(rawLayer->getIconIgnorePlacement().isUndefined(),
@"Unsetting iconIgnoresPlacement should return icon-ignore-placement to the default value.");
- XCTAssertEqualObjects(layer.iconIgnoresPlacement, defaultStyleValue,
+ XCTAssertEqualObjects(layer.iconIgnoresPlacement, defaultExpression,
@"iconIgnoresPlacement should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.iconIgnoresPlacement = 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.iconIgnoresPlacement = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.iconIgnoresPlacement = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.iconIgnoresPlacement = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// icon-image
{
XCTAssertTrue(rawLayer->getIconImage().isUndefined(),
@"icon-image should be unset initially.");
- MGLStyleValue<NSString *> *defaultStyleValue = layer.iconImageName;
+ NSExpression *defaultExpression = layer.iconImageName;
- MGLStyleValue<NSString *> *constantStyleValue = [MGLStyleValue<NSString *> valueWithRawValue:@"Icon Image"];
- layer.iconImageName = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'Icon Image'"];
+ layer.iconImageName = constantExpression;
mbgl::style::DataDrivenPropertyValue<std::string> propertyValue = { "Icon Image" };
XCTAssertEqual(rawLayer->getIconImage(), propertyValue,
- @"Setting iconImageName to a constant value should update icon-image.");
- XCTAssertEqualObjects(layer.iconImageName, constantStyleValue,
- @"iconImageName should round-trip constant values.");
-
- MGLStyleValue<NSString *> * functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.iconImageName = functionStyleValue;
-
- mbgl::style::IntervalStops<std::string> intervalStops = { {{18, "Icon Image"}} };
+ @"Setting iconImageName to a constant value expression should update icon-image.");
+ XCTAssertEqualObjects(layer.iconImageName, constantExpression,
+ @"iconImageName should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"'Icon Image'"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.iconImageName = functionExpression;
+
+ mbgl::style::IntervalStops<std::string> intervalStops = {{
+ { -INFINITY, "Icon Image" },
+ { 18, "Icon Image" },
+ }};
propertyValue = mbgl::style::CameraFunction<std::string> { intervalStops };
XCTAssertEqual(rawLayer->getIconImage(), propertyValue,
- @"Setting iconImageName to a camera function should update icon-image.");
- XCTAssertEqualObjects(layer.iconImageName, functionStyleValue,
- @"iconImageName should round-trip camera functions.");
+ @"Setting iconImageName to a camera expression should update icon-image.");
+ XCTAssertEqualObjects(layer.iconImageName, functionExpression,
+ @"iconImageName should round-trip camera expressions.");
layer.iconImageName = nil;
XCTAssertTrue(rawLayer->getIconImage().isUndefined(),
@"Unsetting iconImageName should return icon-image to the default value.");
- XCTAssertEqualObjects(layer.iconImageName, defaultStyleValue,
+ XCTAssertEqualObjects(layer.iconImageName, defaultExpression,
@"iconImageName should return the default value after being unset.");
}
@@ -198,46 +216,51 @@
{
XCTAssertTrue(rawLayer->getIconOffset().isUndefined(),
@"icon-offset should be unset initially.");
- MGLStyleValue<NSValue *> *defaultStyleValue = layer.iconOffset;
+ NSExpression *defaultExpression = layer.iconOffset;
- MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"%@",
#if TARGET_OS_IPHONE
[NSValue valueWithCGVector:CGVectorMake(1, 1)]
#else
[NSValue valueWithMGLVector:CGVectorMake(1, -1)]
#endif
];
- layer.iconOffset = constantStyleValue;
+ layer.iconOffset = constantExpression;
mbgl::style::DataDrivenPropertyValue<std::array<float, 2>> propertyValue = { { 1, 1 } };
XCTAssertEqual(rawLayer->getIconOffset(), propertyValue,
- @"Setting iconOffset to a constant value should update icon-offset.");
- XCTAssertEqualObjects(layer.iconOffset, constantStyleValue,
- @"iconOffset should round-trip constant values.");
-
- MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.iconOffset = functionStyleValue;
-
- mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = { {{18, { 1, 1 }}} };
+ @"Setting iconOffset to a constant value expression should update icon-offset.");
+ XCTAssertEqualObjects(layer.iconOffset, constantExpression,
+ @"iconOffset should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"{1, 1}"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.iconOffset = functionExpression;
+
+ mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = {{
+ { -INFINITY, { 1, 1 } },
+ { 18, { 1, 1 } },
+ }};
propertyValue = mbgl::style::CameraFunction<std::array<float, 2>> { intervalStops };
XCTAssertEqual(rawLayer->getIconOffset(), propertyValue,
- @"Setting iconOffset to a camera function should update icon-offset.");
- XCTAssertEqualObjects(layer.iconOffset, functionStyleValue,
- @"iconOffset should round-trip camera functions.");
+ @"Setting iconOffset to a camera expression should update icon-offset.");
+ XCTAssertEqualObjects(layer.iconOffset, functionExpression,
+ @"iconOffset should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.iconOffset = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.iconOffset = functionExpression;
mbgl::style::ExponentialStops<std::array<float, 2>> exponentialStops = { {{18, { 1, 1 }}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<std::array<float, 2>> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getIconOffset(), propertyValue,
- @"Setting iconOffset to a source function should update icon-offset.");
- XCTAssertEqualObjects(layer.iconOffset, functionStyleValue,
- @"iconOffset should round-trip source functions.");
+ @"Setting iconOffset to a data expression should update icon-offset.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.iconOffset, pedanticFunctionExpression,
+ @"iconOffset should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.iconOffset = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.iconOffset = functionExpression;
std::map<float, std::array<float, 2>> innerStops { {18, { 1, 1 }} };
mbgl::style::CompositeExponentialStops<std::array<float, 2>> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -245,15 +268,16 @@
propertyValue = mbgl::style::CompositeFunction<std::array<float, 2>> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getIconOffset(), propertyValue,
- @"Setting iconOffset to a composite function should update icon-offset.");
- XCTAssertEqualObjects(layer.iconOffset, functionStyleValue,
- @"iconOffset should round-trip composite functions.");
+ @"Setting iconOffset to a camera-data expression should update icon-offset.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.iconOffset, pedanticFunctionExpression,
+ @"iconOffset should round-trip camera-data expressions.");
layer.iconOffset = nil;
XCTAssertTrue(rawLayer->getIconOffset().isUndefined(),
@"Unsetting iconOffset should return icon-offset to the default value.");
- XCTAssertEqualObjects(layer.iconOffset, defaultStyleValue,
+ XCTAssertEqualObjects(layer.iconOffset, defaultExpression,
@"iconOffset should return the default value after being unset.");
}
@@ -261,157 +285,177 @@
{
XCTAssertTrue(rawLayer->getIconOptional().isUndefined(),
@"icon-optional should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.iconOptional;
+ NSExpression *defaultExpression = layer.iconOptional;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@YES];
- layer.iconOptional = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"true"];
+ layer.iconOptional = constantExpression;
mbgl::style::PropertyValue<bool> propertyValue = { true };
XCTAssertEqual(rawLayer->getIconOptional(), propertyValue,
- @"Setting iconOptional to a constant value should update icon-optional.");
- XCTAssertEqualObjects(layer.iconOptional, constantStyleValue,
- @"iconOptional should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.iconOptional = functionStyleValue;
-
- mbgl::style::IntervalStops<bool> intervalStops = { {{18, true}} };
+ @"Setting iconOptional to a constant value expression should update icon-optional.");
+ XCTAssertEqualObjects(layer.iconOptional, constantExpression,
+ @"iconOptional should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"true"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.iconOptional = functionExpression;
+
+ mbgl::style::IntervalStops<bool> intervalStops = {{
+ { -INFINITY, true },
+ { 18, true },
+ }};
propertyValue = mbgl::style::CameraFunction<bool> { intervalStops };
XCTAssertEqual(rawLayer->getIconOptional(), propertyValue,
- @"Setting iconOptional to a camera function should update icon-optional.");
- XCTAssertEqualObjects(layer.iconOptional, functionStyleValue,
- @"iconOptional should round-trip camera functions.");
+ @"Setting iconOptional to a camera expression should update icon-optional.");
+ XCTAssertEqualObjects(layer.iconOptional, functionExpression,
+ @"iconOptional should round-trip camera expressions.");
layer.iconOptional = nil;
XCTAssertTrue(rawLayer->getIconOptional().isUndefined(),
@"Unsetting iconOptional should return icon-optional to the default value.");
- XCTAssertEqualObjects(layer.iconOptional, defaultStyleValue,
+ XCTAssertEqualObjects(layer.iconOptional, defaultExpression,
@"iconOptional should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.iconOptional = 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.iconOptional = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.iconOptional = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.iconOptional = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// icon-padding
{
XCTAssertTrue(rawLayer->getIconPadding().isUndefined(),
@"icon-padding should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.iconPadding;
+ NSExpression *defaultExpression = layer.iconPadding;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.iconPadding = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.iconPadding = constantExpression;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getIconPadding(), propertyValue,
- @"Setting iconPadding to a constant value should update icon-padding.");
- XCTAssertEqualObjects(layer.iconPadding, constantStyleValue,
- @"iconPadding should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.iconPadding = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting iconPadding to a constant value expression should update icon-padding.");
+ XCTAssertEqualObjects(layer.iconPadding, constantExpression,
+ @"iconPadding should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.iconPadding = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getIconPadding(), propertyValue,
- @"Setting iconPadding to a camera function should update icon-padding.");
- XCTAssertEqualObjects(layer.iconPadding, functionStyleValue,
- @"iconPadding should round-trip camera functions.");
+ @"Setting iconPadding to a camera expression should update icon-padding.");
+ XCTAssertEqualObjects(layer.iconPadding, functionExpression,
+ @"iconPadding should round-trip camera expressions.");
layer.iconPadding = nil;
XCTAssertTrue(rawLayer->getIconPadding().isUndefined(),
@"Unsetting iconPadding should return icon-padding to the default value.");
- XCTAssertEqualObjects(layer.iconPadding, defaultStyleValue,
+ XCTAssertEqualObjects(layer.iconPadding, defaultExpression,
@"iconPadding should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.iconPadding = 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.iconPadding = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.iconPadding = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.iconPadding = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// icon-pitch-alignment
{
XCTAssertTrue(rawLayer->getIconPitchAlignment().isUndefined(),
@"icon-pitch-alignment should be unset initially.");
- MGLStyleValue<NSValue *> *defaultStyleValue = layer.iconPitchAlignment;
+ NSExpression *defaultExpression = layer.iconPitchAlignment;
- MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLIconPitchAlignment:MGLIconPitchAlignmentAuto]];
- layer.iconPitchAlignment = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'auto'"];
+ layer.iconPitchAlignment = constantExpression;
mbgl::style::PropertyValue<mbgl::style::AlignmentType> propertyValue = { mbgl::style::AlignmentType::Auto };
XCTAssertEqual(rawLayer->getIconPitchAlignment(), propertyValue,
- @"Setting iconPitchAlignment to a constant value should update icon-pitch-alignment.");
- XCTAssertEqualObjects(layer.iconPitchAlignment, constantStyleValue,
- @"iconPitchAlignment should round-trip constant values.");
-
- MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.iconPitchAlignment = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::style::AlignmentType> intervalStops = { {{18, mbgl::style::AlignmentType::Auto}} };
+ @"Setting iconPitchAlignment to a constant value expression should update icon-pitch-alignment.");
+ XCTAssertEqualObjects(layer.iconPitchAlignment, constantExpression,
+ @"iconPitchAlignment should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"'auto'"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.iconPitchAlignment = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::style::AlignmentType> intervalStops = {{
+ { -INFINITY, mbgl::style::AlignmentType::Auto },
+ { 18, mbgl::style::AlignmentType::Auto },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::style::AlignmentType> { intervalStops };
XCTAssertEqual(rawLayer->getIconPitchAlignment(), propertyValue,
- @"Setting iconPitchAlignment to a camera function should update icon-pitch-alignment.");
- XCTAssertEqualObjects(layer.iconPitchAlignment, functionStyleValue,
- @"iconPitchAlignment should round-trip camera functions.");
+ @"Setting iconPitchAlignment to a camera expression should update icon-pitch-alignment.");
+ XCTAssertEqualObjects(layer.iconPitchAlignment, functionExpression,
+ @"iconPitchAlignment should round-trip camera expressions.");
layer.iconPitchAlignment = nil;
XCTAssertTrue(rawLayer->getIconPitchAlignment().isUndefined(),
@"Unsetting iconPitchAlignment should return icon-pitch-alignment to the default value.");
- XCTAssertEqualObjects(layer.iconPitchAlignment, defaultStyleValue,
+ XCTAssertEqualObjects(layer.iconPitchAlignment, defaultExpression,
@"iconPitchAlignment should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.iconPitchAlignment = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.iconPitchAlignment = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.iconPitchAlignment = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.iconPitchAlignment = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// icon-rotate
{
XCTAssertTrue(rawLayer->getIconRotate().isUndefined(),
@"icon-rotate should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.iconRotation;
+ NSExpression *defaultExpression = layer.iconRotation;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.iconRotation = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.iconRotation = constantExpression;
mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getIconRotate(), propertyValue,
- @"Setting iconRotation to a constant value should update icon-rotate.");
- XCTAssertEqualObjects(layer.iconRotation, constantStyleValue,
- @"iconRotation should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.iconRotation = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting iconRotation to a constant value expression should update icon-rotate.");
+ XCTAssertEqualObjects(layer.iconRotation, constantExpression,
+ @"iconRotation should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.iconRotation = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getIconRotate(), propertyValue,
- @"Setting iconRotation to a camera function should update icon-rotate.");
- XCTAssertEqualObjects(layer.iconRotation, functionStyleValue,
- @"iconRotation should round-trip camera functions.");
+ @"Setting iconRotation to a camera expression should update icon-rotate.");
+ XCTAssertEqualObjects(layer.iconRotation, functionExpression,
+ @"iconRotation should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.iconRotation = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.iconRotation = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getIconRotate(), propertyValue,
- @"Setting iconRotation to a source function should update icon-rotate.");
- XCTAssertEqualObjects(layer.iconRotation, functionStyleValue,
- @"iconRotation should round-trip source functions.");
+ @"Setting iconRotation to a data expression should update icon-rotate.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.iconRotation, pedanticFunctionExpression,
+ @"iconRotation should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.iconRotation = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.iconRotation = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -419,15 +463,16 @@
propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getIconRotate(), propertyValue,
- @"Setting iconRotation to a composite function should update icon-rotate.");
- XCTAssertEqualObjects(layer.iconRotation, functionStyleValue,
- @"iconRotation should round-trip composite functions.");
+ @"Setting iconRotation to a camera-data expression should update icon-rotate.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.iconRotation, pedanticFunctionExpression,
+ @"iconRotation should round-trip camera-data expressions.");
layer.iconRotation = nil;
XCTAssertTrue(rawLayer->getIconRotate().isUndefined(),
@"Unsetting iconRotation should return icon-rotate to the default value.");
- XCTAssertEqualObjects(layer.iconRotation, defaultStyleValue,
+ XCTAssertEqualObjects(layer.iconRotation, defaultExpression,
@"iconRotation should return the default value after being unset.");
}
@@ -435,79 +480,89 @@
{
XCTAssertTrue(rawLayer->getIconRotationAlignment().isUndefined(),
@"icon-rotation-alignment should be unset initially.");
- MGLStyleValue<NSValue *> *defaultStyleValue = layer.iconRotationAlignment;
+ NSExpression *defaultExpression = layer.iconRotationAlignment;
- MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLIconRotationAlignment:MGLIconRotationAlignmentAuto]];
- layer.iconRotationAlignment = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'auto'"];
+ layer.iconRotationAlignment = constantExpression;
mbgl::style::PropertyValue<mbgl::style::AlignmentType> propertyValue = { mbgl::style::AlignmentType::Auto };
XCTAssertEqual(rawLayer->getIconRotationAlignment(), propertyValue,
- @"Setting iconRotationAlignment to a constant value should update icon-rotation-alignment.");
- XCTAssertEqualObjects(layer.iconRotationAlignment, constantStyleValue,
- @"iconRotationAlignment should round-trip constant values.");
-
- MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.iconRotationAlignment = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::style::AlignmentType> intervalStops = { {{18, mbgl::style::AlignmentType::Auto}} };
+ @"Setting iconRotationAlignment to a constant value expression should update icon-rotation-alignment.");
+ XCTAssertEqualObjects(layer.iconRotationAlignment, constantExpression,
+ @"iconRotationAlignment should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"'auto'"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.iconRotationAlignment = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::style::AlignmentType> intervalStops = {{
+ { -INFINITY, mbgl::style::AlignmentType::Auto },
+ { 18, mbgl::style::AlignmentType::Auto },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::style::AlignmentType> { intervalStops };
XCTAssertEqual(rawLayer->getIconRotationAlignment(), propertyValue,
- @"Setting iconRotationAlignment to a camera function should update icon-rotation-alignment.");
- XCTAssertEqualObjects(layer.iconRotationAlignment, functionStyleValue,
- @"iconRotationAlignment should round-trip camera functions.");
+ @"Setting iconRotationAlignment to a camera expression should update icon-rotation-alignment.");
+ XCTAssertEqualObjects(layer.iconRotationAlignment, functionExpression,
+ @"iconRotationAlignment should round-trip camera expressions.");
layer.iconRotationAlignment = nil;
XCTAssertTrue(rawLayer->getIconRotationAlignment().isUndefined(),
@"Unsetting iconRotationAlignment should return icon-rotation-alignment to the default value.");
- XCTAssertEqualObjects(layer.iconRotationAlignment, defaultStyleValue,
+ XCTAssertEqualObjects(layer.iconRotationAlignment, defaultExpression,
@"iconRotationAlignment should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.iconRotationAlignment = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.iconRotationAlignment = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.iconRotationAlignment = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.iconRotationAlignment = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// icon-size
{
XCTAssertTrue(rawLayer->getIconSize().isUndefined(),
@"icon-size should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.iconScale;
+ NSExpression *defaultExpression = layer.iconScale;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.iconScale = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.iconScale = constantExpression;
mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getIconSize(), propertyValue,
- @"Setting iconScale to a constant value should update icon-size.");
- XCTAssertEqualObjects(layer.iconScale, constantStyleValue,
- @"iconScale should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.iconScale = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting iconScale to a constant value expression should update icon-size.");
+ XCTAssertEqualObjects(layer.iconScale, constantExpression,
+ @"iconScale should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.iconScale = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getIconSize(), propertyValue,
- @"Setting iconScale to a camera function should update icon-size.");
- XCTAssertEqualObjects(layer.iconScale, functionStyleValue,
- @"iconScale should round-trip camera functions.");
+ @"Setting iconScale to a camera expression should update icon-size.");
+ XCTAssertEqualObjects(layer.iconScale, functionExpression,
+ @"iconScale should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.iconScale = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.iconScale = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getIconSize(), propertyValue,
- @"Setting iconScale to a source function should update icon-size.");
- XCTAssertEqualObjects(layer.iconScale, functionStyleValue,
- @"iconScale should round-trip source functions.");
+ @"Setting iconScale to a data expression should update icon-size.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.iconScale, pedanticFunctionExpression,
+ @"iconScale should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.iconScale = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.iconScale = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -515,15 +570,16 @@
propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getIconSize(), propertyValue,
- @"Setting iconScale to a composite function should update icon-size.");
- XCTAssertEqualObjects(layer.iconScale, functionStyleValue,
- @"iconScale should round-trip composite functions.");
+ @"Setting iconScale to a camera-data expression should update icon-size.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.iconScale, pedanticFunctionExpression,
+ @"iconScale should round-trip camera-data expressions.");
layer.iconScale = nil;
XCTAssertTrue(rawLayer->getIconSize().isUndefined(),
@"Unsetting iconScale should return icon-size to the default value.");
- XCTAssertEqualObjects(layer.iconScale, defaultStyleValue,
+ XCTAssertEqualObjects(layer.iconScale, defaultExpression,
@"iconScale should return the default value after being unset.");
}
@@ -531,241 +587,271 @@
{
XCTAssertTrue(rawLayer->getIconTextFit().isUndefined(),
@"icon-text-fit should be unset initially.");
- MGLStyleValue<NSValue *> *defaultStyleValue = layer.iconTextFit;
+ NSExpression *defaultExpression = layer.iconTextFit;
- MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLIconTextFit:MGLIconTextFitBoth]];
- layer.iconTextFit = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'both'"];
+ layer.iconTextFit = constantExpression;
mbgl::style::PropertyValue<mbgl::style::IconTextFitType> propertyValue = { mbgl::style::IconTextFitType::Both };
XCTAssertEqual(rawLayer->getIconTextFit(), propertyValue,
- @"Setting iconTextFit to a constant value should update icon-text-fit.");
- XCTAssertEqualObjects(layer.iconTextFit, constantStyleValue,
- @"iconTextFit should round-trip constant values.");
-
- MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.iconTextFit = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::style::IconTextFitType> intervalStops = { {{18, mbgl::style::IconTextFitType::Both}} };
+ @"Setting iconTextFit to a constant value expression should update icon-text-fit.");
+ XCTAssertEqualObjects(layer.iconTextFit, constantExpression,
+ @"iconTextFit should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"'both'"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.iconTextFit = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::style::IconTextFitType> intervalStops = {{
+ { -INFINITY, mbgl::style::IconTextFitType::Both },
+ { 18, mbgl::style::IconTextFitType::Both },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::style::IconTextFitType> { intervalStops };
XCTAssertEqual(rawLayer->getIconTextFit(), propertyValue,
- @"Setting iconTextFit to a camera function should update icon-text-fit.");
- XCTAssertEqualObjects(layer.iconTextFit, functionStyleValue,
- @"iconTextFit should round-trip camera functions.");
+ @"Setting iconTextFit to a camera expression should update icon-text-fit.");
+ XCTAssertEqualObjects(layer.iconTextFit, functionExpression,
+ @"iconTextFit should round-trip camera expressions.");
layer.iconTextFit = nil;
XCTAssertTrue(rawLayer->getIconTextFit().isUndefined(),
@"Unsetting iconTextFit should return icon-text-fit to the default value.");
- XCTAssertEqualObjects(layer.iconTextFit, defaultStyleValue,
+ XCTAssertEqualObjects(layer.iconTextFit, defaultExpression,
@"iconTextFit should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.iconTextFit = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.iconTextFit = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.iconTextFit = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.iconTextFit = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// icon-text-fit-padding
{
XCTAssertTrue(rawLayer->getIconTextFitPadding().isUndefined(),
@"icon-text-fit-padding should be unset initially.");
- MGLStyleValue<NSValue *> *defaultStyleValue = layer.iconTextFitPadding;
+ NSExpression *defaultExpression = layer.iconTextFitPadding;
- MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"%@",
#if TARGET_OS_IPHONE
[NSValue valueWithUIEdgeInsets:UIEdgeInsetsMake(1, 1, 1, 1)]
#else
[NSValue valueWithEdgeInsets:NSEdgeInsetsMake(1, 1, 1, 1)]
#endif
];
- layer.iconTextFitPadding = constantStyleValue;
+ layer.iconTextFitPadding = constantExpression;
mbgl::style::PropertyValue<std::array<float, 4>> propertyValue = { { 1, 1, 1, 1 } };
XCTAssertEqual(rawLayer->getIconTextFitPadding(), propertyValue,
- @"Setting iconTextFitPadding to a constant value should update icon-text-fit-padding.");
- XCTAssertEqualObjects(layer.iconTextFitPadding, constantStyleValue,
- @"iconTextFitPadding should round-trip constant values.");
-
- MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.iconTextFitPadding = functionStyleValue;
-
- mbgl::style::IntervalStops<std::array<float, 4>> intervalStops = { {{18, { 1, 1, 1, 1 }}} };
+ @"Setting iconTextFitPadding to a constant value expression should update icon-text-fit-padding.");
+ XCTAssertEqualObjects(layer.iconTextFitPadding, constantExpression,
+ @"iconTextFitPadding should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"{1, 1, 1, 1}"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.iconTextFitPadding = functionExpression;
+
+ mbgl::style::IntervalStops<std::array<float, 4>> intervalStops = {{
+ { -INFINITY, { 1, 1, 1, 1 } },
+ { 18, { 1, 1, 1, 1 } },
+ }};
propertyValue = mbgl::style::CameraFunction<std::array<float, 4>> { intervalStops };
XCTAssertEqual(rawLayer->getIconTextFitPadding(), propertyValue,
- @"Setting iconTextFitPadding to a camera function should update icon-text-fit-padding.");
- XCTAssertEqualObjects(layer.iconTextFitPadding, functionStyleValue,
- @"iconTextFitPadding should round-trip camera functions.");
+ @"Setting iconTextFitPadding to a camera expression should update icon-text-fit-padding.");
+ XCTAssertEqualObjects(layer.iconTextFitPadding, functionExpression,
+ @"iconTextFitPadding should round-trip camera expressions.");
layer.iconTextFitPadding = nil;
XCTAssertTrue(rawLayer->getIconTextFitPadding().isUndefined(),
@"Unsetting iconTextFitPadding should return icon-text-fit-padding to the default value.");
- XCTAssertEqualObjects(layer.iconTextFitPadding, defaultStyleValue,
+ XCTAssertEqualObjects(layer.iconTextFitPadding, defaultExpression,
@"iconTextFitPadding should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.iconTextFitPadding = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.iconTextFitPadding = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.iconTextFitPadding = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.iconTextFitPadding = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// icon-keep-upright
{
XCTAssertTrue(rawLayer->getIconKeepUpright().isUndefined(),
@"icon-keep-upright should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.keepsIconUpright;
+ NSExpression *defaultExpression = layer.keepsIconUpright;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@YES];
- layer.keepsIconUpright = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"true"];
+ layer.keepsIconUpright = constantExpression;
mbgl::style::PropertyValue<bool> propertyValue = { true };
XCTAssertEqual(rawLayer->getIconKeepUpright(), propertyValue,
- @"Setting keepsIconUpright to a constant value should update icon-keep-upright.");
- XCTAssertEqualObjects(layer.keepsIconUpright, constantStyleValue,
- @"keepsIconUpright should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.keepsIconUpright = functionStyleValue;
-
- mbgl::style::IntervalStops<bool> intervalStops = { {{18, true}} };
+ @"Setting keepsIconUpright to a constant value expression should update icon-keep-upright.");
+ XCTAssertEqualObjects(layer.keepsIconUpright, constantExpression,
+ @"keepsIconUpright should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"true"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.keepsIconUpright = functionExpression;
+
+ mbgl::style::IntervalStops<bool> intervalStops = {{
+ { -INFINITY, true },
+ { 18, true },
+ }};
propertyValue = mbgl::style::CameraFunction<bool> { intervalStops };
XCTAssertEqual(rawLayer->getIconKeepUpright(), propertyValue,
- @"Setting keepsIconUpright to a camera function should update icon-keep-upright.");
- XCTAssertEqualObjects(layer.keepsIconUpright, functionStyleValue,
- @"keepsIconUpright should round-trip camera functions.");
+ @"Setting keepsIconUpright to a camera expression should update icon-keep-upright.");
+ XCTAssertEqualObjects(layer.keepsIconUpright, functionExpression,
+ @"keepsIconUpright should round-trip camera expressions.");
layer.keepsIconUpright = nil;
XCTAssertTrue(rawLayer->getIconKeepUpright().isUndefined(),
@"Unsetting keepsIconUpright should return icon-keep-upright to the default value.");
- XCTAssertEqualObjects(layer.keepsIconUpright, defaultStyleValue,
+ XCTAssertEqualObjects(layer.keepsIconUpright, defaultExpression,
@"keepsIconUpright should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.keepsIconUpright = 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.keepsIconUpright = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.keepsIconUpright = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.keepsIconUpright = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// text-keep-upright
{
XCTAssertTrue(rawLayer->getTextKeepUpright().isUndefined(),
@"text-keep-upright should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.keepsTextUpright;
+ NSExpression *defaultExpression = layer.keepsTextUpright;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@NO];
- layer.keepsTextUpright = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"false"];
+ layer.keepsTextUpright = constantExpression;
mbgl::style::PropertyValue<bool> propertyValue = { false };
XCTAssertEqual(rawLayer->getTextKeepUpright(), propertyValue,
- @"Setting keepsTextUpright to a constant value should update text-keep-upright.");
- XCTAssertEqualObjects(layer.keepsTextUpright, constantStyleValue,
- @"keepsTextUpright should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.keepsTextUpright = functionStyleValue;
-
- mbgl::style::IntervalStops<bool> intervalStops = { {{18, false}} };
+ @"Setting keepsTextUpright to a constant value expression should update text-keep-upright.");
+ XCTAssertEqualObjects(layer.keepsTextUpright, constantExpression,
+ @"keepsTextUpright should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"false"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.keepsTextUpright = functionExpression;
+
+ mbgl::style::IntervalStops<bool> intervalStops = {{
+ { -INFINITY, false },
+ { 18, false },
+ }};
propertyValue = mbgl::style::CameraFunction<bool> { intervalStops };
XCTAssertEqual(rawLayer->getTextKeepUpright(), propertyValue,
- @"Setting keepsTextUpright to a camera function should update text-keep-upright.");
- XCTAssertEqualObjects(layer.keepsTextUpright, functionStyleValue,
- @"keepsTextUpright should round-trip camera functions.");
+ @"Setting keepsTextUpright to a camera expression should update text-keep-upright.");
+ XCTAssertEqualObjects(layer.keepsTextUpright, functionExpression,
+ @"keepsTextUpright should round-trip camera expressions.");
layer.keepsTextUpright = nil;
XCTAssertTrue(rawLayer->getTextKeepUpright().isUndefined(),
@"Unsetting keepsTextUpright should return text-keep-upright to the default value.");
- XCTAssertEqualObjects(layer.keepsTextUpright, defaultStyleValue,
+ XCTAssertEqualObjects(layer.keepsTextUpright, defaultExpression,
@"keepsTextUpright should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.keepsTextUpright = 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.keepsTextUpright = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.keepsTextUpright = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.keepsTextUpright = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// text-max-angle
{
XCTAssertTrue(rawLayer->getTextMaxAngle().isUndefined(),
@"text-max-angle should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.maximumTextAngle;
+ NSExpression *defaultExpression = layer.maximumTextAngle;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.maximumTextAngle = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.maximumTextAngle = constantExpression;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getTextMaxAngle(), propertyValue,
- @"Setting maximumTextAngle to a constant value should update text-max-angle.");
- XCTAssertEqualObjects(layer.maximumTextAngle, constantStyleValue,
- @"maximumTextAngle should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.maximumTextAngle = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting maximumTextAngle to a constant value expression should update text-max-angle.");
+ XCTAssertEqualObjects(layer.maximumTextAngle, constantExpression,
+ @"maximumTextAngle should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.maximumTextAngle = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getTextMaxAngle(), propertyValue,
- @"Setting maximumTextAngle to a camera function should update text-max-angle.");
- XCTAssertEqualObjects(layer.maximumTextAngle, functionStyleValue,
- @"maximumTextAngle should round-trip camera functions.");
+ @"Setting maximumTextAngle to a camera expression should update text-max-angle.");
+ XCTAssertEqualObjects(layer.maximumTextAngle, functionExpression,
+ @"maximumTextAngle should round-trip camera expressions.");
layer.maximumTextAngle = nil;
XCTAssertTrue(rawLayer->getTextMaxAngle().isUndefined(),
@"Unsetting maximumTextAngle should return text-max-angle to the default value.");
- XCTAssertEqualObjects(layer.maximumTextAngle, defaultStyleValue,
+ XCTAssertEqualObjects(layer.maximumTextAngle, defaultExpression,
@"maximumTextAngle should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.maximumTextAngle = 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.maximumTextAngle = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.maximumTextAngle = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.maximumTextAngle = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// text-max-width
{
XCTAssertTrue(rawLayer->getTextMaxWidth().isUndefined(),
@"text-max-width should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.maximumTextWidth;
+ NSExpression *defaultExpression = layer.maximumTextWidth;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.maximumTextWidth = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.maximumTextWidth = constantExpression;
mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getTextMaxWidth(), propertyValue,
- @"Setting maximumTextWidth to a constant value should update text-max-width.");
- XCTAssertEqualObjects(layer.maximumTextWidth, constantStyleValue,
- @"maximumTextWidth should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.maximumTextWidth = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting maximumTextWidth to a constant value expression should update text-max-width.");
+ XCTAssertEqualObjects(layer.maximumTextWidth, constantExpression,
+ @"maximumTextWidth should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.maximumTextWidth = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getTextMaxWidth(), propertyValue,
- @"Setting maximumTextWidth to a camera function should update text-max-width.");
- XCTAssertEqualObjects(layer.maximumTextWidth, functionStyleValue,
- @"maximumTextWidth should round-trip camera functions.");
+ @"Setting maximumTextWidth to a camera expression should update text-max-width.");
+ XCTAssertEqualObjects(layer.maximumTextWidth, functionExpression,
+ @"maximumTextWidth should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.maximumTextWidth = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.maximumTextWidth = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getTextMaxWidth(), propertyValue,
- @"Setting maximumTextWidth to a source function should update text-max-width.");
- XCTAssertEqualObjects(layer.maximumTextWidth, functionStyleValue,
- @"maximumTextWidth should round-trip source functions.");
+ @"Setting maximumTextWidth to a data expression should update text-max-width.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.maximumTextWidth, pedanticFunctionExpression,
+ @"maximumTextWidth should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.maximumTextWidth = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.maximumTextWidth = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -773,15 +859,16 @@
propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getTextMaxWidth(), propertyValue,
- @"Setting maximumTextWidth to a composite function should update text-max-width.");
- XCTAssertEqualObjects(layer.maximumTextWidth, functionStyleValue,
- @"maximumTextWidth should round-trip composite functions.");
+ @"Setting maximumTextWidth to a camera-data expression should update text-max-width.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.maximumTextWidth, pedanticFunctionExpression,
+ @"maximumTextWidth should round-trip camera-data expressions.");
layer.maximumTextWidth = nil;
XCTAssertTrue(rawLayer->getTextMaxWidth().isUndefined(),
@"Unsetting maximumTextWidth should return text-max-width to the default value.");
- XCTAssertEqualObjects(layer.maximumTextWidth, defaultStyleValue,
+ XCTAssertEqualObjects(layer.maximumTextWidth, defaultExpression,
@"maximumTextWidth should return the default value after being unset.");
}
@@ -789,150 +876,169 @@
{
XCTAssertTrue(rawLayer->getSymbolAvoidEdges().isUndefined(),
@"symbol-avoid-edges should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.symbolAvoidsEdges;
+ NSExpression *defaultExpression = layer.symbolAvoidsEdges;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@YES];
- layer.symbolAvoidsEdges = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"true"];
+ layer.symbolAvoidsEdges = constantExpression;
mbgl::style::PropertyValue<bool> propertyValue = { true };
XCTAssertEqual(rawLayer->getSymbolAvoidEdges(), propertyValue,
- @"Setting symbolAvoidsEdges to a constant value should update symbol-avoid-edges.");
- XCTAssertEqualObjects(layer.symbolAvoidsEdges, constantStyleValue,
- @"symbolAvoidsEdges should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.symbolAvoidsEdges = functionStyleValue;
-
- mbgl::style::IntervalStops<bool> intervalStops = { {{18, true}} };
+ @"Setting symbolAvoidsEdges to a constant value expression should update symbol-avoid-edges.");
+ XCTAssertEqualObjects(layer.symbolAvoidsEdges, constantExpression,
+ @"symbolAvoidsEdges should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"true"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.symbolAvoidsEdges = functionExpression;
+
+ mbgl::style::IntervalStops<bool> intervalStops = {{
+ { -INFINITY, true },
+ { 18, true },
+ }};
propertyValue = mbgl::style::CameraFunction<bool> { intervalStops };
XCTAssertEqual(rawLayer->getSymbolAvoidEdges(), propertyValue,
- @"Setting symbolAvoidsEdges to a camera function should update symbol-avoid-edges.");
- XCTAssertEqualObjects(layer.symbolAvoidsEdges, functionStyleValue,
- @"symbolAvoidsEdges should round-trip camera functions.");
+ @"Setting symbolAvoidsEdges to a camera expression should update symbol-avoid-edges.");
+ XCTAssertEqualObjects(layer.symbolAvoidsEdges, functionExpression,
+ @"symbolAvoidsEdges should round-trip camera expressions.");
layer.symbolAvoidsEdges = nil;
XCTAssertTrue(rawLayer->getSymbolAvoidEdges().isUndefined(),
@"Unsetting symbolAvoidsEdges should return symbol-avoid-edges to the default value.");
- XCTAssertEqualObjects(layer.symbolAvoidsEdges, defaultStyleValue,
+ XCTAssertEqualObjects(layer.symbolAvoidsEdges, defaultExpression,
@"symbolAvoidsEdges should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.symbolAvoidsEdges = 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.symbolAvoidsEdges = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.symbolAvoidsEdges = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.symbolAvoidsEdges = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// symbol-placement
{
XCTAssertTrue(rawLayer->getSymbolPlacement().isUndefined(),
@"symbol-placement should be unset initially.");
- MGLStyleValue<NSValue *> *defaultStyleValue = layer.symbolPlacement;
+ NSExpression *defaultExpression = layer.symbolPlacement;
- MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLSymbolPlacement:MGLSymbolPlacementLine]];
- layer.symbolPlacement = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'line'"];
+ layer.symbolPlacement = constantExpression;
mbgl::style::PropertyValue<mbgl::style::SymbolPlacementType> propertyValue = { mbgl::style::SymbolPlacementType::Line };
XCTAssertEqual(rawLayer->getSymbolPlacement(), propertyValue,
- @"Setting symbolPlacement to a constant value should update symbol-placement.");
- XCTAssertEqualObjects(layer.symbolPlacement, constantStyleValue,
- @"symbolPlacement should round-trip constant values.");
-
- MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.symbolPlacement = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::style::SymbolPlacementType> intervalStops = { {{18, mbgl::style::SymbolPlacementType::Line}} };
+ @"Setting symbolPlacement to a constant value expression should update symbol-placement.");
+ XCTAssertEqualObjects(layer.symbolPlacement, constantExpression,
+ @"symbolPlacement should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"'line'"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.symbolPlacement = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::style::SymbolPlacementType> intervalStops = {{
+ { -INFINITY, mbgl::style::SymbolPlacementType::Line },
+ { 18, mbgl::style::SymbolPlacementType::Line },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::style::SymbolPlacementType> { intervalStops };
XCTAssertEqual(rawLayer->getSymbolPlacement(), propertyValue,
- @"Setting symbolPlacement to a camera function should update symbol-placement.");
- XCTAssertEqualObjects(layer.symbolPlacement, functionStyleValue,
- @"symbolPlacement should round-trip camera functions.");
+ @"Setting symbolPlacement to a camera expression should update symbol-placement.");
+ XCTAssertEqualObjects(layer.symbolPlacement, functionExpression,
+ @"symbolPlacement should round-trip camera expressions.");
layer.symbolPlacement = nil;
XCTAssertTrue(rawLayer->getSymbolPlacement().isUndefined(),
@"Unsetting symbolPlacement should return symbol-placement to the default value.");
- XCTAssertEqualObjects(layer.symbolPlacement, defaultStyleValue,
+ XCTAssertEqualObjects(layer.symbolPlacement, defaultExpression,
@"symbolPlacement should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.symbolPlacement = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.symbolPlacement = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.symbolPlacement = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.symbolPlacement = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// symbol-spacing
{
XCTAssertTrue(rawLayer->getSymbolSpacing().isUndefined(),
@"symbol-spacing should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.symbolSpacing;
+ NSExpression *defaultExpression = layer.symbolSpacing;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.symbolSpacing = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.symbolSpacing = constantExpression;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getSymbolSpacing(), propertyValue,
- @"Setting symbolSpacing to a constant value should update symbol-spacing.");
- XCTAssertEqualObjects(layer.symbolSpacing, constantStyleValue,
- @"symbolSpacing should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.symbolSpacing = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting symbolSpacing to a constant value expression should update symbol-spacing.");
+ XCTAssertEqualObjects(layer.symbolSpacing, constantExpression,
+ @"symbolSpacing should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.symbolSpacing = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getSymbolSpacing(), propertyValue,
- @"Setting symbolSpacing to a camera function should update symbol-spacing.");
- XCTAssertEqualObjects(layer.symbolSpacing, functionStyleValue,
- @"symbolSpacing should round-trip camera functions.");
+ @"Setting symbolSpacing to a camera expression should update symbol-spacing.");
+ XCTAssertEqualObjects(layer.symbolSpacing, functionExpression,
+ @"symbolSpacing should round-trip camera expressions.");
layer.symbolSpacing = nil;
XCTAssertTrue(rawLayer->getSymbolSpacing().isUndefined(),
@"Unsetting symbolSpacing should return symbol-spacing to the default value.");
- XCTAssertEqualObjects(layer.symbolSpacing, defaultStyleValue,
+ XCTAssertEqualObjects(layer.symbolSpacing, defaultExpression,
@"symbolSpacing should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.symbolSpacing = 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.symbolSpacing = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.symbolSpacing = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.symbolSpacing = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// text-field
{
XCTAssertTrue(rawLayer->getTextField().isUndefined(),
@"text-field should be unset initially.");
- MGLStyleValue<NSString *> *defaultStyleValue = layer.text;
+ NSExpression *defaultExpression = layer.text;
- MGLStyleValue<NSString *> *constantStyleValue = [MGLStyleValue<NSString *> valueWithRawValue:@"Text Field"];
- layer.text = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'Text Field'"];
+ layer.text = constantExpression;
mbgl::style::DataDrivenPropertyValue<std::string> propertyValue = { "Text Field" };
XCTAssertEqual(rawLayer->getTextField(), propertyValue,
- @"Setting text to a constant value should update text-field.");
- XCTAssertEqualObjects(layer.text, constantStyleValue,
- @"text should round-trip constant values.");
-
- MGLStyleValue<NSString *> * functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.text = functionStyleValue;
-
- mbgl::style::IntervalStops<std::string> intervalStops = { {{18, "Text Field"}} };
+ @"Setting text to a constant value expression should update text-field.");
+ XCTAssertEqualObjects(layer.text, constantExpression,
+ @"text should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"'Text Field'"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.text = functionExpression;
+
+ mbgl::style::IntervalStops<std::string> intervalStops = {{
+ { -INFINITY, "Text Field" },
+ { 18, "Text Field" },
+ }};
propertyValue = mbgl::style::CameraFunction<std::string> { intervalStops };
XCTAssertEqual(rawLayer->getTextField(), propertyValue,
- @"Setting text to a camera function should update text-field.");
- XCTAssertEqualObjects(layer.text, functionStyleValue,
- @"text should round-trip camera functions.");
+ @"Setting text to a camera expression should update text-field.");
+ XCTAssertEqualObjects(layer.text, functionExpression,
+ @"text should round-trip camera expressions.");
layer.text = nil;
XCTAssertTrue(rawLayer->getTextField().isUndefined(),
@"Unsetting text should return text-field to the default value.");
- XCTAssertEqualObjects(layer.text, defaultStyleValue,
+ XCTAssertEqualObjects(layer.text, defaultExpression,
@"text should return the default value after being unset.");
}
@@ -940,72 +1046,81 @@
{
XCTAssertTrue(rawLayer->getTextAllowOverlap().isUndefined(),
@"text-allow-overlap should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.textAllowsOverlap;
+ NSExpression *defaultExpression = layer.textAllowsOverlap;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@YES];
- layer.textAllowsOverlap = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"true"];
+ layer.textAllowsOverlap = constantExpression;
mbgl::style::PropertyValue<bool> propertyValue = { true };
XCTAssertEqual(rawLayer->getTextAllowOverlap(), propertyValue,
- @"Setting textAllowsOverlap to a constant value should update text-allow-overlap.");
- XCTAssertEqualObjects(layer.textAllowsOverlap, constantStyleValue,
- @"textAllowsOverlap should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.textAllowsOverlap = functionStyleValue;
-
- mbgl::style::IntervalStops<bool> intervalStops = { {{18, true}} };
+ @"Setting textAllowsOverlap to a constant value expression should update text-allow-overlap.");
+ XCTAssertEqualObjects(layer.textAllowsOverlap, constantExpression,
+ @"textAllowsOverlap should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"true"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.textAllowsOverlap = functionExpression;
+
+ mbgl::style::IntervalStops<bool> intervalStops = {{
+ { -INFINITY, true },
+ { 18, true },
+ }};
propertyValue = mbgl::style::CameraFunction<bool> { intervalStops };
XCTAssertEqual(rawLayer->getTextAllowOverlap(), propertyValue,
- @"Setting textAllowsOverlap to a camera function should update text-allow-overlap.");
- XCTAssertEqualObjects(layer.textAllowsOverlap, functionStyleValue,
- @"textAllowsOverlap should round-trip camera functions.");
+ @"Setting textAllowsOverlap to a camera expression should update text-allow-overlap.");
+ XCTAssertEqualObjects(layer.textAllowsOverlap, functionExpression,
+ @"textAllowsOverlap should round-trip camera expressions.");
layer.textAllowsOverlap = nil;
XCTAssertTrue(rawLayer->getTextAllowOverlap().isUndefined(),
@"Unsetting textAllowsOverlap should return text-allow-overlap to the default value.");
- XCTAssertEqualObjects(layer.textAllowsOverlap, defaultStyleValue,
+ XCTAssertEqualObjects(layer.textAllowsOverlap, defaultExpression,
@"textAllowsOverlap should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.textAllowsOverlap = 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.textAllowsOverlap = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.textAllowsOverlap = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.textAllowsOverlap = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// text-anchor
{
XCTAssertTrue(rawLayer->getTextAnchor().isUndefined(),
@"text-anchor should be unset initially.");
- MGLStyleValue<NSValue *> *defaultStyleValue = layer.textAnchor;
+ NSExpression *defaultExpression = layer.textAnchor;
- MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLTextAnchor:MGLTextAnchorBottomRight]];
- layer.textAnchor = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'bottom-right'"];
+ layer.textAnchor = constantExpression;
mbgl::style::DataDrivenPropertyValue<mbgl::style::SymbolAnchorType> propertyValue = { mbgl::style::SymbolAnchorType::BottomRight };
XCTAssertEqual(rawLayer->getTextAnchor(), propertyValue,
- @"Setting textAnchor to a constant value should update text-anchor.");
- XCTAssertEqualObjects(layer.textAnchor, constantStyleValue,
- @"textAnchor should round-trip constant values.");
-
- MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.textAnchor = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::style::SymbolAnchorType> intervalStops = { {{18, mbgl::style::SymbolAnchorType::BottomRight}} };
+ @"Setting textAnchor to a constant value expression should update text-anchor.");
+ XCTAssertEqualObjects(layer.textAnchor, constantExpression,
+ @"textAnchor should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"'bottom-right'"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.textAnchor = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::style::SymbolAnchorType> intervalStops = {{
+ { -INFINITY, mbgl::style::SymbolAnchorType::BottomRight },
+ { 18, mbgl::style::SymbolAnchorType::BottomRight },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::style::SymbolAnchorType> { intervalStops };
XCTAssertEqual(rawLayer->getTextAnchor(), propertyValue,
- @"Setting textAnchor to a camera function should update text-anchor.");
- XCTAssertEqualObjects(layer.textAnchor, functionStyleValue,
- @"textAnchor should round-trip camera functions.");
+ @"Setting textAnchor to a camera expression should update text-anchor.");
+ XCTAssertEqualObjects(layer.textAnchor, functionExpression,
+ @"textAnchor should round-trip camera expressions.");
layer.textAnchor = nil;
XCTAssertTrue(rawLayer->getTextAnchor().isUndefined(),
@"Unsetting textAnchor should return text-anchor to the default value.");
- XCTAssertEqualObjects(layer.textAnchor, defaultStyleValue,
+ XCTAssertEqualObjects(layer.textAnchor, defaultExpression,
@"textAnchor should return the default value after being unset.");
}
@@ -1013,79 +1128,83 @@
{
XCTAssertTrue(rawLayer->getTextFont().isUndefined(),
@"text-font should be unset initially.");
- MGLStyleValue<NSArray<NSString *> *> *defaultStyleValue = layer.textFontNames;
+ NSExpression *defaultExpression = layer.textFontNames;
- MGLStyleValue<NSArray<NSString *> *> *constantStyleValue = [MGLStyleValue<NSArray<NSString *> *> valueWithRawValue:@[@"Text Font", @"Tnof Txet"]];
- layer.textFontNames = constantStyleValue;
- mbgl::style::PropertyValue<std::vector<std::string>> propertyValue = { { "Text Font", "Tnof Txet" } };
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"{'Text Font', 'Tnof Txet'}"];
+ layer.textFontNames = constantExpression;
+ mbgl::style::DataDrivenPropertyValue<std::vector<std::string>> propertyValue = { { "Text Font", "Tnof Txet" } };
XCTAssertEqual(rawLayer->getTextFont(), propertyValue,
- @"Setting textFontNames to a constant value should update text-font.");
- XCTAssertEqualObjects(layer.textFontNames, constantStyleValue,
- @"textFontNames should round-trip constant values.");
-
- MGLStyleValue<NSArray<NSString *> *> * functionStyleValue = [MGLStyleValue<NSArray<NSString *> *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.textFontNames = functionStyleValue;
-
- mbgl::style::IntervalStops<std::vector<std::string>> intervalStops = { {{18, { "Text Font", "Tnof Txet" }}} };
+ @"Setting textFontNames to a constant value expression should update text-font.");
+ XCTAssertEqualObjects(layer.textFontNames, constantExpression,
+ @"textFontNames should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"{'Text Font', 'Tnof Txet'}"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.textFontNames = functionExpression;
+
+ mbgl::style::IntervalStops<std::vector<std::string>> intervalStops = {{
+ { -INFINITY, { "Text Font", "Tnof Txet" } },
+ { 18, { "Text Font", "Tnof Txet" } },
+ }};
propertyValue = mbgl::style::CameraFunction<std::vector<std::string>> { intervalStops };
XCTAssertEqual(rawLayer->getTextFont(), propertyValue,
- @"Setting textFontNames to a camera function should update text-font.");
- XCTAssertEqualObjects(layer.textFontNames, functionStyleValue,
- @"textFontNames should round-trip camera functions.");
+ @"Setting textFontNames to a camera expression should update text-font.");
+ XCTAssertEqualObjects(layer.textFontNames, functionExpression,
+ @"textFontNames should round-trip camera expressions.");
layer.textFontNames = nil;
XCTAssertTrue(rawLayer->getTextFont().isUndefined(),
@"Unsetting textFontNames should return text-font to the default value.");
- XCTAssertEqualObjects(layer.textFontNames, defaultStyleValue,
+ XCTAssertEqualObjects(layer.textFontNames, defaultExpression,
@"textFontNames should return the default value after being unset.");
-
- functionStyleValue = [MGLStyleValue<NSArray<NSString *> *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.textFontNames = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSArray<NSString *> *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.textFontNames = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
// text-size
{
XCTAssertTrue(rawLayer->getTextSize().isUndefined(),
@"text-size should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.textFontSize;
+ NSExpression *defaultExpression = layer.textFontSize;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.textFontSize = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.textFontSize = constantExpression;
mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getTextSize(), propertyValue,
- @"Setting textFontSize to a constant value should update text-size.");
- XCTAssertEqualObjects(layer.textFontSize, constantStyleValue,
- @"textFontSize should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.textFontSize = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting textFontSize to a constant value expression should update text-size.");
+ XCTAssertEqualObjects(layer.textFontSize, constantExpression,
+ @"textFontSize should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.textFontSize = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getTextSize(), propertyValue,
- @"Setting textFontSize to a camera function should update text-size.");
- XCTAssertEqualObjects(layer.textFontSize, functionStyleValue,
- @"textFontSize should round-trip camera functions.");
+ @"Setting textFontSize to a camera expression should update text-size.");
+ XCTAssertEqualObjects(layer.textFontSize, functionExpression,
+ @"textFontSize should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.textFontSize = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.textFontSize = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getTextSize(), propertyValue,
- @"Setting textFontSize to a source function should update text-size.");
- XCTAssertEqualObjects(layer.textFontSize, functionStyleValue,
- @"textFontSize should round-trip source functions.");
+ @"Setting textFontSize to a data expression should update text-size.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.textFontSize, pedanticFunctionExpression,
+ @"textFontSize should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.textFontSize = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.textFontSize = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -1093,15 +1212,16 @@
propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getTextSize(), propertyValue,
- @"Setting textFontSize to a composite function should update text-size.");
- XCTAssertEqualObjects(layer.textFontSize, functionStyleValue,
- @"textFontSize should round-trip composite functions.");
+ @"Setting textFontSize to a camera-data expression should update text-size.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.textFontSize, pedanticFunctionExpression,
+ @"textFontSize should round-trip camera-data expressions.");
layer.textFontSize = nil;
XCTAssertTrue(rawLayer->getTextSize().isUndefined(),
@"Unsetting textFontSize should return text-size to the default value.");
- XCTAssertEqualObjects(layer.textFontSize, defaultStyleValue,
+ XCTAssertEqualObjects(layer.textFontSize, defaultExpression,
@"textFontSize should return the default value after being unset.");
}
@@ -1109,72 +1229,81 @@
{
XCTAssertTrue(rawLayer->getTextIgnorePlacement().isUndefined(),
@"text-ignore-placement should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.textIgnoresPlacement;
+ NSExpression *defaultExpression = layer.textIgnoresPlacement;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@YES];
- layer.textIgnoresPlacement = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"true"];
+ layer.textIgnoresPlacement = constantExpression;
mbgl::style::PropertyValue<bool> propertyValue = { true };
XCTAssertEqual(rawLayer->getTextIgnorePlacement(), propertyValue,
- @"Setting textIgnoresPlacement to a constant value should update text-ignore-placement.");
- XCTAssertEqualObjects(layer.textIgnoresPlacement, constantStyleValue,
- @"textIgnoresPlacement should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.textIgnoresPlacement = functionStyleValue;
-
- mbgl::style::IntervalStops<bool> intervalStops = { {{18, true}} };
+ @"Setting textIgnoresPlacement to a constant value expression should update text-ignore-placement.");
+ XCTAssertEqualObjects(layer.textIgnoresPlacement, constantExpression,
+ @"textIgnoresPlacement should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"true"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.textIgnoresPlacement = functionExpression;
+
+ mbgl::style::IntervalStops<bool> intervalStops = {{
+ { -INFINITY, true },
+ { 18, true },
+ }};
propertyValue = mbgl::style::CameraFunction<bool> { intervalStops };
XCTAssertEqual(rawLayer->getTextIgnorePlacement(), propertyValue,
- @"Setting textIgnoresPlacement to a camera function should update text-ignore-placement.");
- XCTAssertEqualObjects(layer.textIgnoresPlacement, functionStyleValue,
- @"textIgnoresPlacement should round-trip camera functions.");
+ @"Setting textIgnoresPlacement to a camera expression should update text-ignore-placement.");
+ XCTAssertEqualObjects(layer.textIgnoresPlacement, functionExpression,
+ @"textIgnoresPlacement should round-trip camera expressions.");
layer.textIgnoresPlacement = nil;
XCTAssertTrue(rawLayer->getTextIgnorePlacement().isUndefined(),
@"Unsetting textIgnoresPlacement should return text-ignore-placement to the default value.");
- XCTAssertEqualObjects(layer.textIgnoresPlacement, defaultStyleValue,
+ XCTAssertEqualObjects(layer.textIgnoresPlacement, defaultExpression,
@"textIgnoresPlacement should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.textIgnoresPlacement = 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.textIgnoresPlacement = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.textIgnoresPlacement = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.textIgnoresPlacement = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// text-justify
{
XCTAssertTrue(rawLayer->getTextJustify().isUndefined(),
@"text-justify should be unset initially.");
- MGLStyleValue<NSValue *> *defaultStyleValue = layer.textJustification;
+ NSExpression *defaultExpression = layer.textJustification;
- MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLTextJustification:MGLTextJustificationRight]];
- layer.textJustification = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'right'"];
+ layer.textJustification = constantExpression;
mbgl::style::DataDrivenPropertyValue<mbgl::style::TextJustifyType> propertyValue = { mbgl::style::TextJustifyType::Right };
XCTAssertEqual(rawLayer->getTextJustify(), propertyValue,
- @"Setting textJustification to a constant value should update text-justify.");
- XCTAssertEqualObjects(layer.textJustification, constantStyleValue,
- @"textJustification should round-trip constant values.");
-
- MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.textJustification = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::style::TextJustifyType> intervalStops = { {{18, mbgl::style::TextJustifyType::Right}} };
+ @"Setting textJustification to a constant value expression should update text-justify.");
+ XCTAssertEqualObjects(layer.textJustification, constantExpression,
+ @"textJustification should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"'right'"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.textJustification = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::style::TextJustifyType> intervalStops = {{
+ { -INFINITY, mbgl::style::TextJustifyType::Right },
+ { 18, mbgl::style::TextJustifyType::Right },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::style::TextJustifyType> { intervalStops };
XCTAssertEqual(rawLayer->getTextJustify(), propertyValue,
- @"Setting textJustification to a camera function should update text-justify.");
- XCTAssertEqualObjects(layer.textJustification, functionStyleValue,
- @"textJustification should round-trip camera functions.");
+ @"Setting textJustification to a camera expression should update text-justify.");
+ XCTAssertEqualObjects(layer.textJustification, functionExpression,
+ @"textJustification should round-trip camera expressions.");
layer.textJustification = nil;
XCTAssertTrue(rawLayer->getTextJustify().isUndefined(),
@"Unsetting textJustification should return text-justify to the default value.");
- XCTAssertEqualObjects(layer.textJustification, defaultStyleValue,
+ XCTAssertEqualObjects(layer.textJustification, defaultExpression,
@"textJustification should return the default value after being unset.");
}
@@ -1182,40 +1311,45 @@
{
XCTAssertTrue(rawLayer->getTextLetterSpacing().isUndefined(),
@"text-letter-spacing should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.textLetterSpacing;
+ NSExpression *defaultExpression = layer.textLetterSpacing;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.textLetterSpacing = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.textLetterSpacing = constantExpression;
mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getTextLetterSpacing(), propertyValue,
- @"Setting textLetterSpacing to a constant value should update text-letter-spacing.");
- XCTAssertEqualObjects(layer.textLetterSpacing, constantStyleValue,
- @"textLetterSpacing should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.textLetterSpacing = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting textLetterSpacing to a constant value expression should update text-letter-spacing.");
+ XCTAssertEqualObjects(layer.textLetterSpacing, constantExpression,
+ @"textLetterSpacing should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.textLetterSpacing = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getTextLetterSpacing(), propertyValue,
- @"Setting textLetterSpacing to a camera function should update text-letter-spacing.");
- XCTAssertEqualObjects(layer.textLetterSpacing, functionStyleValue,
- @"textLetterSpacing should round-trip camera functions.");
+ @"Setting textLetterSpacing to a camera expression should update text-letter-spacing.");
+ XCTAssertEqualObjects(layer.textLetterSpacing, functionExpression,
+ @"textLetterSpacing should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.textLetterSpacing = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.textLetterSpacing = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getTextLetterSpacing(), propertyValue,
- @"Setting textLetterSpacing to a source function should update text-letter-spacing.");
- XCTAssertEqualObjects(layer.textLetterSpacing, functionStyleValue,
- @"textLetterSpacing should round-trip source functions.");
+ @"Setting textLetterSpacing to a data expression should update text-letter-spacing.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.textLetterSpacing, pedanticFunctionExpression,
+ @"textLetterSpacing should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.textLetterSpacing = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.textLetterSpacing = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -1223,15 +1357,16 @@
propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getTextLetterSpacing(), propertyValue,
- @"Setting textLetterSpacing to a composite function should update text-letter-spacing.");
- XCTAssertEqualObjects(layer.textLetterSpacing, functionStyleValue,
- @"textLetterSpacing should round-trip composite functions.");
+ @"Setting textLetterSpacing to a camera-data expression should update text-letter-spacing.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.textLetterSpacing, pedanticFunctionExpression,
+ @"textLetterSpacing should round-trip camera-data expressions.");
layer.textLetterSpacing = nil;
XCTAssertTrue(rawLayer->getTextLetterSpacing().isUndefined(),
@"Unsetting textLetterSpacing should return text-letter-spacing to the default value.");
- XCTAssertEqualObjects(layer.textLetterSpacing, defaultStyleValue,
+ XCTAssertEqualObjects(layer.textLetterSpacing, defaultExpression,
@"textLetterSpacing should return the default value after being unset.");
}
@@ -1239,85 +1374,95 @@
{
XCTAssertTrue(rawLayer->getTextLineHeight().isUndefined(),
@"text-line-height should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.textLineHeight;
+ NSExpression *defaultExpression = layer.textLineHeight;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.textLineHeight = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.textLineHeight = constantExpression;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getTextLineHeight(), propertyValue,
- @"Setting textLineHeight to a constant value should update text-line-height.");
- XCTAssertEqualObjects(layer.textLineHeight, constantStyleValue,
- @"textLineHeight should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.textLineHeight = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting textLineHeight to a constant value expression should update text-line-height.");
+ XCTAssertEqualObjects(layer.textLineHeight, constantExpression,
+ @"textLineHeight should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.textLineHeight = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getTextLineHeight(), propertyValue,
- @"Setting textLineHeight to a camera function should update text-line-height.");
- XCTAssertEqualObjects(layer.textLineHeight, functionStyleValue,
- @"textLineHeight should round-trip camera functions.");
+ @"Setting textLineHeight to a camera expression should update text-line-height.");
+ XCTAssertEqualObjects(layer.textLineHeight, functionExpression,
+ @"textLineHeight should round-trip camera expressions.");
layer.textLineHeight = nil;
XCTAssertTrue(rawLayer->getTextLineHeight().isUndefined(),
@"Unsetting textLineHeight should return text-line-height to the default value.");
- XCTAssertEqualObjects(layer.textLineHeight, defaultStyleValue,
+ XCTAssertEqualObjects(layer.textLineHeight, defaultExpression,
@"textLineHeight should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.textLineHeight = 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.textLineHeight = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.textLineHeight = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.textLineHeight = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// text-offset
{
XCTAssertTrue(rawLayer->getTextOffset().isUndefined(),
@"text-offset should be unset initially.");
- MGLStyleValue<NSValue *> *defaultStyleValue = layer.textOffset;
+ NSExpression *defaultExpression = layer.textOffset;
- MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"%@",
#if TARGET_OS_IPHONE
[NSValue valueWithCGVector:CGVectorMake(1, 1)]
#else
[NSValue valueWithMGLVector:CGVectorMake(1, -1)]
#endif
];
- layer.textOffset = constantStyleValue;
+ layer.textOffset = constantExpression;
mbgl::style::DataDrivenPropertyValue<std::array<float, 2>> propertyValue = { { 1, 1 } };
XCTAssertEqual(rawLayer->getTextOffset(), propertyValue,
- @"Setting textOffset to a constant value should update text-offset.");
- XCTAssertEqualObjects(layer.textOffset, constantStyleValue,
- @"textOffset should round-trip constant values.");
-
- MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.textOffset = functionStyleValue;
-
- mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = { {{18, { 1, 1 }}} };
+ @"Setting textOffset to a constant value expression should update text-offset.");
+ XCTAssertEqualObjects(layer.textOffset, constantExpression,
+ @"textOffset should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"{1, 1}"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.textOffset = functionExpression;
+
+ mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = {{
+ { -INFINITY, { 1, 1 } },
+ { 18, { 1, 1 } },
+ }};
propertyValue = mbgl::style::CameraFunction<std::array<float, 2>> { intervalStops };
XCTAssertEqual(rawLayer->getTextOffset(), propertyValue,
- @"Setting textOffset to a camera function should update text-offset.");
- XCTAssertEqualObjects(layer.textOffset, functionStyleValue,
- @"textOffset should round-trip camera functions.");
+ @"Setting textOffset to a camera expression should update text-offset.");
+ XCTAssertEqualObjects(layer.textOffset, functionExpression,
+ @"textOffset should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.textOffset = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.textOffset = functionExpression;
mbgl::style::ExponentialStops<std::array<float, 2>> exponentialStops = { {{18, { 1, 1 }}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<std::array<float, 2>> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getTextOffset(), propertyValue,
- @"Setting textOffset to a source function should update text-offset.");
- XCTAssertEqualObjects(layer.textOffset, functionStyleValue,
- @"textOffset should round-trip source functions.");
+ @"Setting textOffset to a data expression should update text-offset.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.textOffset, pedanticFunctionExpression,
+ @"textOffset should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.textOffset = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.textOffset = functionExpression;
std::map<float, std::array<float, 2>> innerStops { {18, { 1, 1 }} };
mbgl::style::CompositeExponentialStops<std::array<float, 2>> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -1325,15 +1470,16 @@
propertyValue = mbgl::style::CompositeFunction<std::array<float, 2>> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getTextOffset(), propertyValue,
- @"Setting textOffset to a composite function should update text-offset.");
- XCTAssertEqualObjects(layer.textOffset, functionStyleValue,
- @"textOffset should round-trip composite functions.");
+ @"Setting textOffset to a camera-data expression should update text-offset.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.textOffset, pedanticFunctionExpression,
+ @"textOffset should round-trip camera-data expressions.");
layer.textOffset = nil;
XCTAssertTrue(rawLayer->getTextOffset().isUndefined(),
@"Unsetting textOffset should return text-offset to the default value.");
- XCTAssertEqualObjects(layer.textOffset, defaultStyleValue,
+ XCTAssertEqualObjects(layer.textOffset, defaultExpression,
@"textOffset should return the default value after being unset.");
}
@@ -1341,157 +1487,177 @@
{
XCTAssertTrue(rawLayer->getTextOptional().isUndefined(),
@"text-optional should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.textOptional;
+ NSExpression *defaultExpression = layer.textOptional;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@YES];
- layer.textOptional = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"true"];
+ layer.textOptional = constantExpression;
mbgl::style::PropertyValue<bool> propertyValue = { true };
XCTAssertEqual(rawLayer->getTextOptional(), propertyValue,
- @"Setting textOptional to a constant value should update text-optional.");
- XCTAssertEqualObjects(layer.textOptional, constantStyleValue,
- @"textOptional should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.textOptional = functionStyleValue;
-
- mbgl::style::IntervalStops<bool> intervalStops = { {{18, true}} };
+ @"Setting textOptional to a constant value expression should update text-optional.");
+ XCTAssertEqualObjects(layer.textOptional, constantExpression,
+ @"textOptional should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"true"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.textOptional = functionExpression;
+
+ mbgl::style::IntervalStops<bool> intervalStops = {{
+ { -INFINITY, true },
+ { 18, true },
+ }};
propertyValue = mbgl::style::CameraFunction<bool> { intervalStops };
XCTAssertEqual(rawLayer->getTextOptional(), propertyValue,
- @"Setting textOptional to a camera function should update text-optional.");
- XCTAssertEqualObjects(layer.textOptional, functionStyleValue,
- @"textOptional should round-trip camera functions.");
+ @"Setting textOptional to a camera expression should update text-optional.");
+ XCTAssertEqualObjects(layer.textOptional, functionExpression,
+ @"textOptional should round-trip camera expressions.");
layer.textOptional = nil;
XCTAssertTrue(rawLayer->getTextOptional().isUndefined(),
@"Unsetting textOptional should return text-optional to the default value.");
- XCTAssertEqualObjects(layer.textOptional, defaultStyleValue,
+ XCTAssertEqualObjects(layer.textOptional, defaultExpression,
@"textOptional should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.textOptional = 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.textOptional = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.textOptional = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.textOptional = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// text-padding
{
XCTAssertTrue(rawLayer->getTextPadding().isUndefined(),
@"text-padding should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.textPadding;
+ NSExpression *defaultExpression = layer.textPadding;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.textPadding = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.textPadding = constantExpression;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getTextPadding(), propertyValue,
- @"Setting textPadding to a constant value should update text-padding.");
- XCTAssertEqualObjects(layer.textPadding, constantStyleValue,
- @"textPadding should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.textPadding = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting textPadding to a constant value expression should update text-padding.");
+ XCTAssertEqualObjects(layer.textPadding, constantExpression,
+ @"textPadding should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.textPadding = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getTextPadding(), propertyValue,
- @"Setting textPadding to a camera function should update text-padding.");
- XCTAssertEqualObjects(layer.textPadding, functionStyleValue,
- @"textPadding should round-trip camera functions.");
+ @"Setting textPadding to a camera expression should update text-padding.");
+ XCTAssertEqualObjects(layer.textPadding, functionExpression,
+ @"textPadding should round-trip camera expressions.");
layer.textPadding = nil;
XCTAssertTrue(rawLayer->getTextPadding().isUndefined(),
@"Unsetting textPadding should return text-padding to the default value.");
- XCTAssertEqualObjects(layer.textPadding, defaultStyleValue,
+ XCTAssertEqualObjects(layer.textPadding, defaultExpression,
@"textPadding should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.textPadding = 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.textPadding = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.textPadding = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.textPadding = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// text-pitch-alignment
{
XCTAssertTrue(rawLayer->getTextPitchAlignment().isUndefined(),
@"text-pitch-alignment should be unset initially.");
- MGLStyleValue<NSValue *> *defaultStyleValue = layer.textPitchAlignment;
+ NSExpression *defaultExpression = layer.textPitchAlignment;
- MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLTextPitchAlignment:MGLTextPitchAlignmentAuto]];
- layer.textPitchAlignment = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'auto'"];
+ layer.textPitchAlignment = constantExpression;
mbgl::style::PropertyValue<mbgl::style::AlignmentType> propertyValue = { mbgl::style::AlignmentType::Auto };
XCTAssertEqual(rawLayer->getTextPitchAlignment(), propertyValue,
- @"Setting textPitchAlignment to a constant value should update text-pitch-alignment.");
- XCTAssertEqualObjects(layer.textPitchAlignment, constantStyleValue,
- @"textPitchAlignment should round-trip constant values.");
-
- MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.textPitchAlignment = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::style::AlignmentType> intervalStops = { {{18, mbgl::style::AlignmentType::Auto}} };
+ @"Setting textPitchAlignment to a constant value expression should update text-pitch-alignment.");
+ XCTAssertEqualObjects(layer.textPitchAlignment, constantExpression,
+ @"textPitchAlignment should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"'auto'"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.textPitchAlignment = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::style::AlignmentType> intervalStops = {{
+ { -INFINITY, mbgl::style::AlignmentType::Auto },
+ { 18, mbgl::style::AlignmentType::Auto },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::style::AlignmentType> { intervalStops };
XCTAssertEqual(rawLayer->getTextPitchAlignment(), propertyValue,
- @"Setting textPitchAlignment to a camera function should update text-pitch-alignment.");
- XCTAssertEqualObjects(layer.textPitchAlignment, functionStyleValue,
- @"textPitchAlignment should round-trip camera functions.");
+ @"Setting textPitchAlignment to a camera expression should update text-pitch-alignment.");
+ XCTAssertEqualObjects(layer.textPitchAlignment, functionExpression,
+ @"textPitchAlignment should round-trip camera expressions.");
layer.textPitchAlignment = nil;
XCTAssertTrue(rawLayer->getTextPitchAlignment().isUndefined(),
@"Unsetting textPitchAlignment should return text-pitch-alignment to the default value.");
- XCTAssertEqualObjects(layer.textPitchAlignment, defaultStyleValue,
+ XCTAssertEqualObjects(layer.textPitchAlignment, defaultExpression,
@"textPitchAlignment should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.textPitchAlignment = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.textPitchAlignment = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.textPitchAlignment = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.textPitchAlignment = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// text-rotate
{
XCTAssertTrue(rawLayer->getTextRotate().isUndefined(),
@"text-rotate should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.textRotation;
+ NSExpression *defaultExpression = layer.textRotation;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.textRotation = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.textRotation = constantExpression;
mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getTextRotate(), propertyValue,
- @"Setting textRotation to a constant value should update text-rotate.");
- XCTAssertEqualObjects(layer.textRotation, constantStyleValue,
- @"textRotation should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.textRotation = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting textRotation to a constant value expression should update text-rotate.");
+ XCTAssertEqualObjects(layer.textRotation, constantExpression,
+ @"textRotation should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.textRotation = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getTextRotate(), propertyValue,
- @"Setting textRotation to a camera function should update text-rotate.");
- XCTAssertEqualObjects(layer.textRotation, functionStyleValue,
- @"textRotation should round-trip camera functions.");
+ @"Setting textRotation to a camera expression should update text-rotate.");
+ XCTAssertEqualObjects(layer.textRotation, functionExpression,
+ @"textRotation should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.textRotation = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.textRotation = functionExpression;
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.");
+ @"Setting textRotation to a data expression should update text-rotate.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.textRotation, pedanticFunctionExpression,
+ @"textRotation should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.textRotation = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.textRotation = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -1499,15 +1665,16 @@
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.");
+ @"Setting textRotation to a camera-data expression should update text-rotate.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.textRotation, pedanticFunctionExpression,
+ @"textRotation should round-trip camera-data expressions.");
layer.textRotation = nil;
XCTAssertTrue(rawLayer->getTextRotate().isUndefined(),
@"Unsetting textRotation should return text-rotate to the default value.");
- XCTAssertEqualObjects(layer.textRotation, defaultStyleValue,
+ XCTAssertEqualObjects(layer.textRotation, defaultExpression,
@"textRotation should return the default value after being unset.");
}
@@ -1515,72 +1682,81 @@
{
XCTAssertTrue(rawLayer->getTextRotationAlignment().isUndefined(),
@"text-rotation-alignment should be unset initially.");
- MGLStyleValue<NSValue *> *defaultStyleValue = layer.textRotationAlignment;
+ NSExpression *defaultExpression = layer.textRotationAlignment;
- MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLTextRotationAlignment:MGLTextRotationAlignmentAuto]];
- layer.textRotationAlignment = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'auto'"];
+ layer.textRotationAlignment = constantExpression;
mbgl::style::PropertyValue<mbgl::style::AlignmentType> propertyValue = { mbgl::style::AlignmentType::Auto };
XCTAssertEqual(rawLayer->getTextRotationAlignment(), propertyValue,
- @"Setting textRotationAlignment to a constant value should update text-rotation-alignment.");
- XCTAssertEqualObjects(layer.textRotationAlignment, constantStyleValue,
- @"textRotationAlignment should round-trip constant values.");
-
- MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.textRotationAlignment = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::style::AlignmentType> intervalStops = { {{18, mbgl::style::AlignmentType::Auto}} };
+ @"Setting textRotationAlignment to a constant value expression should update text-rotation-alignment.");
+ XCTAssertEqualObjects(layer.textRotationAlignment, constantExpression,
+ @"textRotationAlignment should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"'auto'"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.textRotationAlignment = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::style::AlignmentType> intervalStops = {{
+ { -INFINITY, mbgl::style::AlignmentType::Auto },
+ { 18, mbgl::style::AlignmentType::Auto },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::style::AlignmentType> { intervalStops };
XCTAssertEqual(rawLayer->getTextRotationAlignment(), propertyValue,
- @"Setting textRotationAlignment to a camera function should update text-rotation-alignment.");
- XCTAssertEqualObjects(layer.textRotationAlignment, functionStyleValue,
- @"textRotationAlignment should round-trip camera functions.");
+ @"Setting textRotationAlignment to a camera expression should update text-rotation-alignment.");
+ XCTAssertEqualObjects(layer.textRotationAlignment, functionExpression,
+ @"textRotationAlignment should round-trip camera expressions.");
layer.textRotationAlignment = nil;
XCTAssertTrue(rawLayer->getTextRotationAlignment().isUndefined(),
@"Unsetting textRotationAlignment should return text-rotation-alignment to the default value.");
- XCTAssertEqualObjects(layer.textRotationAlignment, defaultStyleValue,
+ XCTAssertEqualObjects(layer.textRotationAlignment, defaultExpression,
@"textRotationAlignment should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.textRotationAlignment = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.textRotationAlignment = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.textRotationAlignment = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.textRotationAlignment = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// text-transform
{
XCTAssertTrue(rawLayer->getTextTransform().isUndefined(),
@"text-transform should be unset initially.");
- MGLStyleValue<NSValue *> *defaultStyleValue = layer.textTransform;
+ NSExpression *defaultExpression = layer.textTransform;
- MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLTextTransform:MGLTextTransformLowercase]];
- layer.textTransform = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'lowercase'"];
+ layer.textTransform = constantExpression;
mbgl::style::DataDrivenPropertyValue<mbgl::style::TextTransformType> propertyValue = { mbgl::style::TextTransformType::Lowercase };
XCTAssertEqual(rawLayer->getTextTransform(), propertyValue,
- @"Setting textTransform to a constant value should update text-transform.");
- XCTAssertEqualObjects(layer.textTransform, constantStyleValue,
- @"textTransform should round-trip constant values.");
-
- MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.textTransform = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::style::TextTransformType> intervalStops = { {{18, mbgl::style::TextTransformType::Lowercase}} };
+ @"Setting textTransform to a constant value expression should update text-transform.");
+ XCTAssertEqualObjects(layer.textTransform, constantExpression,
+ @"textTransform should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"'lowercase'"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.textTransform = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::style::TextTransformType> intervalStops = {{
+ { -INFINITY, mbgl::style::TextTransformType::Lowercase },
+ { 18, mbgl::style::TextTransformType::Lowercase },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::style::TextTransformType> { intervalStops };
XCTAssertEqual(rawLayer->getTextTransform(), propertyValue,
- @"Setting textTransform to a camera function should update text-transform.");
- XCTAssertEqualObjects(layer.textTransform, functionStyleValue,
- @"textTransform should round-trip camera functions.");
+ @"Setting textTransform to a camera expression should update text-transform.");
+ XCTAssertEqualObjects(layer.textTransform, functionExpression,
+ @"textTransform should round-trip camera expressions.");
layer.textTransform = nil;
XCTAssertTrue(rawLayer->getTextTransform().isUndefined(),
@"Unsetting textTransform should return text-transform to the default value.");
- XCTAssertEqualObjects(layer.textTransform, defaultStyleValue,
+ XCTAssertEqualObjects(layer.textTransform, defaultExpression,
@"textTransform should return the default value after being unset.");
}
@@ -1588,40 +1764,45 @@
{
XCTAssertTrue(rawLayer->getIconColor().isUndefined(),
@"icon-color should be unset initially.");
- MGLStyleValue<MGLColor *> *defaultStyleValue = layer.iconColor;
+ NSExpression *defaultExpression = layer.iconColor;
- MGLStyleValue<MGLColor *> *constantStyleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
- layer.iconColor = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ layer.iconColor = constantExpression;
mbgl::style::DataDrivenPropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getIconColor(), propertyValue,
- @"Setting iconColor to a constant value should update icon-color.");
- XCTAssertEqualObjects(layer.iconColor, constantStyleValue,
- @"iconColor should round-trip constant values.");
-
- MGLStyleValue<MGLColor *> * functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.iconColor = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::Color> intervalStops = { {{18, { 1, 0, 0, 1 }}} };
+ @"Setting iconColor to a constant value expression should update icon-color.");
+ XCTAssertEqualObjects(layer.iconColor, constantExpression,
+ @"iconColor should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.iconColor = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::Color> intervalStops = {{
+ { -INFINITY, { 1, 0, 0, 1 } },
+ { 18, { 1, 0, 0, 1 } },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::Color> { intervalStops };
XCTAssertEqual(rawLayer->getIconColor(), propertyValue,
- @"Setting iconColor to a camera function should update icon-color.");
- XCTAssertEqualObjects(layer.iconColor, functionStyleValue,
- @"iconColor should round-trip camera functions.");
+ @"Setting iconColor to a camera expression should update icon-color.");
+ XCTAssertEqualObjects(layer.iconColor, functionExpression,
+ @"iconColor should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.iconColor = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.iconColor = functionExpression;
mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<mbgl::Color> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getIconColor(), propertyValue,
- @"Setting iconColor to a source function should update icon-color.");
- XCTAssertEqualObjects(layer.iconColor, functionStyleValue,
- @"iconColor should round-trip source functions.");
+ @"Setting iconColor to a data expression should update icon-color.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.iconColor, pedanticFunctionExpression,
+ @"iconColor should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.iconColor = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.iconColor = functionExpression;
std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
mbgl::style::CompositeExponentialStops<mbgl::Color> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -1629,15 +1810,16 @@
propertyValue = mbgl::style::CompositeFunction<mbgl::Color> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getIconColor(), propertyValue,
- @"Setting iconColor to a composite function should update icon-color.");
- XCTAssertEqualObjects(layer.iconColor, functionStyleValue,
- @"iconColor should round-trip composite functions.");
+ @"Setting iconColor to a camera-data expression should update icon-color.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.iconColor, pedanticFunctionExpression,
+ @"iconColor should round-trip camera-data expressions.");
layer.iconColor = nil;
XCTAssertTrue(rawLayer->getIconColor().isUndefined(),
@"Unsetting iconColor should return icon-color to the default value.");
- XCTAssertEqualObjects(layer.iconColor, defaultStyleValue,
+ XCTAssertEqualObjects(layer.iconColor, defaultExpression,
@"iconColor should return the default value after being unset.");
// Transition property test
layer.iconColorTransition = transitionTest;
@@ -1654,40 +1836,45 @@
{
XCTAssertTrue(rawLayer->getIconHaloBlur().isUndefined(),
@"icon-halo-blur should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.iconHaloBlur;
+ NSExpression *defaultExpression = layer.iconHaloBlur;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.iconHaloBlur = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.iconHaloBlur = constantExpression;
mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getIconHaloBlur(), propertyValue,
- @"Setting iconHaloBlur to a constant value should update icon-halo-blur.");
- XCTAssertEqualObjects(layer.iconHaloBlur, constantStyleValue,
- @"iconHaloBlur should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.iconHaloBlur = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting iconHaloBlur to a constant value expression should update icon-halo-blur.");
+ XCTAssertEqualObjects(layer.iconHaloBlur, constantExpression,
+ @"iconHaloBlur should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.iconHaloBlur = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getIconHaloBlur(), propertyValue,
- @"Setting iconHaloBlur to a camera function should update icon-halo-blur.");
- XCTAssertEqualObjects(layer.iconHaloBlur, functionStyleValue,
- @"iconHaloBlur should round-trip camera functions.");
+ @"Setting iconHaloBlur to a camera expression should update icon-halo-blur.");
+ XCTAssertEqualObjects(layer.iconHaloBlur, functionExpression,
+ @"iconHaloBlur should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.iconHaloBlur = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.iconHaloBlur = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getIconHaloBlur(), propertyValue,
- @"Setting iconHaloBlur to a source function should update icon-halo-blur.");
- XCTAssertEqualObjects(layer.iconHaloBlur, functionStyleValue,
- @"iconHaloBlur should round-trip source functions.");
+ @"Setting iconHaloBlur to a data expression should update icon-halo-blur.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.iconHaloBlur, pedanticFunctionExpression,
+ @"iconHaloBlur should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.iconHaloBlur = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.iconHaloBlur = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -1695,15 +1882,16 @@
propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getIconHaloBlur(), propertyValue,
- @"Setting iconHaloBlur to a composite function should update icon-halo-blur.");
- XCTAssertEqualObjects(layer.iconHaloBlur, functionStyleValue,
- @"iconHaloBlur should round-trip composite functions.");
+ @"Setting iconHaloBlur to a camera-data expression should update icon-halo-blur.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.iconHaloBlur, pedanticFunctionExpression,
+ @"iconHaloBlur should round-trip camera-data expressions.");
layer.iconHaloBlur = nil;
XCTAssertTrue(rawLayer->getIconHaloBlur().isUndefined(),
@"Unsetting iconHaloBlur should return icon-halo-blur to the default value.");
- XCTAssertEqualObjects(layer.iconHaloBlur, defaultStyleValue,
+ XCTAssertEqualObjects(layer.iconHaloBlur, defaultExpression,
@"iconHaloBlur should return the default value after being unset.");
// Transition property test
layer.iconHaloBlurTransition = transitionTest;
@@ -1720,40 +1908,45 @@
{
XCTAssertTrue(rawLayer->getIconHaloColor().isUndefined(),
@"icon-halo-color should be unset initially.");
- MGLStyleValue<MGLColor *> *defaultStyleValue = layer.iconHaloColor;
+ NSExpression *defaultExpression = layer.iconHaloColor;
- MGLStyleValue<MGLColor *> *constantStyleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
- layer.iconHaloColor = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ layer.iconHaloColor = constantExpression;
mbgl::style::DataDrivenPropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getIconHaloColor(), propertyValue,
- @"Setting iconHaloColor to a constant value should update icon-halo-color.");
- XCTAssertEqualObjects(layer.iconHaloColor, constantStyleValue,
- @"iconHaloColor should round-trip constant values.");
-
- MGLStyleValue<MGLColor *> * functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.iconHaloColor = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::Color> intervalStops = { {{18, { 1, 0, 0, 1 }}} };
+ @"Setting iconHaloColor to a constant value expression should update icon-halo-color.");
+ XCTAssertEqualObjects(layer.iconHaloColor, constantExpression,
+ @"iconHaloColor should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.iconHaloColor = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::Color> intervalStops = {{
+ { -INFINITY, { 1, 0, 0, 1 } },
+ { 18, { 1, 0, 0, 1 } },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::Color> { intervalStops };
XCTAssertEqual(rawLayer->getIconHaloColor(), propertyValue,
- @"Setting iconHaloColor to a camera function should update icon-halo-color.");
- XCTAssertEqualObjects(layer.iconHaloColor, functionStyleValue,
- @"iconHaloColor should round-trip camera functions.");
+ @"Setting iconHaloColor to a camera expression should update icon-halo-color.");
+ XCTAssertEqualObjects(layer.iconHaloColor, functionExpression,
+ @"iconHaloColor should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.iconHaloColor = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.iconHaloColor = functionExpression;
mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<mbgl::Color> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getIconHaloColor(), propertyValue,
- @"Setting iconHaloColor to a source function should update icon-halo-color.");
- XCTAssertEqualObjects(layer.iconHaloColor, functionStyleValue,
- @"iconHaloColor should round-trip source functions.");
+ @"Setting iconHaloColor to a data expression should update icon-halo-color.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.iconHaloColor, pedanticFunctionExpression,
+ @"iconHaloColor should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.iconHaloColor = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.iconHaloColor = functionExpression;
std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
mbgl::style::CompositeExponentialStops<mbgl::Color> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -1761,15 +1954,16 @@
propertyValue = mbgl::style::CompositeFunction<mbgl::Color> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getIconHaloColor(), propertyValue,
- @"Setting iconHaloColor to a composite function should update icon-halo-color.");
- XCTAssertEqualObjects(layer.iconHaloColor, functionStyleValue,
- @"iconHaloColor should round-trip composite functions.");
+ @"Setting iconHaloColor to a camera-data expression should update icon-halo-color.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.iconHaloColor, pedanticFunctionExpression,
+ @"iconHaloColor should round-trip camera-data expressions.");
layer.iconHaloColor = nil;
XCTAssertTrue(rawLayer->getIconHaloColor().isUndefined(),
@"Unsetting iconHaloColor should return icon-halo-color to the default value.");
- XCTAssertEqualObjects(layer.iconHaloColor, defaultStyleValue,
+ XCTAssertEqualObjects(layer.iconHaloColor, defaultExpression,
@"iconHaloColor should return the default value after being unset.");
// Transition property test
layer.iconHaloColorTransition = transitionTest;
@@ -1786,40 +1980,45 @@
{
XCTAssertTrue(rawLayer->getIconHaloWidth().isUndefined(),
@"icon-halo-width should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.iconHaloWidth;
+ NSExpression *defaultExpression = layer.iconHaloWidth;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.iconHaloWidth = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.iconHaloWidth = constantExpression;
mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getIconHaloWidth(), propertyValue,
- @"Setting iconHaloWidth to a constant value should update icon-halo-width.");
- XCTAssertEqualObjects(layer.iconHaloWidth, constantStyleValue,
- @"iconHaloWidth should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.iconHaloWidth = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting iconHaloWidth to a constant value expression should update icon-halo-width.");
+ XCTAssertEqualObjects(layer.iconHaloWidth, constantExpression,
+ @"iconHaloWidth should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.iconHaloWidth = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getIconHaloWidth(), propertyValue,
- @"Setting iconHaloWidth to a camera function should update icon-halo-width.");
- XCTAssertEqualObjects(layer.iconHaloWidth, functionStyleValue,
- @"iconHaloWidth should round-trip camera functions.");
+ @"Setting iconHaloWidth to a camera expression should update icon-halo-width.");
+ XCTAssertEqualObjects(layer.iconHaloWidth, functionExpression,
+ @"iconHaloWidth should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.iconHaloWidth = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.iconHaloWidth = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getIconHaloWidth(), propertyValue,
- @"Setting iconHaloWidth to a source function should update icon-halo-width.");
- XCTAssertEqualObjects(layer.iconHaloWidth, functionStyleValue,
- @"iconHaloWidth should round-trip source functions.");
+ @"Setting iconHaloWidth to a data expression should update icon-halo-width.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.iconHaloWidth, pedanticFunctionExpression,
+ @"iconHaloWidth should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.iconHaloWidth = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.iconHaloWidth = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -1827,15 +2026,16 @@
propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getIconHaloWidth(), propertyValue,
- @"Setting iconHaloWidth to a composite function should update icon-halo-width.");
- XCTAssertEqualObjects(layer.iconHaloWidth, functionStyleValue,
- @"iconHaloWidth should round-trip composite functions.");
+ @"Setting iconHaloWidth to a camera-data expression should update icon-halo-width.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.iconHaloWidth, pedanticFunctionExpression,
+ @"iconHaloWidth should round-trip camera-data expressions.");
layer.iconHaloWidth = nil;
XCTAssertTrue(rawLayer->getIconHaloWidth().isUndefined(),
@"Unsetting iconHaloWidth should return icon-halo-width to the default value.");
- XCTAssertEqualObjects(layer.iconHaloWidth, defaultStyleValue,
+ XCTAssertEqualObjects(layer.iconHaloWidth, defaultExpression,
@"iconHaloWidth should return the default value after being unset.");
// Transition property test
layer.iconHaloWidthTransition = transitionTest;
@@ -1852,40 +2052,45 @@
{
XCTAssertTrue(rawLayer->getIconOpacity().isUndefined(),
@"icon-opacity should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.iconOpacity;
+ NSExpression *defaultExpression = layer.iconOpacity;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.iconOpacity = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.iconOpacity = constantExpression;
mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getIconOpacity(), propertyValue,
- @"Setting iconOpacity to a constant value should update icon-opacity.");
- XCTAssertEqualObjects(layer.iconOpacity, constantStyleValue,
- @"iconOpacity should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.iconOpacity = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting iconOpacity to a constant value expression should update icon-opacity.");
+ XCTAssertEqualObjects(layer.iconOpacity, constantExpression,
+ @"iconOpacity should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.iconOpacity = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getIconOpacity(), propertyValue,
- @"Setting iconOpacity to a camera function should update icon-opacity.");
- XCTAssertEqualObjects(layer.iconOpacity, functionStyleValue,
- @"iconOpacity should round-trip camera functions.");
+ @"Setting iconOpacity to a camera expression should update icon-opacity.");
+ XCTAssertEqualObjects(layer.iconOpacity, functionExpression,
+ @"iconOpacity should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.iconOpacity = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.iconOpacity = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getIconOpacity(), propertyValue,
- @"Setting iconOpacity to a source function should update icon-opacity.");
- XCTAssertEqualObjects(layer.iconOpacity, functionStyleValue,
- @"iconOpacity should round-trip source functions.");
+ @"Setting iconOpacity to a data expression should update icon-opacity.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.iconOpacity, pedanticFunctionExpression,
+ @"iconOpacity should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.iconOpacity = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.iconOpacity = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -1893,15 +2098,16 @@
propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getIconOpacity(), propertyValue,
- @"Setting iconOpacity to a composite function should update icon-opacity.");
- XCTAssertEqualObjects(layer.iconOpacity, functionStyleValue,
- @"iconOpacity should round-trip composite functions.");
+ @"Setting iconOpacity to a camera-data expression should update icon-opacity.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.iconOpacity, pedanticFunctionExpression,
+ @"iconOpacity should round-trip camera-data expressions.");
layer.iconOpacity = nil;
XCTAssertTrue(rawLayer->getIconOpacity().isUndefined(),
@"Unsetting iconOpacity should return icon-opacity to the default value.");
- XCTAssertEqualObjects(layer.iconOpacity, defaultStyleValue,
+ XCTAssertEqualObjects(layer.iconOpacity, defaultExpression,
@"iconOpacity should return the default value after being unset.");
// Transition property test
layer.iconOpacityTransition = transitionTest;
@@ -1918,124 +2124,139 @@
{
XCTAssertTrue(rawLayer->getIconTranslate().isUndefined(),
@"icon-translate should be unset initially.");
- MGLStyleValue<NSValue *> *defaultStyleValue = layer.iconTranslation;
+ NSExpression *defaultExpression = layer.iconTranslation;
- MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"%@",
#if TARGET_OS_IPHONE
[NSValue valueWithCGVector:CGVectorMake(1, 1)]
#else
[NSValue valueWithMGLVector:CGVectorMake(1, -1)]
#endif
];
- layer.iconTranslation = constantStyleValue;
+ layer.iconTranslation = constantExpression;
mbgl::style::PropertyValue<std::array<float, 2>> propertyValue = { { 1, 1 } };
XCTAssertEqual(rawLayer->getIconTranslate(), propertyValue,
- @"Setting iconTranslation to a constant value should update icon-translate.");
- XCTAssertEqualObjects(layer.iconTranslation, constantStyleValue,
- @"iconTranslation should round-trip constant values.");
-
- MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.iconTranslation = functionStyleValue;
-
- mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = { {{18, { 1, 1 }}} };
+ @"Setting iconTranslation to a constant value expression should update icon-translate.");
+ XCTAssertEqualObjects(layer.iconTranslation, constantExpression,
+ @"iconTranslation should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"{1, 1}"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.iconTranslation = functionExpression;
+
+ mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = {{
+ { -INFINITY, { 1, 1 } },
+ { 18, { 1, 1 } },
+ }};
propertyValue = mbgl::style::CameraFunction<std::array<float, 2>> { intervalStops };
XCTAssertEqual(rawLayer->getIconTranslate(), propertyValue,
- @"Setting iconTranslation to a camera function should update icon-translate.");
- XCTAssertEqualObjects(layer.iconTranslation, functionStyleValue,
- @"iconTranslation should round-trip camera functions.");
+ @"Setting iconTranslation to a camera expression should update icon-translate.");
+ XCTAssertEqualObjects(layer.iconTranslation, functionExpression,
+ @"iconTranslation should round-trip camera expressions.");
layer.iconTranslation = nil;
XCTAssertTrue(rawLayer->getIconTranslate().isUndefined(),
@"Unsetting iconTranslation should return icon-translate to the default value.");
- XCTAssertEqualObjects(layer.iconTranslation, defaultStyleValue,
+ XCTAssertEqualObjects(layer.iconTranslation, defaultExpression,
@"iconTranslation should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.iconTranslation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.iconTranslation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.iconTranslation = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.iconTranslation = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// icon-translate-anchor
{
XCTAssertTrue(rawLayer->getIconTranslateAnchor().isUndefined(),
@"icon-translate-anchor should be unset initially.");
- MGLStyleValue<NSValue *> *defaultStyleValue = layer.iconTranslationAnchor;
+ NSExpression *defaultExpression = layer.iconTranslationAnchor;
- MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLIconTranslationAnchor:MGLIconTranslationAnchorViewport]];
- layer.iconTranslationAnchor = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'viewport'"];
+ layer.iconTranslationAnchor = constantExpression;
mbgl::style::PropertyValue<mbgl::style::TranslateAnchorType> propertyValue = { mbgl::style::TranslateAnchorType::Viewport };
XCTAssertEqual(rawLayer->getIconTranslateAnchor(), propertyValue,
- @"Setting iconTranslationAnchor to a constant value should update icon-translate-anchor.");
- XCTAssertEqualObjects(layer.iconTranslationAnchor, constantStyleValue,
- @"iconTranslationAnchor should round-trip constant values.");
-
- MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.iconTranslationAnchor = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::style::TranslateAnchorType> intervalStops = { {{18, mbgl::style::TranslateAnchorType::Viewport}} };
+ @"Setting iconTranslationAnchor to a constant value expression should update icon-translate-anchor.");
+ XCTAssertEqualObjects(layer.iconTranslationAnchor, constantExpression,
+ @"iconTranslationAnchor should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"'viewport'"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.iconTranslationAnchor = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::style::TranslateAnchorType> intervalStops = {{
+ { -INFINITY, mbgl::style::TranslateAnchorType::Viewport },
+ { 18, mbgl::style::TranslateAnchorType::Viewport },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::style::TranslateAnchorType> { intervalStops };
XCTAssertEqual(rawLayer->getIconTranslateAnchor(), propertyValue,
- @"Setting iconTranslationAnchor to a camera function should update icon-translate-anchor.");
- XCTAssertEqualObjects(layer.iconTranslationAnchor, functionStyleValue,
- @"iconTranslationAnchor should round-trip camera functions.");
+ @"Setting iconTranslationAnchor to a camera expression should update icon-translate-anchor.");
+ XCTAssertEqualObjects(layer.iconTranslationAnchor, functionExpression,
+ @"iconTranslationAnchor should round-trip camera expressions.");
layer.iconTranslationAnchor = nil;
XCTAssertTrue(rawLayer->getIconTranslateAnchor().isUndefined(),
@"Unsetting iconTranslationAnchor should return icon-translate-anchor to the default value.");
- XCTAssertEqualObjects(layer.iconTranslationAnchor, defaultStyleValue,
+ XCTAssertEqualObjects(layer.iconTranslationAnchor, defaultExpression,
@"iconTranslationAnchor should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.iconTranslationAnchor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.iconTranslationAnchor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.iconTranslationAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.iconTranslationAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// text-color
{
XCTAssertTrue(rawLayer->getTextColor().isUndefined(),
@"text-color should be unset initially.");
- MGLStyleValue<MGLColor *> *defaultStyleValue = layer.textColor;
+ NSExpression *defaultExpression = layer.textColor;
- MGLStyleValue<MGLColor *> *constantStyleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
- layer.textColor = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ layer.textColor = constantExpression;
mbgl::style::DataDrivenPropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getTextColor(), propertyValue,
- @"Setting textColor to a constant value should update text-color.");
- XCTAssertEqualObjects(layer.textColor, constantStyleValue,
- @"textColor should round-trip constant values.");
-
- MGLStyleValue<MGLColor *> * functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.textColor = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::Color> intervalStops = { {{18, { 1, 0, 0, 1 }}} };
+ @"Setting textColor to a constant value expression should update text-color.");
+ XCTAssertEqualObjects(layer.textColor, constantExpression,
+ @"textColor should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.textColor = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::Color> intervalStops = {{
+ { -INFINITY, { 1, 0, 0, 1 } },
+ { 18, { 1, 0, 0, 1 } },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::Color> { intervalStops };
XCTAssertEqual(rawLayer->getTextColor(), propertyValue,
- @"Setting textColor to a camera function should update text-color.");
- XCTAssertEqualObjects(layer.textColor, functionStyleValue,
- @"textColor should round-trip camera functions.");
+ @"Setting textColor to a camera expression should update text-color.");
+ XCTAssertEqualObjects(layer.textColor, functionExpression,
+ @"textColor should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.textColor = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.textColor = functionExpression;
mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<mbgl::Color> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getTextColor(), propertyValue,
- @"Setting textColor to a source function should update text-color.");
- XCTAssertEqualObjects(layer.textColor, functionStyleValue,
- @"textColor should round-trip source functions.");
+ @"Setting textColor to a data expression should update text-color.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.textColor, pedanticFunctionExpression,
+ @"textColor should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.textColor = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.textColor = functionExpression;
std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
mbgl::style::CompositeExponentialStops<mbgl::Color> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -2043,15 +2264,16 @@
propertyValue = mbgl::style::CompositeFunction<mbgl::Color> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getTextColor(), propertyValue,
- @"Setting textColor to a composite function should update text-color.");
- XCTAssertEqualObjects(layer.textColor, functionStyleValue,
- @"textColor should round-trip composite functions.");
+ @"Setting textColor to a camera-data expression should update text-color.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.textColor, pedanticFunctionExpression,
+ @"textColor should round-trip camera-data expressions.");
layer.textColor = nil;
XCTAssertTrue(rawLayer->getTextColor().isUndefined(),
@"Unsetting textColor should return text-color to the default value.");
- XCTAssertEqualObjects(layer.textColor, defaultStyleValue,
+ XCTAssertEqualObjects(layer.textColor, defaultExpression,
@"textColor should return the default value after being unset.");
// Transition property test
layer.textColorTransition = transitionTest;
@@ -2068,40 +2290,45 @@
{
XCTAssertTrue(rawLayer->getTextHaloBlur().isUndefined(),
@"text-halo-blur should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.textHaloBlur;
+ NSExpression *defaultExpression = layer.textHaloBlur;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.textHaloBlur = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.textHaloBlur = constantExpression;
mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getTextHaloBlur(), propertyValue,
- @"Setting textHaloBlur to a constant value should update text-halo-blur.");
- XCTAssertEqualObjects(layer.textHaloBlur, constantStyleValue,
- @"textHaloBlur should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.textHaloBlur = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting textHaloBlur to a constant value expression should update text-halo-blur.");
+ XCTAssertEqualObjects(layer.textHaloBlur, constantExpression,
+ @"textHaloBlur should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.textHaloBlur = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getTextHaloBlur(), propertyValue,
- @"Setting textHaloBlur to a camera function should update text-halo-blur.");
- XCTAssertEqualObjects(layer.textHaloBlur, functionStyleValue,
- @"textHaloBlur should round-trip camera functions.");
+ @"Setting textHaloBlur to a camera expression should update text-halo-blur.");
+ XCTAssertEqualObjects(layer.textHaloBlur, functionExpression,
+ @"textHaloBlur should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.textHaloBlur = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.textHaloBlur = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getTextHaloBlur(), propertyValue,
- @"Setting textHaloBlur to a source function should update text-halo-blur.");
- XCTAssertEqualObjects(layer.textHaloBlur, functionStyleValue,
- @"textHaloBlur should round-trip source functions.");
+ @"Setting textHaloBlur to a data expression should update text-halo-blur.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.textHaloBlur, pedanticFunctionExpression,
+ @"textHaloBlur should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.textHaloBlur = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.textHaloBlur = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -2109,15 +2336,16 @@
propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getTextHaloBlur(), propertyValue,
- @"Setting textHaloBlur to a composite function should update text-halo-blur.");
- XCTAssertEqualObjects(layer.textHaloBlur, functionStyleValue,
- @"textHaloBlur should round-trip composite functions.");
+ @"Setting textHaloBlur to a camera-data expression should update text-halo-blur.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.textHaloBlur, pedanticFunctionExpression,
+ @"textHaloBlur should round-trip camera-data expressions.");
layer.textHaloBlur = nil;
XCTAssertTrue(rawLayer->getTextHaloBlur().isUndefined(),
@"Unsetting textHaloBlur should return text-halo-blur to the default value.");
- XCTAssertEqualObjects(layer.textHaloBlur, defaultStyleValue,
+ XCTAssertEqualObjects(layer.textHaloBlur, defaultExpression,
@"textHaloBlur should return the default value after being unset.");
// Transition property test
layer.textHaloBlurTransition = transitionTest;
@@ -2134,40 +2362,45 @@
{
XCTAssertTrue(rawLayer->getTextHaloColor().isUndefined(),
@"text-halo-color should be unset initially.");
- MGLStyleValue<MGLColor *> *defaultStyleValue = layer.textHaloColor;
+ NSExpression *defaultExpression = layer.textHaloColor;
- MGLStyleValue<MGLColor *> *constantStyleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
- layer.textHaloColor = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ layer.textHaloColor = constantExpression;
mbgl::style::DataDrivenPropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getTextHaloColor(), propertyValue,
- @"Setting textHaloColor to a constant value should update text-halo-color.");
- XCTAssertEqualObjects(layer.textHaloColor, constantStyleValue,
- @"textHaloColor should round-trip constant values.");
-
- MGLStyleValue<MGLColor *> * functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.textHaloColor = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::Color> intervalStops = { {{18, { 1, 0, 0, 1 }}} };
+ @"Setting textHaloColor to a constant value expression should update text-halo-color.");
+ XCTAssertEqualObjects(layer.textHaloColor, constantExpression,
+ @"textHaloColor should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.textHaloColor = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::Color> intervalStops = {{
+ { -INFINITY, { 1, 0, 0, 1 } },
+ { 18, { 1, 0, 0, 1 } },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::Color> { intervalStops };
XCTAssertEqual(rawLayer->getTextHaloColor(), propertyValue,
- @"Setting textHaloColor to a camera function should update text-halo-color.");
- XCTAssertEqualObjects(layer.textHaloColor, functionStyleValue,
- @"textHaloColor should round-trip camera functions.");
+ @"Setting textHaloColor to a camera expression should update text-halo-color.");
+ XCTAssertEqualObjects(layer.textHaloColor, functionExpression,
+ @"textHaloColor should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.textHaloColor = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.textHaloColor = functionExpression;
mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<mbgl::Color> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getTextHaloColor(), propertyValue,
- @"Setting textHaloColor to a source function should update text-halo-color.");
- XCTAssertEqualObjects(layer.textHaloColor, functionStyleValue,
- @"textHaloColor should round-trip source functions.");
+ @"Setting textHaloColor to a data expression should update text-halo-color.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.textHaloColor, pedanticFunctionExpression,
+ @"textHaloColor should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.textHaloColor = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.textHaloColor = functionExpression;
std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
mbgl::style::CompositeExponentialStops<mbgl::Color> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -2175,15 +2408,16 @@
propertyValue = mbgl::style::CompositeFunction<mbgl::Color> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getTextHaloColor(), propertyValue,
- @"Setting textHaloColor to a composite function should update text-halo-color.");
- XCTAssertEqualObjects(layer.textHaloColor, functionStyleValue,
- @"textHaloColor should round-trip composite functions.");
+ @"Setting textHaloColor to a camera-data expression should update text-halo-color.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.textHaloColor, pedanticFunctionExpression,
+ @"textHaloColor should round-trip camera-data expressions.");
layer.textHaloColor = nil;
XCTAssertTrue(rawLayer->getTextHaloColor().isUndefined(),
@"Unsetting textHaloColor should return text-halo-color to the default value.");
- XCTAssertEqualObjects(layer.textHaloColor, defaultStyleValue,
+ XCTAssertEqualObjects(layer.textHaloColor, defaultExpression,
@"textHaloColor should return the default value after being unset.");
// Transition property test
layer.textHaloColorTransition = transitionTest;
@@ -2200,40 +2434,45 @@
{
XCTAssertTrue(rawLayer->getTextHaloWidth().isUndefined(),
@"text-halo-width should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.textHaloWidth;
+ NSExpression *defaultExpression = layer.textHaloWidth;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.textHaloWidth = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.textHaloWidth = constantExpression;
mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getTextHaloWidth(), propertyValue,
- @"Setting textHaloWidth to a constant value should update text-halo-width.");
- XCTAssertEqualObjects(layer.textHaloWidth, constantStyleValue,
- @"textHaloWidth should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.textHaloWidth = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting textHaloWidth to a constant value expression should update text-halo-width.");
+ XCTAssertEqualObjects(layer.textHaloWidth, constantExpression,
+ @"textHaloWidth should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.textHaloWidth = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getTextHaloWidth(), propertyValue,
- @"Setting textHaloWidth to a camera function should update text-halo-width.");
- XCTAssertEqualObjects(layer.textHaloWidth, functionStyleValue,
- @"textHaloWidth should round-trip camera functions.");
+ @"Setting textHaloWidth to a camera expression should update text-halo-width.");
+ XCTAssertEqualObjects(layer.textHaloWidth, functionExpression,
+ @"textHaloWidth should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.textHaloWidth = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.textHaloWidth = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getTextHaloWidth(), propertyValue,
- @"Setting textHaloWidth to a source function should update text-halo-width.");
- XCTAssertEqualObjects(layer.textHaloWidth, functionStyleValue,
- @"textHaloWidth should round-trip source functions.");
+ @"Setting textHaloWidth to a data expression should update text-halo-width.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.textHaloWidth, pedanticFunctionExpression,
+ @"textHaloWidth should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.textHaloWidth = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.textHaloWidth = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -2241,15 +2480,16 @@
propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getTextHaloWidth(), propertyValue,
- @"Setting textHaloWidth to a composite function should update text-halo-width.");
- XCTAssertEqualObjects(layer.textHaloWidth, functionStyleValue,
- @"textHaloWidth should round-trip composite functions.");
+ @"Setting textHaloWidth to a camera-data expression should update text-halo-width.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.textHaloWidth, pedanticFunctionExpression,
+ @"textHaloWidth should round-trip camera-data expressions.");
layer.textHaloWidth = nil;
XCTAssertTrue(rawLayer->getTextHaloWidth().isUndefined(),
@"Unsetting textHaloWidth should return text-halo-width to the default value.");
- XCTAssertEqualObjects(layer.textHaloWidth, defaultStyleValue,
+ XCTAssertEqualObjects(layer.textHaloWidth, defaultExpression,
@"textHaloWidth should return the default value after being unset.");
// Transition property test
layer.textHaloWidthTransition = transitionTest;
@@ -2266,40 +2506,45 @@
{
XCTAssertTrue(rawLayer->getTextOpacity().isUndefined(),
@"text-opacity should be unset initially.");
- MGLStyleValue<NSNumber *> *defaultStyleValue = layer.textOpacity;
+ NSExpression *defaultExpression = layer.textOpacity;
- MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.textOpacity = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ layer.textOpacity = constantExpression;
mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getTextOpacity(), propertyValue,
- @"Setting textOpacity to a constant value should update text-opacity.");
- XCTAssertEqualObjects(layer.textOpacity, constantStyleValue,
- @"textOpacity should round-trip constant values.");
-
- MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.textOpacity = functionStyleValue;
-
- mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ @"Setting textOpacity to a constant value expression should update text-opacity.");
+ XCTAssertEqualObjects(layer.textOpacity, constantExpression,
+ @"textOpacity should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"0xff"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.textOpacity = functionExpression;
+
+ mbgl::style::IntervalStops<float> intervalStops = {{
+ { -INFINITY, 0xff },
+ { 18, 0xff },
+ }};
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
XCTAssertEqual(rawLayer->getTextOpacity(), propertyValue,
- @"Setting textOpacity to a camera function should update text-opacity.");
- XCTAssertEqualObjects(layer.textOpacity, functionStyleValue,
- @"textOpacity should round-trip camera functions.");
+ @"Setting textOpacity to a camera expression should update text-opacity.");
+ XCTAssertEqualObjects(layer.textOpacity, functionExpression,
+ @"textOpacity should round-trip camera expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
- layer.textOpacity = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
+ layer.textOpacity = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
XCTAssertEqual(rawLayer->getTextOpacity(), propertyValue,
- @"Setting textOpacity to a source function should update text-opacity.");
- XCTAssertEqualObjects(layer.textOpacity, functionStyleValue,
- @"textOpacity should round-trip source functions.");
+ @"Setting textOpacity to a data expression should update text-opacity.");
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.textOpacity, pedanticFunctionExpression,
+ @"textOpacity should round-trip data expressions.");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
- layer.textOpacity = functionStyleValue;
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ layer.textOpacity = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
@@ -2307,15 +2552,16 @@
propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
XCTAssertEqual(rawLayer->getTextOpacity(), propertyValue,
- @"Setting textOpacity to a composite function should update text-opacity.");
- XCTAssertEqualObjects(layer.textOpacity, functionStyleValue,
- @"textOpacity should round-trip composite functions.");
+ @"Setting textOpacity to a camera-data expression should update text-opacity.");
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.textOpacity, pedanticFunctionExpression,
+ @"textOpacity should round-trip camera-data expressions.");
layer.textOpacity = nil;
XCTAssertTrue(rawLayer->getTextOpacity().isUndefined(),
@"Unsetting textOpacity should return text-opacity to the default value.");
- XCTAssertEqualObjects(layer.textOpacity, defaultStyleValue,
+ XCTAssertEqualObjects(layer.textOpacity, defaultExpression,
@"textOpacity should return the default value after being unset.");
// Transition property test
layer.textOpacityTransition = transitionTest;
@@ -2332,84 +2578,94 @@
{
XCTAssertTrue(rawLayer->getTextTranslate().isUndefined(),
@"text-translate should be unset initially.");
- MGLStyleValue<NSValue *> *defaultStyleValue = layer.textTranslation;
+ NSExpression *defaultExpression = layer.textTranslation;
- MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"%@",
#if TARGET_OS_IPHONE
[NSValue valueWithCGVector:CGVectorMake(1, 1)]
#else
[NSValue valueWithMGLVector:CGVectorMake(1, -1)]
#endif
];
- layer.textTranslation = constantStyleValue;
+ layer.textTranslation = constantExpression;
mbgl::style::PropertyValue<std::array<float, 2>> propertyValue = { { 1, 1 } };
XCTAssertEqual(rawLayer->getTextTranslate(), propertyValue,
- @"Setting textTranslation to a constant value should update text-translate.");
- XCTAssertEqualObjects(layer.textTranslation, constantStyleValue,
- @"textTranslation should round-trip constant values.");
-
- MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.textTranslation = functionStyleValue;
-
- mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = { {{18, { 1, 1 }}} };
+ @"Setting textTranslation to a constant value expression should update text-translate.");
+ XCTAssertEqualObjects(layer.textTranslation, constantExpression,
+ @"textTranslation should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"{1, 1}"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.textTranslation = functionExpression;
+
+ mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = {{
+ { -INFINITY, { 1, 1 } },
+ { 18, { 1, 1 } },
+ }};
propertyValue = mbgl::style::CameraFunction<std::array<float, 2>> { intervalStops };
XCTAssertEqual(rawLayer->getTextTranslate(), propertyValue,
- @"Setting textTranslation to a camera function should update text-translate.");
- XCTAssertEqualObjects(layer.textTranslation, functionStyleValue,
- @"textTranslation should round-trip camera functions.");
+ @"Setting textTranslation to a camera expression should update text-translate.");
+ XCTAssertEqualObjects(layer.textTranslation, functionExpression,
+ @"textTranslation should round-trip camera expressions.");
layer.textTranslation = nil;
XCTAssertTrue(rawLayer->getTextTranslate().isUndefined(),
@"Unsetting textTranslation should return text-translate to the default value.");
- XCTAssertEqualObjects(layer.textTranslation, defaultStyleValue,
+ XCTAssertEqualObjects(layer.textTranslation, defaultExpression,
@"textTranslation should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.textTranslation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.textTranslation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.textTranslation = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.textTranslation = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
// text-translate-anchor
{
XCTAssertTrue(rawLayer->getTextTranslateAnchor().isUndefined(),
@"text-translate-anchor should be unset initially.");
- MGLStyleValue<NSValue *> *defaultStyleValue = layer.textTranslationAnchor;
+ NSExpression *defaultExpression = layer.textTranslationAnchor;
- MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLTextTranslationAnchor:MGLTextTranslationAnchorViewport]];
- layer.textTranslationAnchor = constantStyleValue;
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'viewport'"];
+ layer.textTranslationAnchor = constantExpression;
mbgl::style::PropertyValue<mbgl::style::TranslateAnchorType> propertyValue = { mbgl::style::TranslateAnchorType::Viewport };
XCTAssertEqual(rawLayer->getTextTranslateAnchor(), propertyValue,
- @"Setting textTranslationAnchor to a constant value should update text-translate-anchor.");
- XCTAssertEqualObjects(layer.textTranslationAnchor, constantStyleValue,
- @"textTranslationAnchor should round-trip constant values.");
-
- MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
- layer.textTranslationAnchor = functionStyleValue;
-
- mbgl::style::IntervalStops<mbgl::style::TranslateAnchorType> intervalStops = { {{18, mbgl::style::TranslateAnchorType::Viewport}} };
+ @"Setting textTranslationAnchor to a constant value expression should update text-translate-anchor.");
+ XCTAssertEqualObjects(layer.textTranslationAnchor, constantExpression,
+ @"textTranslationAnchor should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"'viewport'"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.textTranslationAnchor = functionExpression;
+
+ mbgl::style::IntervalStops<mbgl::style::TranslateAnchorType> intervalStops = {{
+ { -INFINITY, mbgl::style::TranslateAnchorType::Viewport },
+ { 18, mbgl::style::TranslateAnchorType::Viewport },
+ }};
propertyValue = mbgl::style::CameraFunction<mbgl::style::TranslateAnchorType> { intervalStops };
XCTAssertEqual(rawLayer->getTextTranslateAnchor(), propertyValue,
- @"Setting textTranslationAnchor to a camera function should update text-translate-anchor.");
- XCTAssertEqualObjects(layer.textTranslationAnchor, functionStyleValue,
- @"textTranslationAnchor should round-trip camera functions.");
+ @"Setting textTranslationAnchor to a camera expression should update text-translate-anchor.");
+ XCTAssertEqualObjects(layer.textTranslationAnchor, functionExpression,
+ @"textTranslationAnchor should round-trip camera expressions.");
layer.textTranslationAnchor = nil;
XCTAssertTrue(rawLayer->getTextTranslateAnchor().isUndefined(),
@"Unsetting textTranslationAnchor should return text-translate-anchor to the default value.");
- XCTAssertEqualObjects(layer.textTranslationAnchor, defaultStyleValue,
+ XCTAssertEqualObjects(layer.textTranslationAnchor, defaultExpression,
@"textTranslationAnchor should return the default value after being unset.");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.textTranslationAnchor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.textTranslationAnchor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.textTranslationAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.textTranslationAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
}
diff --git a/platform/darwin/test/MGLTileSetTests.mm b/platform/darwin/test/MGLTileSetTests.mm
index 4d5e1fcd05..2319f66447 100644
--- a/platform/darwin/test/MGLTileSetTests.mm
+++ b/platform/darwin/test/MGLTileSetTests.mm
@@ -66,8 +66,16 @@
// when the tile set has attribution infos
MGLAttributionInfo *mapboxInfo = [[MGLAttributionInfo alloc] initWithTitle:[[NSAttributedString alloc] initWithString:@"Mapbox"]
URL:[NSURL URLWithString:@"https://www.mapbox.com/"]];
+#if TARGET_OS_IPHONE
+ UIColor *redColor = [UIColor redColor];
+#else
+ // CSS uses the sRGB color space. In macOS 10.12 Sierra and below,
+ // -[NSColor redColor] is in the calibrated RGB space and has a slightly
+ // different sRGB value than on iOS and macOS 10.13 High Sierra.
+ NSColor *redColor = [NSColor colorWithSRGBRed:1 green:0 blue:0 alpha:1];
+#endif
NSAttributedString *gl = [[NSAttributedString alloc] initWithString:@"GL" attributes:@{
- NSBackgroundColorAttributeName: [MGLColor redColor],
+ NSBackgroundColorAttributeName: redColor,
}];
MGLAttributionInfo *glInfo = [[MGLAttributionInfo alloc] initWithTitle:gl URL:nil];
tileSet = MGLTileSetFromTileURLTemplates(tileURLTemplates, @{
@@ -82,7 +90,7 @@
#else
NSString *html = (@"<font face=\"Helvetica\" size=\"3\" style=\"font: 12.0px Helvetica\">"
@"<a href=\"https://www.mapbox.com/\">Mapbox</a> </font>"
- @"<font face=\"Helvetica\" size=\"3\" style=\"font: 12.0px Helvetica; background-color: #ff2600\">GL</font>\n");
+ @"<font face=\"Helvetica\" size=\"3\" style=\"font: 12.0px Helvetica; background-color: #ff0000\">GL</font>\n");
#endif
XCTAssertEqualObjects(@(tileSet.attribution.c_str()), html);
@@ -102,6 +110,23 @@
// the scheme is reflected by the mbgl tileset
XCTAssertEqual(tileSet.scheme, mbgl::Tileset::Scheme::TMS);
+
+ // when the dem enciding is changed using an NSNumber
+ tileSet = MGLTileSetFromTileURLTemplates(tileURLTemplates, @{
+ MGLTileSourceOptionDEMEncoding: @(MGLDEMEncodingTerrarium),
+ });
+
+ // the encoding is reflected by the mbgl tileset
+ XCTAssertEqual(tileSet.encoding, mbgl::Tileset::DEMEncoding::Terrarium);
+
+ // when the dem enciding is changed using an NSValue
+ MGLDEMEncoding terrarium = MGLDEMEncodingTerrarium;
+ tileSet = MGLTileSetFromTileURLTemplates(tileURLTemplates, @{
+ MGLTileSourceOptionDEMEncoding: [NSValue value:&terrarium withObjCType:@encode(MGLDEMEncoding)],
+ });
+
+ // the encoding is reflected by the mbgl tileset
+ XCTAssertEqual(tileSet.encoding, mbgl::Tileset::DEMEncoding::Terrarium);
}
- (void)testInvalidTileSet {
diff --git a/platform/darwin/test/test-Bridging-Header.h b/platform/darwin/test/test-Bridging-Header.h
index 5d23e9d6c5..1b2cb5d6d0 100644
--- a/platform/darwin/test/test-Bridging-Header.h
+++ b/platform/darwin/test/test-Bridging-Header.h
@@ -1,4 +1,4 @@
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
-#import "MGLStyleValueTests.h"
+