diff options
Diffstat (limited to 'platform/darwin/src')
49 files changed, 1600 insertions, 1028 deletions
diff --git a/platform/darwin/src/MGLAttributionInfo.mm b/platform/darwin/src/MGLAttributionInfo.mm index fa2ae787a5..7583244491 100644 --- a/platform/darwin/src/MGLAttributionInfo.mm +++ b/platform/darwin/src/MGLAttributionInfo.mm @@ -93,7 +93,12 @@ return; } - MGLAttributionInfo *info = [[MGLAttributionInfo alloc] initWithTitle:title URL:value]; + // Remove the link, because it forces the text to be blue on macOS 10.12 + // and above. + NSMutableAttributedString *unlinkedTitle = [title mutableCopy]; + [unlinkedTitle removeAttribute:NSLinkAttributeName range:unlinkedTitle.mgl_wholeRange]; + + MGLAttributionInfo *info = [[MGLAttributionInfo alloc] initWithTitle:unlinkedTitle URL:value]; info.feedbackLink = isFeedbackLink; [infos addObject:info]; }]; diff --git a/platform/darwin/src/MGLBackgroundStyleLayer.h b/platform/darwin/src/MGLBackgroundStyleLayer.h index cd218d9fb4..659903914c 100644 --- a/platform/darwin/src/MGLBackgroundStyleLayer.h +++ b/platform/darwin/src/MGLBackgroundStyleLayer.h @@ -24,7 +24,17 @@ NS_ASSUME_NONNULL_BEGIN MGL_EXPORT @interface MGLBackgroundStyleLayer : MGLStyleLayer -- (instancetype)initWithIdentifier:(NSString *)identifier NS_DESIGNATED_INITIALIZER; +/** +Returns a background style layer initialized with an identifier. + +After initializing and configuring the style layer, add it to a map view’s +style using the `-[MGLStyle addLayer:]` or +`-[MGLStyle insertLayer:belowLayer:]` method. + +@param identifier A string that uniquely identifies the source in the style to +which it is added. +*/ +- (instancetype)initWithIdentifier:(NSString *)identifier; #pragma mark - Accessing the Paint Attributes diff --git a/platform/darwin/src/MGLBackgroundStyleLayer.mm b/platform/darwin/src/MGLBackgroundStyleLayer.mm index 8f416a0ea2..47b491fc65 100644 --- a/platform/darwin/src/MGLBackgroundStyleLayer.mm +++ b/platform/darwin/src/MGLBackgroundStyleLayer.mm @@ -2,35 +2,27 @@ // Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`. #import "MGLSource.h" -#import "MGLMapView_Private.h" #import "NSPredicate+MGLAdditions.h" #import "NSDate+MGLAdditions.h" #import "MGLStyleLayer_Private.h" #import "MGLStyleValue_Private.h" #import "MGLBackgroundStyleLayer.h" -#include <mbgl/map/map.hpp> +#include <mbgl/style/transition_options.hpp> #include <mbgl/style/layers/background_layer.hpp> @interface MGLBackgroundStyleLayer () -@property (nonatomic) mbgl::style::BackgroundLayer *rawLayer; +@property (nonatomic, readonly) mbgl::style::BackgroundLayer *rawLayer; @end @implementation MGLBackgroundStyleLayer -{ - std::unique_ptr<mbgl::style::BackgroundLayer> _pendingLayer; -} - (instancetype)initWithIdentifier:(NSString *)identifier { - if (self = [super initWithIdentifier:identifier]) { - auto layer = std::make_unique<mbgl::style::BackgroundLayer>(identifier.UTF8String); - _pendingLayer = std::move(layer); - self.rawLayer = _pendingLayer.get(); - } - return self; + auto layer = std::make_unique<mbgl::style::BackgroundLayer>(identifier.UTF8String); + return self = [super initWithPendingLayer:std::move(layer)]; } - (mbgl::style::BackgroundLayer *)rawLayer @@ -38,51 +30,6 @@ return (mbgl::style::BackgroundLayer *)super.rawLayer; } -- (void)setRawLayer:(mbgl::style::BackgroundLayer *)rawLayer -{ - super.rawLayer = rawLayer; -} - -#pragma mark - Adding to and removing from a map view - -- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer -{ - if (_pendingLayer == nullptr) { - [NSException raise:@"MGLRedundantLayerException" - format:@"This instance %@ was already added to %@. Adding the same layer instance " \ - "to the style more than once is invalid.", self, mapView.style]; - } - - if (otherLayer) { - const mbgl::optional<std::string> belowLayerId{otherLayer.identifier.UTF8String}; - mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId); - } else { - mapView.mbglMap->addLayer(std::move(_pendingLayer)); - } -} - -- (void)removeFromMapView:(MGLMapView *)mapView -{ - if (self.rawLayer != mapView.mbglMap->getLayer(self.identifier.UTF8String)) { - return; - } - - auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String); - if (!removedLayer) { - return; - } - - mbgl::style::BackgroundLayer *layer = dynamic_cast<mbgl::style::BackgroundLayer *>(removedLayer.get()); - if (!layer) { - return; - } - - removedLayer.release(); - - _pendingLayer = std::unique_ptr<mbgl::style::BackgroundLayer>(layer); - self.rawLayer = _pendingLayer.get(); -} - #pragma mark - Accessing the Paint Attributes - (void)setBackgroundColor:(MGLStyleValue<MGLColor *> *)backgroundColor { diff --git a/platform/darwin/src/MGLCircleStyleLayer.h b/platform/darwin/src/MGLCircleStyleLayer.h index 69c823a868..789ff7a258 100644 --- a/platform/darwin/src/MGLCircleStyleLayer.h +++ b/platform/darwin/src/MGLCircleStyleLayer.h @@ -79,6 +79,21 @@ typedef NS_ENUM(NSUInteger, MGLCircleTranslationAnchor) { MGL_EXPORT @interface MGLCircleStyleLayer : MGLVectorStyleLayer +/** + Returns a circle style layer initialized with an identifier and source. + + After initializing and configuring the style layer, add it to a map view’s + style using the `-[MGLStyle addLayer:]` or + `-[MGLStyle insertLayer:belowLayer:]` method. + + @param identifier A string that uniquely identifies the source in the style to + which it is added. + @param source The source from which to obtain the data to style. If the source + has not yet been added to the current style, the behavior is undefined. + @return An initialized foreground style layer. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier source:(MGLSource *)source; + #pragma mark - Accessing the Paint Attributes /** diff --git a/platform/darwin/src/MGLCircleStyleLayer.mm b/platform/darwin/src/MGLCircleStyleLayer.mm index 330b9cdac0..42961f2e12 100644 --- a/platform/darwin/src/MGLCircleStyleLayer.mm +++ b/platform/darwin/src/MGLCircleStyleLayer.mm @@ -2,14 +2,13 @@ // Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`. #import "MGLSource.h" -#import "MGLMapView_Private.h" #import "NSPredicate+MGLAdditions.h" #import "NSDate+MGLAdditions.h" #import "MGLStyleLayer_Private.h" #import "MGLStyleValue_Private.h" #import "MGLCircleStyleLayer.h" -#include <mbgl/map/map.hpp> +#include <mbgl/style/transition_options.hpp> #include <mbgl/style/layers/circle_layer.hpp> namespace mbgl { @@ -28,23 +27,16 @@ namespace mbgl { @interface MGLCircleStyleLayer () -@property (nonatomic) mbgl::style::CircleLayer *rawLayer; +@property (nonatomic, readonly) mbgl::style::CircleLayer *rawLayer; @end @implementation MGLCircleStyleLayer -{ - std::unique_ptr<mbgl::style::CircleLayer> _pendingLayer; -} - (instancetype)initWithIdentifier:(NSString *)identifier source:(MGLSource *)source { - if (self = [super initWithIdentifier:identifier source:source]) { - auto layer = std::make_unique<mbgl::style::CircleLayer>(identifier.UTF8String, source.identifier.UTF8String); - _pendingLayer = std::move(layer); - self.rawLayer = _pendingLayer.get(); - } - return self; + auto layer = std::make_unique<mbgl::style::CircleLayer>(identifier.UTF8String, source.identifier.UTF8String); + return self = [super initWithPendingLayer:std::move(layer)]; } - (mbgl::style::CircleLayer *)rawLayer @@ -52,11 +44,6 @@ namespace mbgl { return (mbgl::style::CircleLayer *)super.rawLayer; } -- (void)setRawLayer:(mbgl::style::CircleLayer *)rawLayer -{ - super.rawLayer = rawLayer; -} - - (NSString *)sourceIdentifier { MGLAssertStyleLayerIsValid(); @@ -93,46 +80,6 @@ namespace mbgl { return [NSPredicate mgl_predicateWithFilter:self.rawLayer->getFilter()]; } -#pragma mark - Adding to and removing from a map view - -- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer -{ - if (_pendingLayer == nullptr) { - [NSException raise:@"MGLRedundantLayerException" - format:@"This instance %@ was already added to %@. Adding the same layer instance " \ - "to the style more than once is invalid.", self, mapView.style]; - } - - if (otherLayer) { - const mbgl::optional<std::string> belowLayerId{otherLayer.identifier.UTF8String}; - mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId); - } else { - mapView.mbglMap->addLayer(std::move(_pendingLayer)); - } -} - -- (void)removeFromMapView:(MGLMapView *)mapView -{ - if (self.rawLayer != mapView.mbglMap->getLayer(self.identifier.UTF8String)) { - return; - } - - auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String); - if (!removedLayer) { - return; - } - - mbgl::style::CircleLayer *layer = dynamic_cast<mbgl::style::CircleLayer *>(removedLayer.get()); - if (!layer) { - return; - } - - removedLayer.release(); - - _pendingLayer = std::unique_ptr<mbgl::style::CircleLayer>(layer); - self.rawLayer = _pendingLayer.get(); -} - #pragma mark - Accessing the Paint Attributes - (void)setCircleBlur:(MGLStyleValue<NSNumber *> *)circleBlur { diff --git a/platform/darwin/src/MGLDistanceFormatter.m b/platform/darwin/src/MGLDistanceFormatter.m index e77e48b512..a7a2f9c9e1 100644 --- a/platform/darwin/src/MGLDistanceFormatter.m +++ b/platform/darwin/src/MGLDistanceFormatter.m @@ -24,7 +24,7 @@ static const double FEET_PER_MILE = YARDS_PER_MILE * 3.0; return [self stringFromValue:miles unit:unit]; } else { unit = NSLengthFormatterUnitFoot; - self.numberFormatter.roundingIncrement = @50; + self.numberFormatter.roundingIncrement = @1; return [self stringFromValue:feet unit:unit]; } } else { diff --git a/platform/darwin/src/MGLFillExtrusionStyleLayer.h b/platform/darwin/src/MGLFillExtrusionStyleLayer.h new file mode 100644 index 0000000000..84f6bedde4 --- /dev/null +++ b/platform/darwin/src/MGLFillExtrusionStyleLayer.h @@ -0,0 +1,364 @@ +// This file is generated. +// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`. + +#import "MGLFoundation.h" +#import "MGLStyleValue.h" +#import "MGLVectorStyleLayer.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + Controls the translation reference point. + + Values of this type are used in the `MGLFillExtrusionStyleLayer.fillExtrusionTranslationAnchor` + property. + */ +typedef NS_ENUM(NSUInteger, MGLFillExtrusionTranslationAnchor) { + /** + The fill extrusion is translated relative to the map. + */ + MGLFillExtrusionTranslationAnchorMap, + /** + The fill extrusion is translated relative to the viewport. + */ + MGLFillExtrusionTranslationAnchorViewport, +}; + +/** + An `MGLFillExtrusionStyleLayer` is a style layer that renders one or more 3D + extruded polygons on the map. + + Use a fill-extrusion style layer to configure the visual appearance of polygon + or multipolygon features in vector tiles loaded by an `MGLVectorSource` object + or `MGLPolygon`, `MGLPolygonFeature`, `MGLMultiPolygon`, or + `MGLMultiPolygonFeature` instances in an `MGLShapeSource` object. + + You can access an existing fill-extrusion style layer using the + `-[MGLStyle layerWithIdentifier:]` method if you know its identifier; + otherwise, find it using the `MGLStyle.layers` property. You can also create a + new fill-extrusion style layer and add it to the style using a method such as + `-[MGLStyle addLayer:]`. + + ### Example + + ```swift + let layer = MGLFillExtrusionStyleLayer(identifier: "buildings", source: buildings) + layer.sourceLayerIdentifier = "building" + layer.fillExtrusionHeight = MGLStyleValue(interpolationMode: .identity, sourceStops: nil, attributeName: "height", options: nil) + layer.fillExtrusionBase = MGLStyleValue(interpolationMode: .identity, sourceStops: nil, attributeName: "min_height", options: nil) + layer.predicate = NSPredicate(format: "extrude == TRUE") + mapView.style?.addLayer(layer) + ``` + */ +MGL_EXPORT +@interface MGLFillExtrusionStyleLayer : MGLVectorStyleLayer + +/** + Returns a fill-extrusion style layer initialized with an identifier and source. + + After initializing and configuring the style layer, add it to a map view’s + style using the `-[MGLStyle addLayer:]` or + `-[MGLStyle insertLayer:belowLayer:]` method. + + @param identifier A string that uniquely identifies the source in the style to + which it is added. + @param source The source from which to obtain the data to style. If the source + has not yet been added to the current style, the behavior is undefined. + @return An initialized foreground style layer. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier source:(MGLSource *)source; + +#pragma mark - Accessing the Paint Attributes + +/** + The height with which to extrude the base of this layer. Must be less than or + equal to `fillExtrusionHeight`. + + This property is measured in meters. + + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `0`. Set this property to `nil` to reset + it to the default value. + + This property is only applied to the style if `fillExtrusionHeight` is + non-`nil`. Otherwise, it is ignored. + + You can set this property to an instance of: + + * `MGLConstantStyleValue` + * `MGLCameraStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLSourceStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLInterpolationModeCategorical` + * `MGLInterpolationModeIdentity` + * `MGLCompositeStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLInterpolationModeCategorical` + */ +@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *fillExtrusionBase; + +/** + The transition affecting any changes to this layer’s `fillExtrusionBase` property. + + This property corresponds to the `fill-extrusion-base-transition` property in the style JSON file format. +*/ +@property (nonatomic) MGLTransition fillExtrusionBaseTransition; + +#if TARGET_OS_IPHONE +/** + The base color of this layer. The extrusion's surfaces will be shaded + differently based on this color in combination with the `light` settings. If + this color is specified with an alpha component, the alpha component will be + ignored; use `fillExtrusionOpacity` to set layer opacityco. + + The default value of this property is an `MGLStyleValue` object containing + `UIColor.blackColor`. Set this property to `nil` to reset it to the default + value. + + This property is only applied to the style if `fillExtrusionPattern` is set to + `nil`. Otherwise, it is ignored. + + You can set this property to an instance of: + + * `MGLConstantStyleValue` + * `MGLCameraStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLSourceStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLInterpolationModeCategorical` + * `MGLInterpolationModeIdentity` + * `MGLCompositeStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLInterpolationModeCategorical` + */ +@property (nonatomic, null_resettable) MGLStyleValue<UIColor *> *fillExtrusionColor; +#else +/** + The base color of this layer. The extrusion's surfaces will be shaded + differently based on this color in combination with the `light` settings. If + this color is specified with an alpha component, the alpha component will be + ignored; use `fillExtrusionOpacity` to set layer opacityco. + + The default value of this property is an `MGLStyleValue` object containing + `NSColor.blackColor`. Set this property to `nil` to reset it to the default + value. + + This property is only applied to the style if `fillExtrusionPattern` is set to + `nil`. Otherwise, it is ignored. + + You can set this property to an instance of: + + * `MGLConstantStyleValue` + * `MGLCameraStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLSourceStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLInterpolationModeCategorical` + * `MGLInterpolationModeIdentity` + * `MGLCompositeStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLInterpolationModeCategorical` + */ +@property (nonatomic, null_resettable) MGLStyleValue<NSColor *> *fillExtrusionColor; +#endif + +/** + The transition affecting any changes to this layer’s `fillExtrusionColor` property. + + This property corresponds to the `fill-extrusion-color-transition` property in the style JSON file format. +*/ +@property (nonatomic) MGLTransition fillExtrusionColorTransition; + +/** + The height with which to extrude this layer. + + This property is measured in meters. + + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `0`. Set this property to `nil` to reset + it to the default value. + + You can set this property to an instance of: + + * `MGLConstantStyleValue` + * `MGLCameraStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLSourceStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLInterpolationModeCategorical` + * `MGLInterpolationModeIdentity` + * `MGLCompositeStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLInterpolationModeCategorical` + */ +@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *fillExtrusionHeight; + +/** + The transition affecting any changes to this layer’s `fillExtrusionHeight` property. + + This property corresponds to the `fill-extrusion-height-transition` property in the style JSON file format. +*/ +@property (nonatomic) MGLTransition fillExtrusionHeightTransition; + +/** + The opacity of the entire fill extrusion layer. This is rendered on a + per-layer, not per-feature, basis, and data-driven styling is not available. + + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `1`. Set this property to `nil` to reset + it to the default value. + + You can set this property to an instance of: + + * `MGLConstantStyleValue` + * `MGLCameraStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + */ +@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *fillExtrusionOpacity; + +/** + The transition affecting any changes to this layer’s `fillExtrusionOpacity` property. + + This property corresponds to the `fill-extrusion-opacity-transition` property in the style JSON file format. +*/ +@property (nonatomic) MGLTransition fillExtrusionOpacityTransition; + +/** + Name of image in style images to use for drawing image fill-extrusions. For + seamless patterns, image width and height must be a factor of two (2, 4, 8, + ..., 512). + + You can set this property to an instance of: + + * `MGLConstantStyleValue` + * `MGLCameraStyleFunction` with an interpolation mode of + `MGLInterpolationModeInterval` + */ +@property (nonatomic, null_resettable) MGLStyleValue<NSString *> *fillExtrusionPattern; + +/** + The transition affecting any changes to this layer’s `fillExtrusionPattern` property. + + This property corresponds to the `fill-extrusion-pattern-transition` property in the style JSON file format. +*/ +@property (nonatomic) MGLTransition fillExtrusionPatternTransition; + +#if TARGET_OS_IPHONE +/** + The geometry's offset. + + This property is measured in points. + + The default value of this property is an `MGLStyleValue` object containing an + `NSValue` object containing a `CGVector` struct set to 0 points rightward and 0 + points downward. Set this property to `nil` to reset it to the default value. + + This attribute corresponds to the <a + href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-fill-extrusion-translate"><code>fill-extrusion-translate</code></a> + layout property in the Mapbox Style Specification. + + You can set this property to an instance of: + + * `MGLConstantStyleValue` + * `MGLCameraStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + */ +@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *fillExtrusionTranslation; +#else +/** + The geometry's offset. + + This property is measured in points. + + The default value of this property is an `MGLStyleValue` object containing an + `NSValue` object containing a `CGVector` struct set to 0 points rightward and 0 + points upward. Set this property to `nil` to reset it to the default value. + + This attribute corresponds to the <a + href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-fill-extrusion-translate"><code>fill-extrusion-translate</code></a> + layout property in the Mapbox Style Specification. + + You can set this property to an instance of: + + * `MGLConstantStyleValue` + * `MGLCameraStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + */ +@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *fillExtrusionTranslation; +#endif + +/** + The transition affecting any changes to this layer’s `fillExtrusionTranslation` property. + + This property corresponds to the `fill-extrusion-translate-transition` property in the style JSON file format. +*/ +@property (nonatomic) MGLTransition fillExtrusionTranslationTransition; + +@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *fillExtrusionTranslate __attribute__((unavailable("Use fillExtrusionTranslation instead."))); + +/** + Controls the translation reference point. + + The default value of this property is an `MGLStyleValue` object containing an + `NSValue` object containing `MGLFillExtrusionTranslationAnchorMap`. Set this + property to `nil` to reset it to the default value. + + This property is only applied to the style if `fillExtrusionTranslation` is + non-`nil`. Otherwise, it is ignored. + + This attribute corresponds to the <a + href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-fill-extrusion-translate-anchor"><code>fill-extrusion-translate-anchor</code></a> + layout property in the Mapbox Style Specification. + + You can set this property to an instance of: + + * `MGLConstantStyleValue` + * `MGLCameraStyleFunction` with an interpolation mode of + `MGLInterpolationModeInterval` + */ +@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *fillExtrusionTranslationAnchor; + +@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *fillExtrusionTranslateAnchor __attribute__((unavailable("Use fillExtrusionTranslationAnchor instead."))); + +@end + +/** + Methods for wrapping an enumeration value for a style layer attribute in an + `MGLFillExtrusionStyleLayer` object and unwrapping its raw value. + */ +@interface NSValue (MGLFillExtrusionStyleLayerAdditions) + +#pragma mark Working with Fill extrusion Style Layer Attribute Values + +/** + Creates a new value object containing the given `MGLFillExtrusionTranslationAnchor` enumeration. + + @param fillExtrusionTranslationAnchor The value for the new object. + @return A new value object that contains the enumeration value. + */ ++ (instancetype)valueWithMGLFillExtrusionTranslationAnchor:(MGLFillExtrusionTranslationAnchor)fillExtrusionTranslationAnchor; + +/** + The `MGLFillExtrusionTranslationAnchor` enumeration representation of the value. + */ +@property (readonly) MGLFillExtrusionTranslationAnchor MGLFillExtrusionTranslationAnchorValue; + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLFillExtrusionStyleLayer.mm b/platform/darwin/src/MGLFillExtrusionStyleLayer.mm new file mode 100644 index 0000000000..b00ed8e09f --- /dev/null +++ b/platform/darwin/src/MGLFillExtrusionStyleLayer.mm @@ -0,0 +1,335 @@ +// This file is generated. +// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`. + +#import "MGLSource.h" +#import "NSPredicate+MGLAdditions.h" +#import "NSDate+MGLAdditions.h" +#import "MGLStyleLayer_Private.h" +#import "MGLStyleValue_Private.h" +#import "MGLFillExtrusionStyleLayer.h" + +#include <mbgl/style/transition_options.hpp> +#include <mbgl/style/layers/fill_extrusion_layer.hpp> + +namespace mbgl { + + MBGL_DEFINE_ENUM(MGLFillExtrusionTranslationAnchor, { + { MGLFillExtrusionTranslationAnchorMap, "map" }, + { MGLFillExtrusionTranslationAnchorViewport, "viewport" }, + }); + +} + +@interface MGLFillExtrusionStyleLayer () + +@property (nonatomic, readonly) mbgl::style::FillExtrusionLayer *rawLayer; + +@end + +@implementation MGLFillExtrusionStyleLayer + +- (instancetype)initWithIdentifier:(NSString *)identifier source:(MGLSource *)source +{ + auto layer = std::make_unique<mbgl::style::FillExtrusionLayer>(identifier.UTF8String, source.identifier.UTF8String); + return self = [super initWithPendingLayer:std::move(layer)]; +} + +- (mbgl::style::FillExtrusionLayer *)rawLayer +{ + return (mbgl::style::FillExtrusionLayer *)super.rawLayer; +} + +- (NSString *)sourceIdentifier +{ + MGLAssertStyleLayerIsValid(); + + return @(self.rawLayer->getSourceID().c_str()); +} + +- (NSString *)sourceLayerIdentifier +{ + MGLAssertStyleLayerIsValid(); + + auto layerID = self.rawLayer->getSourceLayer(); + return layerID.empty() ? nil : @(layerID.c_str()); +} + +- (void)setSourceLayerIdentifier:(NSString *)sourceLayerIdentifier +{ + MGLAssertStyleLayerIsValid(); + + self.rawLayer->setSourceLayer(sourceLayerIdentifier.UTF8String ?: ""); +} + +- (void)setPredicate:(NSPredicate *)predicate +{ + MGLAssertStyleLayerIsValid(); + + self.rawLayer->setFilter(predicate ? predicate.mgl_filter : mbgl::style::NullFilter()); +} + +- (NSPredicate *)predicate +{ + MGLAssertStyleLayerIsValid(); + + return [NSPredicate mgl_predicateWithFilter:self.rawLayer->getFilter()]; +} + +#pragma mark - Accessing the Paint Attributes + +- (void)setFillExtrusionBase:(MGLStyleValue<NSNumber *> *)fillExtrusionBase { + MGLAssertStyleLayerIsValid(); + + auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenPropertyValue(fillExtrusionBase); + self.rawLayer->setFillExtrusionBase(mbglValue); +} + +- (MGLStyleValue<NSNumber *> *)fillExtrusionBase { + MGLAssertStyleLayerIsValid(); + + auto propertyValue = self.rawLayer->getFillExtrusionBase(); + if (propertyValue.isUndefined()) { + return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(self.rawLayer->getDefaultFillExtrusionBase()); + } + return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(propertyValue); +} + +- (void)setFillExtrusionBaseTransition:(MGLTransition )transition { + MGLAssertStyleLayerIsValid(); + + mbgl::style::TransitionOptions options { { MGLDurationFromTimeInterval(transition.duration) }, { MGLDurationFromTimeInterval(transition.delay) } }; + self.rawLayer->setFillExtrusionBaseTransition(options); +} + +- (MGLTransition)fillExtrusionBaseTransition { + MGLAssertStyleLayerIsValid(); + + mbgl::style::TransitionOptions transitionOptions = self.rawLayer->getFillExtrusionBaseTransition(); + MGLTransition transition; + transition.duration = MGLTimeIntervalFromDuration(transitionOptions.duration.value_or(mbgl::Duration::zero())); + transition.delay = MGLTimeIntervalFromDuration(transitionOptions.delay.value_or(mbgl::Duration::zero())); + + return transition; +} + +- (void)setFillExtrusionColor:(MGLStyleValue<MGLColor *> *)fillExtrusionColor { + MGLAssertStyleLayerIsValid(); + + auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenPropertyValue(fillExtrusionColor); + self.rawLayer->setFillExtrusionColor(mbglValue); +} + +- (MGLStyleValue<MGLColor *> *)fillExtrusionColor { + MGLAssertStyleLayerIsValid(); + + auto propertyValue = self.rawLayer->getFillExtrusionColor(); + if (propertyValue.isUndefined()) { + return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenStyleValue(self.rawLayer->getDefaultFillExtrusionColor()); + } + return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenStyleValue(propertyValue); +} + +- (void)setFillExtrusionColorTransition:(MGLTransition )transition { + MGLAssertStyleLayerIsValid(); + + mbgl::style::TransitionOptions options { { MGLDurationFromTimeInterval(transition.duration) }, { MGLDurationFromTimeInterval(transition.delay) } }; + self.rawLayer->setFillExtrusionColorTransition(options); +} + +- (MGLTransition)fillExtrusionColorTransition { + MGLAssertStyleLayerIsValid(); + + mbgl::style::TransitionOptions transitionOptions = self.rawLayer->getFillExtrusionColorTransition(); + MGLTransition transition; + transition.duration = MGLTimeIntervalFromDuration(transitionOptions.duration.value_or(mbgl::Duration::zero())); + transition.delay = MGLTimeIntervalFromDuration(transitionOptions.delay.value_or(mbgl::Duration::zero())); + + return transition; +} + +- (void)setFillExtrusionHeight:(MGLStyleValue<NSNumber *> *)fillExtrusionHeight { + MGLAssertStyleLayerIsValid(); + + auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenPropertyValue(fillExtrusionHeight); + self.rawLayer->setFillExtrusionHeight(mbglValue); +} + +- (MGLStyleValue<NSNumber *> *)fillExtrusionHeight { + MGLAssertStyleLayerIsValid(); + + auto propertyValue = self.rawLayer->getFillExtrusionHeight(); + if (propertyValue.isUndefined()) { + return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(self.rawLayer->getDefaultFillExtrusionHeight()); + } + return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(propertyValue); +} + +- (void)setFillExtrusionHeightTransition:(MGLTransition )transition { + MGLAssertStyleLayerIsValid(); + + mbgl::style::TransitionOptions options { { MGLDurationFromTimeInterval(transition.duration) }, { MGLDurationFromTimeInterval(transition.delay) } }; + self.rawLayer->setFillExtrusionHeightTransition(options); +} + +- (MGLTransition)fillExtrusionHeightTransition { + MGLAssertStyleLayerIsValid(); + + mbgl::style::TransitionOptions transitionOptions = self.rawLayer->getFillExtrusionHeightTransition(); + MGLTransition transition; + transition.duration = MGLTimeIntervalFromDuration(transitionOptions.duration.value_or(mbgl::Duration::zero())); + transition.delay = MGLTimeIntervalFromDuration(transitionOptions.delay.value_or(mbgl::Duration::zero())); + + return transition; +} + +- (void)setFillExtrusionOpacity:(MGLStyleValue<NSNumber *> *)fillExtrusionOpacity { + MGLAssertStyleLayerIsValid(); + + auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(fillExtrusionOpacity); + self.rawLayer->setFillExtrusionOpacity(mbglValue); +} + +- (MGLStyleValue<NSNumber *> *)fillExtrusionOpacity { + MGLAssertStyleLayerIsValid(); + + auto propertyValue = self.rawLayer->getFillExtrusionOpacity(); + if (propertyValue.isUndefined()) { + return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultFillExtrusionOpacity()); + } + return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue); +} + +- (void)setFillExtrusionOpacityTransition:(MGLTransition )transition { + MGLAssertStyleLayerIsValid(); + + mbgl::style::TransitionOptions options { { MGLDurationFromTimeInterval(transition.duration) }, { MGLDurationFromTimeInterval(transition.delay) } }; + self.rawLayer->setFillExtrusionOpacityTransition(options); +} + +- (MGLTransition)fillExtrusionOpacityTransition { + MGLAssertStyleLayerIsValid(); + + mbgl::style::TransitionOptions transitionOptions = self.rawLayer->getFillExtrusionOpacityTransition(); + MGLTransition transition; + transition.duration = MGLTimeIntervalFromDuration(transitionOptions.duration.value_or(mbgl::Duration::zero())); + transition.delay = MGLTimeIntervalFromDuration(transitionOptions.delay.value_or(mbgl::Duration::zero())); + + return transition; +} + +- (void)setFillExtrusionPattern:(MGLStyleValue<NSString *> *)fillExtrusionPattern { + MGLAssertStyleLayerIsValid(); + + auto mbglValue = MGLStyleValueTransformer<std::string, NSString *>().toPropertyValue(fillExtrusionPattern); + self.rawLayer->setFillExtrusionPattern(mbglValue); +} + +- (MGLStyleValue<NSString *> *)fillExtrusionPattern { + MGLAssertStyleLayerIsValid(); + + auto propertyValue = self.rawLayer->getFillExtrusionPattern(); + if (propertyValue.isUndefined()) { + return MGLStyleValueTransformer<std::string, NSString *>().toStyleValue(self.rawLayer->getDefaultFillExtrusionPattern()); + } + return MGLStyleValueTransformer<std::string, NSString *>().toStyleValue(propertyValue); +} + +- (void)setFillExtrusionPatternTransition:(MGLTransition )transition { + MGLAssertStyleLayerIsValid(); + + mbgl::style::TransitionOptions options { { MGLDurationFromTimeInterval(transition.duration) }, { MGLDurationFromTimeInterval(transition.delay) } }; + self.rawLayer->setFillExtrusionPatternTransition(options); +} + +- (MGLTransition)fillExtrusionPatternTransition { + MGLAssertStyleLayerIsValid(); + + mbgl::style::TransitionOptions transitionOptions = self.rawLayer->getFillExtrusionPatternTransition(); + MGLTransition transition; + transition.duration = MGLTimeIntervalFromDuration(transitionOptions.duration.value_or(mbgl::Duration::zero())); + transition.delay = MGLTimeIntervalFromDuration(transitionOptions.delay.value_or(mbgl::Duration::zero())); + + return transition; +} + +- (void)setFillExtrusionTranslation:(MGLStyleValue<NSValue *> *)fillExtrusionTranslation { + MGLAssertStyleLayerIsValid(); + + auto mbglValue = MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toInterpolatablePropertyValue(fillExtrusionTranslation); + self.rawLayer->setFillExtrusionTranslate(mbglValue); +} + +- (MGLStyleValue<NSValue *> *)fillExtrusionTranslation { + MGLAssertStyleLayerIsValid(); + + auto propertyValue = self.rawLayer->getFillExtrusionTranslate(); + if (propertyValue.isUndefined()) { + return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toStyleValue(self.rawLayer->getDefaultFillExtrusionTranslate()); + } + return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toStyleValue(propertyValue); +} + +- (void)setFillExtrusionTranslationTransition:(MGLTransition )transition { + MGLAssertStyleLayerIsValid(); + + mbgl::style::TransitionOptions options { { MGLDurationFromTimeInterval(transition.duration) }, { MGLDurationFromTimeInterval(transition.delay) } }; + self.rawLayer->setFillExtrusionTranslateTransition(options); +} + +- (MGLTransition)fillExtrusionTranslationTransition { + MGLAssertStyleLayerIsValid(); + + mbgl::style::TransitionOptions transitionOptions = self.rawLayer->getFillExtrusionTranslateTransition(); + MGLTransition transition; + transition.duration = MGLTimeIntervalFromDuration(transitionOptions.duration.value_or(mbgl::Duration::zero())); + transition.delay = MGLTimeIntervalFromDuration(transitionOptions.delay.value_or(mbgl::Duration::zero())); + + return transition; +} + +- (void)setFillExtrusionTranslate:(MGLStyleValue<NSValue *> *)fillExtrusionTranslate { +} + +- (MGLStyleValue<NSValue *> *)fillExtrusionTranslate { + return self.fillExtrusionTranslation; +} + +- (void)setFillExtrusionTranslationAnchor:(MGLStyleValue<NSValue *> *)fillExtrusionTranslationAnchor { + MGLAssertStyleLayerIsValid(); + + auto mbglValue = MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *, mbgl::style::TranslateAnchorType, MGLFillExtrusionTranslationAnchor>().toEnumPropertyValue(fillExtrusionTranslationAnchor); + self.rawLayer->setFillExtrusionTranslateAnchor(mbglValue); +} + +- (MGLStyleValue<NSValue *> *)fillExtrusionTranslationAnchor { + MGLAssertStyleLayerIsValid(); + + auto propertyValue = self.rawLayer->getFillExtrusionTranslateAnchor(); + if (propertyValue.isUndefined()) { + return MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *, mbgl::style::TranslateAnchorType, MGLFillExtrusionTranslationAnchor>().toEnumStyleValue(self.rawLayer->getDefaultFillExtrusionTranslateAnchor()); + } + return MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *, mbgl::style::TranslateAnchorType, MGLFillExtrusionTranslationAnchor>().toEnumStyleValue(propertyValue); +} + +- (void)setFillExtrusionTranslateAnchor:(MGLStyleValue<NSValue *> *)fillExtrusionTranslateAnchor { +} + +- (MGLStyleValue<NSValue *> *)fillExtrusionTranslateAnchor { + return self.fillExtrusionTranslationAnchor; +} + +@end + +@implementation NSValue (MGLFillExtrusionStyleLayerAdditions) + ++ (NSValue *)valueWithMGLFillExtrusionTranslationAnchor:(MGLFillExtrusionTranslationAnchor)fillExtrusionTranslationAnchor { + return [NSValue value:&fillExtrusionTranslationAnchor withObjCType:@encode(MGLFillExtrusionTranslationAnchor)]; +} + +- (MGLFillExtrusionTranslationAnchor)MGLFillExtrusionTranslationAnchorValue { + MGLFillExtrusionTranslationAnchor fillExtrusionTranslationAnchor; + [self getValue:&fillExtrusionTranslationAnchor]; + return fillExtrusionTranslationAnchor; +} + +@end diff --git a/platform/darwin/src/MGLFillStyleLayer.h b/platform/darwin/src/MGLFillStyleLayer.h index 1f3cfc8af5..6e3297bdec 100644 --- a/platform/darwin/src/MGLFillStyleLayer.h +++ b/platform/darwin/src/MGLFillStyleLayer.h @@ -52,6 +52,21 @@ typedef NS_ENUM(NSUInteger, MGLFillTranslationAnchor) { MGL_EXPORT @interface MGLFillStyleLayer : MGLVectorStyleLayer +/** + Returns a fill style layer initialized with an identifier and source. + + After initializing and configuring the style layer, add it to a map view’s + style using the `-[MGLStyle addLayer:]` or + `-[MGLStyle insertLayer:belowLayer:]` method. + + @param identifier A string that uniquely identifies the source in the style to + which it is added. + @param source The source from which to obtain the data to style. If the source + has not yet been added to the current style, the behavior is undefined. + @return An initialized foreground style layer. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier source:(MGLSource *)source; + #pragma mark - Accessing the Paint Attributes /** diff --git a/platform/darwin/src/MGLFillStyleLayer.mm b/platform/darwin/src/MGLFillStyleLayer.mm index 1322a7a0b6..71b01a6661 100644 --- a/platform/darwin/src/MGLFillStyleLayer.mm +++ b/platform/darwin/src/MGLFillStyleLayer.mm @@ -2,14 +2,13 @@ // Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`. #import "MGLSource.h" -#import "MGLMapView_Private.h" #import "NSPredicate+MGLAdditions.h" #import "NSDate+MGLAdditions.h" #import "MGLStyleLayer_Private.h" #import "MGLStyleValue_Private.h" #import "MGLFillStyleLayer.h" -#include <mbgl/map/map.hpp> +#include <mbgl/style/transition_options.hpp> #include <mbgl/style/layers/fill_layer.hpp> namespace mbgl { @@ -23,23 +22,16 @@ namespace mbgl { @interface MGLFillStyleLayer () -@property (nonatomic) mbgl::style::FillLayer *rawLayer; +@property (nonatomic, readonly) mbgl::style::FillLayer *rawLayer; @end @implementation MGLFillStyleLayer -{ - std::unique_ptr<mbgl::style::FillLayer> _pendingLayer; -} - (instancetype)initWithIdentifier:(NSString *)identifier source:(MGLSource *)source { - if (self = [super initWithIdentifier:identifier source:source]) { - auto layer = std::make_unique<mbgl::style::FillLayer>(identifier.UTF8String, source.identifier.UTF8String); - _pendingLayer = std::move(layer); - self.rawLayer = _pendingLayer.get(); - } - return self; + auto layer = std::make_unique<mbgl::style::FillLayer>(identifier.UTF8String, source.identifier.UTF8String); + return self = [super initWithPendingLayer:std::move(layer)]; } - (mbgl::style::FillLayer *)rawLayer @@ -47,11 +39,6 @@ namespace mbgl { return (mbgl::style::FillLayer *)super.rawLayer; } -- (void)setRawLayer:(mbgl::style::FillLayer *)rawLayer -{ - super.rawLayer = rawLayer; -} - - (NSString *)sourceIdentifier { MGLAssertStyleLayerIsValid(); @@ -88,46 +75,6 @@ namespace mbgl { return [NSPredicate mgl_predicateWithFilter:self.rawLayer->getFilter()]; } -#pragma mark - Adding to and removing from a map view - -- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer -{ - if (_pendingLayer == nullptr) { - [NSException raise:@"MGLRedundantLayerException" - format:@"This instance %@ was already added to %@. Adding the same layer instance " \ - "to the style more than once is invalid.", self, mapView.style]; - } - - if (otherLayer) { - const mbgl::optional<std::string> belowLayerId{otherLayer.identifier.UTF8String}; - mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId); - } else { - mapView.mbglMap->addLayer(std::move(_pendingLayer)); - } -} - -- (void)removeFromMapView:(MGLMapView *)mapView -{ - if (self.rawLayer != mapView.mbglMap->getLayer(self.identifier.UTF8String)) { - return; - } - - auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String); - if (!removedLayer) { - return; - } - - mbgl::style::FillLayer *layer = dynamic_cast<mbgl::style::FillLayer *>(removedLayer.get()); - if (!layer) { - return; - } - - removedLayer.release(); - - _pendingLayer = std::unique_ptr<mbgl::style::FillLayer>(layer); - self.rawLayer = _pendingLayer.get(); -} - #pragma mark - Accessing the Paint Attributes - (void)setFillAntialiased:(MGLStyleValue<NSNumber *> *)fillAntialiased { diff --git a/platform/darwin/src/MGLForegroundStyleLayer.h b/platform/darwin/src/MGLForegroundStyleLayer.h index 87763f4634..16a973630e 100644 --- a/platform/darwin/src/MGLForegroundStyleLayer.h +++ b/platform/darwin/src/MGLForegroundStyleLayer.h @@ -20,23 +20,7 @@ MGL_EXPORT #pragma mark Initializing a Style Layer -- (instancetype)init __attribute__((unavailable("Use -initWithIdentifier:source: instead."))); -- (instancetype)initWithIdentifier:(NSString *)identifier __attribute__((unavailable("Use -initWithIdentifier:source: instead."))); - -/** - Returns a foreground style layer initialized with an identifier and source. - - After initializing and configuring the style layer, add it to a map view’s - style using the `-[MGLStyle addLayer:]` or - `-[MGLStyle insertLayer:belowLayer:]` method. - - @param identifier A string that uniquely identifies the source in the style to - which it is added. - @param source The source from which to obtain the data to style. If the source - has not yet been added to the current style, the behavior is undefined. - @return An initialized foreground style layer. - */ -- (instancetype)initWithIdentifier:(NSString *)identifier source:(MGLSource *)source NS_DESIGNATED_INITIALIZER; +- (instancetype)init __attribute__((unavailable("Use -init methods of concrete subclasses instead."))); #pragma mark Specifying a Style Layer’s Content diff --git a/platform/darwin/src/MGLForegroundStyleLayer.m b/platform/darwin/src/MGLForegroundStyleLayer.mm index b7a0379af2..6888f89b92 100644 --- a/platform/darwin/src/MGLForegroundStyleLayer.m +++ b/platform/darwin/src/MGLForegroundStyleLayer.mm @@ -1,13 +1,11 @@ #import "MGLForegroundStyleLayer.h" -#import "MGLSource.h" @implementation MGLForegroundStyleLayer -- (instancetype)initWithIdentifier:(NSString *)identifier source:(MGLSource *)source { - if (self = [super initWithIdentifier:identifier]) { - _sourceIdentifier = source.identifier; - } - return self; +- (NSString *)sourceIdentifier { + [NSException raise:@"MGLAbstractClassException" + format:@"MGLForegroundStyleLayer is an abstract class"]; + return nil; } - (NSString *)description { diff --git a/platform/darwin/src/MGLGeometry.mm b/platform/darwin/src/MGLGeometry.mm index 8c0c5f9cb7..1540a3a741 100644 --- a/platform/darwin/src/MGLGeometry.mm +++ b/platform/darwin/src/MGLGeometry.mm @@ -32,6 +32,15 @@ CGRect MGLExtendRect(CGRect rect, CGPoint point) { return rect; } +mbgl::LatLng MGLLatLngFromLocationCoordinate2D(CLLocationCoordinate2D coordinate) { + try { + return mbgl::LatLng(coordinate.latitude, coordinate.longitude); + } catch (std::domain_error &error) { + [NSException raise:NSInvalidArgumentException format:@"%s", error.what()]; + return {}; + } +} + MGL_EXPORT CLLocationDistance MGLAltitudeForZoomLevel(double zoomLevel, CGFloat pitch, CLLocationDegrees latitude, CGSize size) { CLLocationDistance metersPerPixel = mbgl::Projection::getMetersPerPixelAtLatitude(latitude, zoomLevel); diff --git a/platform/darwin/src/MGLGeometry_Private.h b/platform/darwin/src/MGLGeometry_Private.h index e6b37b3530..3e029e8ee0 100644 --- a/platform/darwin/src/MGLGeometry_Private.h +++ b/platform/darwin/src/MGLGeometry_Private.h @@ -12,16 +12,14 @@ /// the given point. CGRect MGLExtendRect(CGRect rect, CGPoint point); -NS_INLINE mbgl::LatLng MGLLatLngFromLocationCoordinate2D(CLLocationCoordinate2D coordinate) { - return mbgl::LatLng(coordinate.latitude, coordinate.longitude); -} +mbgl::LatLng MGLLatLngFromLocationCoordinate2D(CLLocationCoordinate2D coordinate); NS_INLINE mbgl::Point<double> MGLPointFromLocationCoordinate2D(CLLocationCoordinate2D coordinate) { return mbgl::Point<double>(coordinate.longitude, coordinate.latitude); } NS_INLINE CLLocationCoordinate2D MGLLocationCoordinate2DFromLatLng(mbgl::LatLng latLng) { - return CLLocationCoordinate2DMake(latLng.latitude, latLng.longitude); + return CLLocationCoordinate2DMake(latLng.latitude(), latLng.longitude()); } NS_INLINE MGLCoordinateBounds MGLCoordinateBoundsFromLatLngBounds(mbgl::LatLngBounds latLngBounds) { diff --git a/platform/darwin/src/MGLLineStyleLayer.h b/platform/darwin/src/MGLLineStyleLayer.h index e03f3e347e..38513652c5 100644 --- a/platform/darwin/src/MGLLineStyleLayer.h +++ b/platform/darwin/src/MGLLineStyleLayer.h @@ -107,6 +107,21 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslationAnchor) { MGL_EXPORT @interface MGLLineStyleLayer : MGLVectorStyleLayer +/** + Returns a line style layer initialized with an identifier and source. + + After initializing and configuring the style layer, add it to a map view’s + style using the `-[MGLStyle addLayer:]` or + `-[MGLStyle insertLayer:belowLayer:]` method. + + @param identifier A string that uniquely identifies the source in the style to + which it is added. + @param source The source from which to obtain the data to style. If the source + has not yet been added to the current style, the behavior is undefined. + @return An initialized foreground style layer. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier source:(MGLSource *)source; + #pragma mark - Accessing the Layout Attributes /** diff --git a/platform/darwin/src/MGLLineStyleLayer.mm b/platform/darwin/src/MGLLineStyleLayer.mm index e37489cf0b..8b90efd0c4 100644 --- a/platform/darwin/src/MGLLineStyleLayer.mm +++ b/platform/darwin/src/MGLLineStyleLayer.mm @@ -2,14 +2,13 @@ // Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`. #import "MGLSource.h" -#import "MGLMapView_Private.h" #import "NSPredicate+MGLAdditions.h" #import "NSDate+MGLAdditions.h" #import "MGLStyleLayer_Private.h" #import "MGLStyleValue_Private.h" #import "MGLLineStyleLayer.h" -#include <mbgl/map/map.hpp> +#include <mbgl/style/transition_options.hpp> #include <mbgl/style/layers/line_layer.hpp> namespace mbgl { @@ -35,23 +34,16 @@ namespace mbgl { @interface MGLLineStyleLayer () -@property (nonatomic) mbgl::style::LineLayer *rawLayer; +@property (nonatomic, readonly) mbgl::style::LineLayer *rawLayer; @end @implementation MGLLineStyleLayer -{ - std::unique_ptr<mbgl::style::LineLayer> _pendingLayer; -} - (instancetype)initWithIdentifier:(NSString *)identifier source:(MGLSource *)source { - if (self = [super initWithIdentifier:identifier source:source]) { - auto layer = std::make_unique<mbgl::style::LineLayer>(identifier.UTF8String, source.identifier.UTF8String); - _pendingLayer = std::move(layer); - self.rawLayer = _pendingLayer.get(); - } - return self; + auto layer = std::make_unique<mbgl::style::LineLayer>(identifier.UTF8String, source.identifier.UTF8String); + return self = [super initWithPendingLayer:std::move(layer)]; } - (mbgl::style::LineLayer *)rawLayer @@ -59,11 +51,6 @@ namespace mbgl { return (mbgl::style::LineLayer *)super.rawLayer; } -- (void)setRawLayer:(mbgl::style::LineLayer *)rawLayer -{ - super.rawLayer = rawLayer; -} - - (NSString *)sourceIdentifier { MGLAssertStyleLayerIsValid(); @@ -100,46 +87,6 @@ namespace mbgl { return [NSPredicate mgl_predicateWithFilter:self.rawLayer->getFilter()]; } -#pragma mark - Adding to and removing from a map view - -- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer -{ - if (_pendingLayer == nullptr) { - [NSException raise:@"MGLRedundantLayerException" - format:@"This instance %@ was already added to %@. Adding the same layer instance " \ - "to the style more than once is invalid.", self, mapView.style]; - } - - if (otherLayer) { - const mbgl::optional<std::string> belowLayerId{otherLayer.identifier.UTF8String}; - mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId); - } else { - mapView.mbglMap->addLayer(std::move(_pendingLayer)); - } -} - -- (void)removeFromMapView:(MGLMapView *)mapView -{ - if (self.rawLayer != mapView.mbglMap->getLayer(self.identifier.UTF8String)) { - return; - } - - auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String); - if (!removedLayer) { - return; - } - - mbgl::style::LineLayer *layer = dynamic_cast<mbgl::style::LineLayer *>(removedLayer.get()); - if (!layer) { - return; - } - - removedLayer.release(); - - _pendingLayer = std::unique_ptr<mbgl::style::LineLayer>(layer); - self.rawLayer = _pendingLayer.get(); -} - #pragma mark - Accessing the Layout Attributes - (void)setLineCap:(MGLStyleValue<NSValue *> *)lineCap { diff --git a/platform/darwin/src/MGLMapCamera.mm b/platform/darwin/src/MGLMapCamera.mm index 613124da66..1611dbf4a3 100644 --- a/platform/darwin/src/MGLMapCamera.mm +++ b/platform/darwin/src/MGLMapCamera.mm @@ -1,4 +1,5 @@ #import "MGLMapCamera.h" +#import "MGLGeometry_Private.h" #include <mbgl/util/projection.hpp> @@ -23,17 +24,21 @@ BOOL MGLEqualFloatWithAccuracy(CGFloat left, CGFloat right, CGFloat accuracy) fromEyeCoordinate:(CLLocationCoordinate2D)eyeCoordinate eyeAltitude:(CLLocationDistance)eyeAltitude { - mbgl::LatLng centerLatLng = mbgl::LatLng(centerCoordinate.latitude, centerCoordinate.longitude); - mbgl::LatLng eyeLatLng = mbgl::LatLng(eyeCoordinate.latitude, eyeCoordinate.longitude); - - mbgl::ProjectedMeters centerMeters = mbgl::Projection::projectedMetersForLatLng(centerLatLng); - mbgl::ProjectedMeters eyeMeters = mbgl::Projection::projectedMetersForLatLng(eyeLatLng); - CLLocationDirection heading = std::atan((centerMeters.northing - eyeMeters.northing) / - (centerMeters.easting - eyeMeters.easting)); - - double groundDistance = std::hypot(centerMeters.northing - eyeMeters.northing, - centerMeters.easting - eyeMeters.easting); - CGFloat pitch = std::atan(eyeAltitude / groundDistance); + CLLocationDirection heading = -1; + CGFloat pitch = -1; + if (CLLocationCoordinate2DIsValid(centerCoordinate) && CLLocationCoordinate2DIsValid(eyeCoordinate)) { + mbgl::LatLng centerLatLng = MGLLatLngFromLocationCoordinate2D(centerCoordinate); + mbgl::LatLng eyeLatLng = MGLLatLngFromLocationCoordinate2D(eyeCoordinate); + + mbgl::ProjectedMeters centerMeters = mbgl::Projection::projectedMetersForLatLng(centerLatLng); + mbgl::ProjectedMeters eyeMeters = mbgl::Projection::projectedMetersForLatLng(eyeLatLng); + heading = std::atan((centerMeters.northing() - eyeMeters.northing()) / + (centerMeters.easting() - eyeMeters.easting())); + + double groundDistance = std::hypot(centerMeters.northing() - eyeMeters.northing(), + centerMeters.easting() - eyeMeters.easting()); + pitch = std::atan(eyeAltitude / groundDistance); + } return [[self alloc] initWithCenterCoordinate:centerCoordinate altitude:eyeAltitude diff --git a/platform/darwin/src/MGLMultiPoint.h b/platform/darwin/src/MGLMultiPoint.h index ca08e5405a..429bbdb22d 100644 --- a/platform/darwin/src/MGLMultiPoint.h +++ b/platform/darwin/src/MGLMultiPoint.h @@ -58,8 +58,12 @@ MGL_EXPORT - (void)setCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count; /** - Inserts the given vertices into the shape. If the shape is currently visible on - the map, it is redrawn immediately. + Inserts the given vertices into the shape. + + If the shape is currently visible on the map as an annotation, it is redrawn + immediately. If the shape is part of an `MGLShapeSource` object, you must + explicitly set the `MGLShapeSource.shape` property in order for any style + layers that use the source to be redrawn. @param coords The array of coordinates to insert into the shape. The data in this array is copied to the shape’s `coordinates` property. @@ -70,8 +74,12 @@ MGL_EXPORT - (void)insertCoordinates:(const CLLocationCoordinate2D *)coords count:(NSUInteger)count atIndex:(NSUInteger)index; /** - Appends the given vertices to the shape. If the shape is currently visible on - the map, it is redrawn immediately. + Appends the given vertices to the shape. + + If the shape is currently visible on the map as an annotation, it is redrawn + immediately. If the shape is part of an `MGLShapeSource` object, you must + explicitly set the `MGLShapeSource.shape` property in order for any style + layers that use the source to be redrawn. @param coords The array of coordinates to add to the shape. The data in this array is copied to the shape’s `coordinates` property. @@ -81,8 +89,12 @@ MGL_EXPORT /** Replaces the vertices at the given range in the shape with the same number of - vertices from a given C array. If the shape is currently visible on the map, it - is redrawn immediately. + vertices from a given C array. + + If the shape is currently visible on the map as an annotation, it is redrawn + immediately. If the shape is part of an `MGLShapeSource` object, you must + explicitly set the `MGLShapeSource.shape` property in order for any style + layers that use the source to be redrawn. The number of coordinates in `coords` must be equal to the length of `range`. If you want to insert or delete one or more vertices, use the @@ -103,8 +115,12 @@ MGL_EXPORT /** Replaces the vertices at the given range in the shape with the specified number - of vertices from a given C array. If the shape is currently visible on the map, - it is redrawn immediately. + of vertices from a given C array. + + If the shape is currently visible on the map as an annotation, it is redrawn + immediately. If the shape is part of an `MGLShapeSource` object, you must + explicitly set the `MGLShapeSource.shape` property in order for any style + layers that use the source to be redrawn. If `count` is greater than the `length` field of `range`, some vertices will effectively be inserted into the shape. On the other hand, if `count` is less @@ -128,8 +144,12 @@ MGL_EXPORT - (void)replaceCoordinatesInRange:(NSRange)range withCoordinates:(const CLLocationCoordinate2D *)coords count:(NSUInteger)count; /** - Removes the vertices at the given range from the shape. If the shape is - currently visible on the map, it is redrawn immediately. + Removes the vertices at the given range from the shape. + + If the shape is currently visible on the map as an annotation, it is redrawn + immediately. If the shape is part of an `MGLShapeSource` object, you must + explicitly set the `MGLShapeSource.shape` property in order for any style + layers that use the source to be redrawn. If `range` extends beyond the shape’s `coordinates` property, an `NSRangeException` is raised. diff --git a/platform/darwin/src/MGLMultiPoint.mm b/platform/darwin/src/MGLMultiPoint.mm index 8e8c5be304..ef46bbb0fe 100644 --- a/platform/darwin/src/MGLMultiPoint.mm +++ b/platform/darwin/src/MGLMultiPoint.mm @@ -163,7 +163,11 @@ if (!_bounds) { mbgl::LatLngBounds bounds = mbgl::LatLngBounds::empty(); for (auto coordinate : _coordinates) { - bounds.extend(mbgl::LatLng(coordinate.latitude, coordinate.longitude)); + if (!CLLocationCoordinate2DIsValid(coordinate)) { + bounds = mbgl::LatLngBounds::empty(); + break; + } + bounds.extend(MGLLatLngFromLocationCoordinate2D(coordinate)); } _bounds = bounds; } diff --git a/platform/darwin/src/MGLOpenGLStyleLayer.h b/platform/darwin/src/MGLOpenGLStyleLayer.h index de4fc92b17..bdad5f9d07 100644 --- a/platform/darwin/src/MGLOpenGLStyleLayer.h +++ b/platform/darwin/src/MGLOpenGLStyleLayer.h @@ -23,6 +23,8 @@ MGL_EXPORT @property (nonatomic, weak, readonly) MGLMapView *mapView; +- (instancetype)initWithIdentifier:(NSString *)identifier; + - (void)didMoveToMapView:(MGLMapView *)mapView; - (void)willMoveFromMapView:(MGLMapView *)mapView; diff --git a/platform/darwin/src/MGLOpenGLStyleLayer.mm b/platform/darwin/src/MGLOpenGLStyleLayer.mm index da131b6de8..39eda758eb 100644 --- a/platform/darwin/src/MGLOpenGLStyleLayer.mm +++ b/platform/darwin/src/MGLOpenGLStyleLayer.mm @@ -72,7 +72,7 @@ void MGLFinishCustomStyleLayer(void *context) { */ @interface MGLOpenGLStyleLayer () -@property (nonatomic) mbgl::style::CustomLayer *rawLayer; +@property (nonatomic, readonly) mbgl::style::CustomLayer *rawLayer; /** The map view whose style currently contains the layer. @@ -84,9 +84,7 @@ void MGLFinishCustomStyleLayer(void *context) { @end -@implementation MGLOpenGLStyleLayer { - std::unique_ptr<mbgl::style::CustomLayer> _pendingLayer; -} +@implementation MGLOpenGLStyleLayer /** Returns an OpenGL style layer object initialized with the given identifier. @@ -100,26 +98,18 @@ void MGLFinishCustomStyleLayer(void *context) { @return An initialized OpenGL style layer. */ - (instancetype)initWithIdentifier:(NSString *)identifier { - if (self = [super initWithIdentifier:identifier]) { - auto layer = std::make_unique<mbgl::style::CustomLayer>(identifier.UTF8String, - MGLPrepareCustomStyleLayer, - MGLDrawCustomStyleLayer, - MGLFinishCustomStyleLayer, - (__bridge void *)self); - _pendingLayer = std::move(layer); - self.rawLayer = _pendingLayer.get(); - } - return self; + auto layer = std::make_unique<mbgl::style::CustomLayer>(identifier.UTF8String, + MGLPrepareCustomStyleLayer, + MGLDrawCustomStyleLayer, + MGLFinishCustomStyleLayer, + (__bridge void *)self); + return self = [super initWithPendingLayer:std::move(layer)]; } - (mbgl::style::CustomLayer *)rawLayer { return (mbgl::style::CustomLayer *)super.rawLayer; } -- (void)setRawLayer:(mbgl::style::CustomLayer *)rawLayer { - super.rawLayer = rawLayer; -} - #pragma mark - Adding to and removing from a map view - (void)setMapView:(MGLMapView *)mapView { @@ -134,22 +124,12 @@ void MGLFinishCustomStyleLayer(void *context) { - (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer { self.mapView = mapView; - if (otherLayer) { - const mbgl::optional<std::string> belowLayerId{ otherLayer.identifier.UTF8String }; - mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId); - } else { - mapView.mbglMap->addLayer(std::move(_pendingLayer)); - } + [super addToMapView:mapView belowLayer:otherLayer]; } - (void)removeFromMapView:(MGLMapView *)mapView { - auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String); + [super removeFromMapView:mapView]; self.mapView = nil; - if (!removedLayer) { - return; - } - _pendingLayer = std::move(reinterpret_cast<std::unique_ptr<mbgl::style::CustomLayer> &>(removedLayer)); - self.rawLayer = _pendingLayer.get(); } /** diff --git a/platform/darwin/src/MGLPointCollection.mm b/platform/darwin/src/MGLPointCollection.mm index ac4aaed60c..8f20d91a42 100644 --- a/platform/darwin/src/MGLPointCollection.mm +++ b/platform/darwin/src/MGLPointCollection.mm @@ -54,7 +54,11 @@ NS_ASSUME_NONNULL_BEGIN if (!_bounds) { mbgl::LatLngBounds bounds = mbgl::LatLngBounds::empty(); for (auto coordinate : _coordinates) { - bounds.extend(mbgl::LatLng(coordinate.latitude, coordinate.longitude)); + if (!CLLocationCoordinate2DIsValid(coordinate)) { + bounds = mbgl::LatLngBounds::empty(); + break; + } + bounds.extend(MGLLatLngFromLocationCoordinate2D(coordinate)); } _bounds = bounds; } @@ -119,8 +123,9 @@ NS_ASSUME_NONNULL_BEGIN - (NSString *)description { - return [NSString stringWithFormat:@"<%@: %p; count = %lu>", - NSStringFromClass([self class]), (void *)self, (unsigned long)[self pointCount]]; + return [NSString stringWithFormat:@"<%@: %p; count = %lu; bounds = %@>", + NSStringFromClass([self class]), (void *)self, (unsigned long)[self pointCount], + MGLStringFromCoordinateBounds(self.overlayBounds)]; } @end diff --git a/platform/darwin/src/MGLRasterSource.h b/platform/darwin/src/MGLRasterSource.h index 694a818246..519784f4f1 100644 --- a/platform/darwin/src/MGLRasterSource.h +++ b/platform/darwin/src/MGLRasterSource.h @@ -104,6 +104,109 @@ MGL_EXPORT */ - (instancetype)initWithIdentifier:(NSString *)identifier configurationURL:(NSURL *)configurationURL tileSize:(CGFloat)tileSize NS_DESIGNATED_INITIALIZER; +/** + Returns a raster source initialized an identifier, tile URL templates, and + options. + + After initializing and configuring the source, add it to a map view’s style + using the `-[MGLStyle addSource:]` method. + + #### Tile URL templates + + Tile URL templates are strings that specify the URLs of the tile images to + load. Each template resembles an absolute URL, but with any number of + placeholder strings that the source evaluates based on the tile it needs to + load. For example: + + <ul> + <li><code>http://www.example.com/tiles/{z}/{x}/{y}.pbf</code> could be + evaluated as <code>http://www.example.com/tiles/14/6/9.pbf</code>.</li> + <li><code>http://www.example.com/tiles/{z}/{x}/{y}{ratio}.png</code> could be + evaluated as <code>http://www.example.com/tiles/14/6/9@2x.png</code>.</li> + </ul> + + Tile sources support the following placeholder strings in tile URL templates, + all of which are optional: + + <table> + <thead> + <tr><th>Placeholder string</th><th>Description</th></tr> + </thead> + <tbody> + <tr> + <td><code>{x}</code></td> + <td>The index of the tile along the map’s x axis according to Spherical + Mercator projection. If the value is 0, the tile’s left edge corresponds + to the 180th meridian west. If the value is 2<sup><var>z</var></sup>−1, + the tile’s right edge corresponds to the 180th meridian east.</td> + </tr> + <tr> + <td><code>{y}</code></td> + <td>The index of the tile along the map’s y axis according to Spherical + Mercator projection. If the value is 0, the tile’s tile edge corresponds + to arctan(sinh(π)), or approximately 85.0511 degrees north. If the value + is 2<sup><var>z</var></sup>−1, the tile’s bottom edge corresponds to + −arctan(sinh(π)), or approximately 85.0511 degrees south. The y axis is + inverted if the <code>options</code> parameter contains + <code>MGLTileSourceOptionTileCoordinateSystem</code> with a value of + <code>MGLTileCoordinateSystemTMS</code>.</td> + </tr> + <tr> + <td><code>{z}</code></td> + <td>The tile’s zoom level. At zoom level 0, each tile covers the entire + world map; at zoom level 1, it covers ¼ of the world; at zoom level 2, + <sup>1</sup>⁄<sub>16</sub> of the world, and so on. For tiles loaded by + a <code>MGLRasterSource</code> object, whether the tile zoom level + matches the map’s current zoom level depends on the value of the + source’s tile size as specified in the + <code>MGLTileSourceOptionTileSize</code> key of the + <code>options</code> parameter.</td> + </tr> + <tr> + <td><code>{bbox-epsg-3857}</code></td> + <td>The tile’s bounding box, expressed as a comma-separated list of the + tile’s western, southern, eastern, and northern extents according to + Spherical Mercator (EPSG:3857) projection. The bounding box is typically + used with map services conforming to the + <a href="http://www.opengeospatial.org/standards/wms">Web Map Service</a> + protocol.</td> + </tr> + <tr> + <td><code>{quadkey}</code></td> + <td>A quadkey indicating both the tile’s location and its zoom level. The + quadkey is typically used with + <a href="https://msdn.microsoft.com/en-us/library/bb259689.aspx">Bing Maps</a>. + </td> + </tr> + <tr> + <td><code>{ratio}</code></td> + <td>A suffix indicating the resolution of the tile image. The suffix is the + empty string for standard resolution displays and <code>@2x</code> for + Retina displays, including displays for which + <code>NSScreen.backingScaleFactor</code> or <code>UIScreen.scale</code> + is 3.</td> + </tr> + <tr> + <td><code>{prefix}</code></td> + <td>Two hexadecimal digits chosen such that each visible tile has a + different prefix. The prefix is typically used for domain sharding.</td> + </tr> + </tbody> + </table> + + For more information about the `{x}`, `{y}`, and `{z}` placeholder strings, + consult the + <a href="https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames">OpenStreetMap Wiki</a>. + + @param identifier A string that uniquely identifies the source in the style to + which it is added. + @param tileURLTemplates An array of tile URL template strings. Only the first + string is used; any additional strings are ignored. + @param options A dictionary containing configuration options. See + `MGLTileSourceOption` for available keys and values. Pass in `nil` to use + the default values. + @return An initialized tile source. + */ - (instancetype)initWithIdentifier:(NSString *)identifier tileURLTemplates:(NS_ARRAY_OF(NSString *) *)tileURLTemplates options:(nullable NS_DICTIONARY_OF(MGLTileSourceOption, id) *)options NS_DESIGNATED_INITIALIZER; @end diff --git a/platform/darwin/src/MGLRasterSource.mm b/platform/darwin/src/MGLRasterSource.mm index c73a824ea8..8fc18ba69d 100644 --- a/platform/darwin/src/MGLRasterSource.mm +++ b/platform/darwin/src/MGLRasterSource.mm @@ -15,15 +15,11 @@ static const CGFloat MGLRasterSourceRetinaTileSize = 512; @interface MGLRasterSource () -- (instancetype)initWithRawSource:(mbgl::style::RasterSource *)rawSource NS_DESIGNATED_INITIALIZER; - -@property (nonatomic) mbgl::style::RasterSource *rawSource; +@property (nonatomic, readonly) mbgl::style::RasterSource *rawSource; @end -@implementation MGLRasterSource { - std::unique_ptr<mbgl::style::RasterSource> _pendingSource; -} +@implementation MGLRasterSource - (instancetype)initWithIdentifier:(NSString *)identifier configurationURL:(NSURL *)configurationURL { // The style specification default is 512, but 256 is the expected value for @@ -37,76 +33,32 @@ static const CGFloat MGLRasterSourceRetinaTileSize = 512; } - (instancetype)initWithIdentifier:(NSString *)identifier configurationURL:(NSURL *)configurationURL tileSize:(CGFloat)tileSize { - if (self = [super initWithIdentifier:identifier configurationURL:configurationURL]) { - auto source = std::make_unique<mbgl::style::RasterSource>(identifier.UTF8String, - configurationURL.mgl_URLByStandardizingScheme.absoluteString.UTF8String, - uint16_t(round(tileSize))); - _pendingSource = std::move(source); - self.rawSource = _pendingSource.get(); - } - return self; + auto source = std::make_unique<mbgl::style::RasterSource>(identifier.UTF8String, + configurationURL.mgl_URLByStandardizingScheme.absoluteString.UTF8String, + uint16_t(round(tileSize))); + return self = [super initWithPendingSource:std::move(source)]; } - (instancetype)initWithIdentifier:(NSString *)identifier tileURLTemplates:(NS_ARRAY_OF(NSString *) *)tileURLTemplates options:(nullable NS_DICTIONARY_OF(MGLTileSourceOption, id) *)options { - if (self = [super initWithIdentifier:identifier tileURLTemplates:tileURLTemplates options:options]) { - mbgl::Tileset tileSet = MGLTileSetFromTileURLTemplates(tileURLTemplates, options); - - uint16_t tileSize = MGLRasterSourceRetinaTileSize; - if (NSNumber *tileSizeNumber = options[MGLTileSourceOptionTileSize]) { - if (![tileSizeNumber isKindOfClass:[NSNumber class]]) { - [NSException raise:NSInvalidArgumentException - format:@"MGLTileSourceOptionTileSize must be set to an NSNumber."]; - } - tileSize = static_cast<uint16_t>(round(tileSizeNumber.doubleValue)); - } - - auto source = std::make_unique<mbgl::style::RasterSource>(identifier.UTF8String, tileSet, tileSize); - _pendingSource = std::move(source); - self.rawSource = _pendingSource.get(); - } - return self; -} - -- (instancetype)initWithRawSource:(mbgl::style::RasterSource *)rawSource { - return [super initWithRawSource:rawSource]; -} - -- (void)addToMapView:(MGLMapView *)mapView { - if (_pendingSource == nullptr) { - [NSException raise:@"MGLRedundantSourceException" - format:@"This instance %@ was already added to %@. Adding the same source instance " \ - @"to the style more than once is invalid.", self, mapView.style]; - } - - mapView.mbglMap->addSource(std::move(_pendingSource)); -} - -- (void)removeFromMapView:(MGLMapView *)mapView { - if (self.rawSource != mapView.mbglMap->getSource(self.identifier.UTF8String)) { - return; - } + mbgl::Tileset tileSet = MGLTileSetFromTileURLTemplates(tileURLTemplates, options); - auto removedSource = mapView.mbglMap->removeSource(self.identifier.UTF8String); - - mbgl::style::RasterSource *source = dynamic_cast<mbgl::style::RasterSource *>(removedSource.get()); - if (!source) { - return; + uint16_t tileSize = MGLRasterSourceRetinaTileSize; + if (NSNumber *tileSizeNumber = options[MGLTileSourceOptionTileSize]) { + if (![tileSizeNumber isKindOfClass:[NSNumber class]]) { + [NSException raise:NSInvalidArgumentException + format:@"MGLTileSourceOptionTileSize must be set to an NSNumber."]; + } + tileSize = static_cast<uint16_t>(round(tileSizeNumber.doubleValue)); } - removedSource.release(); - - _pendingSource = std::unique_ptr<mbgl::style::RasterSource>(source); - self.rawSource = _pendingSource.get(); + auto source = std::make_unique<mbgl::style::RasterSource>(identifier.UTF8String, tileSet, tileSize); + return self = [super initWithPendingSource:std::move(source)]; } - (mbgl::style::RasterSource *)rawSource { return (mbgl::style::RasterSource *)super.rawSource; } -- (void)setRawSource:(mbgl::style::RasterSource *)rawSource { - super.rawSource = rawSource; -} - - (NSURL *)configurationURL { auto url = self.rawSource->getURL(); return url ? [NSURL URLWithString:@(url->c_str())] : nil; diff --git a/platform/darwin/src/MGLRasterSource_Private.h b/platform/darwin/src/MGLRasterSource_Private.h index 47b1c13517..76790bd053 100644 --- a/platform/darwin/src/MGLRasterSource_Private.h +++ b/platform/darwin/src/MGLRasterSource_Private.h @@ -2,16 +2,7 @@ NS_ASSUME_NONNULL_BEGIN -namespace mbgl { - namespace style { - class RasterSource; - } -} - @interface MGLRasterSource (Private) - -- (instancetype)initWithRawSource:(mbgl::style::RasterSource *)rawSource; - @end NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLRasterStyleLayer.h b/platform/darwin/src/MGLRasterStyleLayer.h index 377b7f45cd..53a6a98b8a 100644 --- a/platform/darwin/src/MGLRasterStyleLayer.h +++ b/platform/darwin/src/MGLRasterStyleLayer.h @@ -36,6 +36,21 @@ NS_ASSUME_NONNULL_BEGIN MGL_EXPORT @interface MGLRasterStyleLayer : MGLForegroundStyleLayer +/** + Returns a raster style layer initialized with an identifier and source. + + After initializing and configuring the style layer, add it to a map view’s + style using the `-[MGLStyle addLayer:]` or + `-[MGLStyle insertLayer:belowLayer:]` method. + + @param identifier A string that uniquely identifies the source in the style to + which it is added. + @param source The source from which to obtain the data to style. If the source + has not yet been added to the current style, the behavior is undefined. + @return An initialized foreground style layer. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier source:(MGLSource *)source; + #pragma mark - Accessing the Paint Attributes /** diff --git a/platform/darwin/src/MGLRasterStyleLayer.mm b/platform/darwin/src/MGLRasterStyleLayer.mm index 80508e4e70..c63fd23529 100644 --- a/platform/darwin/src/MGLRasterStyleLayer.mm +++ b/platform/darwin/src/MGLRasterStyleLayer.mm @@ -2,35 +2,27 @@ // Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`. #import "MGLSource.h" -#import "MGLMapView_Private.h" #import "NSPredicate+MGLAdditions.h" #import "NSDate+MGLAdditions.h" #import "MGLStyleLayer_Private.h" #import "MGLStyleValue_Private.h" #import "MGLRasterStyleLayer.h" -#include <mbgl/map/map.hpp> +#include <mbgl/style/transition_options.hpp> #include <mbgl/style/layers/raster_layer.hpp> @interface MGLRasterStyleLayer () -@property (nonatomic) mbgl::style::RasterLayer *rawLayer; +@property (nonatomic, readonly) mbgl::style::RasterLayer *rawLayer; @end @implementation MGLRasterStyleLayer -{ - std::unique_ptr<mbgl::style::RasterLayer> _pendingLayer; -} - (instancetype)initWithIdentifier:(NSString *)identifier source:(MGLSource *)source { - if (self = [super initWithIdentifier:identifier source:source]) { - auto layer = std::make_unique<mbgl::style::RasterLayer>(identifier.UTF8String, source.identifier.UTF8String); - _pendingLayer = std::move(layer); - self.rawLayer = _pendingLayer.get(); - } - return self; + auto layer = std::make_unique<mbgl::style::RasterLayer>(identifier.UTF8String, source.identifier.UTF8String); + return self = [super initWithPendingLayer:std::move(layer)]; } - (mbgl::style::RasterLayer *)rawLayer @@ -38,11 +30,6 @@ return (mbgl::style::RasterLayer *)super.rawLayer; } -- (void)setRawLayer:(mbgl::style::RasterLayer *)rawLayer -{ - super.rawLayer = rawLayer; -} - - (NSString *)sourceIdentifier { MGLAssertStyleLayerIsValid(); @@ -50,46 +37,6 @@ return @(self.rawLayer->getSourceID().c_str()); } -#pragma mark - Adding to and removing from a map view - -- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer -{ - if (_pendingLayer == nullptr) { - [NSException raise:@"MGLRedundantLayerException" - format:@"This instance %@ was already added to %@. Adding the same layer instance " \ - "to the style more than once is invalid.", self, mapView.style]; - } - - if (otherLayer) { - const mbgl::optional<std::string> belowLayerId{otherLayer.identifier.UTF8String}; - mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId); - } else { - mapView.mbglMap->addLayer(std::move(_pendingLayer)); - } -} - -- (void)removeFromMapView:(MGLMapView *)mapView -{ - if (self.rawLayer != mapView.mbglMap->getLayer(self.identifier.UTF8String)) { - return; - } - - auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String); - if (!removedLayer) { - return; - } - - mbgl::style::RasterLayer *layer = dynamic_cast<mbgl::style::RasterLayer *>(removedLayer.get()); - if (!layer) { - return; - } - - removedLayer.release(); - - _pendingLayer = std::unique_ptr<mbgl::style::RasterLayer>(layer); - self.rawLayer = _pendingLayer.get(); -} - #pragma mark - Accessing the Paint Attributes - (void)setMaximumRasterBrightness:(MGLStyleValue<NSNumber *> *)maximumRasterBrightness { diff --git a/platform/darwin/src/MGLShapeSource.mm b/platform/darwin/src/MGLShapeSource.mm index 7de2d69af3..023a81bba8 100644 --- a/platform/darwin/src/MGLShapeSource.mm +++ b/platform/darwin/src/MGLShapeSource.mm @@ -20,38 +20,26 @@ const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance = @"MGLSh @interface MGLShapeSource () -- (instancetype)initWithRawSource:(mbgl::style::GeoJSONSource *)rawSource NS_DESIGNATED_INITIALIZER; - @property (nonatomic, readwrite) NSDictionary *options; -@property (nonatomic) mbgl::style::GeoJSONSource *rawSource; +@property (nonatomic, readonly) mbgl::style::GeoJSONSource *rawSource; @end -@implementation MGLShapeSource { - std::unique_ptr<mbgl::style::GeoJSONSource> _pendingSource; -} +@implementation MGLShapeSource - (instancetype)initWithIdentifier:(NSString *)identifier URL:(NSURL *)url options:(NS_DICTIONARY_OF(NSString *, id) *)options { - if (self = [super initWithIdentifier:identifier]) { - auto geoJSONOptions = MGLGeoJSONOptionsFromDictionary(options); - auto source = std::make_unique<mbgl::style::GeoJSONSource>(identifier.UTF8String, geoJSONOptions); - - _pendingSource = std::move(source); - self.rawSource = _pendingSource.get(); - + auto geoJSONOptions = MGLGeoJSONOptionsFromDictionary(options); + auto source = std::make_unique<mbgl::style::GeoJSONSource>(identifier.UTF8String, geoJSONOptions); + if (self = [super initWithPendingSource:std::move(source)]) { self.URL = url; } return self; } - (instancetype)initWithIdentifier:(NSString *)identifier shape:(nullable MGLShape *)shape options:(NS_DICTIONARY_OF(MGLShapeSourceOption, id) *)options { - if (self = [super initWithIdentifier:identifier]) { - auto geoJSONOptions = MGLGeoJSONOptionsFromDictionary(options); - auto source = std::make_unique<mbgl::style::GeoJSONSource>(identifier.UTF8String, geoJSONOptions); - - _pendingSource = std::move(source); - self.rawSource = _pendingSource.get(); - + auto geoJSONOptions = MGLGeoJSONOptionsFromDictionary(options); + auto source = std::make_unique<mbgl::style::GeoJSONSource>(identifier.UTF8String, geoJSONOptions); + if (self = [super initWithPendingSource:std::move(source)]) { self.shape = shape; } return self; @@ -72,46 +60,10 @@ const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance = @"MGLSh return [self initWithIdentifier:identifier shape:shapeCollection options:options]; } -- (instancetype)initWithRawSource:(mbgl::style::GeoJSONSource *)rawSource { - return [super initWithRawSource:rawSource]; -} - -- (void)addToMapView:(MGLMapView *)mapView { - if (_pendingSource == nullptr) { - [NSException raise:@"MGLRedundantSourceException" - format:@"This instance %@ was already added to %@. Adding the same source instance " \ - "to the style more than once is invalid.", self, mapView.style]; - } - - mapView.mbglMap->addSource(std::move(_pendingSource)); -} - -- (void)removeFromMapView:(MGLMapView *)mapView { - if (self.rawSource != mapView.mbglMap->getSource(self.identifier.UTF8String)) { - return; - } - - auto removedSource = mapView.mbglMap->removeSource(self.identifier.UTF8String); - - mbgl::style::GeoJSONSource *source = dynamic_cast<mbgl::style::GeoJSONSource *>(removedSource.get()); - if (!source) { - return; - } - - removedSource.release(); - - _pendingSource = std::unique_ptr<mbgl::style::GeoJSONSource>(source); - self.rawSource = _pendingSource.get(); -} - - (mbgl::style::GeoJSONSource *)rawSource { return (mbgl::style::GeoJSONSource *)super.rawSource; } -- (void)setRawSource:(mbgl::style::GeoJSONSource *)rawSource { - super.rawSource = rawSource; -} - - (NSURL *)URL { auto url = self.rawSource->getURL(); return url ? [NSURL URLWithString:@(url->c_str())] : nil; @@ -143,7 +95,10 @@ const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance = @"MGLSh optionalFilter = predicate.mgl_filter; } - std::vector<mbgl::Feature> features = self.rawSource->querySourceFeatures({ {}, optionalFilter }); + std::vector<mbgl::Feature> features; + if (self.mapView) { + features = self.mapView.mbglMap->querySourceFeatures(self.rawSource->getID(), { {}, optionalFilter }); + } return MGLFeaturesFromMBGLFeatures(features); } diff --git a/platform/darwin/src/MGLShapeSource_Private.h b/platform/darwin/src/MGLShapeSource_Private.h index c14f4fbb59..84eb5deed4 100644 --- a/platform/darwin/src/MGLShapeSource_Private.h +++ b/platform/darwin/src/MGLShapeSource_Private.h @@ -6,14 +6,10 @@ NS_ASSUME_NONNULL_BEGIN namespace mbgl { namespace style { class GeoJSONOptions; - struct GeoJSONSource; } } @interface MGLShapeSource (Private) - -- (instancetype)initWithRawSource:(mbgl::style::GeoJSONSource *)rawSource; - @end MGL_EXPORT diff --git a/platform/darwin/src/MGLSource.mm b/platform/darwin/src/MGLSource.mm index c96b6c41c6..eb859ba2c0 100644 --- a/platform/darwin/src/MGLSource.mm +++ b/platform/darwin/src/MGLSource.mm @@ -1,16 +1,23 @@ #import "MGLSource_Private.h" +#import "MGLMapView_Private.h" +#include <mbgl/map/map.hpp> #include <mbgl/style/source.hpp> @interface MGLSource () // Even though this class is abstract, MGLStyle uses it to represent some // special internal source types like mbgl::AnnotationSource. -@property (nonatomic) mbgl::style::Source *rawSource; +@property (nonatomic, readonly) mbgl::style::Source *rawSource; + +@property (nonatomic, readonly, weak) MGLMapView *mapView; @end -@implementation MGLSource +@implementation MGLSource { + std::unique_ptr<mbgl::style::Source> _pendingSource; +} + - (instancetype)initWithIdentifier:(NSString *)identifier { @@ -24,22 +31,34 @@ NSString *identifier = @(rawSource->getID().c_str()); if (self = [self initWithIdentifier:identifier]) { _rawSource = rawSource; + _rawSource->peer = SourceWrapper { self }; + } + return self; +} + +- (instancetype)initWithPendingSource:(std::unique_ptr<mbgl::style::Source>)pendingSource { + if (self = [self initWithRawSource:pendingSource.get()]) { + _pendingSource = std::move(pendingSource); } return self; } - (void)addToMapView:(MGLMapView *)mapView { - [NSException raise:NSInvalidArgumentException format: - @"The source %@ cannot be added to the style. " - @"Make sure the source was created as a member of a concrete subclass of MGLSource.", - self]; + if (_pendingSource == nullptr) { + [NSException raise:@"MGLRedundantSourceException" + format:@"This instance %@ was already added to %@. Adding the same source instance " \ + "to the style more than once is invalid.", self, mapView.style]; + } + + _mapView = mapView; + mapView.mbglMap->addSource(std::move(_pendingSource)); } - (void)removeFromMapView:(MGLMapView *)mapView { - [NSException raise:NSInvalidArgumentException format: - @"The source %@ cannot be removed from the style. " - @"Make sure the source was created as a member of a concrete subclass of MGLSource.", - self]; + if (self.rawSource == mapView.mbglMap->getSource(self.identifier.UTF8String)) { + _pendingSource = mapView.mbglMap->removeSource(self.identifier.UTF8String); + _mapView = nil; + } } - (NSString *)description { diff --git a/platform/darwin/src/MGLSource_Private.h b/platform/darwin/src/MGLSource_Private.h index acb325e2f3..91bfac6390 100644 --- a/platform/darwin/src/MGLSource_Private.h +++ b/platform/darwin/src/MGLSource_Private.h @@ -1,5 +1,7 @@ #import "MGLSource.h" +#include <memory> + NS_ASSUME_NONNULL_BEGIN namespace mbgl { @@ -8,23 +10,46 @@ namespace mbgl { } } +// A struct to be stored in the `peer` member of mbgl::style::Source, in order to implement +// object identity. We don't store a MGLSource pointer directly because that doesn't +// interoperate with ARC. The inner pointer is weak in order to avoid a reference cycle for +// "pending" MGLSources, which have a strong owning pointer to the mbgl::style::Source. +struct SourceWrapper { + __weak MGLSource *source; +}; + @class MGLMapView; @interface MGLSource (Private) /** - Initializes and returns a source with a raw pointer to the backing store. + Initializes and returns a source with a raw pointer to the backing store, + associated with a style. */ - (instancetype)initWithRawSource:(mbgl::style::Source *)rawSource; /** + Initializes and returns a source with an owning pointer to the backing store, + unassociated from a style. + */ +- (instancetype)initWithPendingSource:(std::unique_ptr<mbgl::style::Source>)pendingSource; + +/** A raw pointer to the mbgl object, which is always initialized, either to the value returned by `mbgl::Map getSource`, or for independently created objects, to the pointer value held in `pendingSource`. In the latter case, this raw pointer value stays even after ownership of the object is transferred via `mbgl::Map addSource`. */ -@property (nonatomic) mbgl::style::Source *rawSource; +@property (nonatomic, readonly) mbgl::style::Source *rawSource; + +/** + The map view whose style currently contains the source. + + If the source is not currently part of any map view’s style, this property is + set to `nil`. + */ +@property (nonatomic, readonly, weak) MGLMapView *mapView; /** Adds the mbgl source that this object represents to the mbgl map. diff --git a/platform/darwin/src/MGLStyle.h b/platform/darwin/src/MGLStyle.h index bd17fdec44..ccec863236 100644 --- a/platform/darwin/src/MGLStyle.h +++ b/platform/darwin/src/MGLStyle.h @@ -10,9 +10,9 @@ NS_ASSUME_NONNULL_BEGIN /** - A version number identifying the default version of the suite of default styles - provided by Mapbox. This version number may be passed into one of the - “StyleURLWithVersion” class methods of MGLStyle. + A version number identifying the default version of the Mapbox Streets style + obtained through the `-streetsStyleURL` method. This version number may also be + passed into the `-streetsStyleURLWithVersion:` method. The value of this constant generally corresponds to the latest released version as of the date on which this SDK was published. You can use this constant to @@ -28,7 +28,7 @@ NS_ASSUME_NONNULL_BEGIN the constant itself. Such details may change significantly from version to version. */ -static MGL_EXPORT const NSInteger MGLStyleDefaultVersion = 9; +static MGL_EXPORT const NSInteger MGLStyleDefaultVersion = 10; /** The proxy object for the current map style. @@ -52,15 +52,22 @@ MGL_EXPORT #pragma mark Accessing Default Styles /** - Returns the URL to version 8 of the - <a href="https://www.mapbox.com/maps/streets/">Mapbox Streets</a> style. + Returns the URL to the current version of the + <a href="https://www.mapbox.com/maps/streets/">Mapbox Streets</a> style as of + publication. Streets is a general-purpose style with detailed road and transit networks. `MGLMapView` and `MGLTilePyramidOfflineRegion` use Mapbox Streets when no style is specified explicitly. + + @warning The return value may change in a future release of the SDK. If you use + any feature that depends on a specific aspect of a default style – for + instance, the minimum zoom level that includes roads – use the + `-streetsStyleURLWithVersion:` method instead. Such details may change + significantly from version to version. */ -+ (NSURL *)streetsStyleURL __attribute__((deprecated("Use -streetsStyleURLWithVersion:."))); ++ (NSURL *)streetsStyleURL; /** Returns the URL to the given version of the @@ -71,8 +78,7 @@ MGL_EXPORT `MGLMapView` and `MGLTilePyramidOfflineRegion` use Mapbox Streets when no style is specified explicitly. - @param version The style’s latest released version. As of publication, the - current version is `9`. + @param version A specific version of the style. */ + (NSURL *)streetsStyleURLWithVersion:(NSInteger)version; @@ -85,70 +91,102 @@ MGL_EXPORT + (NSURL *)emeraldStyleURL __attribute__((deprecated("Create an NSURL object with the string “mapbox://styles/mapbox/emerald-v8”."))); /** + Returns the URL to the current version of the + <a href="https://www.mapbox.com/maps/outdoors/">Mapbox Outdoors</a> style as of + publication. + + Outdoors is a general-purpose style tailored to outdoor activities. + + @warning The return value may change in a future release of the SDK. If you use + any feature that depends on a specific aspect of a default style – for + instance, the minimum zoom level that includes roads – use the + `-outdoorsStyleURLWithVersion:` method instead. Such details may change + significantly from version to version. + */ ++ (NSURL *)outdoorsStyleURL; + +/** Returns the URL to the given version of the <a href="https://www.mapbox.com/maps/outdoors/">Mapbox Outdoors</a> style. Outdoors is a general-purpose style tailored to outdoor activities. - @param version The style’s latest released version. As of publication, the - current version is `9`. + @param version A specific version of the style. */ + (NSURL *)outdoorsStyleURLWithVersion:(NSInteger)version; /** - Returns the URL to version 8 of the + Returns the URL to the current version of the <a href="https://www.mapbox.com/maps/light-dark/">Mapbox Light</a> style. Light is a subtle, light-colored backdrop for data visualizations. + + @warning The return value may change in a future release of the SDK. If you use + any feature that depends on a specific aspect of a default style – for + instance, the minimum zoom level that includes roads – use the + `-lightStyleURLWithVersion:` method instead. Such details may change + significantly from version to version. */ -+ (NSURL *)lightStyleURL __attribute__((deprecated("Use -lightStyleURLWithVersion:."))); ++ (NSURL *)lightStyleURL; /** Returns the URL to the given version of the - <a href="https://www.mapbox.com/maps/light-dark/">Mapbox Light</a> style. + <a href="https://www.mapbox.com/maps/light-dark/">Mapbox Light</a> style as of + publication. Light is a subtle, light-colored backdrop for data visualizations. - @param version The style’s latest released version. As of publication, the - current version is `9`. + @param version A specific version of the style. */ + (NSURL *)lightStyleURLWithVersion:(NSInteger)version; /** - Returns the URL to version 8 of the + Returns the URL to the current version of the <a href="https://www.mapbox.com/maps/light-dark/">Mapbox Dark</a> style. Dark is a subtle, dark-colored backdrop for data visualizations. + + @warning The return value may change in a future release of the SDK. If you use + any feature that depends on a specific aspect of a default style – for + instance, the minimum zoom level that includes roads – use the + `-darkStyleURLWithVersion:` method instead. Such details may change + significantly from version to version. */ -+ (NSURL *)darkStyleURL __attribute__((deprecated("Use -darkStyleURLWithVersion:."))); ++ (NSURL *)darkStyleURL; /** Returns the URL to the given version of the - <a href="https://www.mapbox.com/maps/light-dark/">Mapbox Dark</a> style. + <a href="https://www.mapbox.com/maps/light-dark/">Mapbox Dark</a> style as of + publication. Dark is a subtle, dark-colored backdrop for data visualizations. - @param version The style’s latest released version. As of publication, the - current version is `9`. + @param version A specific version of the style. */ + (NSURL *)darkStyleURLWithVersion:(NSInteger)version; /** - Returns the URL to version 8 of the + Returns the URL to the current version of the <a href="https://www.mapbox.com/maps/satellite/">Mapbox Satellite</a> style. Satellite is high-resolution satellite and aerial imagery. + + @warning The return value may change in a future release of the SDK. If you use + any feature that depends on a specific aspect of a default style – for + instance, the raster tile sets included in the style – use the + `-satelliteStyleURLWithVersion:` method instead. Such details may change + significantly from version to version. */ -+ (NSURL *)satelliteStyleURL __attribute__((deprecated("Use -satelliteStyleURLWithVersion:."))); ++ (NSURL *)satelliteStyleURL; /** Returns the URL to the given version of the - <a href="https://www.mapbox.com/maps/satellite/">Mapbox Satellite</a> style. + <a href="https://www.mapbox.com/maps/satellite/">Mapbox Satellite</a> style as + of publication. Satellite is high-resolution satellite and aerial imagery. - @param version The style’s latest released version. As of publication, the - current version is `9`. + @param version A specific version of the style. */ + (NSURL *)satelliteStyleURLWithVersion:(NSInteger)version; @@ -161,7 +199,24 @@ MGL_EXPORT Mapbox Satellite with unobtrusive labels and translucent roads from Mapbox Streets. */ -+ (NSURL *)hybridStyleURL __attribute__((deprecated("Use -satelliteStreetsStyleURLWithVersion:."))); ++ (NSURL *)hybridStyleURL __attribute__((deprecated("Use -satelliteStreetsStyleURL."))); + +/** + Returns the URL to the current version of the + <a href="https://www.mapbox.com/maps/satellite/">Mapbox Satellite Streets</a> + style as of publication. + + Satellite Streets combines the high-resolution satellite and aerial imagery of + Mapbox Satellite with unobtrusive labels and translucent roads from Mapbox + Streets. + + @warning The return value may change in a future release of the SDK. If you use + any feature that depends on a specific aspect of a default style – for + instance, the minimum zoom level that includes roads – use the + `-satelliteStreetsStyleURLWithVersion:` method instead. Such details may + change significantly from version to version. + */ ++ (NSURL *)satelliteStreetsStyleURL; /** Returns the URL to the given version of the @@ -172,11 +227,72 @@ MGL_EXPORT Mapbox Satellite with unobtrusive labels and translucent roads from Mapbox Streets. - @param version The style’s latest released version. As of publication, the - current version is `9`. + @param version A specific version of the style. */ + (NSURL *)satelliteStreetsStyleURLWithVersion:(NSInteger)version; +/** + Returns the URL to the current version of the + <a href="https://www.mapbox.com/blog/live-traffic-maps/">Mapbox Traffic Day</a> + style. + + Traffic Day color-codes roads based on live traffic congestion data. Traffic + data is currently available in + <a href="https://www.mapbox.com/api-documentation/pages/traffic-countries.html">these select countries</a>. + + @warning The return value may change in a future release of the SDK. If you use + any feature that depends on a specific aspect of a default style – for + instance, the minimum zoom level that includes roads – use the + `-trafficDayStyleURLWithVersion:` method instead. Such details may change + significantly from version to version. + */ ++ (NSURL *)trafficDayStyleURL; + +/** + Returns the URL to the given version of the + <a href="https://www.mapbox.com/blog/live-traffic-maps/">Mapbox Traffic Day</a> + style as of publication. + + Traffic Day color-codes roads based on live traffic congestion data. Traffic + data is currently available in + <a href="https://www.mapbox.com/api-documentation/pages/traffic-countries.html">these select countries</a>. + + @param version A specific version of the style. + */ ++ (NSURL *)trafficDayStyleURLWithVersion:(NSInteger)version; + +/** + Returns the URL to the current version of the + <a href="https://www.mapbox.com/blog/live-traffic-maps/">Mapbox Traffic Night</a> + style. + + Traffic Night color-codes roads based on live traffic congestion data and is + designed to maximize legibility in low-light situations. Traffic data is + currently available in + <a href="https://www.mapbox.com/api-documentation/pages/traffic-countries.html">these select countries</a>. + + @warning The return value may change in a future release of the SDK. If you use + any feature that depends on a specific aspect of a default style – for + instance, the minimum zoom level that includes roads – use the + `-trafficNightStyleURLWithVersion:` method instead. Such details may change + significantly from version to version. + */ ++ (NSURL *)trafficNightStyleURL; + +/** + Returns the URL to the given version of the + <a href="https://www.mapbox.com/blog/live-traffic-maps/">Mapbox Traffic Night</a> + style as of publication. + + Traffic Night color-codes roads based on live traffic congestion data and is + designed to maximize legibility in low-light situations. Traffic data is + currently available in + <a href="https://www.mapbox.com/api-documentation/pages/traffic-countries.html">these select countries</a>. + + @param version A specific version of the style. + */ ++ (NSURL *)trafficNightStyleURLWithVersion:(NSInteger)version; + #pragma mark Accessing Metadata About the Style /** @@ -367,40 +483,24 @@ MGL_EXPORT #pragma mark Managing Style Classes /** - Currently active style classes, represented as an array of string identifiers. + Support for style classes has been removed. This property always returns an empty array. */ -@property (nonatomic) NS_ARRAY_OF(NSString *) *styleClasses __attribute__((deprecated("This property will be removed in a future release."))); +@property (nonatomic) NS_ARRAY_OF(NSString *) *styleClasses __attribute__((deprecated("This property is non-functional."))); /** - Returns a Boolean value indicating whether the style class with the given - identifier is currently active. - - @param styleClass The style class to query for. - @return Whether the style class is currently active. + Support for style classes has been removed. This method always returns NO. */ -- (BOOL)hasStyleClass:(NSString *)styleClass __attribute__((deprecated("This method will be removed in a future release."))); +- (BOOL)hasStyleClass:(NSString *)styleClass __attribute__((deprecated("This method is non-functional."))); /** - Activates the style class with the given identifier. - - @param styleClass The style class to activate. + Support for style classes has been removed. This method is a no-op. */ -- (void)addStyleClass:(NSString *)styleClass __attribute__((deprecated("This method will be removed in a future release."))); +- (void)addStyleClass:(NSString *)styleClass __attribute__((deprecated("This method is non-functional."))); /** - Deactivates the style class with the given identifier. - - @note Style class names are not guaranteed to exist across styles or different - versions of the same style. Applications that use this API must first set the - style URL to an explicitly versioned style using a convenience method like - `+[MGLStyle outdoorsStyleURLWithVersion:]`, `MGLMapView`’s “Style URL” - inspectable in Interface Builder, or a manually constructed `NSURL`. This - approach also avoids style class name changes that will occur in the default - style over time. - - @param styleClass The style class to deactivate. + Support for style classes has been removed. This method is a no-op. */ -- (void)removeStyleClass:(NSString *)styleClass __attribute__((deprecated("This method will be removed in a future release."))); +- (void)removeStyleClass:(NSString *)styleClass __attribute__((deprecated("This method is non-functional."))); #pragma mark Managing a Style’s Images diff --git a/platform/darwin/src/MGLStyle.mm b/platform/darwin/src/MGLStyle.mm index aa493d9ef7..5f26b4fed2 100644 --- a/platform/darwin/src/MGLStyle.mm +++ b/platform/darwin/src/MGLStyle.mm @@ -3,6 +3,7 @@ #import "MGLMapView_Private.h" #import "MGLStyleLayer.h" #import "MGLFillStyleLayer.h" +#import "MGLFillExtrusionStyleLayer.h" #import "MGLLineStyleLayer.h" #import "MGLCircleStyleLayer.h" #import "MGLSymbolStyleLayer.h" @@ -26,8 +27,9 @@ #include <mbgl/map/map.hpp> #include <mbgl/util/default_styles.hpp> -#include <mbgl/sprite/sprite_image.hpp> +#include <mbgl/style/image.hpp> #include <mbgl/style/layers/fill_layer.hpp> +#include <mbgl/style/layers/fill_extrusion_layer.hpp> #include <mbgl/style/layers/line_layer.hpp> #include <mbgl/style/layers/symbol_layer.hpp> #include <mbgl/style/layers/raster_layer.hpp> @@ -56,8 +58,6 @@ #pragma mark Default style URLs -static_assert(mbgl::util::default_styles::currentVersion == MGLStyleDefaultVersion, "mbgl::util::default_styles::currentVersion and MGLStyleDefaultVersion disagree."); - /// @param name The style’s marketing name, written in lower camelCase. /// @param fileName The last path component in the style’s URL, excluding the version suffix. #define MGL_DEFINE_STYLE(name, fileName) \ @@ -65,17 +65,13 @@ static_assert(mbgl::util::default_styles::currentVersion == MGLStyleDefaultVersi + (NSURL *)name##StyleURL { \ static dispatch_once_t onceToken; \ dispatch_once(&onceToken, ^{ \ - MGLStyleURL_##name = [self name##StyleURLWithVersion:8]; \ + MGLStyleURL_##name = [self name##StyleURLWithVersion:mbgl::util::default_styles::name.currentVersion]; \ }); \ return MGLStyleURL_##name; \ } \ \ + (NSURL *)name##StyleURL##WithVersion:(NSInteger)version { \ - if (mbgl::util::default_styles::currentVersion == version) { \ - return [NSURL URLWithString:@(mbgl::util::default_styles::name.url)]; \ - } else { \ - return [NSURL URLWithString:[@"mapbox://styles/mapbox/" #fileName "-v" stringByAppendingFormat:@"%li", (long)version]]; \ - } \ + return [NSURL URLWithString:[@"mapbox://styles/mapbox/" #fileName "-v" stringByAppendingFormat:@"%li", (long)version]]; \ } MGL_DEFINE_STYLE(streets, streets) @@ -84,10 +80,12 @@ MGL_DEFINE_STYLE(light, light) MGL_DEFINE_STYLE(dark, dark) MGL_DEFINE_STYLE(satellite, satellite) MGL_DEFINE_STYLE(satelliteStreets, satellite-streets) +MGL_DEFINE_STYLE(trafficDay, traffic-day) +MGL_DEFINE_STYLE(trafficNight, traffic-night) // Make sure all the styles listed in mbgl::util::default_styles::orderedStyles // are defined above and also declared in MGLStyle.h. -static_assert(6 == mbgl::util::default_styles::numOrderedStyles, +static_assert(8 == mbgl::util::default_styles::numOrderedStyles, "mbgl::util::default_styles::orderedStyles and MGLStyle have different numbers of styles."); // Hybrid has been renamed Satellite Streets, so the last Hybrid version is hard-coded here. @@ -165,17 +163,21 @@ static NSURL *MGLStyleURL_emerald; return rawSource ? [self sourceFromMBGLSource:rawSource] : nil; } -- (MGLSource *)sourceFromMBGLSource:(mbgl::style::Source *)source { +- (MGLSource *)sourceFromMBGLSource:(mbgl::style::Source *)rawSource { + if (MGLSource *source = rawSource->peer.empty() ? nil : mbgl::any_cast<SourceWrapper>(rawSource->peer).source) { + return source; + } + // TODO: Fill in options specific to the respective source classes // https://github.com/mapbox/mapbox-gl-native/issues/6584 - if (auto vectorSource = source->as<mbgl::style::VectorSource>()) { + if (auto vectorSource = rawSource->as<mbgl::style::VectorSource>()) { return [[MGLVectorSource alloc] initWithRawSource:vectorSource]; - } else if (auto geoJSONSource = source->as<mbgl::style::GeoJSONSource>()) { + } else if (auto geoJSONSource = rawSource->as<mbgl::style::GeoJSONSource>()) { return [[MGLShapeSource alloc] initWithRawSource:geoJSONSource]; - } else if (auto rasterSource = source->as<mbgl::style::RasterSource>()) { + } else if (auto rasterSource = rawSource->as<mbgl::style::RasterSource>()) { return [[MGLRasterSource alloc] initWithRawSource:rasterSource]; } else { - return [[MGLSource alloc] initWithRawSource:source]; + return [[MGLSource alloc] initWithRawSource:rawSource]; } } @@ -318,44 +320,34 @@ static NSURL *MGLStyleURL_emerald; [styleLayer removeFromMapView:self.mapView]; } -- (MGLStyleLayer *)layerFromMBGLLayer:(mbgl::style::Layer *)mbglLayer +- (MGLStyleLayer *)layerFromMBGLLayer:(mbgl::style::Layer *)rawLayer { - NSParameterAssert(mbglLayer); - - NSString *identifier = @(mbglLayer->getID().c_str()); - MGLStyleLayer *styleLayer; - if (auto fillLayer = mbglLayer->as<mbgl::style::FillLayer>()) { - MGLSource *source = [self sourceWithIdentifier:@(fillLayer->getSourceID().c_str())]; - styleLayer = [[MGLFillStyleLayer alloc] initWithIdentifier:identifier source:source]; - } else if (auto lineLayer = mbglLayer->as<mbgl::style::LineLayer>()) { - MGLSource *source = [self sourceWithIdentifier:@(lineLayer->getSourceID().c_str())]; - styleLayer = [[MGLLineStyleLayer alloc] initWithIdentifier:identifier source:source]; - } else if (auto symbolLayer = mbglLayer->as<mbgl::style::SymbolLayer>()) { - MGLSource *source = [self sourceWithIdentifier:@(symbolLayer->getSourceID().c_str())]; - styleLayer = [[MGLSymbolStyleLayer alloc] initWithIdentifier:identifier source:source]; - } else if (auto rasterLayer = mbglLayer->as<mbgl::style::RasterLayer>()) { - MGLSource *source = [self sourceWithIdentifier:@(rasterLayer->getSourceID().c_str())]; - styleLayer = [[MGLRasterStyleLayer alloc] initWithIdentifier:identifier source:source]; - } else if (auto circleLayer = mbglLayer->as<mbgl::style::CircleLayer>()) { - MGLSource *source = [self sourceWithIdentifier:@(circleLayer->getSourceID().c_str())]; - styleLayer = [[MGLCircleStyleLayer alloc] initWithIdentifier:identifier source:source]; - } else if (mbglLayer->is<mbgl::style::BackgroundLayer>()) { - styleLayer = [[MGLBackgroundStyleLayer alloc] initWithIdentifier:identifier]; - } else if (mbglLayer->is<mbgl::style::CustomLayer>()) { - styleLayer = self.openGLLayers[identifier]; - if (styleLayer) { - NSAssert(styleLayer.rawLayer == mbglLayer->as<mbgl::style::CustomLayer>(), @"%@ wraps a CustomLayer that differs from the one associated with the underlying style.", styleLayer); - return styleLayer; - } - styleLayer = [[MGLOpenGLStyleLayer alloc] initWithIdentifier:identifier]; + NSParameterAssert(rawLayer); + + if (MGLStyleLayer *layer = rawLayer->peer.empty() ? nil : mbgl::any_cast<LayerWrapper>(rawLayer->peer).layer) { + return layer; + } + + if (auto fillLayer = rawLayer->as<mbgl::style::FillLayer>()) { + return [[MGLFillStyleLayer alloc] initWithRawLayer:fillLayer]; + } else if (auto fillExtrusionLayer = rawLayer->as<mbgl::style::FillExtrusionLayer>()) { + return [[MGLFillExtrusionStyleLayer alloc] initWithRawLayer:fillExtrusionLayer]; + } else if (auto lineLayer = rawLayer->as<mbgl::style::LineLayer>()) { + return [[MGLLineStyleLayer alloc] initWithRawLayer:lineLayer]; + } else if (auto symbolLayer = rawLayer->as<mbgl::style::SymbolLayer>()) { + return [[MGLSymbolStyleLayer alloc] initWithRawLayer:symbolLayer]; + } else if (auto rasterLayer = rawLayer->as<mbgl::style::RasterLayer>()) { + return [[MGLRasterStyleLayer alloc] initWithRawLayer:rasterLayer]; + } else if (auto circleLayer = rawLayer->as<mbgl::style::CircleLayer>()) { + return [[MGLCircleStyleLayer alloc] initWithRawLayer:circleLayer]; + } else if (auto backgroundLayer = rawLayer->as<mbgl::style::BackgroundLayer>()) { + return [[MGLBackgroundStyleLayer alloc] initWithRawLayer:backgroundLayer]; + } else if (auto customLayer = rawLayer->as<mbgl::style::CustomLayer>()) { + return [[MGLOpenGLStyleLayer alloc] initWithRawLayer:customLayer]; } else { NSAssert(NO, @"Unrecognized layer type"); return nil; } - - styleLayer.rawLayer = mbglLayer; - - return styleLayer; } - (MGLStyleLayer *)layerWithIdentifier:(NSString *)identifier @@ -477,60 +469,32 @@ static NSURL *MGLStyleURL_emerald; - (NS_ARRAY_OF(NSString *) *)styleClasses { - const std::vector<std::string> &appliedClasses = self.mapView.mbglMap->getClasses(); - - NSMutableArray *returnArray = [NSMutableArray arrayWithCapacity:appliedClasses.size()]; - - for (auto appliedClass : appliedClasses) { - [returnArray addObject:@(appliedClass.c_str())]; - } - - return returnArray; + return @[]; } - (void)setStyleClasses:(NS_ARRAY_OF(NSString *) *)appliedClasses { - [self setStyleClasses:appliedClasses transitionDuration:0]; } - (void)setStyleClasses:(NS_ARRAY_OF(NSString *) *)appliedClasses transitionDuration:(NSTimeInterval)transitionDuration { - std::vector<std::string> newAppliedClasses; - - for (NSString *appliedClass in appliedClasses) - { - newAppliedClasses.push_back([appliedClass UTF8String]); - } - - mbgl::style::TransitionOptions transition { { MGLDurationFromTimeInterval(transitionDuration) } }; - self.mapView.mbglMap->setTransitionOptions(transition); - self.mapView.mbglMap->setClasses(newAppliedClasses); } - (NSUInteger)countOfStyleClasses { - const auto &classes = self.mapView.mbglMap->getClasses(); - return classes.size(); + return 0; } - (BOOL)hasStyleClass:(NSString *)styleClass { - return styleClass && self.mapView.mbglMap->hasClass([styleClass UTF8String]); + return NO; } - (void)addStyleClass:(NSString *)styleClass { - if (styleClass) - { - self.mapView.mbglMap->addClass([styleClass UTF8String]); - } } - (void)removeStyleClass:(NSString *)styleClass { - if (styleClass) - { - self.mapView.mbglMap->removeClass([styleClass UTF8String]); - } } #pragma mark Style images @@ -546,7 +510,7 @@ static NSURL *MGLStyleURL_emerald; format:@"Cannot assign image %@ to a nil name.", image]; } - self.mapView.mbglMap->addImage([name UTF8String], image.mgl_spriteImage); + self.mapView.mbglMap->addImage([image mgl_styleImageWithIdentifier:name]); } - (void)removeImageForName:(NSString *)name @@ -566,8 +530,8 @@ static NSURL *MGLStyleURL_emerald; format:@"Cannot get image with nil name."]; } - auto spriteImage = self.mapView.mbglMap->getImage([name UTF8String]); - return spriteImage ? [[MGLImage alloc] initWithMGLSpriteImage:spriteImage] : nil; + auto styleImage = self.mapView.mbglMap->getImage([name UTF8String]); + return styleImage ? [[MGLImage alloc] initWithMGLStyleImage:styleImage] : nil; } #pragma mark Style transitions diff --git a/platform/darwin/src/MGLStyleLayer.h b/platform/darwin/src/MGLStyleLayer.h index ac9b739c74..7d181667d6 100644 --- a/platform/darwin/src/MGLStyleLayer.h +++ b/platform/darwin/src/MGLStyleLayer.h @@ -27,25 +27,7 @@ MGL_EXPORT #pragma mark Initializing a Style Layer -- (instancetype)init __attribute__((unavailable("Use -initWithIdentifier: instead."))); - -/** - Returns a style layer object initialized with the given identifier. - - The default implementation of this initializer in MGLStyleLayer creates an - invalid style layer. Call this initializer on `MGLBackgroundStyleLayer` or one of - the concrete subclasses of `MGLForegroundStyleLayer` to create a valid style - layer. - - After initializing and configuring the style layer, add it to a map view’s - style using the `-[MGLStyle addLayer:]` or - `-[MGLStyle insertLayer:belowLayer:]` method. - - @param identifier A string that uniquely identifies the layer in the style to - which it is added. - @return An initialized style layer. - */ -- (instancetype)initWithIdentifier:(NSString *)identifier; +- (instancetype)init __attribute__((unavailable("Use -init methods of concrete subclasses instead."))); #pragma mark Identifying a Style Layer diff --git a/platform/darwin/src/MGLStyleLayer.h.ejs b/platform/darwin/src/MGLStyleLayer.h.ejs index e6c60a76db..df42621c6d 100644 --- a/platform/darwin/src/MGLStyleLayer.h.ejs +++ b/platform/darwin/src/MGLStyleLayer.h.ejs @@ -84,7 +84,33 @@ MGL_EXPORT %>StyleLayer <% if (type === 'background') { -%> -- (instancetype)initWithIdentifier:(NSString *)identifier NS_DESIGNATED_INITIALIZER; +/** +Returns a <%- type %> style layer initialized with an identifier. + +After initializing and configuring the style layer, add it to a map view’s +style using the `-[MGLStyle addLayer:]` or +`-[MGLStyle insertLayer:belowLayer:]` method. + +@param identifier A string that uniquely identifies the source in the style to +which it is added. +*/ +- (instancetype)initWithIdentifier:(NSString *)identifier; +<% } else { -%> + +/** + Returns a <%- type %> style layer initialized with an identifier and source. + + After initializing and configuring the style layer, add it to a map view’s + style using the `-[MGLStyle addLayer:]` or + `-[MGLStyle insertLayer:belowLayer:]` method. + + @param identifier A string that uniquely identifies the source in the style to + which it is added. + @param source The source from which to obtain the data to style. If the source + has not yet been added to the current style, the behavior is undefined. + @return An initialized foreground style layer. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier source:(MGLSource *)source; <% } -%> <% if (layoutProperties.length) { -%> @@ -135,7 +161,7 @@ MGL_EXPORT */ @interface NSValue (MGL<%- camelize(type) %>StyleLayerAdditions) -#pragma mark Working with <%- camelize(type) %> Style Layer Attribute Values +#pragma mark Working with <%- camelize(unhyphenate(type)) %> Style Layer Attribute Values <% for (let property of enumProperties) { -%> /** diff --git a/platform/darwin/src/MGLStyleLayer.mm b/platform/darwin/src/MGLStyleLayer.mm index 47f41e0388..4bfaea934b 100644 --- a/platform/darwin/src/MGLStyleLayer.mm +++ b/platform/darwin/src/MGLStyleLayer.mm @@ -1,24 +1,58 @@ #import "MGLStyleLayer_Private.h" #import "MGLMapView_Private.h" +#include <mbgl/map/map.hpp> #include <mbgl/style/layer.hpp> @interface MGLStyleLayer () -@property (nonatomic) mbgl::style::Layer *rawLayer; +@property (nonatomic, readonly) mbgl::style::Layer *rawLayer; @end -@implementation MGLStyleLayer +@implementation MGLStyleLayer { + std::unique_ptr<mbgl::style::Layer> _pendingLayer; +} -- (instancetype)initWithIdentifier:(NSString *)identifier -{ +- (instancetype)initWithRawLayer:(mbgl::style::Layer *)rawLayer { if (self = [super init]) { - _identifier = identifier; + _identifier = @(rawLayer->getID().c_str()); + _rawLayer = rawLayer; + _rawLayer->peer = LayerWrapper { self }; + } + return self; +} + +- (instancetype)initWithPendingLayer:(std::unique_ptr<mbgl::style::Layer>)pendingLayer { + if (self = [self initWithRawLayer:pendingLayer.get()]) { + _pendingLayer = std::move(pendingLayer); } return self; } +- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer +{ + if (_pendingLayer == nullptr) { + [NSException raise:@"MGLRedundantLayerException" + format:@"This instance %@ was already added to %@. Adding the same layer instance " \ + "to the style more than once is invalid.", self, mapView.style]; + } + + if (otherLayer) { + const mbgl::optional<std::string> belowLayerId{otherLayer.identifier.UTF8String}; + mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId); + } else { + mapView.mbglMap->addLayer(std::move(_pendingLayer)); + } +} + +- (void)removeFromMapView:(MGLMapView *)mapView +{ + if (self.rawLayer == mapView.mbglMap->getLayer(self.identifier.UTF8String)) { + _pendingLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String); + } +} + - (void)setVisible:(BOOL)visible { MGLAssertStyleLayerIsValid(); diff --git a/platform/darwin/src/MGLStyleLayer.mm.ejs b/platform/darwin/src/MGLStyleLayer.mm.ejs index 1e5f3df160..da67cbd633 100644 --- a/platform/darwin/src/MGLStyleLayer.mm.ejs +++ b/platform/darwin/src/MGLStyleLayer.mm.ejs @@ -8,14 +8,13 @@ // Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`. #import "MGLSource.h" -#import "MGLMapView_Private.h" #import "NSPredicate+MGLAdditions.h" #import "NSDate+MGLAdditions.h" #import "MGLStyleLayer_Private.h" #import "MGLStyleValue_Private.h" #import "MGL<%- camelize(type) %>StyleLayer.h" -#include <mbgl/map/map.hpp> +#include <mbgl/style/transition_options.hpp> #include <mbgl/style/layers/<%- type.replace('-', '_') %>_layer.hpp> <% if (enumProperties) { -%> @@ -50,35 +49,24 @@ namespace mbgl { @interface MGL<%- camelize(type) %>StyleLayer () -@property (nonatomic) mbgl::style::<%- camelize(type) %>Layer *rawLayer; +@property (nonatomic, readonly) mbgl::style::<%- camelize(type) %>Layer *rawLayer; @end @implementation MGL<%- camelize(type) %>StyleLayer -{ - std::unique_ptr<mbgl::style::<%- camelize(type) %>Layer> _pendingLayer; -} <% if (type == 'background') { -%> - (instancetype)initWithIdentifier:(NSString *)identifier { - if (self = [super initWithIdentifier:identifier]) { - auto layer = std::make_unique<mbgl::style::<%- camelize(type) %>Layer>(identifier.UTF8String); - _pendingLayer = std::move(layer); - self.rawLayer = _pendingLayer.get(); - } - return self; + auto layer = std::make_unique<mbgl::style::<%- camelize(type) %>Layer>(identifier.UTF8String); + return self = [super initWithPendingLayer:std::move(layer)]; } <% } else { -%> - (instancetype)initWithIdentifier:(NSString *)identifier source:(MGLSource *)source { - if (self = [super initWithIdentifier:identifier source:source]) { - auto layer = std::make_unique<mbgl::style::<%- camelize(type) %>Layer>(identifier.UTF8String, source.identifier.UTF8String); - _pendingLayer = std::move(layer); - self.rawLayer = _pendingLayer.get(); - } - return self; + auto layer = std::make_unique<mbgl::style::<%- camelize(type) %>Layer>(identifier.UTF8String, source.identifier.UTF8String); + return self = [super initWithPendingLayer:std::move(layer)]; } <% } -%> @@ -87,11 +75,6 @@ namespace mbgl { return (mbgl::style::<%- camelize(type) %>Layer *)super.rawLayer; } -- (void)setRawLayer:(mbgl::style::<%- camelize(type) %>Layer *)rawLayer -{ - super.rawLayer = rawLayer; -} - <% if (type !== 'background') { -%> - (NSString *)sourceIdentifier { @@ -131,46 +114,6 @@ namespace mbgl { } <% }} -%> -#pragma mark - Adding to and removing from a map view - -- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer -{ - if (_pendingLayer == nullptr) { - [NSException raise:@"MGLRedundantLayerException" - format:@"This instance %@ was already added to %@. Adding the same layer instance " \ - "to the style more than once is invalid.", self, mapView.style]; - } - - if (otherLayer) { - const mbgl::optional<std::string> belowLayerId{otherLayer.identifier.UTF8String}; - mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId); - } else { - mapView.mbglMap->addLayer(std::move(_pendingLayer)); - } -} - -- (void)removeFromMapView:(MGLMapView *)mapView -{ - if (self.rawLayer != mapView.mbglMap->getLayer(self.identifier.UTF8String)) { - return; - } - - auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String); - if (!removedLayer) { - return; - } - - mbgl::style::<%- camelize(type) %>Layer *layer = dynamic_cast<mbgl::style::<%- camelize(type) %>Layer *>(removedLayer.get()); - if (!layer) { - return; - } - - removedLayer.release(); - - _pendingLayer = std::unique_ptr<mbgl::style::<%- camelize(type) %>Layer>(layer); - self.rawLayer = _pendingLayer.get(); -} - <% if (layoutProperties.length) { -%> #pragma mark - Accessing the Layout Attributes diff --git a/platform/darwin/src/MGLStyleLayer_Private.h b/platform/darwin/src/MGLStyleLayer_Private.h index b5d709a7af..ed8ec31755 100644 --- a/platform/darwin/src/MGLStyleLayer_Private.h +++ b/platform/darwin/src/MGLStyleLayer_Private.h @@ -7,6 +7,14 @@ NS_ASSUME_NONNULL_BEGIN +// A struct to be stored in the `peer` member of mbgl::style::Layer, in order to implement +// object identity. We don't store a MGLStyleLayer pointer directly because that doesn't +// interoperate with ARC. The inner pointer is weak in order to avoid a reference cycle for +// "pending" MGLStyleLayers, which have a strong owning pointer to the mbgl::style::Layer. +struct LayerWrapper { + __weak MGLStyleLayer *layer; +}; + /** Assert that the style layer is valid. @@ -30,6 +38,18 @@ NS_ASSUME_NONNULL_BEGIN @interface MGLStyleLayer (Private) +/** + Initializes and returns a layer with a raw pointer to the backing store, + associated with a style. + */ +- (instancetype)initWithRawLayer:(mbgl::style::Layer *)rawLayer; + +/** + Initializes and returns a layer with an owning pointer to the backing store, + unassociated from a style. + */ +- (instancetype)initWithPendingLayer:(std::unique_ptr<mbgl::style::Layer>)pendingLayer; + @property (nonatomic, readwrite, copy) NSString *identifier; /** @@ -39,7 +59,7 @@ NS_ASSUME_NONNULL_BEGIN pointer value stays even after ownership of the object is transferred via `mbgl::Map addLayer`. */ -@property (nonatomic) mbgl::style::Layer *rawLayer; +@property (nonatomic, readonly) mbgl::style::Layer *rawLayer; /** Adds the mbgl style layer that this object represents to the mbgl map below the diff --git a/platform/darwin/src/MGLStyleValue_Private.h b/platform/darwin/src/MGLStyleValue_Private.h index 90d6622c93..263b54d7e5 100644 --- a/platform/darwin/src/MGLStyleValue_Private.h +++ b/platform/darwin/src/MGLStyleValue_Private.h @@ -123,8 +123,9 @@ public: return toMBGLConstantValue((MGLConstantStyleValue<ObjCType> *)value); } else if ([value isKindOfClass:[MGLStyleFunction class]]) { auto rawValue = toRawStyleSpecValue((MGLStyleFunction<ObjCType> *) value); - auto result = mbgl::style::conversion::convert<mbgl::style::DataDrivenPropertyValue<MBGLType>>(rawValue); - NSCAssert(result, @(result.error().message.c_str())); + mbgl::style::conversion::Error error; + auto result = mbgl::style::conversion::convert<mbgl::style::DataDrivenPropertyValue<MBGLType>>(rawValue, error); + NSCAssert(result, @(error.message.c_str())); return *result; } else { return {}; diff --git a/platform/darwin/src/MGLSymbolStyleLayer.h b/platform/darwin/src/MGLSymbolStyleLayer.h index c76efe2de7..b6c6372324 100644 --- a/platform/darwin/src/MGLSymbolStyleLayer.h +++ b/platform/darwin/src/MGLSymbolStyleLayer.h @@ -280,6 +280,21 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) { MGL_EXPORT @interface MGLSymbolStyleLayer : MGLVectorStyleLayer +/** + Returns a symbol style layer initialized with an identifier and source. + + After initializing and configuring the style layer, add it to a map view’s + style using the `-[MGLStyle addLayer:]` or + `-[MGLStyle insertLayer:belowLayer:]` method. + + @param identifier A string that uniquely identifies the source in the style to + which it is added. + @param source The source from which to obtain the data to style. If the source + has not yet been added to the current style, the behavior is undefined. + @return An initialized foreground style layer. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier source:(MGLSource *)source; + #pragma mark - Accessing the Layout Attributes /** @@ -344,8 +359,18 @@ MGL_EXPORT You can set this property to an instance of: * `MGLConstantStyleValue` - * `MGLCameraStyleFunction` with an interpolation mode of - `MGLInterpolationModeInterval` + * `MGLCameraStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLSourceStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLInterpolationModeCategorical` + * `MGLInterpolationModeIdentity` + * `MGLCompositeStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLInterpolationModeCategorical` */ @property (nonatomic, null_resettable) MGLStyleValue<NSString *> *iconImageName; @@ -527,6 +552,15 @@ MGL_EXPORT * `MGLCameraStyleFunction` with an interpolation mode of: * `MGLInterpolationModeExponential` * `MGLInterpolationModeInterval` + * `MGLSourceStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLInterpolationModeCategorical` + * `MGLInterpolationModeIdentity` + * `MGLCompositeStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLInterpolationModeCategorical` */ @property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *iconScale; @@ -909,6 +943,15 @@ MGL_EXPORT * `MGLCameraStyleFunction` with an interpolation mode of: * `MGLInterpolationModeExponential` * `MGLInterpolationModeInterval` + * `MGLSourceStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLInterpolationModeCategorical` + * `MGLInterpolationModeIdentity` + * `MGLCompositeStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLInterpolationModeCategorical` */ @property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textFontSize; @@ -1026,6 +1069,15 @@ MGL_EXPORT * `MGLCameraStyleFunction` with an interpolation mode of: * `MGLInterpolationModeExponential` * `MGLInterpolationModeInterval` + * `MGLSourceStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLInterpolationModeCategorical` + * `MGLInterpolationModeIdentity` + * `MGLCompositeStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLInterpolationModeCategorical` */ @property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *textOffset; #else @@ -1047,6 +1099,15 @@ MGL_EXPORT * `MGLCameraStyleFunction` with an interpolation mode of: * `MGLInterpolationModeExponential` * `MGLInterpolationModeInterval` + * `MGLSourceStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLInterpolationModeCategorical` + * `MGLInterpolationModeIdentity` + * `MGLCompositeStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLInterpolationModeCategorical` */ @property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *textOffset; #endif @@ -1132,6 +1193,15 @@ MGL_EXPORT * `MGLCameraStyleFunction` with an interpolation mode of: * `MGLInterpolationModeExponential` * `MGLInterpolationModeInterval` + * `MGLSourceStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLInterpolationModeCategorical` + * `MGLInterpolationModeIdentity` + * `MGLCompositeStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + * `MGLInterpolationModeCategorical` */ @property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textRotation; diff --git a/platform/darwin/src/MGLSymbolStyleLayer.mm b/platform/darwin/src/MGLSymbolStyleLayer.mm index 8441931685..5a8f8c6084 100644 --- a/platform/darwin/src/MGLSymbolStyleLayer.mm +++ b/platform/darwin/src/MGLSymbolStyleLayer.mm @@ -2,14 +2,13 @@ // Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`. #import "MGLSource.h" -#import "MGLMapView_Private.h" #import "NSPredicate+MGLAdditions.h" #import "NSDate+MGLAdditions.h" #import "MGLStyleLayer_Private.h" #import "MGLStyleValue_Private.h" #import "MGLSymbolStyleLayer.h" -#include <mbgl/map/map.hpp> +#include <mbgl/style/transition_options.hpp> #include <mbgl/style/layers/symbol_layer.hpp> namespace mbgl { @@ -82,23 +81,16 @@ namespace mbgl { @interface MGLSymbolStyleLayer () -@property (nonatomic) mbgl::style::SymbolLayer *rawLayer; +@property (nonatomic, readonly) mbgl::style::SymbolLayer *rawLayer; @end @implementation MGLSymbolStyleLayer -{ - std::unique_ptr<mbgl::style::SymbolLayer> _pendingLayer; -} - (instancetype)initWithIdentifier:(NSString *)identifier source:(MGLSource *)source { - if (self = [super initWithIdentifier:identifier source:source]) { - auto layer = std::make_unique<mbgl::style::SymbolLayer>(identifier.UTF8String, source.identifier.UTF8String); - _pendingLayer = std::move(layer); - self.rawLayer = _pendingLayer.get(); - } - return self; + auto layer = std::make_unique<mbgl::style::SymbolLayer>(identifier.UTF8String, source.identifier.UTF8String); + return self = [super initWithPendingLayer:std::move(layer)]; } - (mbgl::style::SymbolLayer *)rawLayer @@ -106,11 +98,6 @@ namespace mbgl { return (mbgl::style::SymbolLayer *)super.rawLayer; } -- (void)setRawLayer:(mbgl::style::SymbolLayer *)rawLayer -{ - super.rawLayer = rawLayer; -} - - (NSString *)sourceIdentifier { MGLAssertStyleLayerIsValid(); @@ -147,46 +134,6 @@ namespace mbgl { return [NSPredicate mgl_predicateWithFilter:self.rawLayer->getFilter()]; } -#pragma mark - Adding to and removing from a map view - -- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer -{ - if (_pendingLayer == nullptr) { - [NSException raise:@"MGLRedundantLayerException" - format:@"This instance %@ was already added to %@. Adding the same layer instance " \ - "to the style more than once is invalid.", self, mapView.style]; - } - - if (otherLayer) { - const mbgl::optional<std::string> belowLayerId{otherLayer.identifier.UTF8String}; - mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId); - } else { - mapView.mbglMap->addLayer(std::move(_pendingLayer)); - } -} - -- (void)removeFromMapView:(MGLMapView *)mapView -{ - if (self.rawLayer != mapView.mbglMap->getLayer(self.identifier.UTF8String)) { - return; - } - - auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String); - if (!removedLayer) { - return; - } - - mbgl::style::SymbolLayer *layer = dynamic_cast<mbgl::style::SymbolLayer *>(removedLayer.get()); - if (!layer) { - return; - } - - removedLayer.release(); - - _pendingLayer = std::unique_ptr<mbgl::style::SymbolLayer>(layer); - self.rawLayer = _pendingLayer.get(); -} - #pragma mark - Accessing the Layout Attributes - (void)setIconAllowsOverlap:(MGLStyleValue<NSNumber *> *)iconAllowsOverlap { @@ -240,7 +187,7 @@ namespace mbgl { - (void)setIconImageName:(MGLStyleValue<NSString *> *)iconImageName { MGLAssertStyleLayerIsValid(); - auto mbglValue = MGLStyleValueTransformer<std::string, NSString *>().toPropertyValue(iconImageName); + auto mbglValue = MGLStyleValueTransformer<std::string, NSString *>().toDataDrivenPropertyValue(iconImageName); self.rawLayer->setIconImage(mbglValue); } @@ -249,9 +196,9 @@ namespace mbgl { auto propertyValue = self.rawLayer->getIconImage(); if (propertyValue.isUndefined()) { - return MGLStyleValueTransformer<std::string, NSString *>().toStyleValue(self.rawLayer->getDefaultIconImage()); + return MGLStyleValueTransformer<std::string, NSString *>().toDataDrivenStyleValue(self.rawLayer->getDefaultIconImage()); } - return MGLStyleValueTransformer<std::string, NSString *>().toStyleValue(propertyValue); + return MGLStyleValueTransformer<std::string, NSString *>().toDataDrivenStyleValue(propertyValue); } - (void)setIconImage:(MGLStyleValue<NSString *> *)iconImage { @@ -356,7 +303,7 @@ namespace mbgl { - (void)setIconScale:(MGLStyleValue<NSNumber *> *)iconScale { MGLAssertStyleLayerIsValid(); - auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(iconScale); + auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenPropertyValue(iconScale); self.rawLayer->setIconSize(mbglValue); } @@ -365,9 +312,9 @@ namespace mbgl { auto propertyValue = self.rawLayer->getIconSize(); if (propertyValue.isUndefined()) { - return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultIconSize()); + return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(self.rawLayer->getDefaultIconSize()); } - return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue); + return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(propertyValue); } - (void)setIconSize:(MGLStyleValue<NSNumber *> *)iconSize { @@ -657,7 +604,7 @@ namespace mbgl { - (void)setTextFontSize:(MGLStyleValue<NSNumber *> *)textFontSize { MGLAssertStyleLayerIsValid(); - auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(textFontSize); + auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenPropertyValue(textFontSize); self.rawLayer->setTextSize(mbglValue); } @@ -666,9 +613,9 @@ namespace mbgl { auto propertyValue = self.rawLayer->getTextSize(); if (propertyValue.isUndefined()) { - return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultTextSize()); + return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(self.rawLayer->getDefaultTextSize()); } - return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue); + return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(propertyValue); } - (void)setTextSize:(MGLStyleValue<NSNumber *> *)textSize { @@ -763,7 +710,7 @@ namespace mbgl { - (void)setTextOffset:(MGLStyleValue<NSValue *> *)textOffset { MGLAssertStyleLayerIsValid(); - auto mbglValue = MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toInterpolatablePropertyValue(textOffset); + auto mbglValue = MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toDataDrivenPropertyValue(textOffset); self.rawLayer->setTextOffset(mbglValue); } @@ -772,9 +719,9 @@ namespace mbgl { auto propertyValue = self.rawLayer->getTextOffset(); if (propertyValue.isUndefined()) { - return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toStyleValue(self.rawLayer->getDefaultTextOffset()); + return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toDataDrivenStyleValue(self.rawLayer->getDefaultTextOffset()); } - return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toStyleValue(propertyValue); + return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toDataDrivenStyleValue(propertyValue); } - (void)setTextOptional:(MGLStyleValue<NSNumber *> *)textOptional { @@ -831,7 +778,7 @@ namespace mbgl { - (void)setTextRotation:(MGLStyleValue<NSNumber *> *)textRotation { MGLAssertStyleLayerIsValid(); - auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(textRotation); + auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenPropertyValue(textRotation); self.rawLayer->setTextRotate(mbglValue); } @@ -840,9 +787,9 @@ namespace mbgl { auto propertyValue = self.rawLayer->getTextRotate(); if (propertyValue.isUndefined()) { - return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultTextRotate()); + return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(self.rawLayer->getDefaultTextRotate()); } - return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue); + return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(propertyValue); } - (void)setTextRotate:(MGLStyleValue<NSNumber *> *)textRotate { diff --git a/platform/darwin/src/MGLTileSource.h b/platform/darwin/src/MGLTileSource.h index 54c756332d..538b94037e 100644 --- a/platform/darwin/src/MGLTileSource.h +++ b/platform/darwin/src/MGLTileSource.h @@ -147,135 +147,6 @@ typedef NS_ENUM(NSUInteger, MGLTileCoordinateSystem) { MGL_EXPORT @interface MGLTileSource : MGLSource -#pragma mark Initializing a Source - -- (instancetype)init __attribute__((unavailable("Use -initWithIdentifier:configurationURL: or -initWithIdentifier:tileURLTemplates:options: instead."))); -- (instancetype)initWithIdentifier:(NSString *)identifier __attribute__((unavailable("Use -initWithIdentifier:configurationURL: or -initWithIdentifier:tileURLTemplates:options: instead."))); - -/** - Returns a tile source initialized with an identifier and configuration URL. - - After initializing and configuring the source, add it to a map view’s style - using the `-[MGLStyle addSource:]` method. - - The URL may be a full HTTP or HTTPS URL or, for tile sets hosted by Mapbox, a - Mapbox URL indicating a map identifier (`mapbox://<mapid>`). The URL should - point to a JSON file that conforms to the - <a href="https://github.com/mapbox/tilejson-spec/">TileJSON specification</a>. - - @param identifier A string that uniquely identifies the source in the style to - which it is added. - @param configurationURL A URL to a TileJSON configuration file describing the - source’s contents and other metadata. - @return An initialized tile source. - */ -- (instancetype)initWithIdentifier:(NSString *)identifier configurationURL:(NSURL *)configurationURL; - -/** - Returns a tile source initialized an identifier, tile URL templates, and - options. - - After initializing and configuring the source, add it to a map view’s style - using the `-[MGLStyle addSource:]` method. - - #### Tile URL templates - - Tile URL templates are strings that specify the URLs of the tile images to - load. Each template resembles an absolute URL, but with any number of - placeholder strings that the source evaluates based on the tile it needs to - load. For example: - - <ul> - <li><code>http://www.example.com/tiles/{z}/{x}/{y}.pbf</code> could be - evaluated as <code>http://www.example.com/tiles/14/6/9.pbf</code>.</li> - <li><code>http://www.example.com/tiles/{z}/{x}/{y}{ratio}.png</code> could be - evaluated as <code>http://www.example.com/tiles/14/6/9@2x.png</code>.</li> - </ul> - - Tile sources support the following placeholder strings in tile URL templates, - all of which are optional: - - <table> - <thead> - <tr><th>Placeholder string</th><th>Description</th></tr> - </thead> - <tbody> - <tr> - <td><code>{x}</code></td> - <td>The index of the tile along the map’s x axis according to Spherical - Mercator projection. If the value is 0, the tile’s left edge corresponds - to the 180th meridian west. If the value is 2<sup><var>z</var></sup>−1, - the tile’s right edge corresponds to the 180th meridian east.</td> - </tr> - <tr> - <td><code>{y}</code></td> - <td>The index of the tile along the map’s y axis according to Spherical - Mercator projection. If the value is 0, the tile’s tile edge corresponds - to arctan(sinh(π)), or approximately 85.0511 degrees north. If the value - is 2<sup><var>z</var></sup>−1, the tile’s bottom edge corresponds to - −arctan(sinh(π)), or approximately 85.0511 degrees south. The y axis is - inverted if the <code>options</code> parameter contains - <code>MGLTileSourceOptionTileCoordinateSystem</code> with a value of - <code>MGLTileCoordinateSystemTMS</code>.</td> - </tr> - <tr> - <td><code>{z}</code></td> - <td>The tile’s zoom level. At zoom level 0, each tile covers the entire - world map; at zoom level 1, it covers ¼ of the world; at zoom level 2, - <sup>1</sup>⁄<sub>16</sub> of the world, and so on. For tiles loaded by - a <code>MGLRasterSource</code> object, whether the tile zoom level - matches the map’s current zoom level depends on the value of the - source’s tile size as specified in the - <code>MGLTileSourceOptionTileSize</code> key of the - <code>options</code> parameter.</td> - </tr> - <tr> - <td><code>{bbox-epsg-3857}</code></td> - <td>The tile’s bounding box, expressed as a comma-separated list of the - tile’s western, southern, eastern, and northern extents according to - Spherical Mercator (EPSG:3857) projection. The bounding box is typically - used with map services conforming to the - <a href="http://www.opengeospatial.org/standards/wms">Web Map Service</a> - protocol.</td> - </tr> - <tr> - <td><code>{quadkey}</code></td> - <td>A quadkey indicating both the tile’s location and its zoom level. The - quadkey is typically used with - <a href="https://msdn.microsoft.com/en-us/library/bb259689.aspx">Bing Maps</a>. - </td> - </tr> - <tr> - <td><code>{ratio}</code></td> - <td>A suffix indicating the resolution of the tile image. The suffix is the - empty string for standard resolution displays and <code>@2x</code> for - Retina displays, including displays for which - <code>NSScreen.backingScaleFactor</code> or <code>UIScreen.scale</code> - is 3.</td> - </tr> - <tr> - <td><code>{prefix}</code></td> - <td>Two hexadecimal digits chosen such that each visible tile has a - different prefix. The prefix is typically used for domain sharding.</td> - </tr> - </tbody> - </table> - - For more information about the `{x}`, `{y}`, and `{z}` placeholder strings, - consult the - <a href="https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames">OpenStreetMap Wiki</a>. - - @param identifier A string that uniquely identifies the source in the style to - which it is added. - @param tileURLTemplates An array of tile URL template strings. Only the first - string is used; any additional strings are ignored. - @param options A dictionary containing configuration options. See - `MGLTileSourceOption` for available keys and values. Pass in `nil` to use - the default values. - @return An initialized tile source. - */ -- (instancetype)initWithIdentifier:(NSString *)identifier tileURLTemplates:(NS_ARRAY_OF(NSString *) *)tileURLTemplates options:(nullable NS_DICTIONARY_OF(MGLTileSourceOption, id) *)options; - #pragma mark Accessing a Source’s Content /** diff --git a/platform/darwin/src/MGLTileSource.mm b/platform/darwin/src/MGLTileSource.mm index aa2a299a46..5644ad9a06 100644 --- a/platform/darwin/src/MGLTileSource.mm +++ b/platform/darwin/src/MGLTileSource.mm @@ -19,14 +19,6 @@ const MGLTileSourceOption MGLTileSourceOptionTileCoordinateSystem = @"MGLTileSou @implementation MGLTileSource -- (instancetype)initWithIdentifier:(NSString *)identifier configurationURL:(NSURL *)configurationURL { - return [super initWithIdentifier:identifier]; -} - -- (instancetype)initWithIdentifier:(NSString *)identifier tileURLTemplates:(NS_ARRAY_OF(NSString *) *)tileURLTemplates options:(NS_DICTIONARY_OF(MGLTileSourceOption, id) *)options { - return [super initWithIdentifier:identifier]; -} - - (NSURL *)configurationURL { [NSException raise:@"MGLAbstractClassException" format:@"MGLTileSource is an abstract class"]; diff --git a/platform/darwin/src/MGLTypes.h b/platform/darwin/src/MGLTypes.h index 5216e921f1..c06fd8b0e7 100644 --- a/platform/darwin/src/MGLTypes.h +++ b/platform/darwin/src/MGLTypes.h @@ -42,6 +42,10 @@ typedef NS_ENUM(NSInteger, MGLErrorCode) { MGLErrorCodeBadServerResponse = 2, /** An attempt to establish a connection failed. */ MGLErrorCodeConnectionFailed = 3, + /** A style parse error occurred while attempting to load the map. */ + MGLErrorCodeParseStyleFailed = 4, + /** An attempt to load the style failed. */ + MGLErrorCodeLoadStyleFailed = 5, }; /** Options for enabling debugging features in an `MGLMapView` instance. */ diff --git a/platform/darwin/src/MGLVectorSource.h b/platform/darwin/src/MGLVectorSource.h index 83926fd287..a48434f7a3 100644 --- a/platform/darwin/src/MGLVectorSource.h +++ b/platform/darwin/src/MGLVectorSource.h @@ -51,8 +51,128 @@ MGL_EXPORT #pragma mark Initializing a Source +/** + Returns a vector source initialized with an identifier and configuration URL. + + After initializing and configuring the source, add it to a map view’s style + using the `-[MGLStyle addSource:]` method. + + The URL may be a full HTTP or HTTPS URL or, for tile sets hosted by Mapbox, a + Mapbox URL indicating a map identifier (`mapbox://<mapid>`). The URL should + point to a JSON file that conforms to the + <a href="https://github.com/mapbox/tilejson-spec/">TileJSON specification</a>. + + @param identifier A string that uniquely identifies the source in the style to + which it is added. + @param configurationURL A URL to a TileJSON configuration file describing the + source’s contents and other metadata. + @return An initialized vector source. + */ - (instancetype)initWithIdentifier:(NSString *)identifier configurationURL:(NSURL *)configurationURL NS_DESIGNATED_INITIALIZER; +/** + Returns a vector source initialized an identifier, tile URL templates, and + options. + + After initializing and configuring the source, add it to a map view’s style + using the `-[MGLStyle addSource:]` method. + + #### Tile URL templates + + Tile URL templates are strings that specify the URLs of the tile images to + load. Each template resembles an absolute URL, but with any number of + placeholder strings that the source evaluates based on the tile it needs to + load. For example: + + <ul> + <li><code>http://www.example.com/tiles/{z}/{x}/{y}.pbf</code> could be + evaluated as <code>http://www.example.com/tiles/14/6/9.pbf</code>.</li> + <li><code>http://www.example.com/tiles/{z}/{x}/{y}{ratio}.png</code> could be + evaluated as <code>http://www.example.com/tiles/14/6/9@2x.png</code>.</li> + </ul> + + Tile sources support the following placeholder strings in tile URL templates, + all of which are optional: + + <table> + <thead> + <tr><th>Placeholder string</th><th>Description</th></tr> + </thead> + <tbody> + <tr> + <td><code>{x}</code></td> + <td>The index of the tile along the map’s x axis according to Spherical + Mercator projection. If the value is 0, the tile’s left edge corresponds + to the 180th meridian west. If the value is 2<sup><var>z</var></sup>−1, + the tile’s right edge corresponds to the 180th meridian east.</td> + </tr> + <tr> + <td><code>{y}</code></td> + <td>The index of the tile along the map’s y axis according to Spherical + Mercator projection. If the value is 0, the tile’s tile edge corresponds + to arctan(sinh(π)), or approximately 85.0511 degrees north. If the value + is 2<sup><var>z</var></sup>−1, the tile’s bottom edge corresponds to + −arctan(sinh(π)), or approximately 85.0511 degrees south. The y axis is + inverted if the <code>options</code> parameter contains + <code>MGLTileSourceOptionTileCoordinateSystem</code> with a value of + <code>MGLTileCoordinateSystemTMS</code>.</td> + </tr> + <tr> + <td><code>{z}</code></td> + <td>The tile’s zoom level. At zoom level 0, each tile covers the entire + world map; at zoom level 1, it covers ¼ of the world; at zoom level 2, + <sup>1</sup>⁄<sub>16</sub> of the world, and so on. For tiles loaded by + a <code>MGLRasterSource</code> object, whether the tile zoom level + matches the map’s current zoom level depends on the value of the + source’s tile size as specified in the + <code>MGLTileSourceOptionTileSize</code> key of the + <code>options</code> parameter.</td> + </tr> + <tr> + <td><code>{bbox-epsg-3857}</code></td> + <td>The tile’s bounding box, expressed as a comma-separated list of the + tile’s western, southern, eastern, and northern extents according to + Spherical Mercator (EPSG:3857) projection. The bounding box is typically + used with map services conforming to the + <a href="http://www.opengeospatial.org/standards/wms">Web Map Service</a> + protocol.</td> + </tr> + <tr> + <td><code>{quadkey}</code></td> + <td>A quadkey indicating both the tile’s location and its zoom level. The + quadkey is typically used with + <a href="https://msdn.microsoft.com/en-us/library/bb259689.aspx">Bing Maps</a>. + </td> + </tr> + <tr> + <td><code>{ratio}</code></td> + <td>A suffix indicating the resolution of the tile image. The suffix is the + empty string for standard resolution displays and <code>@2x</code> for + Retina displays, including displays for which + <code>NSScreen.backingScaleFactor</code> or <code>UIScreen.scale</code> + is 3.</td> + </tr> + <tr> + <td><code>{prefix}</code></td> + <td>Two hexadecimal digits chosen such that each visible tile has a + different prefix. The prefix is typically used for domain sharding.</td> + </tr> + </tbody> + </table> + + For more information about the `{x}`, `{y}`, and `{z}` placeholder strings, + consult the + <a href="https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames">OpenStreetMap Wiki</a>. + + @param identifier A string that uniquely identifies the source in the style to + which it is added. + @param tileURLTemplates An array of tile URL template strings. Only the first + string is used; any additional strings are ignored. + @param options A dictionary containing configuration options. See + `MGLTileSourceOption` for available keys and values. Pass in `nil` to use + the default values. + @return An initialized tile source. + */ - (instancetype)initWithIdentifier:(NSString *)identifier tileURLTemplates:(NS_ARRAY_OF(NSString *) *)tileURLTemplates options:(nullable NS_DICTIONARY_OF(MGLTileSourceOption, id) *)options NS_DESIGNATED_INITIALIZER; #pragma mark Accessing a Source’s Content diff --git a/platform/darwin/src/MGLVectorSource.mm b/platform/darwin/src/MGLVectorSource.mm index aeec2e40ac..5e9f4f4a6e 100644 --- a/platform/darwin/src/MGLVectorSource.mm +++ b/platform/darwin/src/MGLVectorSource.mm @@ -1,9 +1,9 @@ #import "MGLVectorSource_Private.h" -#import "MGLMapView_Private.h" #import "MGLFeature_Private.h" #import "MGLSource_Private.h" #import "MGLTileSource_Private.h" +#import "MGLMapView_Private.h" #import "NSPredicate+MGLAdditions.h" #import "NSURL+MGLAdditions.h" @@ -12,77 +12,28 @@ @interface MGLVectorSource () -- (instancetype)initWithRawSource:(mbgl::style::VectorSource *)rawSource NS_DESIGNATED_INITIALIZER; - -@property (nonatomic) mbgl::style::VectorSource *rawSource; +@property (nonatomic, readonly) mbgl::style::VectorSource *rawSource; @end -@implementation MGLVectorSource { - std::unique_ptr<mbgl::style::VectorSource> _pendingSource; -} +@implementation MGLVectorSource - (instancetype)initWithIdentifier:(NSString *)identifier configurationURL:(NSURL *)configurationURL { - if (self = [super initWithIdentifier:identifier configurationURL:configurationURL]) { - auto source = std::make_unique<mbgl::style::VectorSource>(identifier.UTF8String, - configurationURL.mgl_URLByStandardizingScheme.absoluteString.UTF8String); - _pendingSource = std::move(source); - self.rawSource = _pendingSource.get(); - } - return self; + auto source = std::make_unique<mbgl::style::VectorSource>(identifier.UTF8String, + configurationURL.mgl_URLByStandardizingScheme.absoluteString.UTF8String); + return self = [super initWithPendingSource:std::move(source)]; } - (instancetype)initWithIdentifier:(NSString *)identifier tileURLTemplates:(NS_ARRAY_OF(NSString *) *)tileURLTemplates options:(nullable NS_DICTIONARY_OF(MGLTileSourceOption, id) *)options { - if (self = [super initWithIdentifier:identifier tileURLTemplates:tileURLTemplates options:options]) { - mbgl::Tileset tileSet = MGLTileSetFromTileURLTemplates(tileURLTemplates, options); - - auto source = std::make_unique<mbgl::style::VectorSource>(identifier.UTF8String, tileSet); - _pendingSource = std::move(source); - self.rawSource = _pendingSource.get(); - } - return self; -} - -- (instancetype)initWithRawSource:(mbgl::style::VectorSource *)rawSource { - return [super initWithRawSource:rawSource]; -} - -- (void)addToMapView:(MGLMapView *)mapView { - if (_pendingSource == nullptr) { - [NSException raise:@"MGLRedundantSourceException" - format:@"This instance %@ was already added to %@. Adding the same source instance " \ - "to the style more than once is invalid.", self, mapView.style]; - } - - mapView.mbglMap->addSource(std::move(_pendingSource)); -} - -- (void)removeFromMapView:(MGLMapView *)mapView { - if (self.rawSource != mapView.mbglMap->getSource(self.identifier.UTF8String)) { - return; - } - - auto removedSource = mapView.mbglMap->removeSource(self.identifier.UTF8String); - - mbgl::style::VectorSource *source = dynamic_cast<mbgl::style::VectorSource *>(removedSource.get()); - if (!source) { - return; - } - - removedSource.release(); - - _pendingSource = std::unique_ptr<mbgl::style::VectorSource>(source); - self.rawSource = _pendingSource.get(); + mbgl::Tileset tileSet = MGLTileSetFromTileURLTemplates(tileURLTemplates, options); + auto source = std::make_unique<mbgl::style::VectorSource>(identifier.UTF8String, tileSet); + return self = [super initWithPendingSource:std::move(source)]; } - (mbgl::style::VectorSource *)rawSource { return (mbgl::style::VectorSource *)super.rawSource; } -- (void)setRawSource:(mbgl::style::VectorSource *)rawSource { - super.rawSource = rawSource; -} - - (NSURL *)configurationURL { auto url = self.rawSource->getURL(); return url ? [NSURL URLWithString:@(url->c_str())] : nil; @@ -110,7 +61,10 @@ optionalFilter = predicate.mgl_filter; } - std::vector<mbgl::Feature> features = self.rawSource->querySourceFeatures({ optionalSourceLayerIDs, optionalFilter }); + std::vector<mbgl::Feature> features; + if (self.mapView) { + features = self.mapView.mbglMap->querySourceFeatures(self.rawSource->getID(), { optionalSourceLayerIDs, optionalFilter }); + } return MGLFeaturesFromMBGLFeatures(features); } diff --git a/platform/darwin/src/MGLVectorSource_Private.h b/platform/darwin/src/MGLVectorSource_Private.h index 12fcd82012..335743173e 100644 --- a/platform/darwin/src/MGLVectorSource_Private.h +++ b/platform/darwin/src/MGLVectorSource_Private.h @@ -2,16 +2,7 @@ NS_ASSUME_NONNULL_BEGIN -namespace mbgl { - namespace style { - class VectorSource; - } -} - @interface MGLVectorSource (Private) - -- (instancetype)initWithRawSource:(mbgl::style::VectorSource *)rawSource; - @end NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/headless_backend_cgl.cpp b/platform/darwin/src/headless_backend_cgl.cpp index 7069738fb1..6ad98f4326 100644 --- a/platform/darwin/src/headless_backend_cgl.cpp +++ b/platform/darwin/src/headless_backend_cgl.cpp @@ -36,7 +36,7 @@ struct CGLImpl : public HeadlessBackend::Impl { CGLContextObj glContext = nullptr; }; -gl::glProc HeadlessBackend::initializeExtension(const char* name) { +gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) { static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl")); if (!framework) { throw std::runtime_error("Failed to load OpenGL framework."); @@ -46,7 +46,7 @@ gl::glProc HeadlessBackend::initializeExtension(const char* name) { void* symbol = CFBundleGetFunctionPointerForName(framework, str); CFRelease(str); - return reinterpret_cast<gl::glProc>(symbol); + return reinterpret_cast<gl::ProcAddress>(symbol); } bool HeadlessBackend::hasDisplay() { diff --git a/platform/darwin/src/headless_backend_eagl.mm b/platform/darwin/src/headless_backend_eagl.mm index bd4a202ec5..1daaeaf54c 100644 --- a/platform/darwin/src/headless_backend_eagl.mm +++ b/platform/darwin/src/headless_backend_eagl.mm @@ -1,7 +1,5 @@ #include <mbgl/gl/headless_backend.hpp> -#include <mbgl/gl/extension.hpp> - #include <OpenGLES/EAGL.h> #include <stdexcept> @@ -29,7 +27,7 @@ struct EAGLImpl : public HeadlessBackend::Impl { EAGLContext* glContext = nullptr; }; -gl::glProc HeadlessBackend::initializeExtension(const char* name) { +gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) { static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengles")); if (!framework) { throw std::runtime_error("Failed to load OpenGL framework."); @@ -39,7 +37,7 @@ gl::glProc HeadlessBackend::initializeExtension(const char* name) { void* symbol = CFBundleGetFunctionPointerForName(framework, str); CFRelease(str); - return reinterpret_cast<gl::glProc>(symbol); + return reinterpret_cast<gl::ProcAddress>(symbol); } bool HeadlessBackend::hasDisplay() { |