summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Guerra <fabian.guerra@mapbox.com>2019-03-12 16:08:08 -0700
committerFabian Guerra <fabian.guerra@mapbox.com>2019-03-14 12:59:45 -0700
commita76a9c749480864b92e0b81c40733a752816ba51 (patch)
tree957b3e0b89fe120d8e135f7f73fe80401c3ecc70
parentf693a72ca37029b014850f99a0c0fe9ba57fd593 (diff)
downloadqtlocation-mapboxgl-a76a9c749480864b92e0b81c40733a752816ba51.tar.gz
[ios, macos] Add format expression support.
-rw-r--r--platform/darwin/src/NSExpression+MGLAdditions.h2
-rw-r--r--platform/darwin/src/NSExpression+MGLAdditions.mm57
-rw-r--r--platform/darwin/test/MGLExpressionTests.mm39
3 files changed, 80 insertions, 18 deletions
diff --git a/platform/darwin/src/NSExpression+MGLAdditions.h b/platform/darwin/src/NSExpression+MGLAdditions.h
index 1e6fd6fc46..c7a5f5a969 100644
--- a/platform/darwin/src/NSExpression+MGLAdditions.h
+++ b/platform/darwin/src/NSExpression+MGLAdditions.h
@@ -7,6 +7,8 @@
#import "MGLTypes.h"
+@class MGLAttributedExpression;
+
NS_ASSUME_NONNULL_BEGIN
typedef NSString *MGLExpressionInterpolationMode NS_TYPED_ENUM;
diff --git a/platform/darwin/src/NSExpression+MGLAdditions.mm b/platform/darwin/src/NSExpression+MGLAdditions.mm
index 6aaba4dd90..b53fe63d55 100644
--- a/platform/darwin/src/NSExpression+MGLAdditions.mm
+++ b/platform/darwin/src/NSExpression+MGLAdditions.mm
@@ -11,6 +11,7 @@
#import "NSPredicate+MGLAdditions.h"
#import "NSValue+MGLStyleAttributeAdditions.h"
#import "MGLVectorTileSource_Private.h"
+#import "MGLAttributedExpression.h"
#import <objc/runtime.h>
@@ -75,6 +76,7 @@ const MGLExpressionInterpolationMode MGLExpressionInterpolationModeCubicBezier =
INSTALL_METHOD(mgl_atan:);
INSTALL_METHOD(mgl_tan:);
INSTALL_METHOD(mgl_log2:);
+ INSTALL_METHOD(mgl_attributed:);
// Install functions that resemble control structures, taking arbitrary
// numbers of arguments. Vararg aftermarket functions need to be declared
@@ -96,6 +98,12 @@ const MGLExpressionInterpolationMode MGLExpressionInterpolationModeCubicBezier =
return [components componentsJoinedByString:@""];
}
+- (NSString *)mgl_attributed:(NSArray<MGLAttributedExpression *> *)attributedExpressions {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Text format expressions lack underlying Objective-C implementations."];
+ return nil;
+}
+
/**
Rounds the given number to the nearest integer. If the number is halfway
between two integers, this method rounds it away from zero.
@@ -229,7 +237,6 @@ const MGLExpressionInterpolationMode MGLExpressionInterpolationModeCubicBezier =
return nil;
}
-
/**
A placeholder for a catch-all method that evaluates an arbitrary number of
arguments as an expression according to the Mapbox Style Specification’s
@@ -860,6 +867,23 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
return [NSExpression expressionForFunction:@"MGL_MATCH"
arguments:optionsArray];
+ } else if ([op isEqualToString:@"format"]) {
+ NSMutableArray *attributedExpressions = [NSMutableArray array];
+
+ for (NSUInteger index = 0; index < argumentObjects.count; index+=2) {
+ NSExpression *expression = [NSExpression expressionWithMGLJSONObject:argumentObjects[index]];
+ NSMutableDictionary *attrs = [NSMutableDictionary dictionary];
+ if ((index + 1) < argumentObjects.count) {
+ attrs = argumentObjects[index + 1];
+ }
+
+ MGLAttributedExpression *attributedExpression = [[MGLAttributedExpression alloc] initWithExpression:expression attributes:attrs];
+
+ [attributedExpressions addObject:attributedExpression];
+ }
+ NSExpression *subexpression = [NSExpression expressionForConstantValue:attributedExpressions];
+ return [NSExpression expressionForFunction:@"mgl_attributed:" arguments:@[subexpression]];
+
} else if ([op isEqualToString:@"coalesce"]) {
NSMutableArray *expressions = [NSMutableArray array];
for (id operand in argumentObjects) {
@@ -1115,6 +1139,11 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
}
[NSException raise:NSInvalidArgumentException
format:@"Casting expression to %@ not yet implemented.", type];
+ } else if ([function isEqualToString:@"mgl_attributed:"] ||
+ [function isEqualToString:@"MGL_FORMAT:"] ||
+ [function isEqualToString:@"MGL_FORMAT"]) {
+ return [self mgl_jsonFormatExpressionObject];
+
} else if ([function isEqualToString:@"MGL_FUNCTION"] ||
[function isEqualToString:@"MGL_FUNCTION:"]) {
NSExpression *firstOp = self.arguments.firstObject;
@@ -1363,6 +1392,32 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
return expressionObject;
}
+- (id)mgl_jsonFormatExpressionObject {
+ BOOL isAftermarketFunction = [self.function hasPrefix:@"mgl_attributed:"];
+ NSExpression *formatParameter;
+ NSArray<MGLAttributedExpression *> *attributedExpressions;
+
+ if (isAftermarketFunction) {
+ formatParameter = self.arguments.firstObject;
+ } else {
+ formatParameter = self.operand;
+ }
+
+ if ([formatParameter respondsToSelector:@selector(constantValue)] && [formatParameter.constantValue isKindOfClass:[NSArray class]]) {
+ attributedExpressions = (NSArray *)formatParameter.constantValue;
+ }
+
+ NSMutableArray *expressionObject = [NSMutableArray arrayWithObjects:@"format", nil];
+
+ for (NSUInteger index = 0; index < attributedExpressions.count; index++) {
+ MGLAttributedExpression *attributedExpression = attributedExpressions[index];
+ [expressionObject addObject:attributedExpression.expression.mgl_jsonExpressionObject];
+ [expressionObject addObject:attributedExpression.attributes];
+ }
+
+ return expressionObject;
+}
+
#pragma mark Localization
/**
diff --git a/platform/darwin/test/MGLExpressionTests.mm b/platform/darwin/test/MGLExpressionTests.mm
index bcc30e49fd..1152ed3c13 100644
--- a/platform/darwin/test/MGLExpressionTests.mm
+++ b/platform/darwin/test/MGLExpressionTests.mm
@@ -12,6 +12,7 @@
#else
#import "NSColor+MGLAdditions.h"
#endif
+#import "MGLAttributedExpression.h"
#define MGLAssertEqualValues(actual, expected, ...) \
XCTAssertTrue(actual.is<__typeof__(expected)>()); \
@@ -990,6 +991,27 @@ using namespace std::string_literals;
}
}
+- (void)testFormatExpressionObject {
+ {
+ MGLAttributedExpression *attribute1 = [MGLAttributedExpression initWithExpression:[NSExpression expressionForConstantValue:@"foo"]
+ fontNames:nil
+ fontSize:@(1.2)];
+ MGLAttributedExpression *attribute2 = [MGLAttributedExpression initWithExpression:[NSExpression expressionForConstantValue:@"biz"]
+ fontNames:nil
+ fontSize:@(1.0)];
+ MGLAttributedExpression *attribute3 = [MGLAttributedExpression initWithExpression:[NSExpression expressionForConstantValue:@"bar"]
+ fontNames:nil
+ fontSize:@(0.8)];
+ MGLAttributedExpression *attribute4 = [MGLAttributedExpression initWithExpression:[NSExpression expressionForConstantValue:@"\r"]
+ fontNames:@[]
+ fontSize:nil];
+ NSExpression *expression = [NSExpression expressionWithFormat:@"mgl_attributed(%@)", @[attribute1, attribute4, attribute2, attribute3]];
+ NSArray *jsonExpression = @[@"format", @"foo", @{@"font-scale": @1.2}, @"\r", @{}, @"biz", @{@"font-scale": @1.0}, @"bar", @{@"font-scale": @0.8}];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+}
+
- (void)testGenericExpressionObject {
{
NSExpression *expression = [NSExpression expressionWithFormat:@"MGL_FUNCTION('random', 1, 2, 3, 4, 5)"];
@@ -1002,23 +1024,6 @@ using namespace std::string_literals;
XCTAssertThrowsSpecificNamed([expression expressionValueWithObject:nil context:nil], NSException, NSInvalidArgumentException);
}
{
- NSExpression *expression = [NSExpression expressionWithFormat:@"MGL_FUNCTION('format', 'foo', %@, '\r', %@, 'biz', %@, 'bar', %@)", @{@"font-scale": @1.2}, @{}, @{@"font-scale": @1.0}, @{@"font-scale": @0.8}];
- NSArray *jsonExpression = @[@"format", @"foo", @{@"font-scale": @1.2}, @"\r", @{}, @"biz", @{@"font-scale": @1.0}, @"bar", @{@"font-scale": @0.8}];
-
- XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
-
- NSExpression *encodedExpression = [NSExpression expressionWithMGLJSONObject:jsonExpression];
-
- // Expressions encoded from a json create a different constant abstract type
- // thus even tho knowing that the constant values are the same, the base
- // class is not. This compares the resulting array which is type agnostic encoding.
- for (NSUInteger index = 0; index < jsonExpression.count; index++) {
- NSExpression *left = encodedExpression.mgl_jsonExpressionObject[index];
- NSExpression *right = expression.mgl_jsonExpressionObject[index];
- XCTAssertEqualObjects(left.mgl_jsonExpressionObject, right.mgl_jsonExpressionObject);
- }
- }
- {
NSArray *arguments = @[
MGLConstantExpression(@"one"), MGLConstantExpression(@1),
[NSExpression expressionForVariable:@"one"],