From 31cca05fc6a9d08d3b0028149f7ef2f2348b18e9 Mon Sep 17 00:00:00 2001 From: ryanhamley Date: Thu, 30 Aug 2018 17:18:29 -0700 Subject: Port symbol-z-order symbol layout style-spec property to Native --- include/mbgl/style/layers/symbol_layer.hpp | 4 ++ include/mbgl/style/types.hpp | 5 ++ mapbox-gl-js | 2 +- platform/android/CHANGELOG.md | 1 + .../mapbox/mapboxsdk/style/layers/Property.java | 21 ++++++++ .../mapboxsdk/style/layers/PropertyFactory.java | 20 ++++++++ .../mapbox/mapboxsdk/style/layers/SymbolLayer.java | 14 +++++ .../mapboxsdk/testapp/style/SymbolLayerTest.java | 14 +++++ platform/android/src/style/layers/symbol_layer.cpp | 6 +++ platform/android/src/style/layers/symbol_layer.hpp | 2 + .../darwin/scripts/style-spec-overrides-v8.json | 10 ++++ platform/darwin/src/MGLSymbolStyleLayer.h | 59 ++++++++++++++++++++++ platform/darwin/src/MGLSymbolStyleLayer.mm | 32 ++++++++++++ platform/darwin/test/MGLSymbolStyleLayerTests.mm | 47 +++++++++++++++++ platform/ios/CHANGELOG.md | 3 ++ platform/macos/CHANGELOG.md | 3 ++ platform/node/CHANGELOG.md | 1 + src/mbgl/layout/symbol_layout.cpp | 7 +-- src/mbgl/style/conversion/constant.cpp | 1 + src/mbgl/style/conversion/function.cpp | 2 + src/mbgl/style/conversion/property_value.cpp | 1 + src/mbgl/style/expression/value.cpp | 3 ++ src/mbgl/style/layers/symbol_layer.cpp | 35 +++++++++++++ src/mbgl/style/layers/symbol_layer_properties.hpp | 6 +++ src/mbgl/style/types.cpp | 5 ++ 25 files changed, 300 insertions(+), 4 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 getSymbolAvoidEdges() const; void setSymbolAvoidEdges(PropertyValue); + static PropertyValue getDefaultSymbolZOrder(); + PropertyValue getSymbolZOrder() const; + void setSymbolZOrder(PropertyValue); + static PropertyValue getDefaultIconAllowOverlap(); PropertyValue getIconAllowOverlap() const; void setIconAllowOverlap(PropertyValue); 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 index 53e622b475..e8fd41abae 160000 --- a/mapbox-gl-js +++ b/mapbox-gl-js @@ -1 +1 @@ -Subproject commit 53e622b475b7c9cb26b98d18e3fbd61d27b183a2 +Subproject commit e8fd41abae382f39f17a561a1461db90bd2204f3 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 @@ -1764,6 +1764,26 @@ public class PropertyFactory { return new LayoutPropertyValue<>("symbol-avoid-edges", 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 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 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. * 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 @@ -170,6 +170,17 @@ public class SymbolLayer extends Layer { return (PropertyValue) new PropertyValue("symbol-avoid-edges", nativeGetSymbolAvoidEdges()); } + /** + * Get the SymbolZOrder property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue getSymbolZOrder() { + checkThread(); + return (PropertyValue) new PropertyValue("symbol-z-order", nativeGetSymbolZOrder()); + } + /** * Get the IconAllowOverlap property * @@ -1004,6 +1015,9 @@ public class SymbolLayer extends Layer { @Keep private native Object nativeGetSymbolAvoidEdges(); + @Keep + private native Object nativeGetSymbolZOrder(); + @Keep private native Object nativeGetIconAllowOverlap(); 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 @@ -159,6 +159,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(); 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>>(env, layer.as()->SymbolLayer::getSymbolAvoidEdges())); } + jni::Local> SymbolLayer::getSymbolZOrder(jni::JNIEnv& env) { + using namespace mbgl::android::conversion; + return std::move(*convert>>(env, layer.as()->SymbolLayer::getSymbolZOrder())); + } + jni::Local> SymbolLayer::getIconAllowOverlap(jni::JNIEnv& env) { using namespace mbgl::android::conversion; return std::move(*convert>>(env, layer.as()->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> getSymbolAvoidEdges(jni::JNIEnv&); + jni::Local> getSymbolZOrder(jni::JNIEnv&); + jni::Local> getIconAllowOverlap(jni::JNIEnv&); jni::Local> 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 @@ -150,6 +150,26 @@ typedef NS_ENUM(NSUInteger, MGLSymbolPlacement) { MGLSymbolPlacementLineCenter, }; +/** + 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. @@ -1004,6 +1024,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. @@ -2140,6 +2186,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. 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().toExpression(propertyValue); } +- (void)setSymbolZOrder:(NSExpression *)symbolZOrder { + MGLAssertStyleLayerIsValid(); + + auto mbglValue = MGLStyleValueTransformer().toPropertyValue>(symbolZOrder, false); + self.rawLayer->setSymbolZOrder(mbglValue); +} + +- (NSExpression *)symbolZOrder { + MGLAssertStyleLayerIsValid(); + + auto propertyValue = self.rawLayer->getSymbolZOrder(); + if (propertyValue.isUndefined()) { + propertyValue = self.rawLayer->getDefaultSymbolZOrder(); + } + return MGLStyleValueTransformer().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 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( + 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 CalculateTileDistances(const GeometryCoordinates& line, const } void SymbolLayout::createBucket(const ImagePositions&, std::unique_ptr&, std::unordered_map>& buckets, const bool firstLoad, const bool showCollisionBoxes) { - const bool mayOverlap = layout.get() || layout.get() || - layout.get() || layout.get(); + const bool zOrderByViewport = layout.get() == SymbolZOrderType::ViewportY; + const bool sortFeaturesByY = zOrderByViewport && (layout.get() || layout.get() || + layout.get() || layout.get()); - auto bucket = std::make_shared(layout, layerPaintProperties, textSize, iconSize, zoom, sdfIcons, iconsNeedLinear, mayOverlap, bucketLeaderID, std::move(symbolInstances)); + auto bucket = std::make_shared(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 Converter::operator()(const Conver template optional Converter::operator()(const Convertible&, Error&) const; template optional Converter::operator()(const Convertible&, Error&) const; template optional Converter::operator()(const Convertible&, Error&) const; +template optional Converter::operator()(const Convertible&, Error&) const; template optional Converter::operator()(const Convertible&, Error&) const; template optional Converter::operator()(const Convertible&, Error&) const; template optional Converter::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> convertFunctionToExpression(const Convertible&, Error&, bool); template optional> convertFunctionToExpression(const Convertible&, Error&, bool); +template optional> + convertFunctionToExpression(const Convertible&, Error&, bool); template optional> convertFunctionToExpression(const Convertible&, Error&, bool); template optional> 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> Converter>::o template optional> Converter>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const; template optional> Converter>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const; template optional> Converter>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const; +template optional> Converter>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const; template optional> Converter>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const; template optional> Converter>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const; template optional> Converter>::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; template type::Type valueTypeToExpressionType(); template struct ValueConverter; + +template type::Type valueTypeToExpressionType(); +template struct ValueConverter; template type::Type valueTypeToExpressionType(); template struct ValueConverter; 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 value) { baseImpl = std::move(impl_); observer->onLayerChanged(*this); } +PropertyValue SymbolLayer::getDefaultSymbolZOrder() { + return SymbolZOrder::defaultValue(); +} + +PropertyValue SymbolLayer::getSymbolZOrder() const { + return impl().layout.get(); +} + +void SymbolLayer::setSymbolZOrder(PropertyValue value) { + if (value == getSymbolZOrder()) + return; + auto impl_ = mutableImpl(); + impl_->layout.get() = value; + baseImpl = std::move(impl_); + observer->onLayerChanged(*this); +} PropertyValue SymbolLayer::getDefaultIconAllowOverlap() { return IconAllowOverlap::defaultValue(); } @@ -1440,6 +1456,7 @@ optional SymbolLayer::setLayoutProperty(const std::string& name, const Co SymbolPlacement, SymbolSpacing, SymbolAvoidEdges, + SymbolZOrder, IconAllowOverlap, IconIgnorePlacement, IconOptional, @@ -1496,6 +1513,12 @@ optional 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 SymbolLayer::setLayoutProperty(const std::string& name, const Co } + if (property == Property::SymbolZOrder) { + Error error; + optional> typedValue = convert>(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> typedValue = convert>(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 { static bool defaultValue() { return false; } }; +struct SymbolZOrder : LayoutProperty { + static constexpr const char * key = "symbol-z-order"; + static SymbolZOrderType defaultValue() { return SymbolZOrderType::ViewportY; } +}; + struct IconAllowOverlap : LayoutProperty { 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" }, -- cgit v1.2.1