diff options
Diffstat (limited to 'platform/darwin/src/MGLStyleValue_Private.h')
-rw-r--r-- | platform/darwin/src/MGLStyleValue_Private.h | 620 |
1 files changed, 113 insertions, 507 deletions
diff --git a/platform/darwin/src/MGLStyleValue_Private.h b/platform/darwin/src/MGLStyleValue_Private.h index 5914e0a2aa..ba4b413a3c 100644 --- a/platform/darwin/src/MGLStyleValue_Private.h +++ b/platform/darwin/src/MGLStyleValue_Private.h @@ -4,11 +4,13 @@ #import "NSValue+MGLStyleAttributeAdditions.h" #import "NSValue+MGLAdditions.h" +#import "NSExpression+MGLPrivateAdditions.h" #import "MGLTypes.h" #import "MGLConversion.h" +#include <mbgl/style/conversion/property_value.hpp> #include <mbgl/style/conversion/data_driven_property_value.hpp> -#include <mbgl/style/conversion.hpp> +#include <mbgl/style/conversion/position.hpp> #import <mbgl/style/types.hpp> #import <mbgl/util/enum.hpp> @@ -23,166 +25,68 @@ #import "NSColor+MGLAdditions.h" #endif +namespace mbgl { + namespace style { + namespace expression { + class Expression; + } + } +} + +id MGLJSONObjectFromMBGLExpression(const mbgl::style::expression::Expression &mbglExpression); + template <typename MBGLType, typename ObjCType, typename MBGLElement = MBGLType, typename ObjCEnum = ObjCType> class MGLStyleValueTransformer { public: - - // Convert an mbgl property value into an mgl style value - MGLStyleValue<ObjCType> *toStyleValue(const mbgl::style::PropertyValue<MBGLType> &mbglValue) { - PropertyValueEvaluator evaluator; - return mbglValue.evaluate(evaluator); - } - - // Convert an mbgl data driven property value into an mgl style value - MGLStyleValue<ObjCType> *toDataDrivenStyleValue(const mbgl::style::DataDrivenPropertyValue<MBGLType> &mbglValue) { - PropertyValueEvaluator evaluator; + + /// Convert an mbgl property value into an mgl style value + NSExpression *toExpression(const mbgl::style::PropertyValue<MBGLType> &mbglValue) { + PropertyExpressionEvaluator evaluator; return mbglValue.evaluate(evaluator); } - - // Convert an mbgl property value containing an enum into an mgl style value - template <typename MBGLEnum = MBGLType, - class = typename std::enable_if<std::is_enum<MBGLEnum>::value>::type, - typename MGLEnum = ObjCEnum, - class = typename std::enable_if<std::is_enum<MGLEnum>::value>::type> - MGLStyleValue<ObjCType> *toEnumStyleValue(const mbgl::style::PropertyValue<MBGLEnum> &mbglValue) { - EnumPropertyValueEvaluator<MBGLEnum, ObjCEnum> evaluator; + + /// Convert an mbgl data driven property value into an mgl style value + template <typename MBGLEnum = MBGLType, typename MGLEnum = ObjCEnum> + NSExpression *toExpression(const mbgl::style::DataDrivenPropertyValue<MBGLEnum> &mbglValue) { + PropertyExpressionEvaluator evaluator; return mbglValue.evaluate(evaluator); } - - // Convert an mgl style value into a non interpolatable (camera with interval stops) mbgl property value - mbgl::style::PropertyValue<MBGLType> toPropertyValue(MGLStyleValue<ObjCType> *value) { - if ([value isKindOfClass:[MGLSourceStyleFunction class]] || [value isKindOfClass:[MGLCompositeStyleFunction class]]) { - [NSException raise:NSInvalidArgumentException - format:@"This property can only be set to camera functions. Use +[MGLStyleValue valueWithInterpolationMode:cameraStops:options:] instead."]; - return {}; - } - - if ([value isKindOfClass:[MGLConstantStyleValue class]]) { - return toMBGLConstantValue((MGLConstantStyleValue<ObjCType> *)value); - } else if ([value isKindOfClass:[MGLCameraStyleFunction class]]) { - MGLCameraStyleFunction<ObjCType> *cameraStyleFunction = (MGLCameraStyleFunction<ObjCType> *)value; - // Intentionally ignore the stop type set by the developer becuase non interpolatable property values - // can only have interval stops. This also allows for backwards compatiblity when the developer uses - // a deprecated MGLStyleValue method (that used to create an MGLStyleFunction) to create a function - // for properties that are piecewise-constant (i.e. enum, bool, string) - return toMBGLIntervalCameraFunction(cameraStyleFunction); - } else if ([value isMemberOfClass:[MGLStyleFunction class]]) { - MGLStyleFunction<ObjCType> *styleFunction = (MGLStyleFunction<ObjCType> *)value; - return toMBGLIntervalCameraFunction(styleFunction); - } else if (value) { - [NSException raise:@"MGLAbstractClassException" format: - @"The style value %@ cannot be applied to the style. " - @"Make sure the style value was created as a member of a concrete subclass of MGLStyleValue.", - NSStringFromClass([value class])]; - return {}; - } else { - return {}; - } - } - - // Convert an mgl style value into a non interpolatable (camera with exponential or interval stops) mbgl property value - mbgl::style::PropertyValue<MBGLType> toInterpolatablePropertyValue(MGLStyleValue<ObjCType> *value) { - if ([value isKindOfClass:[MGLSourceStyleFunction class]] || [value isKindOfClass:[MGLCompositeStyleFunction class]]) { - [NSException raise:NSInvalidArgumentException - format:@"This property can only be set to camera functions. Use +[MGLStyleValue valueWithInterpolationMode:cameraStops:options:] instead."]; + + /** + Converts an NSExpression to an mbgl property value. + */ + template <typename MBGLValue> + MBGLValue toPropertyValue(NSExpression *expression) { + if (!expression) { return {}; } - - if ([value isKindOfClass:[MGLConstantStyleValue class]]) { - return toMBGLConstantValue((MGLConstantStyleValue<ObjCType> *)value); - } else if ([value isMemberOfClass:[MGLStyleFunction class]]) { - MGLStyleFunction<ObjCType> *styleFunction = (MGLStyleFunction<ObjCType> *)value; - return toMBGLExponentialCameraFunction(styleFunction); - } else if ([value isKindOfClass:[MGLCameraStyleFunction class]]) { - MGLCameraStyleFunction<ObjCType> *cameraStyleFunction = (MGLCameraStyleFunction<ObjCType> *)value; - switch (cameraStyleFunction.interpolationMode) { - case MGLInterpolationModeExponential: - return toMBGLExponentialCameraFunction(cameraStyleFunction); - break; - case MGLInterpolationModeInterval: - return toMBGLIntervalCameraFunction(cameraStyleFunction); - break; - default: - [NSException raise:NSInvalidArgumentException - format:@"A camera function must use either exponential or interval stops."]; - break; - } - return {}; - } else if (value) { - [NSException raise:@"MGLAbstractClassException" format: - @"The style value %@ cannot be applied to the style. " - @"Make sure the style value was created as a member of a concrete subclass of MGLStyleValue.", - NSStringFromClass([value class])]; - return {}; - } else { - return {}; + + if (expression.expressionType == NSConstantValueExpressionType) { + MBGLType mbglValue; + getMBGLValue(expression.constantValue, mbglValue); + return mbglValue; } - } - - // Convert an mgl style value into a mbgl data driven property value - mbgl::style::DataDrivenPropertyValue<MBGLType> toDataDrivenPropertyValue(MGLStyleValue<ObjCType> *value) { - if ([value isKindOfClass:[MGLConstantStyleValue class]]) { - return toMBGLConstantValue((MGLConstantStyleValue<ObjCType> *)value); - } else if ([value isKindOfClass:[MGLStyleFunction class]]) { - mbgl::style::conversion::Error error; - auto result = mbgl::style::conversion::convert<mbgl::style::DataDrivenPropertyValue<MBGLType>>( - mbgl::style::conversion::makeConvertible(toRawStyleSpecValue((MGLStyleFunction<ObjCType> *) value)), error); - NSCAssert(result, @(error.message.c_str())); - return *result; - } else { - return {}; + if (expression.expressionType == NSAggregateExpressionType) { + MBGLType mbglValue; + getMBGLValue(expression.collection, mbglValue); + return mbglValue; } - } - - // Convert an mgl style value containing an enum into a mbgl property value containing an enum - template <typename MBGLEnum = MBGLType, - class = typename std::enable_if<std::is_enum<MBGLEnum>::value>::type, - typename MGLEnum = ObjCEnum, - class = typename std::enable_if<std::is_enum<MGLEnum>::value>::type> - mbgl::style::PropertyValue<MBGLEnum> toEnumPropertyValue(MGLStyleValue<ObjCType> *value) { - if ([value isKindOfClass:[MGLSourceStyleFunction class]] || [value isKindOfClass:[MGLCompositeStyleFunction class]]) { + + NSArray *jsonExpression = expression.mgl_jsonExpressionObject; + + mbgl::style::conversion::Error valueError; + auto value = mbgl::style::conversion::convert<MBGLValue>( + mbgl::style::conversion::makeConvertible(jsonExpression), valueError); + if (!value) { [NSException raise:NSInvalidArgumentException - format:@"This property can only be set to camera functions. Use +[MGLStyleValue valueWithInterpolationMode:cameraStops:options:] instead."]; - return {}; - } - - if ([value isKindOfClass:[MGLConstantStyleValue class]]) { - MBGLEnum mbglValue; - getMBGLValue([(MGLConstantStyleValue<ObjCType> *)value rawValue], mbglValue); - return mbglValue; - } else if ([value isKindOfClass:[MGLCameraStyleFunction class]]) { - MGLCameraStyleFunction<NSValue *> *cameraStyleFunction = (MGLCameraStyleFunction<NSValue *> *)value; - __block std::map<float, MBGLType> stops = {}; - [cameraStyleFunction.stops enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull zoomKey, MGLStyleValue<NSValue *> * _Nonnull stopValue, BOOL * _Nonnull stop) { - NSCAssert([stopValue isKindOfClass:[MGLStyleValue class]], @"Stops should be MGLStyleValues"); - auto mbglStopValue = toEnumPropertyValue(stopValue); - NSCAssert(mbglStopValue.isConstant(), @"Stops must be constant"); - stops[zoomKey.floatValue] = mbglStopValue.asConstant(); - }]; - - // Enumerations can only ever use interval stops. - mbgl::style::IntervalStops<MBGLType> intervalStops = {stops}; - - mbgl::style::CameraFunction<MBGLType> cameraFunction = {intervalStops}; - return cameraFunction; - } else if (value) { - [NSException raise:@"MGLAbstractClassException" format: - @"The style value %@ cannot be applied to the style. " - @"Make sure the style value was created as a member of a concrete subclass of MGLStyleValue.", - NSStringFromClass([value class])]; - return {}; - } else { + format:@"Invalid property value: %@", @(valueError.message.c_str())]; return {}; } + + return *value; } private: // Private utilities for converting from mgl to mbgl values - - MBGLType toMBGLConstantValue(MGLConstantStyleValue<ObjCType> *value) { - MBGLType mbglValue; - getMBGLValue(value.rawValue, mbglValue); - return mbglValue; - } /** As hack to allow converting enum => string values, we accept a second, dummy parameter in @@ -220,164 +124,6 @@ private: // Private utilities for converting from mgl to mbgl values return @(color.mgl_color.stringify().c_str()); } - - NSObject* toRawStyleSpecValue(MGLStyleFunction<ObjCType>* styleFunction) { - NSMutableDictionary * rawFunction = [NSMutableDictionary new]; - // interpolationMode => type - switch (styleFunction.interpolationMode) { - case MGLInterpolationModeExponential: - rawFunction[@"type"] = @"exponential"; - break; - case MGLInterpolationModeInterval: - rawFunction[@"type"] = @"interval"; - break; - case MGLInterpolationModeCategorical: - rawFunction[@"type"] = @"categorical"; - break; - case MGLInterpolationModeIdentity: - rawFunction[@"type"] = @"identity"; - break; - } - - // interpolationBase => base - if (styleFunction.interpolationBase) { - rawFunction[@"base"] = @(styleFunction.interpolationBase); - } - - // stops and default value - if ([styleFunction isKindOfClass:[MGLCameraStyleFunction class]]) { - // zoom-only function (no default value) - __block NSMutableArray *stops = [[NSMutableArray alloc] init]; - [styleFunction.stops enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull zoomKey, MGLConstantStyleValue<ObjCType> * _Nonnull outputValue, BOOL * _Nonnull stop) { - MBGLType dummyMbglValue; - NSArray *rawStop = @[zoomKey, toRawStyleSpecValue([outputValue rawValue], dummyMbglValue)]; - [stops addObject:rawStop]; - }]; - rawFunction[@"stops"] = stops; - - } else if ([styleFunction isKindOfClass:[MGLSourceStyleFunction class]]) { - auto sourceStyleFunction = (MGLSourceStyleFunction<ObjCType> *)styleFunction; - rawFunction[@"property"] = sourceStyleFunction.attributeName; - // property-only function - __block NSMutableArray *stops = [[NSMutableArray alloc] init]; - [styleFunction.stops enumerateKeysAndObjectsUsingBlock:^(NSObject * _Nonnull propertyKey, MGLConstantStyleValue<ObjCType> * _Nonnull outputValue, BOOL * _Nonnull stop) { - MBGLType dummyMbglValue; - NSArray *rawStop = @[propertyKey, toRawStyleSpecValue([outputValue rawValue], dummyMbglValue)]; - [stops addObject:rawStop]; - }]; - rawFunction[@"stops"] = stops; - - // defaultValue => default - if (sourceStyleFunction.defaultValue) { - NSCAssert([sourceStyleFunction.defaultValue isKindOfClass:[MGLConstantStyleValue class]], @"Default value must be constant"); - MBGLType dummyMbglValue; - rawFunction[@"default"] = toRawStyleSpecValue([(MGLConstantStyleValue<ObjCType> *)sourceStyleFunction.defaultValue rawValue], dummyMbglValue); - } - } else if ([styleFunction isKindOfClass:[MGLCompositeStyleFunction class]]) { - // zoom-and-property function - auto compositeStyleFunction = (MGLCompositeStyleFunction<ObjCType> *)styleFunction; - rawFunction[@"property"] = compositeStyleFunction.attributeName; - - __block NSMutableArray *stops = [[NSMutableArray alloc] init]; - [compositeStyleFunction.stops enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull zoomKey, NSDictionary * _Nonnull stopValue, BOOL * _Nonnull stop) { - for (NSObject *valueKey in stopValue.allKeys) { - NSDictionary *stopKey = @{ - @"zoom": zoomKey, - @"value": valueKey - }; - MGLConstantStyleValue<ObjCType> *outputValue = stopValue[valueKey]; - NSCAssert([outputValue isKindOfClass:[MGLConstantStyleValue<ObjCType> class]], @"Stop outputs should be MGLConstantStyleValues"); - MBGLType dummyMbglValue; - NSArray *rawStop = @[stopKey, toRawStyleSpecValue([outputValue rawValue], dummyMbglValue)]; - [stops addObject:rawStop]; - } - }]; - rawFunction[@"stops"] = stops; - - // defaultValue => default - if (compositeStyleFunction.defaultValue) { - NSCAssert([compositeStyleFunction.defaultValue isKindOfClass:[MGLConstantStyleValue class]], @"Default value must be constant"); - MBGLType dummyMbglValue; - rawFunction[@"default"] = toRawStyleSpecValue([(MGLConstantStyleValue<ObjCType> *)compositeStyleFunction.defaultValue rawValue], dummyMbglValue); - } - } - - return rawFunction; - } - - mbgl::style::CameraFunction<MBGLType> toMBGLExponentialCameraFunction(MGLStyleFunction<ObjCType> *styleFunction) { - __block std::map<float, MBGLType> stops = {}; - [styleFunction.stops enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull zoomKey, MGLStyleValue<ObjCType> * _Nonnull stopValue, BOOL * _Nonnull stop) { - NSCAssert([stopValue isKindOfClass:[MGLStyleValue class]], @"Stops should be MGLStyleValues"); - auto mbglStopValue = toPropertyValue(stopValue); - NSCAssert(mbglStopValue.isConstant(), @"Stops must be constant"); - stops[zoomKey.floatValue] = mbglStopValue.asConstant(); - }]; - - // Camera function with Exponential stops - mbgl::style::ExponentialStops<MBGLType> exponentialStops = {stops, (float)styleFunction.interpolationBase}; - mbgl::style::CameraFunction<MBGLType> cameraFunction = {exponentialStops}; - - return cameraFunction; - } - - mbgl::style::CameraFunction<MBGLType> toMBGLIntervalCameraFunction(MGLStyleFunction<ObjCType> *styleFunction) { - __block std::map<float, MBGLType> stops = {}; - [styleFunction.stops enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull zoomKey, MGLStyleValue<ObjCType> * _Nonnull stopValue, BOOL * _Nonnull stop) { - NSCAssert([stopValue isKindOfClass:[MGLStyleValue class]], @"Stops should be MGLStyleValues"); - auto mbglStopValue = toPropertyValue(stopValue); - NSCAssert(mbglStopValue.isConstant(), @"Stops must be constant"); - stops[zoomKey.floatValue] = mbglStopValue.asConstant(); - }]; - - // Camera function with Interval stops - mbgl::style::IntervalStops<MBGLType> intervalStops = {stops}; - mbgl::style::CameraFunction<MBGLType> cameraFunction = {intervalStops}; - - return cameraFunction; - } - - mbgl::style::SourceFunction<MBGLType> toMBGLCategoricalSourceFunction(MGLSourceStyleFunction<ObjCType> *sourceStyleFunction) { - __block std::map<mbgl::style::CategoricalValue, MBGLType> stops = {}; - [sourceStyleFunction.stops enumerateKeysAndObjectsUsingBlock:^(id categoryKey, MGLStyleValue<ObjCType> *stopValue, BOOL *stop) { - NSCAssert([stopValue isKindOfClass:[MGLStyleValue class]], @"Stops should be MGLStyleValues"); - auto mbglStopValue = toPropertyValue(stopValue); - NSCAssert(mbglStopValue.isConstant(), @"Stops must be constant"); - - if ([categoryKey isKindOfClass:[NSString class]]) { - const std::string& convertedValueKey = [((NSString *)categoryKey) UTF8String]; - stops[mbgl::style::CategoricalValue(convertedValueKey)] = mbglStopValue.asConstant(); - } else if ([categoryKey isKindOfClass:[NSNumber class]]) { - NSNumber *key = (NSNumber *)categoryKey; - if ((strcmp([key objCType], @encode(char)) == 0) || - (strcmp([key objCType], @encode(BOOL)) == 0)) { - stops[mbgl::style::CategoricalValue((bool)[key boolValue])] = mbglStopValue.asConstant(); - } else if (strcmp([key objCType], @encode(double)) == 0 || - strcmp([key objCType], @encode(float)) == 0) { - NSCAssert(mbglStopValue.isConstant(), @"Categorical stop keys must be strings, booleans, or integers"); - } else if ([key compare:@(0)] == NSOrderedDescending || - [key compare:@(0)] == NSOrderedSame || - [key compare:@(0)] == NSOrderedAscending) { - stops[mbgl::style::CategoricalValue((int64_t)[key integerValue])] = mbglStopValue.asConstant(); - } - } - }]; - mbgl::style::CategoricalStops<MBGLType> categoricalStops = {stops}; - mbgl::style::SourceFunction<MBGLType> sourceFunction = {sourceStyleFunction.attributeName.UTF8String, categoricalStops}; - setDefaultMBGLValue(sourceStyleFunction, sourceFunction); - return sourceFunction; - } - - void setDefaultMBGLValue(MGLSourceStyleFunction<ObjCType> *sourceStyleFunction, mbgl::style::SourceFunction<MBGLType> &sourceFunction) { - if (sourceStyleFunction.defaultValue) { - NSCAssert([sourceStyleFunction.defaultValue isKindOfClass:[MGLConstantStyleValue class]], @"Default value must be constant"); - MBGLType mbglValue; - id mglValue = [(MGLConstantStyleValue<ObjCType> *)sourceStyleFunction.defaultValue rawValue]; - getMBGLValue(mglValue, mbglValue); - sourceFunction.defaultValue = mbglValue; - } - } - // Bool void getMBGLValue(NSNumber *rawValue, bool &mbglValue) { mbglValue = !!rawValue.boolValue; @@ -394,13 +140,28 @@ private: // Private utilities for converting from mgl to mbgl values } // Offsets - void getMBGLValue(NSValue *rawValue, std::array<float, 2> &mbglValue) { - mbglValue = rawValue.mgl_offsetArrayValue; + void getMBGLValue(id rawValue, std::array<float, 2> &mbglValue) { + if ([rawValue isKindOfClass:[NSValue class]]) { + mbglValue = [rawValue mgl_offsetArrayValue]; + } else if ([rawValue isKindOfClass:[NSArray class]]) { + NSArray *array = (NSArray *)rawValue; + getMBGLValue(array[0], mbglValue[0]); + getMBGLValue(array[1], mbglValue[1]); + } } // Padding - void getMBGLValue(NSValue *rawValue, std::array<float, 4> &mbglValue) { - mbglValue = rawValue.mgl_paddingArrayValue; + void getMBGLValue(id rawValue, std::array<float, 4> &mbglValue) { + if ([rawValue isKindOfClass:[NSValue class]]) { + mbglValue = [rawValue mgl_paddingArrayValue]; + } else if ([rawValue isKindOfClass:[NSArray class]]) { + NSArray *array = (NSArray *)rawValue; + getMBGLValue(array[0], mbglValue[0]); + getMBGLValue(array[1], mbglValue[1]); + getMBGLValue(array[2], mbglValue[2]); + getMBGLValue(array[3], mbglValue[3]); + getMBGLValue(array[4], mbglValue[4]); + } } // Color @@ -412,8 +173,12 @@ private: // Private utilities for converting from mgl to mbgl values void getMBGLValue(ObjCType rawValue, std::vector<MBGLElement> &mbglValue) { mbglValue.reserve(rawValue.count); for (id obj in rawValue) { + id constantObject = obj; + if ([obj isKindOfClass:[NSExpression class]] && [obj expressionType] == NSConstantValueExpressionType) { + constantObject = [constantObject constantValue]; + } MBGLElement mbglElement; - getMBGLValue(obj, mbglElement); + getMBGLValue(constantObject, mbglElement); mbglValue.push_back(mbglElement); } } @@ -429,11 +194,15 @@ private: // Private utilities for converting from mgl to mbgl values class = typename std::enable_if<std::is_enum<MBGLEnum>::value>::type, typename MGLEnum = ObjCEnum, class = typename std::enable_if<std::is_enum<MGLEnum>::value>::type> - void getMBGLValue(ObjCType rawValue, MBGLEnum &mbglValue) { - MGLEnum mglEnum; - [rawValue getValue:&mglEnum]; - auto str = mbgl::Enum<MGLEnum>::toString(mglEnum); - mbglValue = *mbgl::Enum<MBGLEnum>::toEnum(str); + void getMBGLValue(id rawValue, MBGLEnum &mbglValue) { + if ([rawValue isKindOfClass:[NSString class]]) { + mbglValue = *mbgl::Enum<MBGLEnum>::toEnum([(NSString *)rawValue UTF8String]); + } else { + MGLEnum mglEnum; + [(NSValue *)rawValue getValue:&mglEnum]; + auto str = mbgl::Enum<MGLEnum>::toString(mglEnum); + mbglValue = *mbgl::Enum<MBGLEnum>::toEnum(str); + } } private: // Private utilities for converting from mbgl to mgl values @@ -477,7 +246,7 @@ private: // Private utilities for converting from mbgl to mgl values static ObjCType toMGLRawStyleValue(const std::vector<MBGLElement> &mbglStopValue) { NSMutableArray *array = [NSMutableArray arrayWithCapacity:mbglStopValue.size()]; for (const auto &mbglElement: mbglStopValue) { - [array addObject:toMGLRawStyleValue(mbglElement)]; + [array addObject:[NSExpression expressionForConstantValue:toMGLRawStyleValue(mbglElement)]]; } return array; } @@ -496,212 +265,49 @@ private: // Private utilities for converting from mbgl to mgl values return [NSValue value:&mglType withObjCType:@encode(MGLEnum)]; } - // Converts mbgl stops to an equivilent NSDictionary for mgl - static NSMutableDictionary *toConvertedStops(const std::map<float, MBGLType> &mbglStops) { - NSMutableDictionary *stops = [NSMutableDictionary dictionaryWithCapacity:mbglStops.size()]; - for (const auto &mbglStop : mbglStops) { - auto rawValue = toMGLRawStyleValue(mbglStop.second); - stops[@(mbglStop.first)] = [MGLStyleValue valueWithRawValue:rawValue]; - } - return stops; - } - - // Converts mbgl interval stop categorical values to an equivilant object for mgl - class CategoricalValueVisitor { - public: - id operator()(const bool value) { - return toMGLRawStyleValue(value); - } - - id operator()(const int64_t value) { - return toMGLRawStyleValue(value); - } - - id operator()(const std::string value) { - return toMGLRawStyleValue(value); - } - }; - - // Converts all types of mbgl property values containing enumerations into an equivilant mgl style value - template <typename MBGLEnum = MBGLType, typename MGLEnum = ObjCEnum> - class EnumPropertyValueEvaluator { + /// Converts all types of mbgl property values into an equivalent NSExpression. + class PropertyExpressionEvaluator { public: - id operator()(const mbgl::style::Undefined) const { + NSExpression *operator()(const mbgl::style::Undefined) const { return nil; } - id operator()(const MBGLEnum &value) const { - auto str = mbgl::Enum<MBGLEnum>::toString(value); - MGLEnum mglType = *mbgl::Enum<MGLEnum>::toEnum(str); - return [MGLConstantStyleValue<ObjCType> valueWithRawValue:[NSValue value:&mglType withObjCType:@encode(MGLEnum)]]; - } - - id operator()(const mbgl::style::CameraFunction<MBGLEnum> &mbglValue) const { - CameraFunctionStopsVisitor visitor; - return apply_visitor(visitor, mbglValue.stops); - } - }; - - // Converts all possible mbgl camera function stops into an equivilant mgl style value - class CameraFunctionStopsVisitor { - public: - id operator()(const mbgl::style::ExponentialStops<MBGLType> &mbglStops) { - return [MGLCameraStyleFunction functionWithInterpolationMode:MGLInterpolationModeExponential - stops:toConvertedStops(mbglStops.stops) - options:@{MGLStyleFunctionOptionInterpolationBase: @(mbglStops.base)}]; - } - - id operator()(const mbgl::style::IntervalStops<MBGLType> &mbglStops) { - return [MGLCameraStyleFunction functionWithInterpolationMode:MGLInterpolationModeInterval - stops:toConvertedStops(mbglStops.stops) - options:nil]; - } - }; - - // Converts a source function and all possible mbgl source function stops into an equivilant mgl style value - class SourceFunctionStopsVisitor { - public: - id operator()(const mbgl::style::ExponentialStops<MBGLType> &mbglStops) { - MGLSourceStyleFunction *sourceFunction = [MGLSourceStyleFunction functionWithInterpolationMode:MGLInterpolationModeExponential - stops:toConvertedStops(mbglStops.stops) - attributeName:@(mbglFunction.property.c_str()) - options:@{MGLStyleFunctionOptionInterpolationBase: @(mbglStops.base)}]; - if (mbglFunction.defaultValue) { - sourceFunction.defaultValue = [MGLStyleValue valueWithRawValue:toMGLRawStyleValue(*mbglFunction.defaultValue)]; + /** + As hack to allow converting enum => string values, we accept a second, dummy parameter in + the toRawStyleSpecValue() methods for converting 'atomic' (non-style-function) values. + This allows us to use `std::enable_if` to test (at compile time) whether or not MBGLType is an Enum. + */ + template <typename MBGLEnum = MBGLType, + class = typename std::enable_if<!std::is_enum<MBGLEnum>::value>::type, + typename MGLEnum = ObjCEnum, + class = typename std::enable_if<!std::is_enum<MGLEnum>::value>::type> + NSExpression *operator()(const MBGLType &value) const { + id constantValue = toMGLRawStyleValue(value); + if ([constantValue isKindOfClass:[NSArray class]]) { + return [NSExpression expressionForAggregate:constantValue]; } - return sourceFunction; + return [NSExpression expressionForConstantValue:constantValue]; } - - id operator()(const mbgl::style::IntervalStops<MBGLType> &mbglStops) { - MGLSourceStyleFunction *sourceFunction = [MGLSourceStyleFunction functionWithInterpolationMode:MGLInterpolationModeInterval - stops:toConvertedStops(mbglStops.stops) - attributeName:@(mbglFunction.property.c_str()) - options:nil]; - if (mbglFunction.defaultValue) { - sourceFunction.defaultValue = [MGLStyleValue valueWithRawValue:toMGLRawStyleValue(*mbglFunction.defaultValue)]; - } - return sourceFunction; - } - - id operator()(const mbgl::style::CategoricalStops<MBGLType> &mbglStops) { - NSMutableDictionary *stops = [NSMutableDictionary dictionaryWithCapacity:mbglStops.stops.size()]; - for (const auto &mbglStop : mbglStops.stops) { - auto categoricalValue = mbglStop.first; - auto rawValue = toMGLRawStyleValue(mbglStop.second); - CategoricalValueVisitor categoricalValueVisitor; - id stopKey = apply_visitor(categoricalValueVisitor, categoricalValue); - stops[stopKey] = [MGLStyleValue valueWithRawValue:rawValue]; - } - - MGLSourceStyleFunction *sourceFunction = [MGLSourceStyleFunction functionWithInterpolationMode:MGLInterpolationModeCategorical - stops:stops - attributeName:@(mbglFunction.property.c_str()) - options:nil]; - if (mbglFunction.defaultValue) { - sourceFunction.defaultValue = [MGLStyleValue valueWithRawValue:toMGLRawStyleValue(*mbglFunction.defaultValue)]; - } - return sourceFunction; - - } - - id operator()(const mbgl::style::IdentityStops<MBGLType> &mbglStops) { - MGLSourceStyleFunction *sourceFunction = [MGLSourceStyleFunction functionWithInterpolationMode:MGLInterpolationModeIdentity - stops:nil - attributeName:@(mbglFunction.property.c_str()) options:nil]; - if (mbglFunction.defaultValue) { - sourceFunction.defaultValue = [MGLStyleValue valueWithRawValue:toMGLRawStyleValue(*mbglFunction.defaultValue)]; - } - return sourceFunction; - } - - const mbgl::style::SourceFunction<MBGLType> &mbglFunction; - }; - - // Converts a composite function and all possible mbgl stops into an equivilant mgl style value - class CompositeFunctionStopsVisitor { - public: - id operator()(const mbgl::style::CompositeExponentialStops<MBGLType> &mbglStops) { - NSMutableDictionary *stops = [NSMutableDictionary dictionaryWithCapacity:mbglStops.stops.size()]; - for (auto const& outerStop: mbglStops.stops) { - stops[@(outerStop.first)] = toConvertedStops(outerStop.second); - } - MGLCompositeStyleFunction *compositeFunction = [MGLCompositeStyleFunction functionWithInterpolationMode:MGLInterpolationModeExponential - stops:stops - attributeName:@(mbglFunction.property.c_str()) - options:@{MGLStyleFunctionOptionInterpolationBase: @(mbglStops.base)}]; - if (mbglFunction.defaultValue) { - compositeFunction.defaultValue = [MGLStyleValue valueWithRawValue:toMGLRawStyleValue(*mbglFunction.defaultValue)]; - } - return compositeFunction; - } - - id operator()(const mbgl::style::CompositeIntervalStops<MBGLType> &mbglStops) { - NSMutableDictionary *stops = [NSMutableDictionary dictionaryWithCapacity:mbglStops.stops.size()]; - for (auto const& outerStop: mbglStops.stops) { - stops[@(outerStop.first)] = toConvertedStops(outerStop.second); - } - MGLCompositeStyleFunction *compositeFunction = [MGLCompositeStyleFunction functionWithInterpolationMode:MGLInterpolationModeInterval - stops:stops - attributeName:@(mbglFunction.property.c_str()) - options:nil]; - if (mbglFunction.defaultValue) { - compositeFunction.defaultValue = [MGLStyleValue valueWithRawValue:toMGLRawStyleValue(*mbglFunction.defaultValue)]; - } - return compositeFunction; - } - - id operator()(const mbgl::style::CompositeCategoricalStops<MBGLType> &mbglStops) { - NSMutableDictionary *stops = [NSMutableDictionary dictionaryWithCapacity:mbglStops.stops.size()]; - for (auto const& outerStop: mbglStops.stops) { - NSMutableDictionary *innerStops = [NSMutableDictionary dictionaryWithCapacity:outerStop.second.size()]; - for (const auto &mbglStop : outerStop.second) { - auto categoricalValue = mbglStop.first; - auto rawValue = toMGLRawStyleValue(mbglStop.second); - CategoricalValueVisitor categoricalValueVisitor; - id stopKey = apply_visitor(categoricalValueVisitor, categoricalValue); - innerStops[stopKey] = [MGLStyleValue valueWithRawValue:rawValue]; - } - stops[@(outerStop.first)] = innerStops; - } - - MGLCompositeStyleFunction *compositeFunction = [MGLCompositeStyleFunction functionWithInterpolationMode:MGLInterpolationModeCategorical - stops:stops attributeName:@(mbglFunction.property.c_str()) - options:nil]; - if (mbglFunction.defaultValue) { - compositeFunction.defaultValue = [MGLStyleValue valueWithRawValue:toMGLRawStyleValue(*mbglFunction.defaultValue)]; - } - return compositeFunction; - } - - const mbgl::style::CompositeFunction<MBGLType> &mbglFunction; - }; - - - // Converts all types of mbgl property values that don't contain enumerations into an equivilant mgl style value - class PropertyValueEvaluator { - public: - id operator()(const mbgl::style::Undefined) const { - return nil; - } - - id operator()(const MBGLType &value) const { - auto rawValue = toMGLRawStyleValue(value); - return [MGLConstantStyleValue<ObjCType> valueWithRawValue:rawValue]; + + template <typename MBGLEnum = MBGLType, + class = typename std::enable_if<std::is_enum<MBGLEnum>::value>::type, + typename MGLEnum = ObjCEnum, + class = typename std::enable_if<std::is_enum<MGLEnum>::value>::type> + NSExpression *operator()(const MBGLEnum &value) const { + NSString *constantValue = @(mbgl::Enum<MBGLEnum>::toString(value)); + return [NSExpression expressionForConstantValue:constantValue]; } - id operator()(const mbgl::style::CameraFunction<MBGLType> &mbglValue) const { - CameraFunctionStopsVisitor visitor; - return apply_visitor(visitor, mbglValue.stops); + NSExpression *operator()(const mbgl::style::CameraFunction<MBGLType> &mbglValue) const { + return [NSExpression mgl_expressionWithJSONObject:MGLJSONObjectFromMBGLExpression(mbglValue.getExpression())]; } - id operator()(const mbgl::style::SourceFunction<MBGLType> &mbglValue) const { - SourceFunctionStopsVisitor visitor { mbglValue }; - return apply_visitor(visitor, mbglValue.stops); + NSExpression *operator()(const mbgl::style::SourceFunction<MBGLType> &mbglValue) const { + return [NSExpression mgl_expressionWithJSONObject:MGLJSONObjectFromMBGLExpression(mbglValue.getExpression())]; } - MGLCompositeStyleFunction<ObjCType> * operator()(const mbgl::style::CompositeFunction<MBGLType> &mbglValue) const { - CompositeFunctionStopsVisitor visitor { mbglValue }; - return apply_visitor(visitor, mbglValue.stops); + NSExpression *operator()(const mbgl::style::CompositeFunction<MBGLType> &mbglValue) const { + return [NSExpression mgl_expressionWithJSONObject:MGLJSONObjectFromMBGLExpression(mbglValue.getExpression())]; } }; }; |