[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.
This commit is contained in:
committed by
Minh Nguyễn
parent
ae96e78ccd
commit
0c8a3feffa
@@ -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.
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
@protocol MGLStyleAttributeValue <NSObject>
|
||||
@optional
|
||||
@end
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user