From 59e92904c360e5aad94a1b789276bf6147120d7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Fri, 30 Mar 2018 16:43:55 -0700 Subject: 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 --- platform/darwin/src/MGLStyleValue.mm | 87 ++--------------- platform/darwin/src/NSExpression+MGLAdditions.mm | 14 ++- platform/darwin/test/MGLCircleStyleLayerTests.mm | 42 +++++--- platform/darwin/test/MGLExpressionTests.mm | 20 ++++ .../darwin/test/MGLFillExtrusionStyleLayerTests.mm | 18 ++-- platform/darwin/test/MGLFillStyleLayerTests.mm | 18 ++-- platform/darwin/test/MGLHeatmapColorTests.mm | 3 +- platform/darwin/test/MGLHeatmapStyleLayerTests.mm | 12 ++- platform/darwin/test/MGLLineStyleLayerTests.mm | 36 ++++--- platform/darwin/test/MGLStyleLayerTests.mm.ejs | 6 +- platform/darwin/test/MGLSymbolStyleLayerTests.mm | 108 ++++++++++++++------- platform/ios/src/UIColor+MGLAdditions.h | 7 ++ platform/ios/src/UIColor+MGLAdditions.mm | 49 ++++++++++ platform/macos/src/NSColor+MGLAdditions.h | 7 ++ platform/macos/src/NSColor+MGLAdditions.mm | 64 ++++++++++++ 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 spherical = value.getSpherical(); MGLSphericalPosition position = MGLSphericalPositionMake(spherical[0], spherical[1], spherical[2]); return [NSValue valueWithMGLSphericalPosition:position]; - }, [&](const std::vector &vector) { + }, [&](const std::vector &vector) { NSMutableArray *array = [NSMutableArray arrayWithCapacity:vector.size()]; for (auto value : vector) { [array addObject:MGLJSONObjectFromMBGLValue(value)]; } - return @[@"literal", array]; - }, [&](const std::unordered_map &map) { + return array; + }, [&](const std::unordered_map &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(&mbglExpression)) { - auto result = literalExpression->evaluate({ nullptr }); - return result ? MGLJSONObjectFromMBGLValue(*result) : nil; - } - if (auto assertExpression = dynamic_cast(&mbglExpression)) { - NSMutableArray *inputs = [NSMutableArray array]; - assertExpression->eachChild([&](const Expression &child) { - [inputs addObject:MGLJSONObjectFromMBGLExpression(child)]; - }); - return @[@"literal", inputs.lastObject]; - } - if (auto assertExpression = dynamic_cast(&mbglExpression)) { - NSMutableArray *inputs = [NSMutableArray array]; - assertExpression->eachChild([&](const Expression &child) { - [inputs addObject:MGLJSONObjectFromMBGLExpression(child)]; - }); - return inputs.firstObject; - } - if (auto compoundExpression = dynamic_cast(&mbglExpression)) { - const std::string name = compoundExpression->getName(); - mbgl::optional 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(&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(&mbglExpression)) { - auto &interpolator = interpolateExpression->getInterpolator(); - auto &input = interpolateExpression->getInput(); - NSArray *interpolatorObject; - if (interpolator.is()) { - auto exponentialInterpolator = interpolator.get(); - interpolatorObject = exponentialInterpolator.base == 1 ? @[@"linear"] : @[@"exponential", @(exponentialInterpolator.base)]; - } else if (interpolator.is()) { - auto cubicBezierInterpolator = interpolator.get(); - 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(&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 @@ -558,6 +558,19 @@ using namespace std::string_literals; // because it returns a primitive instead of an object. 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"]]; @@ -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 *)components; ++ (NSExpression *)mgl_expressionForRGBAComponents:(NSArray *)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 *)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 *)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 *)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)mgl_colorPropertyValue; @end + +@interface NSExpression (MGLColorAdditions) + ++ (NSExpression *)mgl_expressionForRGBComponents:(NSArray *)components; ++ (NSExpression *)mgl_expressionForRGBAComponents:(NSArray *)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 *)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 *)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 *)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 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 -- cgit v1.2.1