diff --git a/platform/darwin/src/MGLLineStyleLayer.h b/platform/darwin/src/MGLLineStyleLayer.h index 5fb9693e7..cee33e138 100644 --- a/platform/darwin/src/MGLLineStyleLayer.h +++ b/platform/darwin/src/MGLLineStyleLayer.h @@ -3,6 +3,7 @@ #import "MGLStyleAttributeValue.h" #import "MGLVectorStyleLayer.h" +#import "MGLStyleAttributeFunction.h" NS_ASSUME_NONNULL_BEGIN @@ -84,7 +85,7 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslateAnchor) { The default value of this property is an `NSValue` object containing `MGLLineJoinMiter`. Set this property to `nil` to reset it to the default value. */ -@property (nonatomic, null_resettable) id lineJoin; +@property (nonatomic, null_resettable) MGLStyleValue *lineJoin; /** Used to automatically convert miter joins to bevel joins for sharp angles. @@ -93,7 +94,7 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslateAnchor) { This property is only applied to the style if `lineJoin` is set to an `NSValue` object containing `MGLLineJoinMiter`. Otherwise, it is ignored. */ -@property (nonatomic, null_resettable) id lineMiterLimit; +@property (nonatomic, null_resettable) MGLStyleValue *lineMiterLimit; /** Used to automatically convert round joins to miter joins for shallow angles. diff --git a/platform/darwin/src/MGLLineStyleLayer.mm b/platform/darwin/src/MGLLineStyleLayer.mm index 9577b0d77..2d202290d 100644 --- a/platform/darwin/src/MGLLineStyleLayer.mm +++ b/platform/darwin/src/MGLLineStyleLayer.mm @@ -56,20 +56,24 @@ MGLGetEnumProperty(LineCap, LineCapType, MGLLineCap); } -- (void)setLineJoin:(id )lineJoin { - MGLSetEnumProperty(lineJoin, LineJoin, LineJoinType, MGLLineJoin); +- (void)setLineJoin:(MGLStyleValue *)lineJoin { + auto propertyValue = MGLStyleValueTransformer().toPropertyValue(lineJoin); + self.layer->setLineJoin(propertyValue); } -- (id )lineJoin { - MGLGetEnumProperty(LineJoin, LineJoinType, MGLLineJoin); +- (MGLStyleValue *)lineJoin { + auto propertyValue = self.layer->getLineJoin() ?: self.layer->getDefaultLineJoin(); + return MGLStyleValueTransformer().toStyleValue(propertyValue); } -- (void)setLineMiterLimit:(id )lineMiterLimit { - self.layer->setLineMiterLimit(lineMiterLimit.mbgl_floatPropertyValue); +- (void)setLineMiterLimit:(MGLStyleValue *)lineMiterLimit { + auto mbglValue = MGLStyleValueTransformer().toPropertyValue(lineMiterLimit); + self.layer->setLineMiterLimit(mbglValue); } -- (id )lineMiterLimit { - return [MGLStyleAttribute mbgl_numberWithPropertyValueNumber:self.layer->getLineMiterLimit() ?: self.layer->getDefaultLineMiterLimit()]; +- (MGLStyleValue *)lineMiterLimit { + auto propertyValue = self.layer->getLineMiterLimit() ?: self.layer->getDefaultLineMiterLimit(); + return MGLStyleValueTransformer().toStyleValue(propertyValue); } - (void)setLineRoundLimit:(id )lineRoundLimit { diff --git a/platform/darwin/src/MGLStyleAttributeFunction.h b/platform/darwin/src/MGLStyleAttributeFunction.h index e636c1add..a676a8a71 100644 --- a/platform/darwin/src/MGLStyleAttributeFunction.h +++ b/platform/darwin/src/MGLStyleAttributeFunction.h @@ -14,4 +14,34 @@ NS_ASSUME_NONNULL_BEGIN @end +@interface MGLStyleValue : NSObject + ++ (instancetype)valueWithRawValue:(T)rawValue; ++ (instancetype)valueWithBase:(CGFloat)base stops:(NSDictionary *> *)stops; ++ (instancetype)valueWithStops:(NSDictionary *> *)stops; + +@end + +@interface MGLStyleConstantValue : MGLStyleValue + ++ (instancetype)valueWithRawValue:(T)rawValue; + +- (instancetype)initWithRawValue:(T)rawValue; + +@property (nonatomic) T rawValue; + +@end + +@interface MGLStyleFunction : MGLStyleValue + ++ (instancetype)functionWithBase:(CGFloat)base stops:(NSDictionary *> *)stops; ++ (instancetype)functionWithStops:(NSDictionary *> *)stops; + +- (instancetype)initWithBase:(CGFloat)base stops:(NSDictionary *> *)stops; + +@property (nonatomic) CGFloat base; +@property (nonatomic, copy) NSDictionary *> *stops; + +@end + NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLStyleAttributeFunction.mm b/platform/darwin/src/MGLStyleAttributeFunction.mm index 7eec5c236..337e29912 100644 --- a/platform/darwin/src/MGLStyleAttributeFunction.mm +++ b/platform/darwin/src/MGLStyleAttributeFunction.mm @@ -4,6 +4,68 @@ #import "MGLStyleAttributeValue_Private.h" #import "MGLStyleAttributeFunction_Private.h" +@implementation MGLStyleValue + ++ (instancetype)valueWithRawValue:(id)rawValue { + return [MGLStyleConstantValue valueWithRawValue:rawValue]; +} + ++ (instancetype)valueWithBase:(CGFloat)base stops:(NSDictionary *)stops { + return [MGLStyleFunction functionWithBase:base stops:stops]; +} + ++ (instancetype)valueWithStops:(NSDictionary *)stops { + return [MGLStyleFunction functionWithStops:stops]; +} + +@end + +@implementation MGLStyleConstantValue + ++ (instancetype)valueWithRawValue:(id)rawValue { + return [[self alloc] initWithRawValue:rawValue]; +} + +- (instancetype)initWithRawValue:(id)rawValue { + if (self = [super init]) { + _rawValue = rawValue; + } + return self; +} + +@end + +@implementation MGLStyleFunction + ++ (instancetype)functionWithBase:(CGFloat)base stops:(NSDictionary *)stops { + return [[self alloc] initWithBase:base stops:stops]; +} + ++ (instancetype)functionWithStops:(NSDictionary *)stops { + return [[self alloc] initWithBase:1 stops:stops]; +} + +- (instancetype)init { + if (self = [super init]) { + _base = 1; + } + return self; +} + +- (instancetype)initWithBase:(CGFloat)base stops:(NSDictionary *)stops { + if (self = [self init]) { + _base = base; + _stops = stops; + } + return self; +} + +@end + + + + + @interface MGLStyleAttributeFunction() @end diff --git a/platform/darwin/src/MGLStyleAttributeFunction_Private.h b/platform/darwin/src/MGLStyleAttributeFunction_Private.h index 92dec0d4a..94a610c62 100644 --- a/platform/darwin/src/MGLStyleAttributeFunction_Private.h +++ b/platform/darwin/src/MGLStyleAttributeFunction_Private.h @@ -1,9 +1,20 @@ #import "MGLStyleAttributeFunction.h" +#import "NSValue+MGLStyleAttributeAdditions_Private.h" + +#if TARGET_OS_IPHONE + #import "UIColor+MGLAdditions.h" +#else + #import "NSColor+MGLAdditions.h" +#endif + #include +#include #include #include +#include + #define MGLSetEnumProperty(name, Name, MBGLType, ObjCType) \ if (name.isFunction) { \ NSAssert([name isKindOfClass:[MGLStyleAttributeFunction class]], @"" #name @" should be a function"); \ @@ -70,4 +81,140 @@ + (instancetype)functionWithEnumProperyValue:(mbgl::style::Function)property type:(const char *)type; -@end; +@end + +template +class MGLStyleValueTransformer { +public: + + MGLStyleValue *toStyleValue(const mbgl::style::PropertyValue &mbglValue) { + if (mbglValue.isConstant()) { + return toStyleConstantValue(mbglValue.asConstant()); + } else if (mbglValue.isFunction()) { + return toStyleFunction(mbglValue.asFunction()); + } else { + return nil; + } + } + + mbgl::style::PropertyValue toPropertyValue(MGLStyleValue *value) { + if ([value isKindOfClass:[MGLStyleConstantValue class]]) { + MBGLType mbglValue; + getMBGLValue([(MGLStyleConstantValue *)value rawValue], mbglValue); + return mbglValue; + } else if ([value isKindOfClass:[MGLStyleFunction class]]) { + MGLStyleFunction *function = (MGLStyleFunction *)value; + __block std::vector> mbglStops; + [function.stops enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull zoomKey, MGLStyleValue * _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"); + mbglStops.emplace_back(zoomKey.floatValue, mbglStopValue.asConstant()); + }]; + return mbgl::style::Function({{mbglStops}}, function.base); + } else { + return {}; + } + } + +private: + + MGLStyleConstantValue *toStyleConstantValue(const MBGLType mbglValue) { + auto rawValue = toMGLRawStyleValue(mbglValue); + return [MGLStyleConstantValue valueWithRawValue:rawValue]; + } + + MGLStyleFunction *toStyleFunction(const mbgl::style::Function &mbglFunction) { + const auto &mbglStops = mbglFunction.getStops(); + NSMutableDictionary *stops = [NSMutableDictionary dictionaryWithCapacity:mbglStops.size()]; + for (const auto &mbglStop : mbglStops) { + auto rawValue = toMGLRawStyleValue(mbglStop.second); + stops[@(mbglStop.first)] = [MGLStyleValue valueWithRawValue:rawValue]; + } + return [MGLStyleFunction functionWithBase:mbglFunction.getBase() stops:stops]; + } + + NSNumber *toMGLRawStyleValue(const bool mbglStopValue) { + return @(mbglStopValue); + } + + NSNumber *toMGLRawStyleValue(const float mbglStopValue) { + return @(mbglStopValue); + } + + NSString *toMGLRawStyleValue(const std::string &mbglStopValue) { + return @(mbglStopValue.c_str()); + } + + // Offsets + NSValue *toMGLRawStyleValue(const std::array &mbglStopValue) { + return [NSValue mgl_valueWithOffsetArray:mbglStopValue]; + } + + // Padding + NSValue *toMGLRawStyleValue(const std::array &mbglStopValue) { + return [NSValue mgl_valueWithPaddingArray:mbglStopValue]; + } + + // Enumerations + template ::value>::type> + ObjCType toMGLRawStyleValue(const MBGLType &mbglStopValue) { + NSUInteger rawValue = static_cast(mbglStopValue); + return [NSValue value:&rawValue withObjCType:@encode(NSUInteger)]; + } + + MGLColor *toMGLRawStyleValue(const mbgl::Color mbglStopValue) { + return [MGLColor mbgl_colorWithColor:mbglStopValue]; + } + + ObjCType toMGLRawStyleValue(const std::vector &mbglStopValue) { + NSMutableArray *array = [NSMutableArray arrayWithCapacity:mbglStopValue.size()]; + for (const auto &mbglElement: mbglStopValue) { + [array addObject:toMGLRawStyleValue(mbglElement)]; + } + return array; + } + +private: + + void getMBGLValue(NSNumber *rawValue, bool &mbglValue) { + mbglValue = !!rawValue.boolValue; + } + + void getMBGLValue(NSNumber *rawValue, float &mbglValue) { + mbglValue = !!rawValue.boolValue; + } + + void getMBGLValue(NSString *rawValue, std::string &mbglValue) { + mbglValue = rawValue.UTF8String; + } + + // Offsets + void getMBGLValue(NSValue *rawValue, std::array &mbglValue) { + mbglValue = rawValue.mgl_offsetArrayValue; + } + + // Padding + void getMBGLValue(NSValue *rawValue, std::array &mbglValue) { + mbglValue = rawValue.mgl_paddingArrayValue; + } + + // Enumerations + template ::value>::type> + void getMBGLValue(ObjCType rawValue, MBGLType &mbglValue) { + [rawValue getValue:&mbglValue]; + } + + void getMBGLValue(MGLColor *rawValue, mbgl::Color &mbglValue) { + mbglValue = rawValue.mbgl_color; + } + + void getMBGLValue(ObjCType rawValue, std::vector &mbglValue) { + mbglValue.reserve(rawValue.count); + for (id obj in rawValue) { + MBGLType mbglElement; + getMBGLValue(obj, mbglElement); + mbglValue.push_back(mbglElement); + } + } +}; diff --git a/platform/darwin/src/MGLStyleAttributeValue.h b/platform/darwin/src/MGLStyleAttributeValue.h index cd3392388..00829b0dc 100644 --- a/platform/darwin/src/MGLStyleAttributeValue.h +++ b/platform/darwin/src/MGLStyleAttributeValue.h @@ -2,4 +2,4 @@ @protocol MGLStyleAttributeValue @optional -@end \ No newline at end of file +@end