summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Shalamov <alexander.shalamov@mapbox.com>2019-06-18 14:41:46 +0300
committerAlexander Shalamov <alexander.shalamov@mapbox.com>2019-08-13 13:32:56 +0300
commitf94460041353be26eb7516d7006a2c83a4aa19f2 (patch)
tree2ae50d7ec0b8da5a230f7a833acaea222ae9596c
parentdad43ba8fcd04698230fefa9c6af93931f6c10f3 (diff)
downloadqtlocation-mapboxgl-f94460041353be26eb7516d7006a2c83a4aa19f2.tar.gz
[darwin] Bindings for new 'text-writing-mode' layout property
-rwxr-xr-xplatform/darwin/scripts/generate-style-code.js37
-rw-r--r--platform/darwin/src/MGLStyleLayer.h.ejs4
-rw-r--r--platform/darwin/src/MGLStyleLayer.mm.ejs4
-rw-r--r--platform/darwin/src/MGLSymbolStyleLayer.h69
-rw-r--r--platform/darwin/src/MGLSymbolStyleLayer.mm33
-rw-r--r--platform/darwin/test/MGLSymbolStyleLayerTests.mm47
6 files changed, 189 insertions, 5 deletions
diff --git a/platform/darwin/scripts/generate-style-code.js b/platform/darwin/scripts/generate-style-code.js
index 37454cba54..2a825ac9c7 100755
--- a/platform/darwin/scripts/generate-style-code.js
+++ b/platform/darwin/scripts/generate-style-code.js
@@ -79,6 +79,28 @@ global.camelizeWithLeadingLowercase = function (str) {
});
};
+// Returns true only if property is an enum or if it is an array
+// property with uniquely defined enum.
+global.definesEnum = function(property, allProperties) {
+ if (property.type === "enum") {
+ return true;
+ }
+
+ if (property.type === 'array' && property.value === 'enum') {
+ const uniqueArrayEnum = (prop, enums) => {
+ if (prop.value !== 'enum') return false;
+ const enumsEqual = (val1, val2) => val1.length === val1.length && val1.every((val, i) => val === val2[i]);
+ return enums.filter(e => enumsEqual(Object.keys(prop.values).sort(), Object.keys(e.values).sort())).length == 0;
+ };
+
+ const allEnumProperties = _(allProperties).filter({'type': 'enum'}).value();
+ const uniqueArrayEnumProperties = _(allProperties).filter({'type': 'array'}).filter(prop => uniqueArrayEnum(prop, allEnumProperties)).value();
+ return _(uniqueArrayEnumProperties).filter({'name': property.name}).value().length != 0;
+ }
+
+ return false;
+}
+
global.objCName = function (property) {
return camelizeWithLeadingLowercase(property.name);
};
@@ -144,6 +166,8 @@ global.objCTestValue = function (property, layerType, arraysAsStructs, indent) {
}
case 'anchor':
return `@"{'top','bottom'}"`;
+ case 'mode':
+ return `@"{'horizontal','vertical'}"`;
default:
throw new Error(`unknown array type for ${property.name}`);
}
@@ -194,6 +218,8 @@ global.mbglTestValue = function (property, layerType) {
return '{ 1, 1 }';
case 'anchor':
return '{ mbgl::style::SymbolAnchorType::Top, mbgl::style::SymbolAnchorType::Bottom }';
+ case 'mode':
+ return '{ mbgl::style::TextWritingModeType::Horizontal, mbgl::style::TextWritingModeType::Vertical }';
default:
throw new Error(`unknown array type for ${property.name}`);
}
@@ -213,6 +239,8 @@ global.mbglExpressionTestValue = function (property, layerType) {
switch (arrayType(property)) {
case 'anchor':
return `{"top", "bottom"}`;
+ case 'mode':
+ return `{"horizontal", "vertical"}`;
default:
break;
}
@@ -439,6 +467,8 @@ global.describeType = function (property) {
return '`MGLSphericalPosition`';
case 'anchor':
return '`MGLTextAnchor` array';
+ case 'mode':
+ return '`MGLTextWritingMode` array';
default:
return 'array';
}
@@ -568,6 +598,7 @@ global.propertyType = function (property) {
case 'translate':
return 'NSValue *';
case 'anchor':
+ case 'mode':
return 'NSArray<NSValue *> *';
default:
throw new Error(`unknown array type for ${property.name}`);
@@ -615,6 +646,8 @@ global.valueTransformerArguments = function (property) {
return ['std::array<float, 2>', objCType];
case 'anchor':
return ['std::vector<mbgl::style::SymbolAnchorType>', objCType, 'mbgl::style::SymbolAnchorType', 'MGLTextAnchor'];
+ case 'mode':
+ return ['std::vector<mbgl::style::TextWritingModeType>', objCType, 'mbgl::style::TextWritingModeType', 'MGLTextWritingMode'];
default:
throw new Error(`unknown array type for ${property.name}`);
}
@@ -666,6 +699,8 @@ global.mbglType = function(property) {
return 'mbgl::style::Position';
case 'anchor':
return 'std::vector<mbgl::style::SymbolAnchorType>';
+ case 'mode':
+ return 'std::vector<mbgl::style::TextWritingModeType>';
default:
throw new Error(`unknown array type for ${property.name}`);
}
@@ -773,7 +808,7 @@ var renamedPropertiesByLayerType = {};
for (var layer of layers) {
layer.properties = _.concat(layer.layoutProperties, layer.paintProperties);
- let enumProperties = _.filter(layer.properties, prop => prop.type === 'enum');
+ let enumProperties = _.filter(layer.properties, prop => definesEnum(prop, layer.properties));
if (enumProperties.length) {
layer.enumProperties = enumProperties;
}
diff --git a/platform/darwin/src/MGLStyleLayer.h.ejs b/platform/darwin/src/MGLStyleLayer.h.ejs
index 9435e0d2ff..4bbb9e9f0d 100644
--- a/platform/darwin/src/MGLStyleLayer.h.ejs
+++ b/platform/darwin/src/MGLStyleLayer.h.ejs
@@ -19,7 +19,7 @@
NS_ASSUME_NONNULL_BEGIN
<% for (const property of layoutProperties) { -%>
-<% if (property.type == "enum") { -%>
+<% if (definesEnum(property, layoutProperties)) { -%>
/**
<%- propertyDoc(property.name, property, type, 'enum').wrap(80, 1) %>
@@ -38,7 +38,7 @@ typedef NS_ENUM(NSUInteger, MGL<%- camelize(property.name) %>) {
<% } -%>
<% } -%>
<% for (const property of paintProperties) { -%>
-<% if (property.type == "enum") { -%>
+<% if (definesEnum(property, paintProperties)) { -%>
/**
<%- propertyDoc(property.name, property, type, 'enum').wrap(80, 1) %>
diff --git a/platform/darwin/src/MGLStyleLayer.mm.ejs b/platform/darwin/src/MGLStyleLayer.mm.ejs
index 26cb3e26f6..e8c8d8cfd9 100644
--- a/platform/darwin/src/MGLStyleLayer.mm.ejs
+++ b/platform/darwin/src/MGLStyleLayer.mm.ejs
@@ -25,7 +25,7 @@ namespace mbgl {
<% if (layoutProperties.length) { -%>
<% for (const property of layoutProperties) { -%>
-<% if (property.type == "enum") { -%>
+<% if (definesEnum(property, layoutProperties)) { -%>
MBGL_DEFINE_ENUM(MGL<%- camelize(property.name) %>, {
<% for (const value in property.values) { -%>
{ MGL<%- camelize(property.name) %><%- camelize(value) %>, "<%-value%>" },
@@ -37,7 +37,7 @@ namespace mbgl {
<% } -%>
<% if (paintProperties.length) { -%>
<% for (const property of paintProperties) { -%>
-<% if (property.type == "enum") { -%>
+<% if (definesEnum(property, paintProperties)) { -%>
MBGL_DEFINE_ENUM(MGL<%- camelize(property.name) %>, {
<% for (const value in property.values) { -%>
{ MGL<%- camelize(property.name) %><%- camelize(value) %>, "<%-value%>" },
diff --git a/platform/darwin/src/MGLSymbolStyleLayer.h b/platform/darwin/src/MGLSymbolStyleLayer.h
index 658a31679e..bbb5dae905 100644
--- a/platform/darwin/src/MGLSymbolStyleLayer.h
+++ b/platform/darwin/src/MGLSymbolStyleLayer.h
@@ -317,6 +317,30 @@ typedef NS_ENUM(NSUInteger, MGLTextTransform) {
};
/**
+ The property allows to control an orientation of a symbol. Note, that the
+ property values act as a hint, so that Symbols whose language doesn't support
+ provided orientation, will be laid out in their natural orientation. Example:
+ English point symbol will be rendered horizontally even if `"textWritingMode":
+ ["vertical"]` is set. The order of elements in an array define priority order
+ for the placement of an orientation variant.
+
+ Values of this type are used in the `MGLSymbolStyleLayer.textWritingMode`
+ property.
+ */
+typedef NS_ENUM(NSUInteger, MGLTextWritingMode) {
+ /**
+ If a text's language supports horizontal writing mode, symbols with point
+ placement would be laid out horizontally.
+ */
+ MGLTextWritingModeHorizontal,
+ /**
+ If a text's language supports vertical writing mode, symbols with point
+ placement would be laid out vertically.
+ */
+ MGLTextWritingModeVertical,
+};
+
+/**
Controls the frame of reference for `MGLSymbolStyleLayer.iconTranslation`.
Values of this type are used in the `MGLSymbolStyleLayer.iconTranslationAnchor`
@@ -1646,6 +1670,38 @@ MGL_EXPORT
*/
@property (nonatomic, null_resettable) NSExpression *textVariableAnchor;
+/**
+ The property allows to control an orientation of a symbol. Note, that the
+ property values act as a hint, so that Symbols whose language doesn't support
+ provided orientation, will be laid out in their natural orientation. Example:
+ English point symbol will be rendered horizontally even if `"textWritingMode":
+ ["vertical"]` is set. The order of elements in an array define priority order
+ for the placement of an orientation variant.
+
+ This property is only applied to the style if `text` is non-`nil`, and
+ `symbolPlacement` is set to an expression that evaluates to or
+ `MGLSymbolPlacementPoint`. Otherwise, it is ignored.
+
+ You can set this property to an expression containing any of the following:
+
+ * Constant `MGLTextWritingMode` array values
+ * Constant array, whose each element is any of the following constant string
+ values:
+ * `horizontal`: If a text's language supports horizontal writing mode,
+ symbols with point placement would be laid out horizontally.
+ * `vertical`: If a text's language supports vertical writing mode, symbols
+ with point placement would be laid out vertically.
+ * Predefined functions, including mathematical and string operators
+ * Conditional expressions
+ * Variable assignments and references to assigned variables
+ * Step functions applied to the `$zoomLevel` variable
+
+ This property does not support applying interpolation functions to the
+ `$zoomLevel` variable or applying interpolation or step functions to feature
+ attributes.
+ */
+@property (nonatomic, null_resettable) NSExpression *textWritingMode;
+
#pragma mark - Accessing the Paint Attributes
#if TARGET_OS_IPHONE
@@ -2383,6 +2439,19 @@ MGL_EXPORT
@property (readonly) MGLTextTransform MGLTextTransformValue;
/**
+ Creates a new value object containing the given `MGLTextWritingMode` enumeration.
+
+ @param textWritingMode The value for the new object.
+ @return A new value object that contains the enumeration value.
+ */
++ (instancetype)valueWithMGLTextWritingMode:(MGLTextWritingMode)textWritingMode;
+
+/**
+ The `MGLTextWritingMode` enumeration representation of the value.
+ */
+@property (readonly) MGLTextWritingMode MGLTextWritingModeValue;
+
+/**
Creates a new value object containing the given `MGLIconTranslationAnchor` enumeration.
@param iconTranslationAnchor The value for the new object.
diff --git a/platform/darwin/src/MGLSymbolStyleLayer.mm b/platform/darwin/src/MGLSymbolStyleLayer.mm
index e54a0b9a15..99cfe5db10 100644
--- a/platform/darwin/src/MGLSymbolStyleLayer.mm
+++ b/platform/darwin/src/MGLSymbolStyleLayer.mm
@@ -96,6 +96,11 @@ namespace mbgl {
{ MGLTextTransformLowercase, "lowercase" },
});
+ MBGL_DEFINE_ENUM(MGLTextWritingMode, {
+ { MGLTextWritingModeHorizontal, "horizontal" },
+ { MGLTextWritingModeVertical, "vertical" },
+ });
+
MBGL_DEFINE_ENUM(MGLIconTranslationAnchor, {
{ MGLIconTranslationAnchorMap, "map" },
{ MGLIconTranslationAnchorViewport, "viewport" },
@@ -1023,6 +1028,24 @@ namespace mbgl {
return MGLStyleValueTransformer<std::vector<mbgl::style::SymbolAnchorType>, NSArray<NSValue *> *, mbgl::style::SymbolAnchorType, MGLTextAnchor>().toExpression(propertyValue);
}
+- (void)setTextWritingMode:(NSExpression *)textWritingMode {
+ MGLAssertStyleLayerIsValid();
+ MGLLogDebug(@"Setting textWritingMode: %@", textWritingMode);
+
+ auto mbglValue = MGLStyleValueTransformer<std::vector<mbgl::style::TextWritingModeType>, NSArray<NSValue *> *, mbgl::style::TextWritingModeType, MGLTextWritingMode>().toPropertyValue<mbgl::style::PropertyValue<std::vector<mbgl::style::TextWritingModeType>>>(textWritingMode, false);
+ self.rawLayer->setTextWritingMode(mbglValue);
+}
+
+- (NSExpression *)textWritingMode {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = self.rawLayer->getTextWritingMode();
+ if (propertyValue.isUndefined()) {
+ propertyValue = self.rawLayer->getDefaultTextWritingMode();
+ }
+ return MGLStyleValueTransformer<std::vector<mbgl::style::TextWritingModeType>, NSArray<NSValue *> *, mbgl::style::TextWritingModeType, MGLTextWritingMode>().toExpression(propertyValue);
+}
+
#pragma mark - Accessing the Paint Attributes
- (void)setIconColor:(NSExpression *)iconColor {
@@ -1599,6 +1622,16 @@ namespace mbgl {
return textTransform;
}
++ (NSValue *)valueWithMGLTextWritingMode:(MGLTextWritingMode)textWritingMode {
+ return [NSValue value:&textWritingMode withObjCType:@encode(MGLTextWritingMode)];
+}
+
+- (MGLTextWritingMode)MGLTextWritingModeValue {
+ MGLTextWritingMode textWritingMode;
+ [self getValue:&textWritingMode];
+ return textWritingMode;
+}
+
+ (NSValue *)valueWithMGLIconTranslationAnchor:(MGLIconTranslationAnchor)iconTranslationAnchor {
return [NSValue value:&iconTranslationAnchor withObjCType:@encode(MGLIconTranslationAnchor)];
}
diff --git a/platform/darwin/test/MGLSymbolStyleLayerTests.mm b/platform/darwin/test/MGLSymbolStyleLayerTests.mm
index 87091acc1b..0f51fd000c 100644
--- a/platform/darwin/test/MGLSymbolStyleLayerTests.mm
+++ b/platform/darwin/test/MGLSymbolStyleLayerTests.mm
@@ -2074,6 +2074,50 @@
XCTAssertThrowsSpecificNamed(layer.textVariableAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
+ // text-writing-mode
+ {
+ XCTAssertTrue(rawLayer->getTextWritingMode().isUndefined(),
+ @"text-writing-mode should be unset initially.");
+ NSExpression *defaultExpression = layer.textWritingMode;
+
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"{'horizontal','vertical'}"];
+ layer.textWritingMode = constantExpression;
+ mbgl::style::PropertyValue<std::vector<mbgl::style::TextWritingModeType>> propertyValue = { { mbgl::style::TextWritingModeType::Horizontal, mbgl::style::TextWritingModeType::Vertical } };
+ XCTAssertEqual(rawLayer->getTextWritingMode(), propertyValue,
+ @"Setting textWritingMode to a constant value expression should update text-writing-mode.");
+ XCTAssertEqualObjects(layer.textWritingMode, constantExpression,
+ @"textWritingMode should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"{'horizontal','vertical'}"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.textWritingMode = functionExpression;
+
+ {
+ using namespace mbgl::style::expression::dsl;
+ propertyValue = mbgl::style::PropertyExpression<std::vector<mbgl::style::TextWritingModeType>>(
+ step(zoom(), literal({"horizontal", "vertical"}), 18.0, literal({"horizontal", "vertical"}))
+ );
+ }
+
+ XCTAssertEqual(rawLayer->getTextWritingMode(), propertyValue,
+ @"Setting textWritingMode to a camera expression should update text-writing-mode.");
+ XCTAssertEqualObjects(layer.textWritingMode, functionExpression,
+ @"textWritingMode should round-trip camera expressions.");
+
+
+ layer.textWritingMode = nil;
+ XCTAssertTrue(rawLayer->getTextWritingMode().isUndefined(),
+ @"Unsetting textWritingMode should return text-writing-mode to the default value.");
+ XCTAssertEqualObjects(layer.textWritingMode, defaultExpression,
+ @"textWritingMode should return the default value after being unset.");
+
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.textWritingMode = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
+ XCTAssertThrowsSpecificNamed(layer.textWritingMode = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
+ }
+
// icon-color
{
XCTAssertTrue(rawLayer->getIconColor().isUndefined(),
@@ -3084,6 +3128,7 @@
[self testPropertyName:@"text-rotation-alignment" isBoolean:NO];
[self testPropertyName:@"text-transform" isBoolean:NO];
[self testPropertyName:@"text-variable-anchor" isBoolean:NO];
+ [self testPropertyName:@"text-writing-mode" isBoolean:NO];
[self testPropertyName:@"icon-color" isBoolean:NO];
[self testPropertyName:@"icon-halo-blur" isBoolean:NO];
[self testPropertyName:@"icon-halo-color" isBoolean:NO];
@@ -3148,6 +3193,8 @@
XCTAssertEqual([NSValue valueWithMGLTextTransform:MGLTextTransformNone].MGLTextTransformValue, MGLTextTransformNone);
XCTAssertEqual([NSValue valueWithMGLTextTransform:MGLTextTransformUppercase].MGLTextTransformValue, MGLTextTransformUppercase);
XCTAssertEqual([NSValue valueWithMGLTextTransform:MGLTextTransformLowercase].MGLTextTransformValue, MGLTextTransformLowercase);
+ XCTAssertEqual([NSValue valueWithMGLTextWritingMode:MGLTextWritingModeHorizontal].MGLTextWritingModeValue, MGLTextWritingModeHorizontal);
+ XCTAssertEqual([NSValue valueWithMGLTextWritingMode:MGLTextWritingModeVertical].MGLTextWritingModeValue, MGLTextWritingModeVertical);
XCTAssertEqual([NSValue valueWithMGLIconTranslationAnchor:MGLIconTranslationAnchorMap].MGLIconTranslationAnchorValue, MGLIconTranslationAnchorMap);
XCTAssertEqual([NSValue valueWithMGLIconTranslationAnchor:MGLIconTranslationAnchorViewport].MGLIconTranslationAnchorValue, MGLIconTranslationAnchorViewport);
XCTAssertEqual([NSValue valueWithMGLTextTranslationAnchor:MGLTextTranslationAnchorMap].MGLTextTranslationAnchorValue, MGLTextTranslationAnchorMap);