summaryrefslogtreecommitdiff
path: root/platform/darwin
diff options
context:
space:
mode:
Diffstat (limited to 'platform/darwin')
-rw-r--r--platform/darwin/scripts/generate-style-code.js14
-rw-r--r--platform/darwin/src/MGLSymbolStyleLayer.h86
-rw-r--r--platform/darwin/src/MGLSymbolStyleLayer.mm45
-rw-r--r--platform/darwin/test/MGLSymbolStyleLayerTests.mm50
4 files changed, 185 insertions, 10 deletions
diff --git a/platform/darwin/scripts/generate-style-code.js b/platform/darwin/scripts/generate-style-code.js
index 5a4936c0ee..4ee86e65da 100644
--- a/platform/darwin/scripts/generate-style-code.js
+++ b/platform/darwin/scripts/generate-style-code.js
@@ -148,6 +148,9 @@ global.mbglTestValue = function (property, layerType) {
if (/-(rotation|pitch)-alignment$/.test(originalPropertyName(property))) {
type = 'Alignment';
}
+ if (/^(text|icon)-anchor$/.test(originalPropertyName(property))) {
+ type = 'SymbolAnchor'
+ }
let value = camelize(_.last(_.keys(property.values)));
if (property['light-property']) {
return `mbgl::style::Light${type}Type::${value}`;
@@ -500,6 +503,9 @@ global.mbglType = function(property) {
if (/-(rotation|pitch)-alignment$/.test(originalPropertyName(property))) {
type = 'Alignment';
}
+ if (/^(text|icon)-anchor$/.test(originalPropertyName(property))) {
+ type = 'SymbolAnchor'
+ }
return `mbgl::style::${type}Type`;
}
case 'color':
@@ -648,10 +654,10 @@ while ((match = exampleRegex.exec(examplesSrc)) !== null) {
let testMethodName = match[1],
indentation = match[2],
exampleCode = match[3];
-
+
// Trim leading whitespace from the example code.
exampleCode = exampleCode.replace(new RegExp('^' + indentation, 'gm'), '');
-
+
examples[testMethodName] = exampleCode;
}
@@ -663,13 +669,13 @@ global.guideExample = function (guide, exampleId, os) {
console.error(`MGLDocumentationExampleTests.test${testMethodName}() not found.`);
process.exit(1);
}
-
+
// Resolve conditional compilation blocks.
example = example.replace(/^(\s*)#if\s+os\((iOS|macOS)\)\n([^]*?)(?:^\1#else\n([^]*?))?^\1#endif\b\n?/gm,
function (m, indentation, ifOs, ifCase, elseCase) {
return (os === ifOs ? ifCase : elseCase).replace(new RegExp('^ ', 'gm'), '');
}).replace(/\n$/, '');
-
+
return '```swift\n' + example + '\n```';
};
diff --git a/platform/darwin/src/MGLSymbolStyleLayer.h b/platform/darwin/src/MGLSymbolStyleLayer.h
index d8dded7dbd..bc39df5b16 100644
--- a/platform/darwin/src/MGLSymbolStyleLayer.h
+++ b/platform/darwin/src/MGLSymbolStyleLayer.h
@@ -8,6 +8,51 @@
NS_ASSUME_NONNULL_BEGIN
/**
+ Part of the icon placed closest to the anchor.
+
+ Values of this type are used in the `MGLSymbolStyleLayer.iconAnchor`
+ property.
+ */
+typedef NS_ENUM(NSUInteger, MGLIconAnchor) {
+ /**
+ The center of the icon is placed closest to the anchor.
+ */
+ MGLIconAnchorCenter,
+ /**
+ The left side of the icon is placed closest to the anchor.
+ */
+ MGLIconAnchorLeft,
+ /**
+ The right side of the icon is placed closest to the anchor.
+ */
+ MGLIconAnchorRight,
+ /**
+ The top of the icon is placed closest to the anchor.
+ */
+ MGLIconAnchorTop,
+ /**
+ The bottom of the icon is placed closest to the anchor.
+ */
+ MGLIconAnchorBottom,
+ /**
+ The top left corner of the icon is placed closest to the anchor.
+ */
+ MGLIconAnchorTopLeft,
+ /**
+ The top right corner of the icon is placed closest to the anchor.
+ */
+ MGLIconAnchorTopRight,
+ /**
+ The bottom left corner of the icon is placed closest to the anchor.
+ */
+ MGLIconAnchorBottomLeft,
+ /**
+ The bottom right corner of the icon is placed closest to the anchor.
+ */
+ MGLIconAnchorBottomRight,
+};
+
+/**
Orientation of icon when map is pitched.
Values of this type are used in the `MGLSymbolStyleLayer.iconPitchAlignment`
@@ -345,6 +390,34 @@ MGL_EXPORT
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *iconAllowOverlap __attribute__((unavailable("Use iconAllowsOverlap instead.")));
/**
+ Part of the icon placed closest to the anchor.
+
+ The default value of this property is an `MGLStyleValue` object containing an
+ `NSValue` object containing `MGLIconAnchorCenter`. Set this property to `nil`
+ to reset it to the default value.
+
+ This property is only applied to the style if `iconImageName` is non-`nil`.
+ Otherwise, it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLConstantStyleValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ */
+@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *iconAnchor;
+
+/**
If true, other symbols can be visible even if they collide with the icon.
The default value of this property is an `MGLStyleValue` object containing an
@@ -1984,6 +2057,19 @@ MGL_EXPORT
#pragma mark Working with Symbol Style Layer Attribute Values
/**
+ Creates a new value object containing the given `MGLIconAnchor` enumeration.
+
+ @param iconAnchor The value for the new object.
+ @return A new value object that contains the enumeration value.
+ */
++ (instancetype)valueWithMGLIconAnchor:(MGLIconAnchor)iconAnchor;
+
+/**
+ The `MGLIconAnchor` enumeration representation of the value.
+ */
+@property (readonly) MGLIconAnchor MGLIconAnchorValue;
+
+/**
Creates a new value object containing the given `MGLIconPitchAlignment` enumeration.
@param iconPitchAlignment The value for the new object.
diff --git a/platform/darwin/src/MGLSymbolStyleLayer.mm b/platform/darwin/src/MGLSymbolStyleLayer.mm
index 2541e6b0a4..7e8b0b247b 100644
--- a/platform/darwin/src/MGLSymbolStyleLayer.mm
+++ b/platform/darwin/src/MGLSymbolStyleLayer.mm
@@ -13,6 +13,18 @@
namespace mbgl {
+ MBGL_DEFINE_ENUM(MGLIconAnchor, {
+ { MGLIconAnchorCenter, "center" },
+ { MGLIconAnchorLeft, "left" },
+ { MGLIconAnchorRight, "right" },
+ { MGLIconAnchorTop, "top" },
+ { MGLIconAnchorBottom, "bottom" },
+ { MGLIconAnchorTopLeft, "top-left" },
+ { MGLIconAnchorTopRight, "top-right" },
+ { MGLIconAnchorBottomLeft, "bottom-left" },
+ { MGLIconAnchorBottomRight, "bottom-right" },
+ });
+
MBGL_DEFINE_ENUM(MGLIconPitchAlignment, {
{ MGLIconPitchAlignmentMap, "map" },
{ MGLIconPitchAlignmentViewport, "viewport" },
@@ -166,6 +178,23 @@ namespace mbgl {
return self.iconAllowsOverlap;
}
+- (void)setIconAnchor:(MGLStyleValue<NSValue *> *)iconAnchor {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<mbgl::style::SymbolAnchorType, NSValue *, mbgl::style::SymbolAnchorType, MGLIconAnchor>().toDataDrivenPropertyValue(iconAnchor);
+ self.rawLayer->setIconAnchor(mbglValue);
+}
+
+- (MGLStyleValue<NSValue *> *)iconAnchor {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = self.rawLayer->getIconAnchor();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::style::SymbolAnchorType, NSValue *, mbgl::style::SymbolAnchorType, MGLIconAnchor>().toDataDrivenStyleValue(self.rawLayer->getDefaultIconAnchor());
+ }
+ return MGLStyleValueTransformer<mbgl::style::SymbolAnchorType, NSValue *, mbgl::style::SymbolAnchorType, MGLIconAnchor>().toDataDrivenStyleValue(propertyValue);
+}
+
- (void)setIconIgnoresPlacement:(MGLStyleValue<NSNumber *> *)iconIgnoresPlacement {
MGLAssertStyleLayerIsValid();
@@ -586,7 +615,7 @@ namespace mbgl {
- (void)setTextAnchor:(MGLStyleValue<NSValue *> *)textAnchor {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<mbgl::style::TextAnchorType, NSValue *, mbgl::style::TextAnchorType, MGLTextAnchor>().toDataDrivenPropertyValue(textAnchor);
+ auto mbglValue = MGLStyleValueTransformer<mbgl::style::SymbolAnchorType, NSValue *, mbgl::style::SymbolAnchorType, MGLTextAnchor>().toDataDrivenPropertyValue(textAnchor);
self.rawLayer->setTextAnchor(mbglValue);
}
@@ -595,9 +624,9 @@ namespace mbgl {
auto propertyValue = self.rawLayer->getTextAnchor();
if (propertyValue.isUndefined()) {
- return MGLStyleValueTransformer<mbgl::style::TextAnchorType, NSValue *, mbgl::style::TextAnchorType, MGLTextAnchor>().toDataDrivenStyleValue(self.rawLayer->getDefaultTextAnchor());
+ return MGLStyleValueTransformer<mbgl::style::SymbolAnchorType, NSValue *, mbgl::style::SymbolAnchorType, MGLTextAnchor>().toDataDrivenStyleValue(self.rawLayer->getDefaultTextAnchor());
}
- return MGLStyleValueTransformer<mbgl::style::TextAnchorType, NSValue *, mbgl::style::TextAnchorType, MGLTextAnchor>().toDataDrivenStyleValue(propertyValue);
+ return MGLStyleValueTransformer<mbgl::style::SymbolAnchorType, NSValue *, mbgl::style::SymbolAnchorType, MGLTextAnchor>().toDataDrivenStyleValue(propertyValue);
}
- (void)setTextFontNames:(MGLStyleValue<NSArray<NSString *> *> *)textFontNames {
@@ -1344,6 +1373,16 @@ namespace mbgl {
@implementation NSValue (MGLSymbolStyleLayerAdditions)
++ (NSValue *)valueWithMGLIconAnchor:(MGLIconAnchor)iconAnchor {
+ return [NSValue value:&iconAnchor withObjCType:@encode(MGLIconAnchor)];
+}
+
+- (MGLIconAnchor)MGLIconAnchorValue {
+ MGLIconAnchor iconAnchor;
+ [self getValue:&iconAnchor];
+ return iconAnchor;
+}
+
+ (NSValue *)valueWithMGLIconPitchAlignment:(MGLIconPitchAlignment)iconPitchAlignment {
return [NSValue value:&iconPitchAlignment withObjCType:@encode(MGLIconPitchAlignment)];
}
diff --git a/platform/darwin/test/MGLSymbolStyleLayerTests.mm b/platform/darwin/test/MGLSymbolStyleLayerTests.mm
index 6b0b20354b..abbaef9159 100644
--- a/platform/darwin/test/MGLSymbolStyleLayerTests.mm
+++ b/platform/darwin/test/MGLSymbolStyleLayerTests.mm
@@ -87,6 +87,40 @@
XCTAssertThrowsSpecificNamed(layer.iconAllowsOverlap = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
+ // icon-anchor
+ {
+ XCTAssertTrue(rawLayer->getIconAnchor().isUndefined(),
+ @"icon-anchor should be unset initially.");
+ MGLStyleValue<NSValue *> *defaultStyleValue = layer.iconAnchor;
+
+ MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLIconAnchor:MGLIconAnchorBottomRight]];
+ layer.iconAnchor = constantStyleValue;
+ mbgl::style::DataDrivenPropertyValue<mbgl::style::SymbolAnchorType> propertyValue = { mbgl::style::SymbolAnchorType::BottomRight };
+ XCTAssertEqual(rawLayer->getIconAnchor(), propertyValue,
+ @"Setting iconAnchor to a constant value should update icon-anchor.");
+ XCTAssertEqualObjects(layer.iconAnchor, constantStyleValue,
+ @"iconAnchor should round-trip constant values.");
+
+ MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.iconAnchor = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::style::SymbolAnchorType> intervalStops = { {{18, mbgl::style::SymbolAnchorType::BottomRight}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::style::SymbolAnchorType> { intervalStops };
+
+ XCTAssertEqual(rawLayer->getIconAnchor(), propertyValue,
+ @"Setting iconAnchor to a camera function should update icon-anchor.");
+ XCTAssertEqualObjects(layer.iconAnchor, functionStyleValue,
+ @"iconAnchor should round-trip camera functions.");
+
+
+
+ layer.iconAnchor = nil;
+ XCTAssertTrue(rawLayer->getIconAnchor().isUndefined(),
+ @"Unsetting iconAnchor should return icon-anchor to the default value.");
+ XCTAssertEqualObjects(layer.iconAnchor, defaultStyleValue,
+ @"iconAnchor should return the default value after being unset.");
+ }
+
// icon-ignore-placement
{
XCTAssertTrue(rawLayer->getIconIgnorePlacement().isUndefined(),
@@ -931,7 +965,7 @@
MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLTextAnchor:MGLTextAnchorBottomRight]];
layer.textAnchor = constantStyleValue;
- mbgl::style::DataDrivenPropertyValue<mbgl::style::TextAnchorType> propertyValue = { mbgl::style::TextAnchorType::BottomRight };
+ mbgl::style::DataDrivenPropertyValue<mbgl::style::SymbolAnchorType> propertyValue = { mbgl::style::SymbolAnchorType::BottomRight };
XCTAssertEqual(rawLayer->getTextAnchor(), propertyValue,
@"Setting textAnchor to a constant value should update text-anchor.");
XCTAssertEqualObjects(layer.textAnchor, constantStyleValue,
@@ -940,8 +974,8 @@
MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
layer.textAnchor = functionStyleValue;
- mbgl::style::IntervalStops<mbgl::style::TextAnchorType> intervalStops = { {{18, mbgl::style::TextAnchorType::BottomRight}} };
- propertyValue = mbgl::style::CameraFunction<mbgl::style::TextAnchorType> { intervalStops };
+ mbgl::style::IntervalStops<mbgl::style::SymbolAnchorType> intervalStops = { {{18, mbgl::style::SymbolAnchorType::BottomRight}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::style::SymbolAnchorType> { intervalStops };
XCTAssertEqual(rawLayer->getTextAnchor(), propertyValue,
@"Setting textAnchor to a camera function should update text-anchor.");
@@ -2345,6 +2379,7 @@
- (void)testPropertyNames {
[self testPropertyName:@"icon-allows-overlap" isBoolean:YES];
+ [self testPropertyName:@"icon-anchor" isBoolean:NO];
[self testPropertyName:@"icon-ignores-placement" isBoolean:YES];
[self testPropertyName:@"icon-image-name" isBoolean:NO];
[self testPropertyName:@"icon-offset" isBoolean:NO];
@@ -2396,6 +2431,15 @@
}
- (void)testValueAdditions {
+ XCTAssertEqual([NSValue valueWithMGLIconAnchor:MGLIconAnchorCenter].MGLIconAnchorValue, MGLIconAnchorCenter);
+ XCTAssertEqual([NSValue valueWithMGLIconAnchor:MGLIconAnchorLeft].MGLIconAnchorValue, MGLIconAnchorLeft);
+ XCTAssertEqual([NSValue valueWithMGLIconAnchor:MGLIconAnchorRight].MGLIconAnchorValue, MGLIconAnchorRight);
+ XCTAssertEqual([NSValue valueWithMGLIconAnchor:MGLIconAnchorTop].MGLIconAnchorValue, MGLIconAnchorTop);
+ XCTAssertEqual([NSValue valueWithMGLIconAnchor:MGLIconAnchorBottom].MGLIconAnchorValue, MGLIconAnchorBottom);
+ XCTAssertEqual([NSValue valueWithMGLIconAnchor:MGLIconAnchorTopLeft].MGLIconAnchorValue, MGLIconAnchorTopLeft);
+ XCTAssertEqual([NSValue valueWithMGLIconAnchor:MGLIconAnchorTopRight].MGLIconAnchorValue, MGLIconAnchorTopRight);
+ XCTAssertEqual([NSValue valueWithMGLIconAnchor:MGLIconAnchorBottomLeft].MGLIconAnchorValue, MGLIconAnchorBottomLeft);
+ XCTAssertEqual([NSValue valueWithMGLIconAnchor:MGLIconAnchorBottomRight].MGLIconAnchorValue, MGLIconAnchorBottomRight);
XCTAssertEqual([NSValue valueWithMGLIconPitchAlignment:MGLIconPitchAlignmentMap].MGLIconPitchAlignmentValue, MGLIconPitchAlignmentMap);
XCTAssertEqual([NSValue valueWithMGLIconPitchAlignment:MGLIconPitchAlignmentViewport].MGLIconPitchAlignmentValue, MGLIconPitchAlignmentViewport);
XCTAssertEqual([NSValue valueWithMGLIconPitchAlignment:MGLIconPitchAlignmentAuto].MGLIconPitchAlignmentValue, MGLIconPitchAlignmentAuto);