summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMinh Nguyễn <mxn@1ec5.org>2016-09-24 11:12:21 -0700
committerMinh Nguyễn <mxn@1ec5.org>2016-10-17 11:47:22 -0700
commit0c8a3feffa94a9594bcaa77fdc18d11a3c482ff5 (patch)
tree9570ab6ad86323a0dcea7616f91d8ca726cd6659
parentae96e78ccd293d12e28e54a9a727d29d05a37980 (diff)
downloadqtlocation-mapboxgl-0c8a3feffa94a9594bcaa77fdc18d11a3c482ff5.tar.gz
[ios, macos] Replaced MGLStyleAttributeValue with MGLStyleValue
MGLStyleValue is an umbrella class serving as a variant container for MGLStyleConstantValue and MGLStyleFunction. These classes use lightweight generics to indicate the underlying type. A templated C++ class concisely converts between mbgl::style::PropertyValue and MGLStyleValue.
-rw-r--r--platform/darwin/src/MGLLineStyleLayer.h5
-rw-r--r--platform/darwin/src/MGLLineStyleLayer.mm20
-rw-r--r--platform/darwin/src/MGLStyleAttributeFunction.h30
-rw-r--r--platform/darwin/src/MGLStyleAttributeFunction.mm62
-rw-r--r--platform/darwin/src/MGLStyleAttributeFunction_Private.h149
-rw-r--r--platform/darwin/src/MGLStyleAttributeValue.h2
6 files changed, 256 insertions, 12 deletions
diff --git a/platform/darwin/src/MGLLineStyleLayer.h b/platform/darwin/src/MGLLineStyleLayer.h
index 5fb9693e78..cee33e1388 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 <MGLStyleAttributeValue> lineJoin;
+@property (nonatomic, null_resettable) MGLStyleValue <NSValue *> *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 <MGLStyleAttributeValue> lineMiterLimit;
+@property (nonatomic, null_resettable) MGLStyleValue <NSNumber *> *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 9577b0d777..2d202290da 100644
--- a/platform/darwin/src/MGLLineStyleLayer.mm
+++ b/platform/darwin/src/MGLLineStyleLayer.mm
@@ -56,20 +56,24 @@
MGLGetEnumProperty(LineCap, LineCapType, MGLLineCap);
}
-- (void)setLineJoin:(id <MGLStyleAttributeValue, MGLStyleAttributeValue_Private>)lineJoin {
- MGLSetEnumProperty(lineJoin, LineJoin, LineJoinType, MGLLineJoin);
+- (void)setLineJoin:(MGLStyleValue <NSValue *> *)lineJoin {
+ auto propertyValue = MGLStyleValueTransformer<mbgl::style::LineJoinType, NSValue *>().toPropertyValue(lineJoin);
+ self.layer->setLineJoin(propertyValue);
}
-- (id <MGLStyleAttributeValue>)lineJoin {
- MGLGetEnumProperty(LineJoin, LineJoinType, MGLLineJoin);
+- (MGLStyleValue <NSValue *> *)lineJoin {
+ auto propertyValue = self.layer->getLineJoin() ?: self.layer->getDefaultLineJoin();
+ return MGLStyleValueTransformer<mbgl::style::LineJoinType, NSValue *>().toStyleValue(propertyValue);
}
-- (void)setLineMiterLimit:(id <MGLStyleAttributeValue, MGLStyleAttributeValue_Private>)lineMiterLimit {
- self.layer->setLineMiterLimit(lineMiterLimit.mbgl_floatPropertyValue);
+- (void)setLineMiterLimit:(MGLStyleValue <NSNumber *> *)lineMiterLimit {
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(lineMiterLimit);
+ self.layer->setLineMiterLimit(mbglValue);
}
-- (id <MGLStyleAttributeValue>)lineMiterLimit {
- return [MGLStyleAttribute mbgl_numberWithPropertyValueNumber:self.layer->getLineMiterLimit() ?: self.layer->getDefaultLineMiterLimit()];
+- (MGLStyleValue <NSNumber *> *)lineMiterLimit {
+ auto propertyValue = self.layer->getLineMiterLimit() ?: self.layer->getDefaultLineMiterLimit();
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
- (void)setLineRoundLimit:(id <MGLStyleAttributeValue, MGLStyleAttributeValue_Private>)lineRoundLimit {
diff --git a/platform/darwin/src/MGLStyleAttributeFunction.h b/platform/darwin/src/MGLStyleAttributeFunction.h
index e636c1addd..a676a8a715 100644
--- a/platform/darwin/src/MGLStyleAttributeFunction.h
+++ b/platform/darwin/src/MGLStyleAttributeFunction.h
@@ -14,4 +14,34 @@ NS_ASSUME_NONNULL_BEGIN
@end
+@interface MGLStyleValue<T> : NSObject
+
++ (instancetype)valueWithRawValue:(T)rawValue;
++ (instancetype)valueWithBase:(CGFloat)base stops:(NSDictionary<NSNumber *, MGLStyleValue<T> *> *)stops;
++ (instancetype)valueWithStops:(NSDictionary<NSNumber *, MGLStyleValue<T> *> *)stops;
+
+@end
+
+@interface MGLStyleConstantValue<T> : MGLStyleValue
+
++ (instancetype)valueWithRawValue:(T)rawValue;
+
+- (instancetype)initWithRawValue:(T)rawValue;
+
+@property (nonatomic) T rawValue;
+
+@end
+
+@interface MGLStyleFunction<T> : MGLStyleValue
+
++ (instancetype)functionWithBase:(CGFloat)base stops:(NSDictionary<NSNumber *, MGLStyleValue<T> *> *)stops;
++ (instancetype)functionWithStops:(NSDictionary<NSNumber *, MGLStyleValue<T> *> *)stops;
+
+- (instancetype)initWithBase:(CGFloat)base stops:(NSDictionary<NSNumber *, MGLStyleValue<T> *> *)stops;
+
+@property (nonatomic) CGFloat base;
+@property (nonatomic, copy) NSDictionary<NSNumber *, MGLStyleValue<T> *> *stops;
+
+@end
+
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLStyleAttributeFunction.mm b/platform/darwin/src/MGLStyleAttributeFunction.mm
index 7eec5c2369..337e299127 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() <MGLStyleAttributeValue_Private>
@end
diff --git a/platform/darwin/src/MGLStyleAttributeFunction_Private.h b/platform/darwin/src/MGLStyleAttributeFunction_Private.h
index 92dec0d4a2..94a610c62a 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 <mbgl/util/color.hpp>
+#include <mbgl/util/variant.hpp>
#include <mbgl/style/function.hpp>
#include <mbgl/style/property_value.hpp>
+#include <array>
+
#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<bool>)property type:(const char *)type;
-@end;
+@end
+
+template <typename MBGLType, typename ObjCType>
+class MGLStyleValueTransformer {
+public:
+
+ MGLStyleValue<ObjCType> *toStyleValue(const mbgl::style::PropertyValue<MBGLType> &mbglValue) {
+ if (mbglValue.isConstant()) {
+ return toStyleConstantValue(mbglValue.asConstant());
+ } else if (mbglValue.isFunction()) {
+ return toStyleFunction(mbglValue.asFunction());
+ } else {
+ return nil;
+ }
+ }
+
+ mbgl::style::PropertyValue<MBGLType> toPropertyValue(MGLStyleValue<ObjCType> *value) {
+ if ([value isKindOfClass:[MGLStyleConstantValue class]]) {
+ MBGLType mbglValue;
+ getMBGLValue([(MGLStyleConstantValue<ObjCType> *)value rawValue], mbglValue);
+ return mbglValue;
+ } else if ([value isKindOfClass:[MGLStyleFunction class]]) {
+ MGLStyleFunction<ObjCType> *function = (MGLStyleFunction<ObjCType> *)value;
+ __block std::vector<std::pair<float, MBGLType>> mbglStops;
+ [function.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");
+ mbglStops.emplace_back(zoomKey.floatValue, mbglStopValue.asConstant());
+ }];
+ return mbgl::style::Function<MBGLType>({{mbglStops}}, function.base);
+ } else {
+ return {};
+ }
+ }
+
+private:
+
+ MGLStyleConstantValue<ObjCType> *toStyleConstantValue(const MBGLType mbglValue) {
+ auto rawValue = toMGLRawStyleValue(mbglValue);
+ return [MGLStyleConstantValue<ObjCType> valueWithRawValue:rawValue];
+ }
+
+ MGLStyleFunction<ObjCType> *toStyleFunction(const mbgl::style::Function<MBGLType> &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<ObjCType> 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<float, 2> &mbglStopValue) {
+ return [NSValue mgl_valueWithOffsetArray:mbglStopValue];
+ }
+
+ // Padding
+ NSValue *toMGLRawStyleValue(const std::array<float, 4> &mbglStopValue) {
+ return [NSValue mgl_valueWithPaddingArray:mbglStopValue];
+ }
+
+ // Enumerations
+ template <typename MBGLEnum = MBGLType, class = typename std::enable_if<std::is_enum<MBGLEnum>::value>::type>
+ ObjCType toMGLRawStyleValue(const MBGLType &mbglStopValue) {
+ NSUInteger rawValue = static_cast<NSUInteger>(mbglStopValue);
+ return [NSValue value:&rawValue withObjCType:@encode(NSUInteger)];
+ }
+
+ MGLColor *toMGLRawStyleValue(const mbgl::Color mbglStopValue) {
+ return [MGLColor mbgl_colorWithColor:mbglStopValue];
+ }
+
+ ObjCType toMGLRawStyleValue(const std::vector<MBGLType> &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<float, 2> &mbglValue) {
+ mbglValue = rawValue.mgl_offsetArrayValue;
+ }
+
+ // Padding
+ void getMBGLValue(NSValue *rawValue, std::array<float, 4> &mbglValue) {
+ mbglValue = rawValue.mgl_paddingArrayValue;
+ }
+
+ // Enumerations
+ template <typename MBGLEnum = MBGLType, class = typename std::enable_if<std::is_enum<MBGLEnum>::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<MBGLType> &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 cd33923889..00829b0dca 100644
--- a/platform/darwin/src/MGLStyleAttributeValue.h
+++ b/platform/darwin/src/MGLStyleAttributeValue.h
@@ -2,4 +2,4 @@
@protocol MGLStyleAttributeValue <NSObject>
@optional
-@end \ No newline at end of file
+@end