summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorryanhamley <ryan.hamley@mapbox.com>2018-08-30 17:18:29 -0700
committerryanhamley <ryan.hamley@mapbox.com>2018-09-07 13:05:19 -0700
commit31cca05fc6a9d08d3b0028149f7ef2f2348b18e9 (patch)
tree0fc6980686269d0deade28823be33bf9446610a7
parent79bf0e8af6bf9ec829a352d56b8e70ccc8f4fa41 (diff)
downloadqtlocation-mapboxgl-31cca05fc6a9d08d3b0028149f7ef2f2348b18e9.tar.gz
Port symbol-z-order symbol layout style-spec property to Nativeupstream/sort-by-y
-rw-r--r--include/mbgl/style/layers/symbol_layer.hpp4
-rw-r--r--include/mbgl/style/types.hpp5
m---------mapbox-gl-js0
-rw-r--r--platform/android/CHANGELOG.md1
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java21
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java20
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/SymbolLayer.java14
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java14
-rw-r--r--platform/android/src/style/layers/symbol_layer.cpp6
-rw-r--r--platform/android/src/style/layers/symbol_layer.hpp2
-rw-r--r--platform/darwin/scripts/style-spec-overrides-v8.json10
-rw-r--r--platform/darwin/src/MGLSymbolStyleLayer.h59
-rw-r--r--platform/darwin/src/MGLSymbolStyleLayer.mm32
-rw-r--r--platform/darwin/test/MGLSymbolStyleLayerTests.mm47
-rw-r--r--platform/ios/CHANGELOG.md3
-rw-r--r--platform/macos/CHANGELOG.md3
-rw-r--r--platform/node/CHANGELOG.md1
-rw-r--r--src/mbgl/layout/symbol_layout.cpp7
-rw-r--r--src/mbgl/style/conversion/constant.cpp1
-rw-r--r--src/mbgl/style/conversion/function.cpp2
-rw-r--r--src/mbgl/style/conversion/property_value.cpp1
-rw-r--r--src/mbgl/style/expression/value.cpp3
-rw-r--r--src/mbgl/style/layers/symbol_layer.cpp35
-rw-r--r--src/mbgl/style/layers/symbol_layer_properties.hpp6
-rw-r--r--src/mbgl/style/types.cpp5
25 files changed, 299 insertions, 3 deletions
diff --git a/include/mbgl/style/layers/symbol_layer.hpp b/include/mbgl/style/layers/symbol_layer.hpp
index fa0b0c4e4e..aabda0d794 100644
--- a/include/mbgl/style/layers/symbol_layer.hpp
+++ b/include/mbgl/style/layers/symbol_layer.hpp
@@ -53,6 +53,10 @@ public:
PropertyValue<bool> getSymbolAvoidEdges() const;
void setSymbolAvoidEdges(PropertyValue<bool>);
+ static PropertyValue<SymbolZOrderType> getDefaultSymbolZOrder();
+ PropertyValue<SymbolZOrderType> getSymbolZOrder() const;
+ void setSymbolZOrder(PropertyValue<SymbolZOrderType>);
+
static PropertyValue<bool> getDefaultIconAllowOverlap();
PropertyValue<bool> getIconAllowOverlap() const;
void setIconAllowOverlap(PropertyValue<bool>);
diff --git a/include/mbgl/style/types.hpp b/include/mbgl/style/types.hpp
index 805cff118c..ed875733c7 100644
--- a/include/mbgl/style/types.hpp
+++ b/include/mbgl/style/types.hpp
@@ -68,6 +68,11 @@ enum class SymbolPlacementType : uint8_t {
Line,
LineCenter
};
+
+enum class SymbolZOrderType : uint8_t {
+ ViewportY,
+ Source
+};
enum class AlignmentType : uint8_t {
Map,
diff --git a/mapbox-gl-js b/mapbox-gl-js
-Subproject 53e622b475b7c9cb26b98d18e3fbd61d27b183a
+Subproject e8fd41abae382f39f17a561a1461db90bd2204f
diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md
index 13162c0b48..8031232d43 100644
--- a/platform/android/CHANGELOG.md
+++ b/platform/android/CHANGELOG.md
@@ -3,6 +3,7 @@
Mapbox welcomes participation and contributions from everyone. If you'd like to do so please see the [`Contributing Guide`](https://github.com/mapbox/mapbox-gl-native/blob/master/CONTRIBUTING.md) first to get started.
## master
+- Add `symbol-z-order` symbol layout property to style spec [#12783](https://github.com/mapbox/mapbox-gl-native/pull/12783)
## 6.5.0-beta.1 - September 5, 2018
- Retain shared thread pool reference [#12811](https://github.com/mapbox/mapbox-gl-native/pull/12811)
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java
index ba3619567d..1c87b9004b 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java
@@ -108,6 +108,27 @@ public final class Property {
@Retention(RetentionPolicy.SOURCE)
public @interface SYMBOL_PLACEMENT {}
+ // SYMBOL_Z_ORDER: Controls the order in which overlapping symbols in the same layer are rendered
+
+ /**
+ * Symbols will be sorted by their y-position relative to the viewport.
+ */
+ public static final String SYMBOL_Z_ORDER_VIEWPORT_Y = "viewport-y";
+ /**
+ * Symbols will be rendered in the same order as the source data with no sorting applied.
+ */
+ public static final String SYMBOL_Z_ORDER_SOURCE = "source";
+
+ /**
+ * Controls the order in which overlapping symbols in the same layer are rendered
+ */
+ @StringDef({
+ SYMBOL_Z_ORDER_VIEWPORT_Y,
+ SYMBOL_Z_ORDER_SOURCE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SYMBOL_Z_ORDER {}
+
// ICON_ROTATION_ALIGNMENT: In combination with `symbol-placement`, determines the rotation behavior of icons.
/**
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java
index c619d0141a..670548f12e 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java
@@ -1765,6 +1765,26 @@ public class PropertyFactory {
}
/**
+ * Controls the order in which overlapping symbols in the same layer are rendered
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static PropertyValue<String> symbolZOrder(@Property.SYMBOL_Z_ORDER String value) {
+ return new LayoutPropertyValue<>("symbol-z-order", value);
+ }
+
+ /**
+ * Controls the order in which overlapping symbols in the same layer are rendered
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static PropertyValue<Expression> symbolZOrder(Expression value) {
+ return new LayoutPropertyValue<>("symbol-z-order", value);
+ }
+
+ /**
* If true, the icon will be visible even if it collides with other previously drawn symbols.
*
* @param value a Boolean value
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/SymbolLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/SymbolLayer.java
index 3c4924bb6f..1d45f34bd3 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/SymbolLayer.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/SymbolLayer.java
@@ -171,6 +171,17 @@ public class SymbolLayer extends Layer {
}
/**
+ * Get the SymbolZOrder property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getSymbolZOrder() {
+ checkThread();
+ return (PropertyValue<String>) new PropertyValue("symbol-z-order", nativeGetSymbolZOrder());
+ }
+
+ /**
* Get the IconAllowOverlap property
*
* @return property wrapper value around Boolean
@@ -1005,6 +1016,9 @@ public class SymbolLayer extends Layer {
private native Object nativeGetSymbolAvoidEdges();
@Keep
+ private native Object nativeGetSymbolZOrder();
+
+ @Keep
private native Object nativeGetIconAllowOverlap();
@Keep
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java
index 8cf452a6cf..98c9c27fc2 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java
@@ -160,6 +160,20 @@ public class SymbolLayerTest extends BaseActivityTest {
}
@Test
+ public void testSymbolZOrderAsConstant() {
+ validateTestSetup();
+ setupLayer();
+ Timber.i("symbol-z-order");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(symbolZOrder(SYMBOL_Z_ORDER_VIEWPORT_Y));
+ assertEquals((String) layer.getSymbolZOrder().getValue(), (String) SYMBOL_Z_ORDER_VIEWPORT_Y);
+ });
+ }
+
+ @Test
public void testIconAllowOverlapAsConstant() {
validateTestSetup();
setupLayer();
diff --git a/platform/android/src/style/layers/symbol_layer.cpp b/platform/android/src/style/layers/symbol_layer.cpp
index a0f37c91d2..f1c77c61a9 100644
--- a/platform/android/src/style/layers/symbol_layer.cpp
+++ b/platform/android/src/style/layers/symbol_layer.cpp
@@ -50,6 +50,11 @@ namespace android {
return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getSymbolAvoidEdges()));
}
+ jni::Local<jni::Object<>> SymbolLayer::getSymbolZOrder(jni::JNIEnv& env) {
+ using namespace mbgl::android::conversion;
+ return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getSymbolZOrder()));
+ }
+
jni::Local<jni::Object<>> SymbolLayer::getIconAllowOverlap(jni::JNIEnv& env) {
using namespace mbgl::android::conversion;
return std::move(*convert<jni::Local<jni::Object<>>>(env, layer.as<mbgl::style::SymbolLayer>()->SymbolLayer::getIconAllowOverlap()));
@@ -463,6 +468,7 @@ namespace android {
METHOD(&SymbolLayer::getSymbolPlacement, "nativeGetSymbolPlacement"),
METHOD(&SymbolLayer::getSymbolSpacing, "nativeGetSymbolSpacing"),
METHOD(&SymbolLayer::getSymbolAvoidEdges, "nativeGetSymbolAvoidEdges"),
+ METHOD(&SymbolLayer::getSymbolZOrder, "nativeGetSymbolZOrder"),
METHOD(&SymbolLayer::getIconAllowOverlap, "nativeGetIconAllowOverlap"),
METHOD(&SymbolLayer::getIconIgnorePlacement, "nativeGetIconIgnorePlacement"),
METHOD(&SymbolLayer::getIconOptional, "nativeGetIconOptional"),
diff --git a/platform/android/src/style/layers/symbol_layer.hpp b/platform/android/src/style/layers/symbol_layer.hpp
index 206a6546c3..9887fd8fb7 100644
--- a/platform/android/src/style/layers/symbol_layer.hpp
+++ b/platform/android/src/style/layers/symbol_layer.hpp
@@ -33,6 +33,8 @@ public:
jni::Local<jni::Object<jni::ObjectTag>> getSymbolAvoidEdges(jni::JNIEnv&);
+ jni::Local<jni::Object<jni::ObjectTag>> getSymbolZOrder(jni::JNIEnv&);
+
jni::Local<jni::Object<jni::ObjectTag>> getIconAllowOverlap(jni::JNIEnv&);
jni::Local<jni::Object<jni::ObjectTag>> getIconIgnorePlacement(jni::JNIEnv&);
diff --git a/platform/darwin/scripts/style-spec-overrides-v8.json b/platform/darwin/scripts/style-spec-overrides-v8.json
index d47b13cdb2..0c787cd96e 100644
--- a/platform/darwin/scripts/style-spec-overrides-v8.json
+++ b/platform/darwin/scripts/style-spec-overrides-v8.json
@@ -39,6 +39,16 @@
}
},
"layout_symbol": {
+ "symbol-z-order": {
+ "values": {
+ "viewport-y": {
+ "doc": "Specify this z order if symbols’ appearance relies on lower features overlapping higher features. For example, symbols with a pin-like appearance would require this z order."
+ },
+ "source": {
+ "doc": "Specify this z order if the order in which features appear in the source is significant."
+ }
+ }
+ },
"icon-text-fit-padding": {
"doc": "Size of the additional area added to dimensions determined by `icon-text-fit`."
},
diff --git a/platform/darwin/src/MGLSymbolStyleLayer.h b/platform/darwin/src/MGLSymbolStyleLayer.h
index afaea9a74f..363f9efee7 100644
--- a/platform/darwin/src/MGLSymbolStyleLayer.h
+++ b/platform/darwin/src/MGLSymbolStyleLayer.h
@@ -151,6 +151,26 @@ typedef NS_ENUM(NSUInteger, MGLSymbolPlacement) {
};
/**
+ Controls the order in which overlapping symbols in the same layer are rendered
+
+ Values of this type are used in the `MGLSymbolStyleLayer.symbolZOrder`
+ property.
+ */
+typedef NS_ENUM(NSUInteger, MGLSymbolZOrder) {
+ /**
+ Specify this z order if symbols’ appearance relies on lower features
+ overlapping higher features. For example, symbols with a pin-like
+ appearance would require this z order.
+ */
+ MGLSymbolZOrderViewportY,
+ /**
+ Specify this z order if the order in which features appear in the source is
+ significant.
+ */
+ MGLSymbolZOrderSource,
+};
+
+/**
Part of the text placed closest to the anchor.
Values of this type are used in the `MGLSymbolStyleLayer.textAnchor`
@@ -1005,6 +1025,32 @@ MGL_EXPORT
@property (nonatomic, null_resettable) NSExpression *symbolSpacing;
/**
+ Controls the order in which overlapping symbols in the same layer are rendered
+
+ The default value of this property is an expression that evaluates to
+ `viewport-y`. Set this property to `nil` to reset it to the default value.
+
+ You can set this property to an expression containing any of the following:
+
+ * Constant `MGLSymbolZOrder` values
+ * Any of the following constant string values:
+ * `viewport-y`: Specify this z order if symbols’ appearance relies on lower
+ features overlapping higher features. For example, symbols with a pin-like
+ appearance would require this z order.
+ * `source`: Specify this z order if the order in which features appear in the
+ source is significant.
+ * 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 *symbolZOrder;
+
+/**
Value to use for a text label.
Within a constant string value, a feature attribute name enclosed in curly
@@ -2141,6 +2187,19 @@ MGL_EXPORT
@property (readonly) MGLSymbolPlacement MGLSymbolPlacementValue;
/**
+ Creates a new value object containing the given `MGLSymbolZOrder` enumeration.
+
+ @param symbolZOrder The value for the new object.
+ @return A new value object that contains the enumeration value.
+ */
++ (instancetype)valueWithMGLSymbolZOrder:(MGLSymbolZOrder)symbolZOrder;
+
+/**
+ The `MGLSymbolZOrder` enumeration representation of the value.
+ */
+@property (readonly) MGLSymbolZOrder MGLSymbolZOrderValue;
+
+/**
Creates a new value object containing the given `MGLTextAnchor` enumeration.
@param textAnchor The value for the new object.
diff --git a/platform/darwin/src/MGLSymbolStyleLayer.mm b/platform/darwin/src/MGLSymbolStyleLayer.mm
index ad023a1a03..4c0fcfe539 100644
--- a/platform/darwin/src/MGLSymbolStyleLayer.mm
+++ b/platform/darwin/src/MGLSymbolStyleLayer.mm
@@ -50,6 +50,11 @@ namespace mbgl {
{ MGLSymbolPlacementLineCenter, "line-center" },
});
+ MBGL_DEFINE_ENUM(MGLSymbolZOrder, {
+ { MGLSymbolZOrderViewportY, "viewport-y" },
+ { MGLSymbolZOrderSource, "source" },
+ });
+
MBGL_DEFINE_ENUM(MGLTextAnchor, {
{ MGLTextAnchorCenter, "center" },
{ MGLTextAnchorLeft, "left" },
@@ -573,6 +578,23 @@ namespace mbgl {
return MGLStyleValueTransformer<float, NSNumber *>().toExpression(propertyValue);
}
+- (void)setSymbolZOrder:(NSExpression *)symbolZOrder {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<mbgl::style::SymbolZOrderType, NSValue *, mbgl::style::SymbolZOrderType, MGLSymbolZOrder>().toPropertyValue<mbgl::style::PropertyValue<mbgl::style::SymbolZOrderType>>(symbolZOrder, false);
+ self.rawLayer->setSymbolZOrder(mbglValue);
+}
+
+- (NSExpression *)symbolZOrder {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = self.rawLayer->getSymbolZOrder();
+ if (propertyValue.isUndefined()) {
+ propertyValue = self.rawLayer->getDefaultSymbolZOrder();
+ }
+ return MGLStyleValueTransformer<mbgl::style::SymbolZOrderType, NSValue *, mbgl::style::SymbolZOrderType, MGLSymbolZOrder>().toExpression(propertyValue);
+}
+
- (void)setText:(NSExpression *)text {
MGLAssertStyleLayerIsValid();
@@ -1440,6 +1462,16 @@ namespace mbgl {
return symbolPlacement;
}
++ (NSValue *)valueWithMGLSymbolZOrder:(MGLSymbolZOrder)symbolZOrder {
+ return [NSValue value:&symbolZOrder withObjCType:@encode(MGLSymbolZOrder)];
+}
+
+- (MGLSymbolZOrder)MGLSymbolZOrderValue {
+ MGLSymbolZOrder symbolZOrder;
+ [self getValue:&symbolZOrder];
+ return symbolZOrder;
+}
+
+ (NSValue *)valueWithMGLTextAnchor:(MGLTextAnchor)textAnchor {
return [NSValue value:&textAnchor withObjCType:@encode(MGLTextAnchor)];
}
diff --git a/platform/darwin/test/MGLSymbolStyleLayerTests.mm b/platform/darwin/test/MGLSymbolStyleLayerTests.mm
index 5c108a1ac3..865de68933 100644
--- a/platform/darwin/test/MGLSymbolStyleLayerTests.mm
+++ b/platform/darwin/test/MGLSymbolStyleLayerTests.mm
@@ -1044,6 +1044,50 @@
XCTAssertThrowsSpecificNamed(layer.symbolSpacing = 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.");
}
+ // symbol-z-order
+ {
+ XCTAssertTrue(rawLayer->getSymbolZOrder().isUndefined(),
+ @"symbol-z-order should be unset initially.");
+ NSExpression *defaultExpression = layer.symbolZOrder;
+
+ NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'source'"];
+ layer.symbolZOrder = constantExpression;
+ mbgl::style::PropertyValue<mbgl::style::SymbolZOrderType> propertyValue = { mbgl::style::SymbolZOrderType::Source };
+ XCTAssertEqual(rawLayer->getSymbolZOrder(), propertyValue,
+ @"Setting symbolZOrder to a constant value expression should update symbol-z-order.");
+ XCTAssertEqualObjects(layer.symbolZOrder, constantExpression,
+ @"symbolZOrder should round-trip constant value expressions.");
+
+ constantExpression = [NSExpression expressionWithFormat:@"'source'"];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
+ layer.symbolZOrder = functionExpression;
+
+ {
+ using namespace mbgl::style::expression::dsl;
+ propertyValue = mbgl::style::PropertyExpression<mbgl::style::SymbolZOrderType>(
+ step(zoom(), literal("source"), 18.0, literal("source"))
+ );
+ }
+
+ XCTAssertEqual(rawLayer->getSymbolZOrder(), propertyValue,
+ @"Setting symbolZOrder to a camera expression should update symbol-z-order.");
+ XCTAssertEqualObjects(layer.symbolZOrder, functionExpression,
+ @"symbolZOrder should round-trip camera expressions.");
+
+
+ layer.symbolZOrder = nil;
+ XCTAssertTrue(rawLayer->getSymbolZOrder().isUndefined(),
+ @"Unsetting symbolZOrder should return symbol-z-order to the default value.");
+ XCTAssertEqualObjects(layer.symbolZOrder, defaultExpression,
+ @"symbolZOrder should return the default value after being unset.");
+
+ functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
+ XCTAssertThrowsSpecificNamed(layer.symbolZOrder = 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.symbolZOrder = 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-field
{
XCTAssertTrue(rawLayer->getTextField().isUndefined(),
@@ -2829,6 +2873,7 @@
[self testPropertyName:@"symbol-avoids-edges" isBoolean:YES];
[self testPropertyName:@"symbol-placement" isBoolean:NO];
[self testPropertyName:@"symbol-spacing" isBoolean:NO];
+ [self testPropertyName:@"symbol-z-order" isBoolean:NO];
[self testPropertyName:@"text" isBoolean:NO];
[self testPropertyName:@"text-allows-overlap" isBoolean:YES];
[self testPropertyName:@"text-anchor" isBoolean:NO];
@@ -2884,6 +2929,8 @@
XCTAssertEqual([NSValue valueWithMGLSymbolPlacement:MGLSymbolPlacementPoint].MGLSymbolPlacementValue, MGLSymbolPlacementPoint);
XCTAssertEqual([NSValue valueWithMGLSymbolPlacement:MGLSymbolPlacementLine].MGLSymbolPlacementValue, MGLSymbolPlacementLine);
XCTAssertEqual([NSValue valueWithMGLSymbolPlacement:MGLSymbolPlacementLineCenter].MGLSymbolPlacementValue, MGLSymbolPlacementLineCenter);
+ XCTAssertEqual([NSValue valueWithMGLSymbolZOrder:MGLSymbolZOrderViewportY].MGLSymbolZOrderValue, MGLSymbolZOrderViewportY);
+ XCTAssertEqual([NSValue valueWithMGLSymbolZOrder:MGLSymbolZOrderSource].MGLSymbolZOrderValue, MGLSymbolZOrderSource);
XCTAssertEqual([NSValue valueWithMGLTextAnchor:MGLTextAnchorCenter].MGLTextAnchorValue, MGLTextAnchorCenter);
XCTAssertEqual([NSValue valueWithMGLTextAnchor:MGLTextAnchorLeft].MGLTextAnchorValue, MGLTextAnchorLeft);
XCTAssertEqual([NSValue valueWithMGLTextAnchor:MGLTextAnchorRight].MGLTextAnchorValue, MGLTextAnchorRight);
diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md
index dc78220b48..409ff19cb5 100644
--- a/platform/ios/CHANGELOG.md
+++ b/platform/ios/CHANGELOG.md
@@ -2,6 +2,9 @@
Mapbox welcomes participation and contributions from everyone. Please read [CONTRIBUTING.md](../../CONTRIBUTING.md) to get started.
+## master
+* Added an `MGLSymbolStyleLayer.symbolZOrder` property for forcing point features in a symbol layer to be layered in the same order that they are specified in the layer’s associated source. [#12783](https://github.com/mapbox/mapbox-gl-native/pull/12783)
+
## 4.4.0
### Styles and rendering
diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md
index 2fb601bf6f..fe042bd56b 100644
--- a/platform/macos/CHANGELOG.md
+++ b/platform/macos/CHANGELOG.md
@@ -2,6 +2,9 @@
## master
+### Styles and rendering
+* Add `symbol-z-order` symbol layout property to style spec [#12783](https://github.com/mapbox/mapbox-gl-native/pull/12783)
+
### Other changes
* Fixed bug where completion block passed to `-[MGLMapSnapshotter startWithQueue:completionHandler:]` was not being called in all code paths. ([#12355](https://github.com/mapbox/mapbox-gl-native/pull/12355))
diff --git a/platform/node/CHANGELOG.md b/platform/node/CHANGELOG.md
index db33ab52db..5b44d5be1f 100644
--- a/platform/node/CHANGELOG.md
+++ b/platform/node/CHANGELOG.md
@@ -1,4 +1,5 @@
# master
+- Add `symbol-z-order` symbol layout property to style spec [#12783](https://github.com/mapbox/mapbox-gl-native/pull/12783)
- Don't default-show text/icons that depend on the placement of a paired icon/text [#12483](https://github.com/mapbox/mapbox-gl-native/issues/12483)
- Fix symbol querying for annotations near tile boundaries at high zoom. ([#12472](https://github.com/mapbox/mapbox-gl-native/issues/12472))
- The `Map` constructor now accepts a `mode` option which can be either `"static"` (default) or `"tile"`. It must be set to `"tile"` when rendering individual tiles in order for the symbols to match across tiles.
diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp
index 344a76bbe9..74abd74f01 100644
--- a/src/mbgl/layout/symbol_layout.cpp
+++ b/src/mbgl/layout/symbol_layout.cpp
@@ -401,10 +401,11 @@ std::vector<float> CalculateTileDistances(const GeometryCoordinates& line, const
}
void SymbolLayout::createBucket(const ImagePositions&, std::unique_ptr<FeatureIndex>&, std::unordered_map<std::string, std::shared_ptr<Bucket>>& buckets, const bool firstLoad, const bool showCollisionBoxes) {
- const bool mayOverlap = layout.get<TextAllowOverlap>() || layout.get<IconAllowOverlap>() ||
- layout.get<TextIgnorePlacement>() || layout.get<IconIgnorePlacement>();
+ const bool zOrderByViewport = layout.get<SymbolZOrder>() == SymbolZOrderType::ViewportY;
+ const bool sortFeaturesByY = zOrderByViewport && (layout.get<TextAllowOverlap>() || layout.get<IconAllowOverlap>() ||
+ layout.get<TextIgnorePlacement>() || layout.get<IconIgnorePlacement>());
- auto bucket = std::make_shared<SymbolBucket>(layout, layerPaintProperties, textSize, iconSize, zoom, sdfIcons, iconsNeedLinear, mayOverlap, bucketLeaderID, std::move(symbolInstances));
+ auto bucket = std::make_shared<SymbolBucket>(layout, layerPaintProperties, textSize, iconSize, zoom, sdfIcons, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(symbolInstances));
for (SymbolInstance &symbolInstance : bucket->symbolInstances) {
diff --git a/src/mbgl/style/conversion/constant.cpp b/src/mbgl/style/conversion/constant.cpp
index de4ab22269..bdc6371722 100644
--- a/src/mbgl/style/conversion/constant.cpp
+++ b/src/mbgl/style/conversion/constant.cpp
@@ -59,6 +59,7 @@ template optional<LineJoinType> Converter<LineJoinType>::operator()(const Conver
template optional<RasterResamplingType> Converter<RasterResamplingType>::operator()(const Convertible&, Error&) const;
template optional<SymbolAnchorType> Converter<SymbolAnchorType>::operator()(const Convertible&, Error&) const;
template optional<SymbolPlacementType> Converter<SymbolPlacementType>::operator()(const Convertible&, Error&) const;
+template optional<SymbolZOrderType> Converter<SymbolZOrderType>::operator()(const Convertible&, Error&) const;
template optional<TextJustifyType> Converter<TextJustifyType>::operator()(const Convertible&, Error&) const;
template optional<TextTransformType> Converter<TextTransformType>::operator()(const Convertible&, Error&) const;
template optional<TranslateAnchorType> Converter<TranslateAnchorType>::operator()(const Convertible&, Error&) const;
diff --git a/src/mbgl/style/conversion/function.cpp b/src/mbgl/style/conversion/function.cpp
index 6aadaad3b3..2ce2f4eafd 100644
--- a/src/mbgl/style/conversion/function.cpp
+++ b/src/mbgl/style/conversion/function.cpp
@@ -131,6 +131,8 @@ template optional<PropertyExpression<SymbolAnchorType>>
convertFunctionToExpression<SymbolAnchorType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<SymbolPlacementType>>
convertFunctionToExpression<SymbolPlacementType>(const Convertible&, Error&, bool);
+template optional<PropertyExpression<SymbolZOrderType>>
+ convertFunctionToExpression<SymbolZOrderType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<TextJustifyType>>
convertFunctionToExpression<TextJustifyType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<TextTransformType>>
diff --git a/src/mbgl/style/conversion/property_value.cpp b/src/mbgl/style/conversion/property_value.cpp
index 8a93c24767..3b79ecc0db 100644
--- a/src/mbgl/style/conversion/property_value.cpp
+++ b/src/mbgl/style/conversion/property_value.cpp
@@ -74,6 +74,7 @@ template optional<PropertyValue<Position>> Converter<PropertyValue<Position>>::o
template optional<PropertyValue<RasterResamplingType>> Converter<PropertyValue<RasterResamplingType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<SymbolAnchorType>> Converter<PropertyValue<SymbolAnchorType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<SymbolPlacementType>> Converter<PropertyValue<SymbolPlacementType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
+template optional<PropertyValue<SymbolZOrderType>> Converter<PropertyValue<SymbolZOrderType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<TextJustifyType>> Converter<PropertyValue<TextJustifyType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<TextTransformType>> Converter<PropertyValue<TextTransformType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<TranslateAnchorType>> Converter<PropertyValue<TranslateAnchorType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
diff --git a/src/mbgl/style/expression/value.cpp b/src/mbgl/style/expression/value.cpp
index ddf1ff0ca4..f089c918cd 100644
--- a/src/mbgl/style/expression/value.cpp
+++ b/src/mbgl/style/expression/value.cpp
@@ -297,6 +297,9 @@ template struct ValueConverter<LineJoinType>;
template type::Type valueTypeToExpressionType<SymbolPlacementType>();
template struct ValueConverter<SymbolPlacementType>;
+
+template type::Type valueTypeToExpressionType<SymbolZOrderType>();
+template struct ValueConverter<SymbolZOrderType>;
template type::Type valueTypeToExpressionType<SymbolAnchorType>();
template struct ValueConverter<SymbolAnchorType>;
diff --git a/src/mbgl/style/layers/symbol_layer.cpp b/src/mbgl/style/layers/symbol_layer.cpp
index 4ea138a7f5..c116d5b7e9 100644
--- a/src/mbgl/style/layers/symbol_layer.cpp
+++ b/src/mbgl/style/layers/symbol_layer.cpp
@@ -149,6 +149,22 @@ void SymbolLayer::setSymbolAvoidEdges(PropertyValue<bool> value) {
baseImpl = std::move(impl_);
observer->onLayerChanged(*this);
}
+PropertyValue<SymbolZOrderType> SymbolLayer::getDefaultSymbolZOrder() {
+ return SymbolZOrder::defaultValue();
+}
+
+PropertyValue<SymbolZOrderType> SymbolLayer::getSymbolZOrder() const {
+ return impl().layout.get<SymbolZOrder>();
+}
+
+void SymbolLayer::setSymbolZOrder(PropertyValue<SymbolZOrderType> value) {
+ if (value == getSymbolZOrder())
+ return;
+ auto impl_ = mutableImpl();
+ impl_->layout.get<SymbolZOrder>() = value;
+ baseImpl = std::move(impl_);
+ observer->onLayerChanged(*this);
+}
PropertyValue<bool> SymbolLayer::getDefaultIconAllowOverlap() {
return IconAllowOverlap::defaultValue();
}
@@ -1440,6 +1456,7 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
SymbolPlacement,
SymbolSpacing,
SymbolAvoidEdges,
+ SymbolZOrder,
IconAllowOverlap,
IconIgnorePlacement,
IconOptional,
@@ -1496,6 +1513,12 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
}
break;
+ case util::hashFNV1a("symbol-z-order"):
+ if (name == "symbol-z-order") {
+ property = Property::SymbolZOrder;
+ }
+ break;
+
case util::hashFNV1a("icon-allow-overlap"):
if (name == "icon-allow-overlap") {
property = Property::IconAllowOverlap;
@@ -1801,6 +1824,18 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
}
+ if (property == Property::SymbolZOrder) {
+ Error error;
+ optional<PropertyValue<SymbolZOrderType>> typedValue = convert<PropertyValue<SymbolZOrderType>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setSymbolZOrder(*typedValue);
+ return nullopt;
+
+ }
+
if (property == Property::IconRotationAlignment || property == Property::IconPitchAlignment || property == Property::TextPitchAlignment || property == Property::TextRotationAlignment) {
Error error;
optional<PropertyValue<AlignmentType>> typedValue = convert<PropertyValue<AlignmentType>>(value, error, false, false);
diff --git a/src/mbgl/style/layers/symbol_layer_properties.hpp b/src/mbgl/style/layers/symbol_layer_properties.hpp
index e70ac28d59..10d059e787 100644
--- a/src/mbgl/style/layers/symbol_layer_properties.hpp
+++ b/src/mbgl/style/layers/symbol_layer_properties.hpp
@@ -27,6 +27,11 @@ struct SymbolAvoidEdges : LayoutProperty<bool> {
static bool defaultValue() { return false; }
};
+struct SymbolZOrder : LayoutProperty<SymbolZOrderType> {
+ static constexpr const char * key = "symbol-z-order";
+ static SymbolZOrderType defaultValue() { return SymbolZOrderType::ViewportY; }
+};
+
struct IconAllowOverlap : LayoutProperty<bool> {
static constexpr const char * key = "icon-allow-overlap";
static bool defaultValue() { return false; }
@@ -252,6 +257,7 @@ class SymbolLayoutProperties : public Properties<
SymbolPlacement,
SymbolSpacing,
SymbolAvoidEdges,
+ SymbolZOrder,
IconAllowOverlap,
IconIgnorePlacement,
IconOptional,
diff --git a/src/mbgl/style/types.cpp b/src/mbgl/style/types.cpp
index 46de0173de..51174cf152 100644
--- a/src/mbgl/style/types.cpp
+++ b/src/mbgl/style/types.cpp
@@ -76,6 +76,11 @@ MBGL_DEFINE_ENUM(SymbolAnchorType, {
{ SymbolAnchorType::BottomLeft, "bottom-left" },
{ SymbolAnchorType::BottomRight, "bottom-right" }
});
+
+MBGL_DEFINE_ENUM(SymbolZOrderType, {
+ { SymbolZOrderType::ViewportY, "viewport-y" },
+ { SymbolZOrderType::Source, "source" }
+});
MBGL_DEFINE_ENUM(TextJustifyType, {
{ TextJustifyType::Center, "center" },