summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMinh Nguyễn <mxn@1ec5.org>2018-03-30 16:43:55 -0700
committerGitHub <noreply@github.com>2018-03-30 16:43:55 -0700
commit59e92904c360e5aad94a1b789276bf6147120d7c (patch)
treefcb675741c492692324d841f8aaae905a3ccf8f4
parentb6866f764e5a804399ed60bbbce43a379b568ece (diff)
downloadqtlocation-mapboxgl-59e92904c360e5aad94a1b789276bf6147120d7c.tar.gz
Eviscerate mbgl expression to Foundation JSON object conversion (#11389)
* [ios, macos] Eviscerate mbgl expression to Foundation JSON object conversion * [ios, macos] Remove literal special case MGLJSONObjectFromMBGLValue() is just a literal translation from C++ types to Foundation types; no need for expression-specific literal wrapping. * [ios, macos] Implemented RGB(A) operators * [ios, macos] More robust color conversion * [macos] Create calibrated RGB from expression on Sierra * [macos] Calibrate colors in expressions at runtime * [ios, macos] Special-case number conversion without fallbacks * [ios, macos] Test mgl_number expressions * [ios, macos] Updated tests for aftermarket expressions * [ios, macos] Relax roundtripping requirement for serialize() * [ios, macos] Fixed interpolation expression tests * [ios, macos] Removed dead code * [ios, macos] Fixed color conversion on Sierra
-rw-r--r--platform/darwin/src/MGLStyleValue.mm87
-rw-r--r--platform/darwin/src/NSExpression+MGLAdditions.mm14
-rw-r--r--platform/darwin/test/MGLCircleStyleLayerTests.mm42
-rw-r--r--platform/darwin/test/MGLExpressionTests.mm20
-rw-r--r--platform/darwin/test/MGLFillExtrusionStyleLayerTests.mm18
-rw-r--r--platform/darwin/test/MGLFillStyleLayerTests.mm18
-rw-r--r--platform/darwin/test/MGLHeatmapColorTests.mm3
-rw-r--r--platform/darwin/test/MGLHeatmapStyleLayerTests.mm12
-rw-r--r--platform/darwin/test/MGLLineStyleLayerTests.mm36
-rw-r--r--platform/darwin/test/MGLStyleLayerTests.mm.ejs6
-rw-r--r--platform/darwin/test/MGLSymbolStyleLayerTests.mm108
-rw-r--r--platform/ios/src/UIColor+MGLAdditions.h7
-rw-r--r--platform/ios/src/UIColor+MGLAdditions.mm49
-rw-r--r--platform/macos/src/NSColor+MGLAdditions.h7
-rw-r--r--platform/macos/src/NSColor+MGLAdditions.mm64
15 files changed, 327 insertions, 164 deletions
diff --git a/platform/darwin/src/MGLStyleValue.mm b/platform/darwin/src/MGLStyleValue.mm
index 74e1926f79..5103b5f5cf 100644
--- a/platform/darwin/src/MGLStyleValue.mm
+++ b/platform/darwin/src/MGLStyleValue.mm
@@ -5,7 +5,7 @@
const MGLStyleFunctionOption MGLStyleFunctionOptionInterpolationBase = @"MGLStyleFunctionOptionInterpolationBase";
const MGLStyleFunctionOption MGLStyleFunctionOptionDefaultValue = @"MGLStyleFunctionOptionDefaultValue";
-id MGLJSONObjectFromMBGLValue(const mbgl::style::expression::Value &value) {
+id MGLJSONObjectFromMBGLValue(const mbgl::Value &value) {
return value.match([](const mbgl::NullValue) -> id {
return [NSNull null];
}, [](const bool value) {
@@ -24,98 +24,23 @@ id MGLJSONObjectFromMBGLValue(const mbgl::style::expression::Value &value) {
std::array<float, 3> spherical = value.getSpherical();
MGLSphericalPosition position = MGLSphericalPositionMake(spherical[0], spherical[1], spherical[2]);
return [NSValue valueWithMGLSphericalPosition:position];
- }, [&](const std::vector<mbgl::style::expression::Value> &vector) {
+ }, [&](const std::vector<mbgl::Value> &vector) {
NSMutableArray *array = [NSMutableArray arrayWithCapacity:vector.size()];
for (auto value : vector) {
[array addObject:MGLJSONObjectFromMBGLValue(value)];
}
- return @[@"literal", array];
- }, [&](const std::unordered_map<std::string, mbgl::style::expression::Value> &map) {
+ return array;
+ }, [&](const std::unordered_map<std::string, mbgl::Value> &map) {
NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithCapacity:map.size()];
for (auto &item : map) {
dictionary[@(item.first.c_str())] = MGLJSONObjectFromMBGLValue(item.second);
}
- return @[@"literal", dictionary];
+ return dictionary;
}, [](const auto &) -> id {
return nil;
});
}
id MGLJSONObjectFromMBGLExpression(const mbgl::style::expression::Expression &mbglExpression) {
- using namespace mbgl::style::expression;
- if (auto literalExpression = dynamic_cast<const Literal *>(&mbglExpression)) {
- auto result = literalExpression->evaluate({ nullptr });
- return result ? MGLJSONObjectFromMBGLValue(*result) : nil;
- }
- if (auto assertExpression = dynamic_cast<const ArrayAssertion *>(&mbglExpression)) {
- NSMutableArray *inputs = [NSMutableArray array];
- assertExpression->eachChild([&](const Expression &child) {
- [inputs addObject:MGLJSONObjectFromMBGLExpression(child)];
- });
- return @[@"literal", inputs.lastObject];
- }
- if (auto assertExpression = dynamic_cast<const Assertion *>(&mbglExpression)) {
- NSMutableArray *inputs = [NSMutableArray array];
- assertExpression->eachChild([&](const Expression &child) {
- [inputs addObject:MGLJSONObjectFromMBGLExpression(child)];
- });
- return inputs.firstObject;
- }
- if (auto compoundExpression = dynamic_cast<const CompoundExpressionBase *>(&mbglExpression)) {
- const std::string name = compoundExpression->getName();
- mbgl::optional<std::size_t> parameterCount = compoundExpression->getParameterCount();
- NSMutableArray *expressionObject = parameterCount ? [NSMutableArray arrayWithCapacity:*parameterCount + 1] : [NSMutableArray array];
- [expressionObject addObject:@(name.c_str())];
- compoundExpression->eachChild([&](const Expression &child) {
- [expressionObject addObject:MGLJSONObjectFromMBGLExpression(child)];
- });
- return expressionObject;
- }
- if (auto stepExpression = dynamic_cast<const Step *>(&mbglExpression)) {
- auto &input = stepExpression->getInput();
- NSMutableArray *expressionObject = [NSMutableArray arrayWithObjects:@"step", MGLJSONObjectFromMBGLExpression(*input.get()), nil];
- stepExpression->eachStop([&](double stop, const Expression &child) {
- [expressionObject addObject:@(stop)];
- [expressionObject addObject:MGLJSONObjectFromMBGLExpression(child)];
- });
- if ([expressionObject[2] isEqual:@(-INFINITY)]) {
- [expressionObject removeObjectAtIndex:2];
- }
- return expressionObject;
- }
- if (auto interpolateExpression = dynamic_cast<const InterpolateBase *>(&mbglExpression)) {
- auto &interpolator = interpolateExpression->getInterpolator();
- auto &input = interpolateExpression->getInput();
- NSArray *interpolatorObject;
- if (interpolator.is<ExponentialInterpolator>()) {
- auto exponentialInterpolator = interpolator.get<ExponentialInterpolator>();
- interpolatorObject = exponentialInterpolator.base == 1 ? @[@"linear"] : @[@"exponential", @(exponentialInterpolator.base)];
- } else if (interpolator.is<CubicBezierInterpolator>()) {
- auto cubicBezierInterpolator = interpolator.get<CubicBezierInterpolator>();
- auto bezier = cubicBezierInterpolator.ub;
- interpolatorObject = @[
- @"cubic-bezier",
- @(bezier.getP1().first), @(bezier.getP1().second),
- @(bezier.getP2().first), @(bezier.getP2().second),
- ];
- } else {
- NSCAssert(NO, @"Unrecognized interpolator type.");
- }
- NSMutableArray *expressionObject = [NSMutableArray arrayWithObjects:@"interpolate", interpolatorObject, MGLJSONObjectFromMBGLExpression(*input.get()), nil];
- interpolateExpression->eachStop([&](double stop, const Expression &child) {
- [expressionObject addObject:@(stop)];
- [expressionObject addObject:MGLJSONObjectFromMBGLExpression(child)];
- });
- return expressionObject;
- }
- if (auto caseExpression = dynamic_cast<const Case *>(&mbglExpression)) {
- NSMutableArray *expressionObject = [NSMutableArray arrayWithObject:@"case"];
- caseExpression->eachChild([&](const Expression &child) {
- [expressionObject addObject:MGLJSONObjectFromMBGLExpression(child)];
- });
- return expressionObject;
- }
- NSCAssert(NO, @"Unrecognized expression type.");
- return nil;
+ return MGLJSONObjectFromMBGLValue(mbglExpression.serialize());
}
-
diff --git a/platform/darwin/src/NSExpression+MGLAdditions.mm b/platform/darwin/src/NSExpression+MGLAdditions.mm
index 7fe8ce3c91..17b130639f 100644
--- a/platform/darwin/src/NSExpression+MGLAdditions.mm
+++ b/platform/darwin/src/NSExpression+MGLAdditions.mm
@@ -541,7 +541,7 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
} else if ([op isEqualToString:@"to-boolean"]) {
NSExpression *operand = [NSExpression mgl_expressionWithJSONObject:argumentObjects.firstObject];
return [NSExpression expressionForFunction:operand selectorName:@"boolValue" arguments:@[]];
- } else if ([op isEqualToString:@"to-number"]) {
+ } else if ([op isEqualToString:@"to-number"] || [op isEqualToString:@"number"]) {
NSExpression *operand = [NSExpression mgl_expressionWithJSONObject:argumentObjects.firstObject];
if (argumentObjects.count == 1) {
return [NSExpression expressionWithFormat:@"CAST(%@, 'NSNumber')", operand];
@@ -570,6 +570,12 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
function = @"length:";
}
return [NSExpression expressionForFunction:function arguments:@[subexpressions.firstObject]];
+ } else if ([op isEqualToString:@"rgb"]) {
+ NSArray *subexpressions = MGLSubexpressionsWithJSONObjects(argumentObjects);
+ return [NSExpression mgl_expressionForRGBComponents:subexpressions];
+ } else if ([op isEqualToString:@"rgba"]) {
+ NSArray *subexpressions = MGLSubexpressionsWithJSONObjects(argumentObjects);
+ return [NSExpression mgl_expressionForRGBAComponents:subexpressions];
} else if ([op isEqualToString:@"min"]) {
NSArray *subexpressions = MGLSubexpressionsWithJSONObjects(argumentObjects);
NSExpression *subexpression = [NSExpression expressionForAggregate:subexpressions];
@@ -842,7 +848,8 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
return @[@"at", self.arguments[1].mgl_jsonExpressionObject, self.arguments[0].mgl_jsonExpressionObject];
} else if ([function isEqualToString:@"boolValue"]) {
return @[@"to-boolean", self.operand.mgl_jsonExpressionObject];
- } else if ([function isEqualToString:@"mgl_numberWithFallbackValues:"] ||
+ } else if ([function isEqualToString:@"mgl_number"] ||
+ [function isEqualToString:@"mgl_numberWithFallbackValues:"] ||
[function isEqualToString:@"decimalValue"] ||
[function isEqualToString:@"floatValue"] ||
[function isEqualToString:@"doubleValue"]) {
@@ -895,6 +902,9 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
format:@"Casting expression to %@ not yet implemented.", type];
} else if ([function isEqualToString:@"MGL_FUNCTION"]) {
return self.arguments.mgl_jsonExpressionObject;
+ } else if (op == [MGLColor class] && [function isEqualToString:@"colorWithRed:green:blue:alpha:"]) {
+ NSArray *arguments = self.arguments.mgl_jsonExpressionObject;
+ return [@[@"rgba"] arrayByAddingObjectsFromArray:arguments];
} else if ([function isEqualToString:@"median:"] ||
[function isEqualToString:@"mode:"] ||
[function isEqualToString:@"stddev:"] ||
diff --git a/platform/darwin/test/MGLCircleStyleLayerTests.mm b/platform/darwin/test/MGLCircleStyleLayerTests.mm
index cb950a1feb..2c877d4ddf 100644
--- a/platform/darwin/test/MGLCircleStyleLayerTests.mm
+++ b/platform/darwin/test/MGLCircleStyleLayerTests.mm
@@ -85,7 +85,8 @@
XCTAssertEqual(rawLayer->getCircleBlur(), propertyValue,
@"Setting circleBlur to a data expression should update circle-blur.");
- XCTAssertEqualObjects(layer.circleBlur, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -98,7 +99,8 @@
XCTAssertEqual(rawLayer->getCircleBlur(), propertyValue,
@"Setting circleBlur to a camera-data expression should update circle-blur.");
- XCTAssertEqualObjects(layer.circleBlur, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.circleBlur, pedanticFunctionExpression,
@"circleBlur should round-trip camera-data expressions.");
@@ -155,7 +157,8 @@
XCTAssertEqual(rawLayer->getCircleColor(), propertyValue,
@"Setting circleColor to a data expression should update circle-color.");
- XCTAssertEqualObjects(layer.circleColor, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -168,7 +171,8 @@
XCTAssertEqual(rawLayer->getCircleColor(), propertyValue,
@"Setting circleColor to a camera-data expression should update circle-color.");
- XCTAssertEqualObjects(layer.circleColor, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.circleColor, pedanticFunctionExpression,
@"circleColor should round-trip camera-data expressions.");
@@ -225,7 +229,8 @@
XCTAssertEqual(rawLayer->getCircleOpacity(), propertyValue,
@"Setting circleOpacity to a data expression should update circle-opacity.");
- XCTAssertEqualObjects(layer.circleOpacity, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -238,7 +243,8 @@
XCTAssertEqual(rawLayer->getCircleOpacity(), propertyValue,
@"Setting circleOpacity to a camera-data expression should update circle-opacity.");
- XCTAssertEqualObjects(layer.circleOpacity, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.circleOpacity, pedanticFunctionExpression,
@"circleOpacity should round-trip camera-data expressions.");
@@ -339,7 +345,8 @@
XCTAssertEqual(rawLayer->getCircleRadius(), propertyValue,
@"Setting circleRadius to a data expression should update circle-radius.");
- XCTAssertEqualObjects(layer.circleRadius, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -352,7 +359,8 @@
XCTAssertEqual(rawLayer->getCircleRadius(), propertyValue,
@"Setting circleRadius to a camera-data expression should update circle-radius.");
- XCTAssertEqualObjects(layer.circleRadius, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.circleRadius, pedanticFunctionExpression,
@"circleRadius should round-trip camera-data expressions.");
@@ -453,7 +461,8 @@
XCTAssertEqual(rawLayer->getCircleStrokeColor(), propertyValue,
@"Setting circleStrokeColor to a data expression should update circle-stroke-color.");
- XCTAssertEqualObjects(layer.circleStrokeColor, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -466,7 +475,8 @@
XCTAssertEqual(rawLayer->getCircleStrokeColor(), propertyValue,
@"Setting circleStrokeColor to a camera-data expression should update circle-stroke-color.");
- XCTAssertEqualObjects(layer.circleStrokeColor, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.circleStrokeColor, pedanticFunctionExpression,
@"circleStrokeColor should round-trip camera-data expressions.");
@@ -523,7 +533,8 @@
XCTAssertEqual(rawLayer->getCircleStrokeOpacity(), propertyValue,
@"Setting circleStrokeOpacity to a data expression should update circle-stroke-opacity.");
- XCTAssertEqualObjects(layer.circleStrokeOpacity, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -536,7 +547,8 @@
XCTAssertEqual(rawLayer->getCircleStrokeOpacity(), propertyValue,
@"Setting circleStrokeOpacity to a camera-data expression should update circle-stroke-opacity.");
- XCTAssertEqualObjects(layer.circleStrokeOpacity, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.circleStrokeOpacity, pedanticFunctionExpression,
@"circleStrokeOpacity should round-trip camera-data expressions.");
@@ -593,7 +605,8 @@
XCTAssertEqual(rawLayer->getCircleStrokeWidth(), propertyValue,
@"Setting circleStrokeWidth to a data expression should update circle-stroke-width.");
- XCTAssertEqualObjects(layer.circleStrokeWidth, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -606,7 +619,8 @@
XCTAssertEqual(rawLayer->getCircleStrokeWidth(), propertyValue,
@"Setting circleStrokeWidth to a camera-data expression should update circle-stroke-width.");
- XCTAssertEqualObjects(layer.circleStrokeWidth, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.circleStrokeWidth, pedanticFunctionExpression,
@"circleStrokeWidth should round-trip camera-data expressions.");
diff --git a/platform/darwin/test/MGLExpressionTests.mm b/platform/darwin/test/MGLExpressionTests.mm
index bcc708e51e..35f97326c6 100644
--- a/platform/darwin/test/MGLExpressionTests.mm
+++ b/platform/darwin/test/MGLExpressionTests.mm
@@ -559,6 +559,19 @@ using namespace std::string_literals;
XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject: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 mgl_expressionWithJSONObject: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);
@@ -624,6 +637,13 @@ using namespace std::string_literals;
XCTAssertEqualObjects(compatibilityExpression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject: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 mgl_expressionWithJSONObject:jsonExpression], expression);
+ }
}
- (void)testMatchExpressionObject {
diff --git a/platform/darwin/test/MGLFillExtrusionStyleLayerTests.mm b/platform/darwin/test/MGLFillExtrusionStyleLayerTests.mm
index 876386948c..9fa5a7eb8b 100644
--- a/platform/darwin/test/MGLFillExtrusionStyleLayerTests.mm
+++ b/platform/darwin/test/MGLFillExtrusionStyleLayerTests.mm
@@ -85,7 +85,8 @@
XCTAssertEqual(rawLayer->getFillExtrusionBase(), propertyValue,
@"Setting fillExtrusionBase to a data expression should update fill-extrusion-base.");
- XCTAssertEqualObjects(layer.fillExtrusionBase, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -98,7 +99,8 @@
XCTAssertEqual(rawLayer->getFillExtrusionBase(), propertyValue,
@"Setting fillExtrusionBase to a camera-data expression should update fill-extrusion-base.");
- XCTAssertEqualObjects(layer.fillExtrusionBase, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.fillExtrusionBase, pedanticFunctionExpression,
@"fillExtrusionBase should round-trip camera-data expressions.");
@@ -155,7 +157,8 @@
XCTAssertEqual(rawLayer->getFillExtrusionColor(), propertyValue,
@"Setting fillExtrusionColor to a data expression should update fill-extrusion-color.");
- XCTAssertEqualObjects(layer.fillExtrusionColor, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -168,7 +171,8 @@
XCTAssertEqual(rawLayer->getFillExtrusionColor(), propertyValue,
@"Setting fillExtrusionColor to a camera-data expression should update fill-extrusion-color.");
- XCTAssertEqualObjects(layer.fillExtrusionColor, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.fillExtrusionColor, pedanticFunctionExpression,
@"fillExtrusionColor should round-trip camera-data expressions.");
@@ -225,7 +229,8 @@
XCTAssertEqual(rawLayer->getFillExtrusionHeight(), propertyValue,
@"Setting fillExtrusionHeight to a data expression should update fill-extrusion-height.");
- XCTAssertEqualObjects(layer.fillExtrusionHeight, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -238,7 +243,8 @@
XCTAssertEqual(rawLayer->getFillExtrusionHeight(), propertyValue,
@"Setting fillExtrusionHeight to a camera-data expression should update fill-extrusion-height.");
- XCTAssertEqualObjects(layer.fillExtrusionHeight, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.fillExtrusionHeight, pedanticFunctionExpression,
@"fillExtrusionHeight should round-trip camera-data expressions.");
diff --git a/platform/darwin/test/MGLFillStyleLayerTests.mm b/platform/darwin/test/MGLFillStyleLayerTests.mm
index 8fa349c135..1c2342bb0f 100644
--- a/platform/darwin/test/MGLFillStyleLayerTests.mm
+++ b/platform/darwin/test/MGLFillStyleLayerTests.mm
@@ -129,7 +129,8 @@
XCTAssertEqual(rawLayer->getFillColor(), propertyValue,
@"Setting fillColor to a data expression should update fill-color.");
- XCTAssertEqualObjects(layer.fillColor, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -142,7 +143,8 @@
XCTAssertEqual(rawLayer->getFillColor(), propertyValue,
@"Setting fillColor to a camera-data expression should update fill-color.");
- XCTAssertEqualObjects(layer.fillColor, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.fillColor, pedanticFunctionExpression,
@"fillColor should round-trip camera-data expressions.");
@@ -199,7 +201,8 @@
XCTAssertEqual(rawLayer->getFillOpacity(), propertyValue,
@"Setting fillOpacity to a data expression should update fill-opacity.");
- XCTAssertEqualObjects(layer.fillOpacity, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -212,7 +215,8 @@
XCTAssertEqual(rawLayer->getFillOpacity(), propertyValue,
@"Setting fillOpacity to a camera-data expression should update fill-opacity.");
- XCTAssertEqualObjects(layer.fillOpacity, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.fillOpacity, pedanticFunctionExpression,
@"fillOpacity should round-trip camera-data expressions.");
@@ -269,7 +273,8 @@
XCTAssertEqual(rawLayer->getFillOutlineColor(), propertyValue,
@"Setting fillOutlineColor to a data expression should update fill-outline-color.");
- XCTAssertEqualObjects(layer.fillOutlineColor, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -282,7 +287,8 @@
XCTAssertEqual(rawLayer->getFillOutlineColor(), propertyValue,
@"Setting fillOutlineColor to a camera-data expression should update fill-outline-color.");
- XCTAssertEqualObjects(layer.fillOutlineColor, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.fillOutlineColor, pedanticFunctionExpression,
@"fillOutlineColor should round-trip camera-data expressions.");
diff --git a/platform/darwin/test/MGLHeatmapColorTests.mm b/platform/darwin/test/MGLHeatmapColorTests.mm
index ba28cc0345..bed777ae05 100644
--- a/platform/darwin/test/MGLHeatmapColorTests.mm
+++ b/platform/darwin/test/MGLHeatmapColorTests.mm
@@ -46,7 +46,8 @@
layer.heatmapColor = nil;
XCTAssertTrue(rawLayer->getHeatmapColor().isUndefined(),
@"Unsetting heatmapColor should return heatmap-color to the default value.");
- XCTAssertEqualObjects(layer.heatmapColor, defaultExpression,
+ // 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}];
diff --git a/platform/darwin/test/MGLHeatmapStyleLayerTests.mm b/platform/darwin/test/MGLHeatmapStyleLayerTests.mm
index 4b51c6cc62..54ba5c2fe9 100644
--- a/platform/darwin/test/MGLHeatmapStyleLayerTests.mm
+++ b/platform/darwin/test/MGLHeatmapStyleLayerTests.mm
@@ -191,7 +191,8 @@
XCTAssertEqual(rawLayer->getHeatmapRadius(), propertyValue,
@"Setting heatmapRadius to a data expression should update heatmap-radius.");
- XCTAssertEqualObjects(layer.heatmapRadius, functionExpression,
+ 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}];
@@ -204,7 +205,8 @@
XCTAssertEqual(rawLayer->getHeatmapRadius(), propertyValue,
@"Setting heatmapRadius to a camera-data expression should update heatmap-radius.");
- XCTAssertEqualObjects(layer.heatmapRadius, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.heatmapRadius, pedanticFunctionExpression,
@"heatmapRadius should round-trip camera-data expressions.");
@@ -261,7 +263,8 @@
XCTAssertEqual(rawLayer->getHeatmapWeight(), propertyValue,
@"Setting heatmapWeight to a data expression should update heatmap-weight.");
- XCTAssertEqualObjects(layer.heatmapWeight, functionExpression,
+ 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}];
@@ -274,7 +277,8 @@
XCTAssertEqual(rawLayer->getHeatmapWeight(), propertyValue,
@"Setting heatmapWeight to a camera-data expression should update heatmap-weight.");
- XCTAssertEqualObjects(layer.heatmapWeight, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.heatmapWeight, pedanticFunctionExpression,
@"heatmapWeight should round-trip camera-data expressions.");
diff --git a/platform/darwin/test/MGLLineStyleLayerTests.mm b/platform/darwin/test/MGLLineStyleLayerTests.mm
index bbc382567b..1a81a16eee 100644
--- a/platform/darwin/test/MGLLineStyleLayerTests.mm
+++ b/platform/darwin/test/MGLLineStyleLayerTests.mm
@@ -255,7 +255,8 @@
XCTAssertEqual(rawLayer->getLineBlur(), propertyValue,
@"Setting lineBlur to a data expression should update line-blur.");
- XCTAssertEqualObjects(layer.lineBlur, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -268,7 +269,8 @@
XCTAssertEqual(rawLayer->getLineBlur(), propertyValue,
@"Setting lineBlur to a camera-data expression should update line-blur.");
- XCTAssertEqualObjects(layer.lineBlur, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.lineBlur, pedanticFunctionExpression,
@"lineBlur should round-trip camera-data expressions.");
@@ -325,7 +327,8 @@
XCTAssertEqual(rawLayer->getLineColor(), propertyValue,
@"Setting lineColor to a data expression should update line-color.");
- XCTAssertEqualObjects(layer.lineColor, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -338,7 +341,8 @@
XCTAssertEqual(rawLayer->getLineColor(), propertyValue,
@"Setting lineColor to a camera-data expression should update line-color.");
- XCTAssertEqualObjects(layer.lineColor, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.lineColor, pedanticFunctionExpression,
@"lineColor should round-trip camera-data expressions.");
@@ -439,7 +443,8 @@
XCTAssertEqual(rawLayer->getLineGapWidth(), propertyValue,
@"Setting lineGapWidth to a data expression should update line-gap-width.");
- XCTAssertEqualObjects(layer.lineGapWidth, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -452,7 +457,8 @@
XCTAssertEqual(rawLayer->getLineGapWidth(), propertyValue,
@"Setting lineGapWidth to a camera-data expression should update line-gap-width.");
- XCTAssertEqualObjects(layer.lineGapWidth, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.lineGapWidth, pedanticFunctionExpression,
@"lineGapWidth should round-trip camera-data expressions.");
@@ -509,7 +515,8 @@
XCTAssertEqual(rawLayer->getLineOffset(), propertyValue,
@"Setting lineOffset to a data expression should update line-offset.");
- XCTAssertEqualObjects(layer.lineOffset, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -522,7 +529,8 @@
XCTAssertEqual(rawLayer->getLineOffset(), propertyValue,
@"Setting lineOffset to a camera-data expression should update line-offset.");
- XCTAssertEqualObjects(layer.lineOffset, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.lineOffset, pedanticFunctionExpression,
@"lineOffset should round-trip camera-data expressions.");
@@ -579,7 +587,8 @@
XCTAssertEqual(rawLayer->getLineOpacity(), propertyValue,
@"Setting lineOpacity to a data expression should update line-opacity.");
- XCTAssertEqualObjects(layer.lineOpacity, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -592,7 +601,8 @@
XCTAssertEqual(rawLayer->getLineOpacity(), propertyValue,
@"Setting lineOpacity to a camera-data expression should update line-opacity.");
- XCTAssertEqualObjects(layer.lineOpacity, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.lineOpacity, pedanticFunctionExpression,
@"lineOpacity should round-trip camera-data expressions.");
@@ -796,7 +806,8 @@
XCTAssertEqual(rawLayer->getLineWidth(), propertyValue,
@"Setting lineWidth to a data expression should update line-width.");
- XCTAssertEqualObjects(layer.lineWidth, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -809,7 +820,8 @@
XCTAssertEqual(rawLayer->getLineWidth(), propertyValue,
@"Setting lineWidth to a camera-data expression should update line-width.");
- XCTAssertEqualObjects(layer.lineWidth, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.lineWidth, pedanticFunctionExpression,
@"lineWidth should round-trip camera-data expressions.");
diff --git a/platform/darwin/test/MGLStyleLayerTests.mm.ejs b/platform/darwin/test/MGLStyleLayerTests.mm.ejs
index ef4ffdb42e..aa62095b09 100644
--- a/platform/darwin/test/MGLStyleLayerTests.mm.ejs
+++ b/platform/darwin/test/MGLStyleLayerTests.mm.ejs
@@ -103,7 +103,8 @@
XCTAssertEqual(rawLayer->get<%- camelize(originalPropertyName(property)) %>(), propertyValue,
@"Setting <%- objCName(property) %> to a data expression should update <%- originalPropertyName(property) %>.");
- XCTAssertEqualObjects(layer.<%- objCName(property) %>, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -116,7 +117,8 @@
XCTAssertEqual(rawLayer->get<%- camelize(originalPropertyName(property)) %>(), propertyValue,
@"Setting <%- objCName(property) %> to a camera-data expression should update <%- originalPropertyName(property) %>.");
- XCTAssertEqualObjects(layer.<%- objCName(property) %>, functionExpression,
+ 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) { -%>
diff --git a/platform/darwin/test/MGLSymbolStyleLayerTests.mm b/platform/darwin/test/MGLSymbolStyleLayerTests.mm
index 06ff058a8e..1d4be119f2 100644
--- a/platform/darwin/test/MGLSymbolStyleLayerTests.mm
+++ b/platform/darwin/test/MGLSymbolStyleLayerTests.mm
@@ -255,7 +255,8 @@
XCTAssertEqual(rawLayer->getIconOffset(), propertyValue,
@"Setting iconOffset to a data expression should update icon-offset.");
- XCTAssertEqualObjects(layer.iconOffset, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -268,7 +269,8 @@
XCTAssertEqual(rawLayer->getIconOffset(), propertyValue,
@"Setting iconOffset to a camera-data expression should update icon-offset.");
- XCTAssertEqualObjects(layer.iconOffset, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.iconOffset, pedanticFunctionExpression,
@"iconOffset should round-trip camera-data expressions.");
@@ -448,7 +450,8 @@
XCTAssertEqual(rawLayer->getIconRotate(), propertyValue,
@"Setting iconRotation to a data expression should update icon-rotate.");
- XCTAssertEqualObjects(layer.iconRotation, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -461,7 +464,8 @@
XCTAssertEqual(rawLayer->getIconRotate(), propertyValue,
@"Setting iconRotation to a camera-data expression should update icon-rotate.");
- XCTAssertEqualObjects(layer.iconRotation, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.iconRotation, pedanticFunctionExpression,
@"iconRotation should round-trip camera-data expressions.");
@@ -553,7 +557,8 @@
XCTAssertEqual(rawLayer->getIconSize(), propertyValue,
@"Setting iconScale to a data expression should update icon-size.");
- XCTAssertEqualObjects(layer.iconScale, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -566,7 +571,8 @@
XCTAssertEqual(rawLayer->getIconSize(), propertyValue,
@"Setting iconScale to a camera-data expression should update icon-size.");
- XCTAssertEqualObjects(layer.iconScale, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.iconScale, pedanticFunctionExpression,
@"iconScale should round-trip camera-data expressions.");
@@ -840,7 +846,8 @@
XCTAssertEqual(rawLayer->getTextMaxWidth(), propertyValue,
@"Setting maximumTextWidth to a data expression should update text-max-width.");
- XCTAssertEqualObjects(layer.maximumTextWidth, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -853,7 +860,8 @@
XCTAssertEqual(rawLayer->getTextMaxWidth(), propertyValue,
@"Setting maximumTextWidth to a camera-data expression should update text-max-width.");
- XCTAssertEqualObjects(layer.maximumTextWidth, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.maximumTextWidth, pedanticFunctionExpression,
@"maximumTextWidth should round-trip camera-data expressions.");
@@ -1191,7 +1199,8 @@
XCTAssertEqual(rawLayer->getTextSize(), propertyValue,
@"Setting textFontSize to a data expression should update text-size.");
- XCTAssertEqualObjects(layer.textFontSize, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -1204,7 +1213,8 @@
XCTAssertEqual(rawLayer->getTextSize(), propertyValue,
@"Setting textFontSize to a camera-data expression should update text-size.");
- XCTAssertEqualObjects(layer.textFontSize, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.textFontSize, pedanticFunctionExpression,
@"textFontSize should round-trip camera-data expressions.");
@@ -1334,7 +1344,8 @@
XCTAssertEqual(rawLayer->getTextLetterSpacing(), propertyValue,
@"Setting textLetterSpacing to a data expression should update text-letter-spacing.");
- XCTAssertEqualObjects(layer.textLetterSpacing, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -1347,7 +1358,8 @@
XCTAssertEqual(rawLayer->getTextLetterSpacing(), propertyValue,
@"Setting textLetterSpacing to a camera-data expression should update text-letter-spacing.");
- XCTAssertEqualObjects(layer.textLetterSpacing, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.textLetterSpacing, pedanticFunctionExpression,
@"textLetterSpacing should round-trip camera-data expressions.");
@@ -1445,7 +1457,8 @@
XCTAssertEqual(rawLayer->getTextOffset(), propertyValue,
@"Setting textOffset to a data expression should update text-offset.");
- XCTAssertEqualObjects(layer.textOffset, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -1458,7 +1471,8 @@
XCTAssertEqual(rawLayer->getTextOffset(), propertyValue,
@"Setting textOffset to a camera-data expression should update text-offset.");
- XCTAssertEqualObjects(layer.textOffset, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.textOffset, pedanticFunctionExpression,
@"textOffset should round-trip camera-data expressions.");
@@ -1638,7 +1652,8 @@
XCTAssertEqual(rawLayer->getTextRotate(), propertyValue,
@"Setting textRotation to a data expression should update text-rotate.");
- XCTAssertEqualObjects(layer.textRotation, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -1651,7 +1666,8 @@
XCTAssertEqual(rawLayer->getTextRotate(), propertyValue,
@"Setting textRotation to a camera-data expression should update text-rotate.");
- XCTAssertEqualObjects(layer.textRotation, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.textRotation, pedanticFunctionExpression,
@"textRotation should round-trip camera-data expressions.");
@@ -1781,7 +1797,8 @@
XCTAssertEqual(rawLayer->getIconColor(), propertyValue,
@"Setting iconColor to a data expression should update icon-color.");
- XCTAssertEqualObjects(layer.iconColor, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -1794,7 +1811,8 @@
XCTAssertEqual(rawLayer->getIconColor(), propertyValue,
@"Setting iconColor to a camera-data expression should update icon-color.");
- XCTAssertEqualObjects(layer.iconColor, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.iconColor, pedanticFunctionExpression,
@"iconColor should round-trip camera-data expressions.");
@@ -1851,7 +1869,8 @@
XCTAssertEqual(rawLayer->getIconHaloBlur(), propertyValue,
@"Setting iconHaloBlur to a data expression should update icon-halo-blur.");
- XCTAssertEqualObjects(layer.iconHaloBlur, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -1864,7 +1883,8 @@
XCTAssertEqual(rawLayer->getIconHaloBlur(), propertyValue,
@"Setting iconHaloBlur to a camera-data expression should update icon-halo-blur.");
- XCTAssertEqualObjects(layer.iconHaloBlur, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.iconHaloBlur, pedanticFunctionExpression,
@"iconHaloBlur should round-trip camera-data expressions.");
@@ -1921,7 +1941,8 @@
XCTAssertEqual(rawLayer->getIconHaloColor(), propertyValue,
@"Setting iconHaloColor to a data expression should update icon-halo-color.");
- XCTAssertEqualObjects(layer.iconHaloColor, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -1934,7 +1955,8 @@
XCTAssertEqual(rawLayer->getIconHaloColor(), propertyValue,
@"Setting iconHaloColor to a camera-data expression should update icon-halo-color.");
- XCTAssertEqualObjects(layer.iconHaloColor, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.iconHaloColor, pedanticFunctionExpression,
@"iconHaloColor should round-trip camera-data expressions.");
@@ -1991,7 +2013,8 @@
XCTAssertEqual(rawLayer->getIconHaloWidth(), propertyValue,
@"Setting iconHaloWidth to a data expression should update icon-halo-width.");
- XCTAssertEqualObjects(layer.iconHaloWidth, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -2004,7 +2027,8 @@
XCTAssertEqual(rawLayer->getIconHaloWidth(), propertyValue,
@"Setting iconHaloWidth to a camera-data expression should update icon-halo-width.");
- XCTAssertEqualObjects(layer.iconHaloWidth, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.iconHaloWidth, pedanticFunctionExpression,
@"iconHaloWidth should round-trip camera-data expressions.");
@@ -2061,7 +2085,8 @@
XCTAssertEqual(rawLayer->getIconOpacity(), propertyValue,
@"Setting iconOpacity to a data expression should update icon-opacity.");
- XCTAssertEqualObjects(layer.iconOpacity, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -2074,7 +2099,8 @@
XCTAssertEqual(rawLayer->getIconOpacity(), propertyValue,
@"Setting iconOpacity to a camera-data expression should update icon-opacity.");
- XCTAssertEqualObjects(layer.iconOpacity, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.iconOpacity, pedanticFunctionExpression,
@"iconOpacity should round-trip camera-data expressions.");
@@ -2225,7 +2251,8 @@
XCTAssertEqual(rawLayer->getTextColor(), propertyValue,
@"Setting textColor to a data expression should update text-color.");
- XCTAssertEqualObjects(layer.textColor, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -2238,7 +2265,8 @@
XCTAssertEqual(rawLayer->getTextColor(), propertyValue,
@"Setting textColor to a camera-data expression should update text-color.");
- XCTAssertEqualObjects(layer.textColor, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.textColor, pedanticFunctionExpression,
@"textColor should round-trip camera-data expressions.");
@@ -2295,7 +2323,8 @@
XCTAssertEqual(rawLayer->getTextHaloBlur(), propertyValue,
@"Setting textHaloBlur to a data expression should update text-halo-blur.");
- XCTAssertEqualObjects(layer.textHaloBlur, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -2308,7 +2337,8 @@
XCTAssertEqual(rawLayer->getTextHaloBlur(), propertyValue,
@"Setting textHaloBlur to a camera-data expression should update text-halo-blur.");
- XCTAssertEqualObjects(layer.textHaloBlur, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.textHaloBlur, pedanticFunctionExpression,
@"textHaloBlur should round-trip camera-data expressions.");
@@ -2365,7 +2395,8 @@
XCTAssertEqual(rawLayer->getTextHaloColor(), propertyValue,
@"Setting textHaloColor to a data expression should update text-halo-color.");
- XCTAssertEqualObjects(layer.textHaloColor, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -2378,7 +2409,8 @@
XCTAssertEqual(rawLayer->getTextHaloColor(), propertyValue,
@"Setting textHaloColor to a camera-data expression should update text-halo-color.");
- XCTAssertEqualObjects(layer.textHaloColor, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.textHaloColor, pedanticFunctionExpression,
@"textHaloColor should round-trip camera-data expressions.");
@@ -2435,7 +2467,8 @@
XCTAssertEqual(rawLayer->getTextHaloWidth(), propertyValue,
@"Setting textHaloWidth to a data expression should update text-halo-width.");
- XCTAssertEqualObjects(layer.textHaloWidth, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -2448,7 +2481,8 @@
XCTAssertEqual(rawLayer->getTextHaloWidth(), propertyValue,
@"Setting textHaloWidth to a camera-data expression should update text-halo-width.");
- XCTAssertEqualObjects(layer.textHaloWidth, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.textHaloWidth, pedanticFunctionExpression,
@"textHaloWidth should round-trip camera-data expressions.");
@@ -2505,7 +2539,8 @@
XCTAssertEqual(rawLayer->getTextOpacity(), propertyValue,
@"Setting textOpacity to a data expression should update text-opacity.");
- XCTAssertEqualObjects(layer.textOpacity, functionExpression,
+ 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.");
functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
@@ -2518,7 +2553,8 @@
XCTAssertEqual(rawLayer->getTextOpacity(), propertyValue,
@"Setting textOpacity to a camera-data expression should update text-opacity.");
- XCTAssertEqualObjects(layer.textOpacity, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.textOpacity, pedanticFunctionExpression,
@"textOpacity should round-trip camera-data expressions.");
diff --git a/platform/ios/src/UIColor+MGLAdditions.h b/platform/ios/src/UIColor+MGLAdditions.h
index ea415d9db9..60cfe1c58b 100644
--- a/platform/ios/src/UIColor+MGLAdditions.h
+++ b/platform/ios/src/UIColor+MGLAdditions.h
@@ -12,3 +12,10 @@
+ (UIColor *)mgl_colorWithColor:(mbgl::Color)color;
@end
+
+@interface NSExpression (MGLColorAdditions)
+
++ (NSExpression *)mgl_expressionForRGBComponents:(NSArray<NSExpression *> *)components;
++ (NSExpression *)mgl_expressionForRGBAComponents:(NSArray<NSExpression *> *)components;
+
+@end
diff --git a/platform/ios/src/UIColor+MGLAdditions.mm b/platform/ios/src/UIColor+MGLAdditions.mm
index 41c066c206..9ca39acda4 100644
--- a/platform/ios/src/UIColor+MGLAdditions.mm
+++ b/platform/ios/src/UIColor+MGLAdditions.mm
@@ -21,3 +21,52 @@
}
@end
+
+@implementation NSExpression (MGLColorAdditions)
+
++ (NSExpression *)mgl_expressionForRGBComponents:(NSArray<NSExpression *> *)components {
+ if (UIColor *color = [self mgl_colorWithRGBComponents:components]) {
+ return [NSExpression expressionForConstantValue:color];
+ }
+
+ NSExpression *color = [NSExpression expressionForConstantValue:[UIColor class]];
+ NSExpression *alpha = [NSExpression expressionForConstantValue:@1.0];
+ return [NSExpression expressionForFunction:color
+ selectorName:@"colorWithRed:green:blue:alpha:"
+ arguments:[components arrayByAddingObject:alpha]];
+}
+
++ (NSExpression *)mgl_expressionForRGBAComponents:(NSArray<NSExpression *> *)components {
+ if (UIColor *color = [self mgl_colorWithRGBComponents:components]) {
+ return [NSExpression expressionForConstantValue:color];
+ }
+
+ NSExpression *color = [NSExpression expressionForConstantValue:[UIColor class]];
+ return [NSExpression expressionForFunction:color
+ selectorName:@"colorWithRed:green:blue:alpha:"
+ arguments:components];
+}
+
++ (UIColor *)mgl_colorWithRGBComponents:(NSArray<NSExpression *> *)components {
+ if (components.count < 3 || components.count > 4) {
+ return nil;
+ }
+
+ for (NSExpression *component in components) {
+ if (component.expressionType != NSConstantValueExpressionType) {
+ return nil;
+ }
+
+ NSNumber *number = (NSNumber *)component.constantValue;
+ if (![number isKindOfClass:[NSNumber class]]) {
+ return nil;
+ }
+ }
+
+ return [UIColor colorWithRed:[components[0].constantValue doubleValue] / 255.0
+ green:[components[1].constantValue doubleValue] / 255.0
+ blue:[components[2].constantValue doubleValue] / 255.0
+ alpha:components.count == 3 ? [components[3].constantValue doubleValue] : 1.0];
+}
+
+@end
diff --git a/platform/macos/src/NSColor+MGLAdditions.h b/platform/macos/src/NSColor+MGLAdditions.h
index af9b8b0255..21c939fec6 100644
--- a/platform/macos/src/NSColor+MGLAdditions.h
+++ b/platform/macos/src/NSColor+MGLAdditions.h
@@ -18,3 +18,10 @@
- (mbgl::style::PropertyValue<mbgl::Color>)mgl_colorPropertyValue;
@end
+
+@interface NSExpression (MGLColorAdditions)
+
++ (NSExpression *)mgl_expressionForRGBComponents:(NSArray<NSExpression *> *)components;
++ (NSExpression *)mgl_expressionForRGBAComponents:(NSArray<NSExpression *> *)components;
+
+@end
diff --git a/platform/macos/src/NSColor+MGLAdditions.mm b/platform/macos/src/NSColor+MGLAdditions.mm
index f44cb8d434..8c9086ccf7 100644
--- a/platform/macos/src/NSColor+MGLAdditions.mm
+++ b/platform/macos/src/NSColor+MGLAdditions.mm
@@ -33,3 +33,67 @@
}
@end
+
+@implementation NSExpression (MGLColorAdditions)
+
++ (NSExpression *)mgl_expressionForRGBComponents:(NSArray<NSExpression *> *)components {
+ if (NSColor *color = [self mgl_colorWithComponentExpressions:components]) {
+ return [NSExpression expressionForConstantValue:color];
+ }
+
+ NSExpression *color = [NSExpression expressionForConstantValue:[NSColor class]];
+ NSExpression *alpha = [NSExpression expressionForConstantValue:@1.0];
+ return [NSExpression expressionForFunction:color
+ selectorName:@"colorWithRed:green:blue:alpha:"
+ arguments:[components arrayByAddingObject:alpha]];
+}
+
++ (NSExpression *)mgl_expressionForRGBAComponents:(NSArray<NSExpression *> *)components {
+ if (NSColor *color = [self mgl_colorWithComponentExpressions:components]) {
+ return [NSExpression expressionForConstantValue:color];
+ }
+
+ NSExpression *color = [NSExpression expressionForConstantValue:[NSColor class]];
+ return [NSExpression expressionForFunction:color
+ selectorName:@"colorWithRed:green:blue:alpha:"
+ arguments:components];
+}
+
+/**
+ Returns a color object corresponding to the given component expressions.
+ */
++ (NSColor *)mgl_colorWithComponentExpressions:(NSArray<NSExpression *> *)componentExpressions {
+ // Map the component expressions to constant components. If any component is
+ // a non-constant expression, the components cannot be converted into a
+ // constant color value.
+ std::vector<CGFloat> components;
+ for (NSExpression *componentExpression in componentExpressions) {
+ if (componentExpression.expressionType != NSConstantValueExpressionType) {
+ return nil;
+ }
+
+ NSNumber *component = (NSNumber *)componentExpression.constantValue;
+ if (![component isKindOfClass:[NSNumber class]]) {
+ return nil;
+ }
+
+ components.push_back(component.doubleValue / 255.0);
+ }
+ // Alpha
+ components.back() *= 255.0;
+
+ // macOS 10.12 Sierra and below uses calibrated RGB by default.
+ if ([NSColor redColor].colorSpaceName == NSCalibratedRGBColorSpace) {
+ return [NSColor colorWithCalibratedRed:components[0]
+ green:components[1]
+ blue:components[2]
+ alpha:components[3]];
+ }
+ // The Mapbox Style Specification does not specify a color space, but it is
+ // assumed to be sRGB for consistency with CSS.
+ return [NSColor colorWithColorSpace:[NSColorSpace sRGBColorSpace]
+ components:&components[0]
+ count:components.size()];
+}
+
+@end