summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMinh Nguyễn <mxn@1ec5.org>2018-04-11 19:19:17 -0700
committerMinh Nguyễn <mxn@1ec5.org>2018-04-16 14:46:51 -0700
commit3cc5a7dc2a306fc4c0c77113266b9e95312516f4 (patch)
treed1501f90579a744993c8ca992b44d8c3da78da3b
parent18d08bb3c45b4c8b2e61a8ae9054687040261ace (diff)
downloadqtlocation-mapboxgl-3cc5a7dc2a306fc4c0c77113266b9e95312516f4.tar.gz
[ios, macos] Streamlined token upgrading
Separated token upgrading into a separate process that only happens as part of the MGLSymbolStyleLayer.text and MGLSymbolStyleLayer.iconImageName properties’ getters, so that it’s easy to remove later when mbgl changes obviate this workaround. Removed the replacesTokens parameter to the expression localization methods.
-rw-r--r--platform/darwin/scripts/style-spec-overrides-v8.json6
-rw-r--r--platform/darwin/src/MGLStyle.mm2
-rw-r--r--platform/darwin/src/MGLStyleLayer.mm.ejs5
-rw-r--r--platform/darwin/src/MGLSymbolStyleLayer.mm6
-rw-r--r--platform/darwin/src/NSExpression+MGLAdditions.h9
-rw-r--r--platform/darwin/src/NSExpression+MGLAdditions.mm83
-rw-r--r--platform/darwin/src/NSExpression+MGLPrivateAdditions.h6
-rw-r--r--platform/ios/CHANGELOG.md2
-rw-r--r--platform/macos/CHANGELOG.md2
9 files changed, 77 insertions, 44 deletions
diff --git a/platform/darwin/scripts/style-spec-overrides-v8.json b/platform/darwin/scripts/style-spec-overrides-v8.json
index d47b13cdb2..8c2afdf4b1 100644
--- a/platform/darwin/scripts/style-spec-overrides-v8.json
+++ b/platform/darwin/scripts/style-spec-overrides-v8.json
@@ -46,10 +46,12 @@
"doc": "Offset distance of icon from its anchor."
},
"icon-image": {
- "doc": "Name of a style image to use for drawing an image background.\n\nUse the `+[MGLStyle setImage:forName:]` method to associate an image with a name that you can set this property to.\n\nWithin a constant string value, a feature attribute name enclosed in curly braces (e.g., `{token}`) is replaced with the value of the named attribute. Tokens inside non-constant expressions are ignored; instead, use `mgl_join:` and key path expressions."
+ "doc": "Name of a style image to use for drawing an image background.\n\nUse the `+[MGLStyle setImage:forName:]` method to associate an image with a name that you can set this property to.\n\nWithin a constant string value, a feature attribute name enclosed in curly braces (e.g., `{token}`) is replaced with the value of the named attribute. Tokens inside non-constant expressions are ignored; instead, use `mgl_join:` and key path expressions.",
+ "tokenized": true
},
"text-field": {
- "doc": "Value to use for a text label.\n\nWithin a constant string value, a feature attribute name enclosed in curly braces (e.g., `{token}`) is replaced with the value of the named attribute. Tokens inside non-constant expressions are ignored; instead, use `mgl_join:` and key path expressions."
+ "doc": "Value to use for a text label.\n\nWithin a constant string value, a feature attribute name enclosed in curly braces (e.g., `{token}`) is replaced with the value of the named attribute. Tokens inside non-constant expressions are ignored; instead, use `mgl_join:` and key path expressions.",
+ "tokenized": true
},
"text-font": {
"doc": "An array of font face names used to display the text.\n\nEach font name must be included in the `{fontstack}` portion of the JSON stylesheet’s <a href=\"https://www.mapbox.com/mapbox-gl-style-spec/#glyphs\"><code>glyphs</code></a> property. You can register a custom font when designing the style in Mapbox Studio. Fonts installed on the system are not used.\n\nThe first font named in the array is applied to the text. For each character in the text, if the first font lacks a glyph for the character, the next font is applied as a fallback, and so on."
diff --git a/platform/darwin/src/MGLStyle.mm b/platform/darwin/src/MGLStyle.mm
index b5bfdb4c7a..cb9e81d3d7 100644
--- a/platform/darwin/src/MGLStyle.mm
+++ b/platform/darwin/src/MGLStyle.mm
@@ -597,7 +597,7 @@ static_assert(6 == mbgl::util::default_styles::numOrderedStyles,
}
NSExpression *text = layer.text;
- NSExpression *localizedText = [layer.text mgl_expressionLocalizedIntoLocale:locale replacingTokens:YES];
+ NSExpression *localizedText = [text mgl_expressionLocalizedIntoLocale:locale];
if (![localizedText isEqual:text]) {
layer.text = localizedText;
}
diff --git a/platform/darwin/src/MGLStyleLayer.mm.ejs b/platform/darwin/src/MGLStyleLayer.mm.ejs
index ac7676a1cc..2a917b8421 100644
--- a/platform/darwin/src/MGLStyleLayer.mm.ejs
+++ b/platform/darwin/src/MGLStyleLayer.mm.ejs
@@ -136,7 +136,12 @@ namespace mbgl {
if (propertyValue.isUndefined()) {
propertyValue = self.rawLayer->getDefault<%- camelize(originalPropertyName(property)) %>();
}
+<% if (property.tokenized) { -%>
+ NSExpression *expression = MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toExpression(propertyValue);
+ return expression.mgl_expressionByReplacingTokensWithKeyPaths;
+<% } else { -%>
return MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toExpression(propertyValue);
+<% } -%>
}
<% if (property.original) { -%>
diff --git a/platform/darwin/src/MGLSymbolStyleLayer.mm b/platform/darwin/src/MGLSymbolStyleLayer.mm
index 24d6643e6c..0d9fac4808 100644
--- a/platform/darwin/src/MGLSymbolStyleLayer.mm
+++ b/platform/darwin/src/MGLSymbolStyleLayer.mm
@@ -233,7 +233,8 @@ namespace mbgl {
if (propertyValue.isUndefined()) {
propertyValue = self.rawLayer->getDefaultIconImage();
}
- return MGLStyleValueTransformer<std::string, NSString *>().toExpression(propertyValue);
+ NSExpression *expression = MGLStyleValueTransformer<std::string, NSString *>().toExpression(propertyValue);
+ return expression.mgl_expressionByReplacingTokensWithKeyPaths;
}
- (void)setIconImage:(NSExpression *)iconImage {
@@ -578,7 +579,8 @@ namespace mbgl {
if (propertyValue.isUndefined()) {
propertyValue = self.rawLayer->getDefaultTextField();
}
- return MGLStyleValueTransformer<std::string, NSString *>().toExpression(propertyValue);
+ NSExpression *expression = MGLStyleValueTransformer<std::string, NSString *>().toExpression(propertyValue);
+ return expression.mgl_expressionByReplacingTokensWithKeyPaths;
}
- (void)setTextField:(NSExpression *)textField {
diff --git a/platform/darwin/src/NSExpression+MGLAdditions.h b/platform/darwin/src/NSExpression+MGLAdditions.h
index 49a6087d4c..a0081cb428 100644
--- a/platform/darwin/src/NSExpression+MGLAdditions.h
+++ b/platform/darwin/src/NSExpression+MGLAdditions.h
@@ -47,9 +47,8 @@ NS_ASSUME_NONNULL_BEGIN
/**
Returns a copy of the receiver localized into the given locale.
- This method assumes the receiver is used with a style layer property such as
- `MGLStyleLayer.text` and refers to the feature attributes that are available in
- vector tiles supplied by the
+ This method assumes the receiver refers to the feature attributes that are
+ available in vector tiles supplied by the
<a href="https://www.mapbox.com/vector-tiles/mapbox-streets-v7/#overview">Mapbox Streets source</a>.
On iOS, the user can set the system’s preferred language in Settings, General
Settings, Language & Region. On macOS, the user can set the system’s preferred
@@ -58,10 +57,8 @@ NS_ASSUME_NONNULL_BEGIN
@param locale The locale into which labels should be localized. To use the
system’s preferred language, if supported, specify `nil`. To use the local
language, specify a locale with the identifier `mul`.
- @param replacesTokens `YES` to localize `{token}` syntax in constant value
- subexpressions; `NO` otherwise.
*/
-- (NSExpression *)mgl_expressionLocalizedIntoLocale:(nullable NSLocale *)locale replacingTokens:(BOOL)replacesTokens;
+- (NSExpression *)mgl_expressionLocalizedIntoLocale:(nullable NSLocale *)locale;
@end
diff --git a/platform/darwin/src/NSExpression+MGLAdditions.mm b/platform/darwin/src/NSExpression+MGLAdditions.mm
index e081d973ab..4b08196054 100644
--- a/platform/darwin/src/NSExpression+MGLAdditions.mm
+++ b/platform/darwin/src/NSExpression+MGLAdditions.mm
@@ -1110,7 +1110,7 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
#pragma mark Localization
-// Selectors of functions that can contain localizable arguments.
+// Selectors of functions that can contain tokens in arguments.
static NSArray * const MGLTokenizedFunctions = @[
@"mgl_interpolateWithCurveType:parameters:stops:",
@"mgl_interpolate:withCurveType:parameters:stops:",
@@ -1139,8 +1139,26 @@ NS_ARRAY_OF(NSExpression *) *MGLCollectionByReplacingTokensWithKeyPaths(NS_ARRAY
};
/**
- Returns a copy of the receiver with tokens replaced by key path expressions.
+ Returns a copy of the given stop dictionary with tokens replaced by key path
+ expressions.
+
+ If no replacements take place, this method returns the original stop
+ dictionary.
*/
+NS_DICTIONARY_OF(NSNumber *, NSExpression *) *MGLStopDictionaryByReplacingTokensWithKeyPaths(NS_DICTIONARY_OF(NSNumber *, NSExpression *) *stops) {
+ __block NSMutableDictionary *upgradedStops;
+ [stops enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull zoomLevel, NSExpression * _Nonnull value, BOOL * _Nonnull stop) {
+ NSExpression *upgradedValue = value.mgl_expressionByReplacingTokensWithKeyPaths;
+ if (upgradedValue != value) {
+ if (!upgradedStops) {
+ upgradedStops = [stops mutableCopy];
+ }
+ upgradedStops[zoomLevel] = upgradedValue;
+ }
+ }];
+ return upgradedStops ?: stops;
+};
+
- (NSExpression *)mgl_expressionByReplacingTokensWithKeyPaths {
switch (self.expressionType) {
case NSConstantValueExpressionType: {
@@ -1165,6 +1183,14 @@ NS_ARRAY_OF(NSExpression *) *MGLCollectionByReplacingTokensWithKeyPaths(NS_ARRAY
return [NSExpression expressionForFunction:@"mgl_join:"
arguments:@[[NSExpression expressionForAggregate:components]]];
}
+ NSDictionary *stops = self.constantValue;
+ // TODO: Check whether the dictionary’s key and value types are consistent with stop dictionaries. Or have the caller pass in whether this is a stop dictionary.
+ if ([stops isKindOfClass:[NSDictionary class]]) {
+ NSDictionary *localizedStops = MGLStopDictionaryByReplacingTokensWithKeyPaths(stops);
+ if (localizedStops != stops) {
+ return [NSExpression expressionForConstantValue:localizedStops];
+ }
+ }
return self;
}
@@ -1189,10 +1215,10 @@ NS_ARRAY_OF(NSExpression *) *MGLCollectionByReplacingTokensWithKeyPaths(NS_ARRAY
If no localization takes place, this method returns the original collection.
*/
-NS_ARRAY_OF(NSExpression *) *MGLLocalizedCollection(NS_ARRAY_OF(NSExpression *) *collection, NSLocale * _Nullable locale, BOOL replacesTokens) {
+NS_ARRAY_OF(NSExpression *) *MGLLocalizedCollection(NS_ARRAY_OF(NSExpression *) *collection, NSLocale * _Nullable locale) {
__block NSMutableArray *localizedCollection;
[collection enumerateObjectsUsingBlock:^(NSExpression * _Nonnull item, NSUInteger idx, BOOL * _Nonnull stop) {
- NSExpression *localizedItem = [item mgl_expressionLocalizedIntoLocale:locale replacingTokens:replacesTokens];
+ NSExpression *localizedItem = [item mgl_expressionLocalizedIntoLocale:locale];
if (localizedItem != item) {
if (!localizedCollection) {
localizedCollection = [collection mutableCopy];
@@ -1209,10 +1235,10 @@ NS_ARRAY_OF(NSExpression *) *MGLLocalizedCollection(NS_ARRAY_OF(NSExpression *)
If no localization takes place, this method returns the original stop
dictionary.
*/
-NS_DICTIONARY_OF(NSNumber *, NSExpression *) *MGLLocalizedStopDictionary(NS_DICTIONARY_OF(NSNumber *, NSExpression *) *stops, NSLocale * _Nullable locale, BOOL replacesTokens) {
+NS_DICTIONARY_OF(NSNumber *, NSExpression *) *MGLLocalizedStopDictionary(NS_DICTIONARY_OF(NSNumber *, NSExpression *) *stops, NSLocale * _Nullable locale) {
__block NSMutableDictionary *localizedStops;
[stops enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull zoomLevel, NSExpression * _Nonnull value, BOOL * _Nonnull stop) {
- NSExpression *localizedValue = [value mgl_expressionLocalizedIntoLocale:locale replacingTokens:replacesTokens];
+ NSExpression *localizedValue = [value mgl_expressionLocalizedIntoLocale:locale];
if (localizedValue != value) {
if (!localizedStops) {
localizedStops = [stops mutableCopy];
@@ -1223,24 +1249,13 @@ NS_DICTIONARY_OF(NSNumber *, NSExpression *) *MGLLocalizedStopDictionary(NS_DICT
return localizedStops ?: stops;
};
-- (NSExpression *)mgl_expressionLocalizedIntoLocale:(nullable NSLocale *)locale replacingTokens:(BOOL)replacesTokens {
- NSString *localizedKeyPath = @"name";
- if (locale && ![locale.localeIdentifier isEqualToString:@"mul"]) {
- localizedKeyPath = [NSString stringWithFormat:@"name_%@", locale.localeIdentifier];
- }
+- (NSExpression *)mgl_expressionLocalizedIntoLocale:(nullable NSLocale *)locale {
switch (self.expressionType) {
case NSConstantValueExpressionType: {
- if (replacesTokens) {
- NSString *constantValue = self.constantValue;
- if ([constantValue isKindOfClass:[NSString class]]
- && ([constantValue containsString:@"{name}"] || [constantValue containsString:@"{name_"])) {
- return [NSExpression expressionForKeyPath:localizedKeyPath];
- }
- }
NSDictionary *stops = self.constantValue;
// TODO: Check whether the dictionary’s key and value types are consistent with stop dictionaries. Or have the caller pass in whether this is a stop dictionary.
if ([stops isKindOfClass:[NSDictionary class]]) {
- NSDictionary *localizedStops = MGLLocalizedStopDictionary(stops, locale, replacesTokens);
+ NSDictionary *localizedStops = MGLLocalizedStopDictionary(stops, locale);
if (localizedStops != stops) {
return [NSExpression expressionForConstantValue:localizedStops];
}
@@ -1250,6 +1265,10 @@ NS_DICTIONARY_OF(NSNumber *, NSExpression *) *MGLLocalizedStopDictionary(NS_DICT
case NSKeyPathExpressionType: {
if ([self.keyPath isEqualToString:@"name"] || [self.keyPath hasPrefix:@"name_"]) {
+ NSString *localizedKeyPath = @"name";
+ if (locale && ![locale.localeIdentifier isEqualToString:@"mul"]) {
+ localizedKeyPath = [NSString stringWithFormat:@"name_%@", locale.localeIdentifier];
+ }
return [NSExpression expressionForKeyPath:localizedKeyPath];
}
return self;
@@ -1257,19 +1276,19 @@ NS_DICTIONARY_OF(NSNumber *, NSExpression *) *MGLLocalizedStopDictionary(NS_DICT
case NSFunctionExpressionType: {
NSExpression *operand = self.operand;
- NSExpression *localizedOperand = [operand mgl_expressionLocalizedIntoLocale:locale replacingTokens:NO];
-
- // Only localize arguments to functions that take stop dictionaries.
- replacesTokens = replacesTokens && [MGLTokenizedFunctions containsObject:self.function];
+ NSExpression *localizedOperand = [operand mgl_expressionLocalizedIntoLocale:locale];
NSArray *arguments = self.arguments;
- NSArray *localizedArguments = MGLLocalizedCollection(arguments, locale, replacesTokens);
+ NSArray *localizedArguments = MGLLocalizedCollection(arguments, locale);
if (localizedArguments != arguments) {
- localizedArguments = MGLCollectionByReplacingTokensWithKeyPaths(localizedArguments);
- return [NSExpression expressionForFunction:localizedOperand selectorName:self.function arguments:localizedArguments];
+ return [NSExpression expressionForFunction:localizedOperand
+ selectorName:self.function
+ arguments:localizedArguments];
}
if (localizedOperand != operand) {
- return [NSExpression expressionForFunction:localizedOperand selectorName:self.function arguments:self.arguments];
+ return [NSExpression expressionForFunction:localizedOperand
+ selectorName:self.function
+ arguments:self.arguments];
}
return self;
}
@@ -1277,11 +1296,13 @@ NS_DICTIONARY_OF(NSNumber *, NSExpression *) *MGLLocalizedStopDictionary(NS_DICT
case NSConditionalExpressionType: {
if (@available(iOS 9.0, *)) {
NSExpression *trueExpression = self.trueExpression;
- NSExpression *localizedTrueExpression = [trueExpression mgl_expressionLocalizedIntoLocale:locale replacingTokens:NO];
+ NSExpression *localizedTrueExpression = [trueExpression mgl_expressionLocalizedIntoLocale:locale];
NSExpression *falseExpression = self.falseExpression;
- NSExpression *localizedFalseExpression = [falseExpression mgl_expressionLocalizedIntoLocale:locale replacingTokens:NO];
+ NSExpression *localizedFalseExpression = [falseExpression mgl_expressionLocalizedIntoLocale:locale];
if (localizedTrueExpression != trueExpression || localizedFalseExpression != falseExpression) {
- return [NSExpression expressionForConditional:self.predicate trueExpression:localizedTrueExpression falseExpression:localizedFalseExpression];
+ return [NSExpression expressionForConditional:self.predicate
+ trueExpression:localizedTrueExpression
+ falseExpression:localizedFalseExpression];
}
}
return self;
@@ -1290,7 +1311,7 @@ NS_DICTIONARY_OF(NSNumber *, NSExpression *) *MGLLocalizedStopDictionary(NS_DICT
case NSAggregateExpressionType: {
NSArray *collection = self.collection;
if ([collection isKindOfClass:[NSArray class]]) {
- NSArray *localizedCollection = MGLLocalizedCollection(collection, locale, NO);
+ NSArray *localizedCollection = MGLLocalizedCollection(collection, locale);
if (localizedCollection != collection) {
return [NSExpression expressionForAggregate:localizedCollection];
}
diff --git a/platform/darwin/src/NSExpression+MGLPrivateAdditions.h b/platform/darwin/src/NSExpression+MGLPrivateAdditions.h
index d255cfdb0f..708b779d8b 100644
--- a/platform/darwin/src/NSExpression+MGLPrivateAdditions.h
+++ b/platform/darwin/src/NSExpression+MGLPrivateAdditions.h
@@ -72,8 +72,14 @@ NS_ASSUME_NONNULL_BEGIN
@interface NSExpression (MGLExpressionAdditions)
+/**
+ Returns a copy of the receiver with tokens replaced by key path expressions.
+ */
+- (NSExpression *)mgl_expressionByReplacingTokensWithKeyPaths;
+
- (NSExpression *)mgl_expressionWithContext:(NSDictionary<NSString *, NSExpression *> *)context;
+
- (id)mgl_has:(id)element;
@end
diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md
index c31b021699..f9644e8817 100644
--- a/platform/ios/CHANGELOG.md
+++ b/platform/ios/CHANGELOG.md
@@ -19,7 +19,7 @@ The 4.0._x_ series of releases will be the last to support iOS 8. The minimum iO
* Renamed `MGLRasterSource` to `MGLRasterTileSource` and `MGLVectorSource` to `MGLVectorTileSource`. ([#11568](https://github.com/mapbox/mapbox-gl-native/pull/11568))
* Added an `MGLComputedShapeSource` class that allows applications to supply vector data to a style layer on a per-tile basis. ([#9983](https://github.com/mapbox/mapbox-gl-native/pull/9983))
* A style can now display smooth hillshading and customize its appearance at runtime using the `MGLHillshadeStyleLayer` class. Hillshading is based on a rasterized digital elevation model supplied by the `MGLRasterDEMSource` class. ([#10642](https://github.com/mapbox/mapbox-gl-native/pull/10642))
-* Replaced the `MGLStyle.localizesLabels` property with an `-[MGLStyle localizeLabelsIntoLocale:]` method that allows you to specify the language to localize into. Also added an `-[NSExpression(MGLAdditions) mgl_expressionLocalizedIntoLocale:replacingTokens:]` method for localizing an individual value used with `MGLSymbolStyleLayer.text`. ([#11651](https://github.com/mapbox/mapbox-gl-native/pull/11651))
+* Replaced the `MGLStyle.localizesLabels` property with an `-[MGLStyle localizeLabelsIntoLocale:]` method that allows you to specify the language to localize into. Also added an `-[NSExpression(MGLAdditions) mgl_expressionLocalizedIntoLocale:]` method for localizing an individual value used with `MGLSymbolStyleLayer.text`. ([#11651](https://github.com/mapbox/mapbox-gl-native/pull/11651))
* The `MGLSymbolStyleLayer.textFontNames` property can now depend on a feature’s attributes. ([#10850](https://github.com/mapbox/mapbox-gl-native/pull/10850))
* Added `MGLShapeSourceOptionWrapsCoordinates`, to specify whether the shape of an `MGLComputedShapeSource` should be wrapped to accommodate coordinates with longitudes beyond −180 and 180; and `MGLShapeSourceOptionClipsCoordinates`, to specify whether the shape of an `MGLComputedShapeSource` should be clipped at the edge of each tile. ([#11041](https://github.com/mapbox/mapbox-gl-native/pull/11041))
* The layer filtering predicate's format strings now can contain arithmetic and calls to built-in `NSExpression` functions. ([#11587](https://github.com/mapbox/mapbox-gl-native/pull/11587))
diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md
index 3c0a4996da..0cfba09455 100644
--- a/platform/macos/CHANGELOG.md
+++ b/platform/macos/CHANGELOG.md
@@ -9,7 +9,7 @@
* Renamed `MGLRasterSource` to `MGLRasterTileSource` and `MGLVectorSource` to `MGLVectorTileSource`. ([#11568](https://github.com/mapbox/mapbox-gl-native/pull/11568))
* Added an `MGLComputedShapeSource` class that allows applications to supply vector data to a style layer on a per-tile basis. ([#9983](https://github.com/mapbox/mapbox-gl-native/pull/9983))
* A style can now display smooth hillshading and customize its appearance at runtime using the `MGLHillshadeStyleLayer` class. Hillshading is based on a rasterized digital elevation model supplied by the `MGLRasterDEMSource` class. ([#10642](https://github.com/mapbox/mapbox-gl-native/pull/10642))
-* Replaced the `MGLStyle.localizesLabels` property with an `-[MGLStyle localizeLabelsIntoLocale:]` method that allows you to specify the language to localize into. Note that this method does not automatically update the style when the system’s preferred language changes. Also added an `-[NSExpression(MGLAdditions) mgl_expressionLocalizedIntoLocale:replacingTokens:]` method for localizing an individual value used with `MGLSymbolStyleLayer.text`. ([#11651](https://github.com/mapbox/mapbox-gl-native/pull/11651))
+* Replaced the `MGLStyle.localizesLabels` property with an `-[MGLStyle localizeLabelsIntoLocale:]` method that allows you to specify the language to localize into. Note that this method does not automatically update the style when the system’s preferred language changes. Also added an `-[NSExpression(MGLAdditions) mgl_expressionLocalizedIntoLocale:]` method for localizing an individual value used with `MGLSymbolStyleLayer.text`. ([#11651](https://github.com/mapbox/mapbox-gl-native/pull/11651))
* Fixed incorrect color calibration on macOS 10.13 High Sierra when using color-related methods of `MGLStyleLayer` subclasses, as well as when displaying an `MGLAttributionInfo`. It is no longer necessary to explicitly convert an `NSColor` to the sRGB color space before using these classes on High Sierra. ([#11391](https://github.com/mapbox/mapbox-gl-native/pull/11391))
* The `MGLSymbolStyleLayer.textFontNames` property can now depend on a feature’s attributes. ([#10850](https://github.com/mapbox/mapbox-gl-native/pull/10850))
* Properties such as `MGLSymbolStyleLayer.iconAllowsOverlap` and `MGLSymbolStyleLayer.iconIgnoresPlacement` now account for symbols in other sources. ([#10436](https://github.com/mapbox/mapbox-gl-native/pull/10436))