diff options
Diffstat (limited to 'platform/darwin')
40 files changed, 606 insertions, 289 deletions
diff --git a/platform/darwin/docs/guides/For Style Authors.md.ejs b/platform/darwin/docs/guides/For Style Authors.md.ejs index 26c533632f..06a8907704 100644 --- a/platform/darwin/docs/guides/For Style Authors.md.ejs +++ b/platform/darwin/docs/guides/For Style Authors.md.ejs @@ -160,7 +160,6 @@ the following terms for concepts defined in the style specification: In the style specification | In the SDK ---------------------------|--------- -class | style class filter | predicate function type | interpolation mode id | identifier @@ -181,8 +180,9 @@ In style JSON | In the SDK `geojson` | `MGLShapeSource` `raster` | `MGLRasterSource` `vector` | `MGLVectorSource` +`image` | `MGLImageSource` -`canvas`, `image`, and `video` sources are not supported. +`canvas` and `video` sources are not supported. ### Tile sources @@ -223,6 +223,12 @@ To create a shape source from local GeoJSON data, first [convert the GeoJSON data into a shape](working-with-geojson-data.html#converting-geojson-data-into-shape-objects), then use the `-[MGLShapeSource initWithIdentifier:shape:options:]` method. +### Image sources + +Image sources accept a non-axis aligned quadrilateral as their geographic coordinates. +These coordinates, in `MGLCoordinateQuad`, are described in counterclockwise order, +in contrast to the clockwise order defined in the style specification. + ## Configuring the map content’s appearance Each layer defined by the style JSON file is represented at runtime by a style diff --git a/platform/darwin/src/MGLCircleStyleLayer.h b/platform/darwin/src/MGLCircleStyleLayer.h index 789ff7a258..823824b50f 100644 --- a/platform/darwin/src/MGLCircleStyleLayer.h +++ b/platform/darwin/src/MGLCircleStyleLayer.h @@ -64,16 +64,6 @@ typedef NS_ENUM(NSUInteger, MGLCircleTranslationAnchor) { ### Example ```swift - let layer = MGLCircleStyleLayer(identifier: "circles", source: population) - layer.sourceLayerIdentifier = "population" - layer.circleColor = MGLStyleValue(rawValue: .green) - layer.circleRadius = MGLStyleValue(interpolationMode: .exponential, - cameraStops: [12: MGLStyleValue(rawValue: 2), - 22: MGLStyleValue(rawValue: 180)], - options: [.interpolationBase: 1.75]) - layer.circleOpacity = MGLStyleValue(rawValue: 0.7) - layer.predicate = NSPredicate(format: "%K == %@", "marital-status", "married") - mapView.style?.addLayer(layer) ``` */ MGL_EXPORT diff --git a/platform/darwin/src/MGLConversion.h b/platform/darwin/src/MGLConversion.h index d51ebd775c..d6363b28eb 100644 --- a/platform/darwin/src/MGLConversion.h +++ b/platform/darwin/src/MGLConversion.h @@ -104,6 +104,14 @@ inline optional<float> toNumber(const id value) { } } +inline optional<double> toDouble(const id value) { + if (_isNumber(value)) { + return ((NSNumber *)value).doubleValue; + } else { + return {}; + } +} + inline optional<std::string> toString(const id value) { if (_isString(value)) { return std::string(static_cast<const char *>([value UTF8String])); diff --git a/platform/darwin/src/MGLFillExtrusionStyleLayer.h b/platform/darwin/src/MGLFillExtrusionStyleLayer.h index c4fb9aa77e..443391756d 100644 --- a/platform/darwin/src/MGLFillExtrusionStyleLayer.h +++ b/platform/darwin/src/MGLFillExtrusionStyleLayer.h @@ -42,12 +42,6 @@ typedef NS_ENUM(NSUInteger, MGLFillExtrusionTranslationAnchor) { ### 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 diff --git a/platform/darwin/src/MGLFillStyleLayer.h b/platform/darwin/src/MGLFillStyleLayer.h index 6e3297bdec..8776f17bcb 100644 --- a/platform/darwin/src/MGLFillStyleLayer.h +++ b/platform/darwin/src/MGLFillStyleLayer.h @@ -42,11 +42,6 @@ typedef NS_ENUM(NSUInteger, MGLFillTranslationAnchor) { ### Example ```swift - let layer = MGLFillStyleLayer(identifier: "parks", source: parks) - layer.sourceLayerIdentifier = "parks" - layer.fillColor = MGLStyleValue(rawValue: .green) - layer.predicate = NSPredicate(format: "type == %@", "national-park") - mapView.style?.addLayer(layer) ``` */ MGL_EXPORT diff --git a/platform/darwin/src/MGLGeometry.h b/platform/darwin/src/MGLGeometry.h index d37741cde5..7c68033abf 100644 --- a/platform/darwin/src/MGLGeometry.h +++ b/platform/darwin/src/MGLGeometry.h @@ -45,6 +45,24 @@ typedef struct __attribute__((objc_boxable)) MGLCoordinateBounds { CLLocationCoordinate2D ne; } MGLCoordinateBounds; +/** + A quadrilateral area as measured on a two-dimensional map projection. + `MGLCoordinateQuad` differs from `MGLCoordinateBounds` in that it allows + representation of non-axis aligned bounds and non-rectangular quadrilaterals. + The coordinates are described in counter clockwise order from top left. + */ +typedef struct MGLCoordinateQuad { + /** Coordinate at the top left corner. */ + CLLocationCoordinate2D topLeft; + /** Coordinate at the bottom left corner. */ + CLLocationCoordinate2D bottomLeft; + /** Coordinate at the bottom right corner. */ + CLLocationCoordinate2D bottomRight; + /** Coordinate at the top right corner. */ + CLLocationCoordinate2D topRight; +} MGLCoordinateQuad; + + /** Creates a new `MGLCoordinateBounds` structure from the given southwest and northeast coordinates. @@ -56,6 +74,33 @@ NS_INLINE MGLCoordinateBounds MGLCoordinateBoundsMake(CLLocationCoordinate2D sw, return bounds; } +/** + Creates a new `MGLCoordinateQuad` structure from the given top left, + bottom left, bottom right, and top right coordinates. + */ +NS_INLINE MGLCoordinateQuad MGLCoordinateQuadMake(CLLocationCoordinate2D topLeft, CLLocationCoordinate2D bottomLeft, CLLocationCoordinate2D bottomRight, CLLocationCoordinate2D topRight) { + MGLCoordinateQuad quad; + quad.topLeft = topLeft; + quad.bottomLeft = bottomLeft; + quad.bottomRight = bottomRight; + quad.topRight = topRight; + return quad; +} + +/** + Creates a new `MGLCoordinateQuad` structure from the given `MGLCoordinateBounds`. + The returned quad uses the bounds' northeast coordinate as the top right, and the + southwest coordinate at the bottom left. + */ +NS_INLINE MGLCoordinateQuad MGLCoordinateQuadFromCoordinateBounds(MGLCoordinateBounds bounds) { + MGLCoordinateQuad quad; + quad.topLeft = CLLocationCoordinate2DMake(bounds.ne.latitude, bounds.sw.longitude); + quad.bottomLeft = bounds.sw; + quad.bottomRight = CLLocationCoordinate2DMake(bounds.sw.latitude, bounds.ne.longitude); + quad.topRight = bounds.ne; + return quad; +} + /** Returns `YES` if the two coordinate bounds are equal to each other. */ NS_INLINE BOOL MGLCoordinateBoundsEqualToCoordinateBounds(MGLCoordinateBounds bounds1, MGLCoordinateBounds bounds2) { return (bounds1.sw.latitude == bounds2.sw.latitude && @@ -117,6 +162,15 @@ NS_INLINE NSString *MGLStringFromCoordinateBounds(MGLCoordinateBounds bounds) { bounds.ne.latitude, bounds.ne.longitude]; } +/** Returns a formatted string for the given coordinate quad. */ +NS_INLINE NSString *MGLStringFromCoordinateQuad(MGLCoordinateQuad quad) { + return [NSString stringWithFormat:@"{ topleft = {%.1f, %.1f}, bottomleft = {%.1f, %.1f}}, bottomright = {%.1f, %.1f}, topright = {%.1f, %.1f}", + quad.topLeft.latitude, quad.topLeft.longitude, + quad.bottomLeft.latitude, quad.bottomLeft.longitude, + quad.bottomRight.latitude, quad.bottomRight.longitude, + quad.topRight.latitude, quad.topRight.longitude]; +} + /** Returns radians, converted from degrees. */ NS_INLINE CGFloat MGLRadiansFromDegrees(CLLocationDegrees degrees) { return (CGFloat)(degrees * M_PI) / 180; diff --git a/platform/darwin/src/MGLGeometry_Private.h b/platform/darwin/src/MGLGeometry_Private.h index 7ad8314a79..88fcf5b576 100644 --- a/platform/darwin/src/MGLGeometry_Private.h +++ b/platform/darwin/src/MGLGeometry_Private.h @@ -8,6 +8,7 @@ #import <mbgl/util/geo.hpp> #import <mbgl/util/geometry.hpp> +#import <array> typedef double MGLLocationRadians; typedef double MGLRadianDistance; typedef double MGLRadianDirection; @@ -56,6 +57,20 @@ NS_INLINE mbgl::LatLngBounds MGLLatLngBoundsFromCoordinateBounds(MGLCoordinateBo MGLLatLngFromLocationCoordinate2D(coordinateBounds.ne)); } +NS_INLINE std::array<mbgl::LatLng, 4> MGLLatLngArrayFromCoordinateQuad(MGLCoordinateQuad quad) { + return { MGLLatLngFromLocationCoordinate2D(quad.topLeft), + MGLLatLngFromLocationCoordinate2D(quad.topRight), + MGLLatLngFromLocationCoordinate2D(quad.bottomRight), + MGLLatLngFromLocationCoordinate2D(quad.bottomLeft) }; +} + +NS_INLINE MGLCoordinateQuad MGLCoordinateQuadFromLatLngArray(std::array<mbgl::LatLng, 4> quad) { + return { MGLLocationCoordinate2DFromLatLng(quad[0]), + MGLLocationCoordinate2DFromLatLng(quad[3]), + MGLLocationCoordinate2DFromLatLng(quad[2]), + MGLLocationCoordinate2DFromLatLng(quad[1]) }; +} + #if TARGET_OS_IPHONE NS_INLINE mbgl::EdgeInsets MGLEdgeInsetsFromNSEdgeInsets(UIEdgeInsets insets) { return { insets.top, insets.left, insets.bottom, insets.right }; diff --git a/platform/darwin/src/MGLImageSource.h b/platform/darwin/src/MGLImageSource.h new file mode 100644 index 0000000000..21487d9739 --- /dev/null +++ b/platform/darwin/src/MGLImageSource.h @@ -0,0 +1,94 @@ +#import "MGLSource.h" + +#import "MGLFoundation.h" +#import "MGLTypes.h" +#import "MGLGeometry.h" + +NS_ASSUME_NONNULL_BEGIN + +MGL_EXPORT +/** + `MGLImageSource` is a content source that is used for a georeferenced raster + image to be shown on the map. The georeferenced image scales and rotates as the + user zooms and rotates the map. Images may also be used as icons or patterns + in a style layer. To register an image for use as an icon or pattern, + use the `-[MGLStyle setImage:forName:]` method. To configure a point + annotation’s image, use the `MGLAnnotationImage` class. + + The geographic location of the raster image content, supplied with + `MGLCoordinateQuad`, can be non-axis aligned. + `MGLImageSource` supports raster content from `NSURL`, `NSImage` (macOS), or + `UIImage` (iOS). + An image source is added to an `MGLStyle` object along with one or more + `MGLRasterStyleLayer` objects. Use a raster style layer to control the + appearance of content supplied by the image source. + + Each + <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-image"><code>image</code></a> + source defined by the style JSON file is represented at runtime by an + `MGLImageSource` object that you can use to initialize new style layers. You + can also add and remove sources dynamically using methods such as + `-[MGLStyle addSource:]` and `-[MGLStyle sourceWithIdentifier:]`. + + ### Example + + ```swift + let coordinates = MGLCoordinateQuad( + topLeft: CLLocationCoordinate2D(latitude: 46.437, longitude: -80.425), + bottomLeft: CLLocationCoordinate2D(latitude: 37.936, longitude: -80.425), + bottomRight: CLLocationCoordinate2D(latitude: 37.936, longitude: -71.516), + topRight: CLLocationCoordinate2D(latitude: 46.437, longitude: -71.516)) + let source = MGLImageSource(identifier: "radar", coordinateQuad: coordinates, url: URL(string: "https://www.mapbox.com/mapbox-gl-js/assets/radar.gif")!) + mapView.style?.addSource(source) + ``` + */ +MGL_EXPORT +@interface MGLImageSource : MGLSource + +#pragma mark Initializing a Source + +/** + Returns a georeferenced image source with an identifier, coordinates and a URL. + + @param identifier A string that uniquely identifies the source. + @param coordinateQuad the top left, top right, bottom right, and bottom left coordinates for the image. + @param url An HTTP(S) URL, absolute file URL, or local file URL relative to the + current application’s resource bundle. + @return An initialized shape source. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier coordinateQuad:(MGLCoordinateQuad)coordinateQuad URL:(NSURL *)url; + +/** + Returns a georeferenced image source with an identifier, coordinates and an image. + + @param identifier A string that uniquely identifies the source. + @param coordinateQuad The top left, top right, bottom right, and bottom left coordinates for the image. + @param image The image to display for the source. + @return An initialized shape source. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier coordinateQuad:(MGLCoordinateQuad)coordinateQuad image:(MGLImage *)image; + +#pragma mark Accessing a Source’s Content + +/** + The URL to the source image. + + If the receiver was initialized using `-initWithIdentifier:coordinateQuad:image:` or + the `image` property is set, this property is set to `nil`. + */ +@property (nonatomic, copy, nullable)NSURL *URL; + +/** + The source image. + + If the receiver was initialized using `-initWithIdentifier:coordinateQuad:URL:` or if the `URL` property is set, this property is set to `nil`. + */ +@property (nonatomic, retain, nullable)MGLImage *image; + +/** + The coordinates at which the corners of the source image will be placed. + */ +@property (nonatomic) MGLCoordinateQuad coordinates; +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLImageSource.mm b/platform/darwin/src/MGLImageSource.mm new file mode 100644 index 0000000000..0a2dc2713f --- /dev/null +++ b/platform/darwin/src/MGLImageSource.mm @@ -0,0 +1,93 @@ +#import "MGLImageSource.h" + +#import "MGLGeometry_Private.h" +#import "MGLSource_Private.h" +#import "MGLTileSource_Private.h" +#import "NSURL+MGLAdditions.h" +#if TARGET_OS_IPHONE + #import "UIImage+MGLAdditions.h" +#else + #import "NSImage+MGLAdditions.h" +#endif + +#include <mbgl/style/sources/image_source.hpp> +#include <mbgl/util/premultiply.hpp> + +@interface MGLImageSource () +- (instancetype)initWithIdentifier:(NSString *)identifier coordinateQuad:(MGLCoordinateQuad)coordinateQuad NS_DESIGNATED_INITIALIZER; + +@property (nonatomic, readonly) mbgl::style::ImageSource *rawSource; + +@end + +@implementation MGLImageSource + +- (instancetype)initWithIdentifier:(NSString *)identifier coordinateQuad:(MGLCoordinateQuad)coordinateQuad { + + const auto coordsArray = MGLLatLngArrayFromCoordinateQuad(coordinateQuad); + auto source = std::make_unique<mbgl::style::ImageSource>(identifier.UTF8String, coordsArray); + return self = [super initWithPendingSource:std::move(source)]; +} + + +- (instancetype)initWithIdentifier:(NSString *)identifier coordinateQuad:(MGLCoordinateQuad)coordinateQuad URL:(NSURL *)url { + self = [self initWithIdentifier:identifier coordinateQuad: coordinateQuad]; + self.URL = url; + return self; +} + + +- (instancetype)initWithIdentifier:(NSString *)identifier coordinateQuad:(MGLCoordinateQuad)coordinateQuad image:(MGLImage *)image { + self = [self initWithIdentifier:identifier coordinateQuad: coordinateQuad]; + self.image = image; + + return self; +} + +- (NSURL *)URL { + auto url = self.rawSource->getURL(); + return url ? [NSURL URLWithString:@(url->c_str())] : nil; +} + +- (void)setURL:(NSURL *)url { + if (url) { + self.rawSource->setURL(url.mgl_URLByStandardizingScheme.absoluteString.UTF8String); + _image = nil; + } else { + self.image = nullptr; + } +} + +- (void)setImage:(MGLImage *)image { + if (image != nullptr) { + mbgl::UnassociatedImage unassociatedImage = mbgl::util::unpremultiply(image.mgl_premultipliedImage); + self.rawSource->setImage(std::move(unassociatedImage)); + } else { + self.rawSource->setImage(mbgl::UnassociatedImage({0,0})); + } + _image = image; +} + +- (MGLCoordinateQuad)coordinates { + return MGLCoordinateQuadFromLatLngArray(self.rawSource->getCoordinates()); +} + +- (void)setCoordinates: (MGLCoordinateQuad)coordinateQuad { + self.rawSource->setCoordinates(MGLLatLngArrayFromCoordinateQuad(coordinateQuad)); +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@: %p; identifier = %@; coordinates = %@; URL = %@; image = %@>", + NSStringFromClass([self class]), (void *)self, self.identifier, MGLStringFromCoordinateQuad(self.coordinates), self.URL, self.image]; +} + +- (mbgl::style::ImageSource *)rawSource { + return (mbgl::style::ImageSource *)super.rawSource; +} + +- (NSString *)attributionHTMLString { + auto attribution = self.rawSource->getAttribution(); + return attribution ? @(attribution->c_str()) : nil; +} + +@end diff --git a/platform/darwin/src/MGLLight.h b/platform/darwin/src/MGLLight.h index 50db3f45fd..55b789f043 100644 --- a/platform/darwin/src/MGLLight.h +++ b/platform/darwin/src/MGLLight.h @@ -27,7 +27,7 @@ typedef NS_ENUM(NSUInteger, MGLLightAnchor) { A structure containing information about the position of the light source relative to lit geometries. */ -typedef struct __attribute__((objc_boxable)) MGLSphericalPosition { +typedef struct MGLSphericalPosition { /** Distance from the center of the base of an object to its light. */ CGFloat radial; /** Position of the light relative to 0° (0° when `MGLLight.anchor` is set to viewport corresponds diff --git a/platform/darwin/src/MGLLineStyleLayer.h b/platform/darwin/src/MGLLineStyleLayer.h index 38513652c5..7c5b66a2c2 100644 --- a/platform/darwin/src/MGLLineStyleLayer.h +++ b/platform/darwin/src/MGLLineStyleLayer.h @@ -92,16 +92,6 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslationAnchor) { ### Example ```swift - let layer = MGLLineStyleLayer(identifier: "trails-path", source: trails) - layer.sourceLayerIdentifier = "trails" - layer.lineWidth = MGLStyleValue(interpolationMode: .exponential, - cameraStops: [14: MGLStyleValue(rawValue: 2), - 18: MGLStyleValue(rawValue: 20)], - options: [.interpolationBase: 1.5]) - layer.lineColor = MGLStyleValue(rawValue: .brown) - layer.lineCap = MGLStyleValue(rawValue: NSValue(mglLineCap: .round)) - layer.predicate = NSPredicate(format: "%K == %@", "trail-type", "mountain-biking") - mapView.style?.addLayer(layer) ``` */ MGL_EXPORT @@ -543,6 +533,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 *> *lineWidth; diff --git a/platform/darwin/src/MGLLineStyleLayer.mm b/platform/darwin/src/MGLLineStyleLayer.mm index 8b90efd0c4..9be1667722 100644 --- a/platform/darwin/src/MGLLineStyleLayer.mm +++ b/platform/darwin/src/MGLLineStyleLayer.mm @@ -480,7 +480,7 @@ namespace mbgl { - (void)setLineWidth:(MGLStyleValue<NSNumber *> *)lineWidth { MGLAssertStyleLayerIsValid(); - auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(lineWidth); + auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenPropertyValue(lineWidth); self.rawLayer->setLineWidth(mbglValue); } @@ -489,9 +489,9 @@ namespace mbgl { auto propertyValue = self.rawLayer->getLineWidth(); if (propertyValue.isUndefined()) { - return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultLineWidth()); + return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(self.rawLayer->getDefaultLineWidth()); } - return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue); + return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(propertyValue); } - (void)setLineWidthTransition:(MGLTransition )transition { diff --git a/platform/darwin/src/MGLOfflineStorage.h b/platform/darwin/src/MGLOfflineStorage.h index 16f134adb1..b009f893b3 100644 --- a/platform/darwin/src/MGLOfflineStorage.h +++ b/platform/darwin/src/MGLOfflineStorage.h @@ -154,6 +154,8 @@ typedef NS_ENUM(NSUInteger, MGLResourceKind) { /** JSON part of a sprite sheet. It is constructed of the prefix in https://www.mapbox.com/mapbox-gl-js/style-spec/#root-sprite and a JSON file extension. */ MGLResourceKindSpriteJSON, + /** Image data for a georeferenced image source. **/ + MGLResourceKindImage, }; /** diff --git a/platform/darwin/src/MGLOfflineStorage.mm b/platform/darwin/src/MGLOfflineStorage.mm index 81774ad3cb..2ddfa649e9 100644 --- a/platform/darwin/src/MGLOfflineStorage.mm +++ b/platform/darwin/src/MGLOfflineStorage.mm @@ -10,8 +10,13 @@ #import "NSBundle+MGLAdditions.h" #import "NSValue+MGLAdditions.h" +#include <mbgl/actor/actor.hpp> +#include <mbgl/storage/resource_transform.hpp> +#include <mbgl/util/run_loop.hpp> #include <mbgl/util/string.hpp> +#include <memory> + static NSString * const MGLOfflineStorageFileName = @"cache.db"; static NSString * const MGLOfflineStorageFileName3_2_0_beta_1 = @"offline.db"; @@ -36,7 +41,9 @@ NSString * const MGLOfflinePackMaximumCountUserInfoKey = MGLOfflinePackUserInfoK @end -@implementation MGLOfflineStorage +@implementation MGLOfflineStorage { + std::unique_ptr<mbgl::Actor<mbgl::ResourceTransform>> _mbglResourceTransform; +} + (instancetype)sharedOfflineStorage { static dispatch_once_t onceToken; @@ -74,7 +81,7 @@ NSString * const MGLOfflinePackMaximumCountUserInfoKey = MGLOfflinePackUserInfoK - (void)setDelegate:(id<MGLOfflineStorageDelegate>)newValue { _delegate = newValue; if ([self.delegate respondsToSelector:@selector(offlineStorage:URLForResourceOfKind:withURL:)]) { - _mbglFileSource->setResourceTransform([offlineStorage = self](auto kind_, std::string&& url_) -> std::string { + _mbglResourceTransform = std::make_unique<mbgl::Actor<mbgl::ResourceTransform>>(*mbgl::util::RunLoop::Get(), [offlineStorage = self](auto kind_, const std::string&& url_) -> std::string { NSURL* url = [NSURL URLWithString:[[NSString alloc] initWithBytes:url_.data() length:url_.length() @@ -99,6 +106,9 @@ NSString * const MGLOfflinePackMaximumCountUserInfoKey = MGLOfflinePackUserInfoK case mbgl::Resource::Kind::SpriteJSON: kind = MGLResourceKindSpriteJSON; break; + case mbgl::Resource::Kind::Image: + kind = MGLResourceKindImage; + break; case mbgl::Resource::Kind::Unknown: kind = MGLResourceKindUnknown; break; @@ -109,8 +119,11 @@ NSString * const MGLOfflinePackMaximumCountUserInfoKey = MGLOfflinePackUserInfoK withURL:url]; return url.absoluteString.UTF8String; }); + + _mbglFileSource->setResourceTransform(_mbglResourceTransform->self()); } else { - _mbglFileSource->setResourceTransform(nullptr); + _mbglResourceTransform.reset(); + _mbglFileSource->setResourceTransform({}); } } diff --git a/platform/darwin/src/MGLOpenGLStyleLayer.h b/platform/darwin/src/MGLOpenGLStyleLayer.h index bdad5f9d07..0b494e8062 100644 --- a/platform/darwin/src/MGLOpenGLStyleLayer.h +++ b/platform/darwin/src/MGLOpenGLStyleLayer.h @@ -8,6 +8,7 @@ NS_ASSUME_NONNULL_BEGIN @class MGLMapView; +@class MGLStyle; typedef struct MGLStyleLayerDrawingContext { CGSize size; @@ -21,7 +22,7 @@ typedef struct MGLStyleLayerDrawingContext { MGL_EXPORT @interface MGLOpenGLStyleLayer : MGLStyleLayer -@property (nonatomic, weak, readonly) MGLMapView *mapView; +@property (nonatomic, weak, readonly) MGLStyle *style; - (instancetype)initWithIdentifier:(NSString *)identifier; diff --git a/platform/darwin/src/MGLOpenGLStyleLayer.mm b/platform/darwin/src/MGLOpenGLStyleLayer.mm index 39eda758eb..36a3c20c97 100644 --- a/platform/darwin/src/MGLOpenGLStyleLayer.mm +++ b/platform/darwin/src/MGLOpenGLStyleLayer.mm @@ -4,7 +4,6 @@ #import "MGLStyle_Private.h" #import "MGLStyleLayer_Private.h" -#include <mbgl/map/map.hpp> #include <mbgl/style/layers/custom_layer.hpp> #include <mbgl/math/wrap.hpp> @@ -17,7 +16,7 @@ */ void MGLPrepareCustomStyleLayer(void *context) { MGLOpenGLStyleLayer *layer = (__bridge MGLOpenGLStyleLayer *)context; - [layer didMoveToMapView:layer.mapView]; + [layer didMoveToMapView:layer.style.mapView]; } /** @@ -37,7 +36,7 @@ void MGLDrawCustomStyleLayer(void *context, const mbgl::style::CustomLayerRender .pitch = static_cast<CGFloat>(params.pitch), .fieldOfView = static_cast<CGFloat>(params.fieldOfView), }; - [layer drawInMapView:layer.mapView withContext:drawingContext]; + [layer drawInMapView:layer.style.mapView withContext:drawingContext]; } /** @@ -49,7 +48,7 @@ void MGLDrawCustomStyleLayer(void *context, const mbgl::style::CustomLayerRender */ void MGLFinishCustomStyleLayer(void *context) { MGLOpenGLStyleLayer *layer = (__bridge MGLOpenGLStyleLayer *)context; - [layer willMoveFromMapView:layer.mapView]; + [layer willMoveFromMapView:layer.style.mapView]; } /** @@ -75,12 +74,12 @@ void MGLFinishCustomStyleLayer(void *context) { @property (nonatomic, readonly) mbgl::style::CustomLayer *rawLayer; /** - The map view whose style currently contains the layer. + The style currently containing the layer. - If the layer is not currently part of any map view’s style, this property is + If the layer is not currently part of any style, this property is set to `nil`. */ -@property (nonatomic, weak, readwrite) MGLMapView *mapView; +@property (nonatomic, weak, readwrite) MGLStyle *style; @end @@ -112,24 +111,24 @@ void MGLFinishCustomStyleLayer(void *context) { #pragma mark - Adding to and removing from a map view -- (void)setMapView:(MGLMapView *)mapView { - if (_mapView && mapView) { +- (void)setStyle:(MGLStyle *)style { + if (_style && style) { [NSException raise:@"MGLLayerReuseException" format:@"%@ cannot be added to more than one MGLStyle at a time.", self]; } - _mapView.style.openGLLayers[self.identifier] = nil; - _mapView = mapView; - _mapView.style.openGLLayers[self.identifier] = self; + _style.openGLLayers[self.identifier] = nil; + _style = style; + _style.openGLLayers[self.identifier] = self; } -- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer { - self.mapView = mapView; - [super addToMapView:mapView belowLayer:otherLayer]; +- (void)addToStyle:(MGLStyle *)style belowLayer:(MGLStyleLayer *)otherLayer { + self.style = style; + [super addToStyle:style belowLayer:otherLayer]; } -- (void)removeFromMapView:(MGLMapView *)mapView { - [super removeFromMapView:mapView]; - self.mapView = nil; +- (void)removeFromStyle:(MGLStyle *)style { + [super removeFromStyle:style]; + self.style = nil; } /** @@ -193,7 +192,7 @@ void MGLFinishCustomStyleLayer(void *context) { causing the `-drawInMapView:withContext:` method to be called. */ - (void)setNeedsDisplay { - [self.mapView setNeedsGLDisplay]; + [self.style.mapView setNeedsGLDisplay]; } @end diff --git a/platform/darwin/src/MGLRasterStyleLayer.h b/platform/darwin/src/MGLRasterStyleLayer.h index 53a6a98b8a..09fafd114d 100644 --- a/platform/darwin/src/MGLRasterStyleLayer.h +++ b/platform/darwin/src/MGLRasterStyleLayer.h @@ -28,9 +28,6 @@ NS_ASSUME_NONNULL_BEGIN ### Example ```swift - let layer = MGLRasterStyleLayer(identifier: "clouds", source: source) - layer.rasterOpacity = MGLStyleValue(rawValue: 0.5) - mapView.style?.addLayer(layer) ``` */ MGL_EXPORT diff --git a/platform/darwin/src/MGLShapeSource.mm b/platform/darwin/src/MGLShapeSource.mm index 023a81bba8..11b1d8eca8 100644 --- a/platform/darwin/src/MGLShapeSource.mm +++ b/platform/darwin/src/MGLShapeSource.mm @@ -1,5 +1,6 @@ #import "MGLShapeSource_Private.h" +#import "MGLStyle_Private.h" #import "MGLMapView_Private.h" #import "MGLSource_Private.h" #import "MGLFeature_Private.h" @@ -96,8 +97,8 @@ const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance = @"MGLSh } std::vector<mbgl::Feature> features; - if (self.mapView) { - features = self.mapView.mbglMap->querySourceFeatures(self.rawSource->getID(), { {}, optionalFilter }); + if (self.style) { + features = self.style.mapView.mbglMap->querySourceFeatures(self.rawSource->getID(), { {}, optionalFilter }); } return MGLFeaturesFromMBGLFeatures(features); } diff --git a/platform/darwin/src/MGLSource.h b/platform/darwin/src/MGLSource.h index a504a01791..8d8c936833 100644 --- a/platform/darwin/src/MGLSource.h +++ b/platform/darwin/src/MGLSource.h @@ -16,7 +16,7 @@ NS_ASSUME_NONNULL_BEGIN add and remove sources dynamically using methods such as `-[MGLStyle addSource:]` and `-[MGLStyle sourceWithIdentifier:]`. - Create instances of `MGLShapeSource` and the concrete subclasses of + Create instances of `MGLShapeSource`, `MGLImageSource` and the concrete subclasses of `MGLTileSource` (`MGLVectorSource` and `MGLRasterSource`) in order to use `MGLSource`'s properties and methods. Do not create instances of `MGLSource` directly, and do not create your own subclasses of this class. diff --git a/platform/darwin/src/MGLSource.mm b/platform/darwin/src/MGLSource.mm index eb859ba2c0..ee012f4d66 100644 --- a/platform/darwin/src/MGLSource.mm +++ b/platform/darwin/src/MGLSource.mm @@ -1,7 +1,7 @@ #import "MGLSource_Private.h" -#import "MGLMapView_Private.h" +#import "MGLStyle_Private.h" -#include <mbgl/map/map.hpp> +#include <mbgl/style/style.hpp> #include <mbgl/style/source.hpp> @interface MGLSource () @@ -10,7 +10,7 @@ // special internal source types like mbgl::AnnotationSource. @property (nonatomic, readonly) mbgl::style::Source *rawSource; -@property (nonatomic, readonly, weak) MGLMapView *mapView; +@property (nonatomic, readonly, weak) MGLStyle *style; @end @@ -43,21 +43,21 @@ return self; } -- (void)addToMapView:(MGLMapView *)mapView { +- (void)addToStyle:(MGLStyle *)style { 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]; + "to the style more than once is invalid.", self, style]; } - _mapView = mapView; - mapView.mbglMap->addSource(std::move(_pendingSource)); + _style = style; + style.rawStyle->addSource(std::move(_pendingSource)); } -- (void)removeFromMapView:(MGLMapView *)mapView { - if (self.rawSource == mapView.mbglMap->getSource(self.identifier.UTF8String)) { - _pendingSource = mapView.mbglMap->removeSource(self.identifier.UTF8String); - _mapView = nil; +- (void)removeFromStyle:(MGLStyle *)style { + if (self.rawSource == style.rawStyle->getSource(self.identifier.UTF8String)) { + _pendingSource = style.rawStyle->removeSource(self.identifier.UTF8String); + _style = nil; } } diff --git a/platform/darwin/src/MGLSource_Private.h b/platform/darwin/src/MGLSource_Private.h index 91bfac6390..ba78973279 100644 --- a/platform/darwin/src/MGLSource_Private.h +++ b/platform/darwin/src/MGLSource_Private.h @@ -18,7 +18,7 @@ struct SourceWrapper { __weak MGLSource *source; }; -@class MGLMapView; +@class MGLStyle; @interface MGLSource (Private) @@ -44,33 +44,33 @@ struct SourceWrapper { @property (nonatomic, readonly) mbgl::style::Source *rawSource; /** - The map view whose style currently contains the source. + The style which currently contains the source. - If the source is not currently part of any map view’s style, this property is + If the source is not currently part of a style, this property is set to `nil`. */ -@property (nonatomic, readonly, weak) MGLMapView *mapView; +@property (nonatomic, readonly, weak) MGLStyle *style; /** - Adds the mbgl source that this object represents to the mbgl map. + Adds the mbgl source that this object represents to the style. Once a mbgl source is added, ownership of the object is transferred to the - `mbgl::Map` and this object no longer has an active unique_ptr reference to the + `mbgl::Style` and this object no longer has an active unique_ptr reference to the `mbgl::Source`. If this object's mbgl source is in that state, the mbgl source can still be changed but the changes will not be visible until the `MGLSource` - is added back to the map via `-[MGLStyle addSource:]` and styled with a + is added back to the style via `-[MGLStyle addSource:]` and styled with a `MGLLayer`. */ -- (void)addToMapView:(MGLMapView *)mapView; +- (void)addToStyle:(MGLStyle *)style; /** - Removes the mbgl source that this object represents from the mbgl map. + Removes the mbgl source that this object represents from the style. When a mbgl source is removed, ownership of the object is transferred back to the `MGLSource` instance and the unique_ptr reference is valid again. It is safe to add the source back to the style after it is removed. */ -- (void)removeFromMapView:(MGLMapView *)mapView; +- (void)removeFromStyle:(MGLStyle *)style; @end diff --git a/platform/darwin/src/MGLStyle.h b/platform/darwin/src/MGLStyle.h index 8ffd7db2b2..6fb4a6cc6b 100644 --- a/platform/darwin/src/MGLStyle.h +++ b/platform/darwin/src/MGLStyle.h @@ -32,51 +32,14 @@ NS_ASSUME_NONNULL_BEGIN static MGL_EXPORT const NSInteger MGLStyleDefaultVersion = 10; /** - An `MGLStyle` object represents the active map style of an `MGLMapView`. A - style defines both the map’s content and every aspect of its appearance. Styles - can be designed in - <a href="https://www.mapbox.com/studio/">Mapbox Studio</a> and hosted on - mapbox.com. `MGLStyle` provides methods for inspecting and manipulating a style - dynamically, with classes and properties that parallel the style JSON format - defined by the - <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/">Mapbox Style Specification</a>. - - You set a map view’s active style using the `MGLMapView.styleURL` property. - `MGLStyle` provides a set of convenience methods that return the URLs of - <a href="https://www.mapbox.com/maps/">popular Mapbox-designed styles</a>. - Once the `-[MGLMapViewDelegate mapView:didFinishLoadingStyle:]` or - `-[MGLMapViewDelegate mapViewDidFinishLoadingMap:]` method is called, signaling - that the style has finished loading, you can use the `MGLMapView.style` - property to obtain the map view’s `MGLStyle`. - - A style primarily consists of the following components: - - * _Content sources_ supply content to be shown on the map. Use methods such as - `-sourceWithIdentifier:` and `-addSource:` to configure the style’s content - sources, which are represented by `MGLSource` objects. - * _Style layers_ manage the layout and appearance of content at specific - z-indices in the style. Most kinds of style layers display content provided - by a content source. Use methods such as `-layerWithIdentifier:` and - `-addLayer:` to configure the style’s layers, which are represented by - `MGLStyleLayer` objects. - * _Style images_ are used as icons and patterns in style layers. Use the - `-setImage:forName:` method to register an image as a style image. - (Annotations are represented by annotation images rather than style images. - To configure an annotation’s appearance, use the - `-[MGLMapViewDelegate mapView:imageForAnnotation:]` method.) - * The style’s _light_ is the light source affecting any 3D extruded fills. - Use the `light` property to configure the style’s light, which is represented - by an `MGLLight` object. - - The `MGLStyle`, `MGLSource`, `MGLStyleLayer`, and `MGLLight` classes are - collectively known as the _runtime styling API_. The active style influences a - related API, visible feature querying, which is available through methods such - as `-[MGLMapView visibleFeaturesInRect:]`. - - Some terminology differs between the Mapbox Style Specification and the various - classes associated with `MGLStyle`. Consult the - “[Information for Style Authors](../for-style-authors.html)” guide for an - overview of these differences. + The proxy object for the current map style. + + MGLStyle provides a set of convenience methods for changing Mapbox + default styles using `-[MGLMapView styleURL]`. + <a href="https://www.mapbox.com/maps/">Learn more about Mapbox default styles</a>. + + It is also possible to directly manipulate the current map style + via `-[MGLMapView style]` by updating the style's data sources or layers. @note Wait until the map style has finished loading before modifying a map's style via any of the `MGLStyle` instance methods below. You can use the @@ -521,40 +484,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 eb838085d7..2365641f02 100644 --- a/platform/darwin/src/MGLStyle.mm +++ b/platform/darwin/src/MGLStyle.mm @@ -2,6 +2,7 @@ #import "MGLMapView_Private.h" #import "MGLStyleLayer.h" +#import "MGLStyleLayer_Private.h" #import "MGLFillStyleLayer.h" #import "MGLFillExtrusionStyleLayer.h" #import "MGLLineStyleLayer.h" @@ -11,23 +12,20 @@ #import "MGLBackgroundStyleLayer.h" #import "MGLOpenGLStyleLayer.h" -#import "MGLStyle_Private.h" -#import "MGLStyleLayer_Private.h" +#import "MGLSource.h" #import "MGLSource_Private.h" #import "MGLLight_Private.h" - -#import "NSDate+MGLAdditions.h" - -#import "MGLSource.h" #import "MGLTileSource_Private.h" #import "MGLVectorSource.h" #import "MGLRasterSource.h" #import "MGLShapeSource.h" +#import "MGLImageSource.h" #import "MGLAttributionInfo_Private.h" #include <mbgl/map/map.hpp> #include <mbgl/util/default_styles.hpp> +#include <mbgl/style/style.hpp> #include <mbgl/style/image.hpp> #include <mbgl/style/light.hpp> #include <mbgl/style/layers/fill_layer.hpp> @@ -41,6 +39,9 @@ #include <mbgl/style/sources/geojson_source.hpp> #include <mbgl/style/sources/vector_source.hpp> #include <mbgl/style/sources/raster_source.hpp> +#include <mbgl/style/sources/image_source.hpp> + +#import "NSDate+MGLAdditions.h" #if TARGET_OS_IPHONE #import "UIImage+MGLAdditions.h" @@ -50,7 +51,8 @@ @interface MGLStyle() -@property (nonatomic, readwrite, weak) MGLMapView *mapView; +@property (nonatomic, readonly, weak) MGLMapView *mapView; +@property (nonatomic, readonly) mbgl::style::Style *rawStyle; @property (readonly, copy, nullable) NSURL *URL; @property (nonatomic, readwrite, strong) NS_MUTABLE_DICTIONARY_OF(NSString *, MGLOpenGLStyleLayer *) *openGLLayers; @@ -112,27 +114,28 @@ static NSURL *MGLStyleURL_emerald; #pragma mark - -- (instancetype)initWithMapView:(MGLMapView *)mapView { +- (instancetype)initWithRawStyle:(mbgl::style::Style *)rawStyle mapView:(MGLMapView *)mapView { if (self = [super init]) { _mapView = mapView; + _rawStyle = rawStyle; _openGLLayers = [NSMutableDictionary dictionary]; } return self; } - (NSURL *)URL { - return [NSURL URLWithString:@(self.mapView.mbglMap->getStyleURL().c_str())]; + return [NSURL URLWithString:@(self.rawStyle->getURL().c_str())]; } - (NSString *)name { - std::string name = self.mapView.mbglMap->getStyleName(); + std::string name = self.rawStyle->getName(); return name.empty() ? nil : @(name.c_str()); } #pragma mark Sources - (NS_SET_OF(__kindof MGLSource *) *)sources { - auto rawSources = self.mapView.mbglMap->getSources(); + auto rawSources = self.rawStyle->getSources(); NS_MUTABLE_SET_OF(__kindof MGLSource *) *sources = [NSMutableSet setWithCapacity:rawSources.size()]; for (auto rawSource = rawSources.begin(); rawSource != rawSources.end(); ++rawSource) { MGLSource *source = [self sourceFromMBGLSource:*rawSource]; @@ -151,8 +154,7 @@ static NSURL *MGLStyleURL_emerald; } - (NSUInteger)countOfSources { - auto rawSources = self.mapView.mbglMap->getSources(); - return rawSources.size(); + return self.rawStyle->getSources().size(); } - (MGLSource *)memberOfSources:(MGLSource *)object { @@ -161,7 +163,7 @@ static NSURL *MGLStyleURL_emerald; - (MGLSource *)sourceWithIdentifier:(NSString *)identifier { - auto rawSource = self.mapView.mbglMap->getSource(identifier.UTF8String); + auto rawSource = self.rawStyle->getSource(identifier.UTF8String); return rawSource ? [self sourceFromMBGLSource:rawSource] : nil; } @@ -178,6 +180,8 @@ static NSURL *MGLStyleURL_emerald; return [[MGLShapeSource alloc] initWithRawSource:geoJSONSource]; } else if (auto rasterSource = rawSource->as<mbgl::style::RasterSource>()) { return [[MGLRasterSource alloc] initWithRawSource:rasterSource]; + } else if (auto imageSource = rawSource->as<mbgl::style::ImageSource>()) { + return [[MGLImageSource alloc] initWithRawSource:imageSource]; } else { return [[MGLSource alloc] initWithRawSource:rawSource]; } @@ -193,7 +197,7 @@ static NSURL *MGLStyleURL_emerald; } try { - [source addToMapView:self.mapView]; + [source addToStyle:self]; } catch (std::runtime_error & err) { [NSException raise:@"MGLRedundantSourceIdentifierException" format:@"%s", err.what()]; } @@ -207,14 +211,14 @@ static NSURL *MGLStyleURL_emerald; @"Make sure the source was created as a member of a concrete subclass of MGLSource.", source]; } - [source removeFromMapView:self.mapView]; + [source removeFromStyle:self]; } - (nullable NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfosWithFontSize:(CGFloat)fontSize linkColor:(nullable MGLColor *)linkColor { // It’d be incredibly convenient to use -sources here, but this operation // depends on the sources being sorted in ascending order by creation, as // with the std::vector used in mbgl. - auto rawSources = self.mapView.mbglMap->getSources(); + auto rawSources = self.rawStyle->getSources(); NSMutableArray *infos = [NSMutableArray arrayWithCapacity:rawSources.size()]; for (auto rawSource = rawSources.begin(); rawSource != rawSources.end(); ++rawSource) { MGLTileSource *source = (MGLTileSource *)[self sourceFromMBGLSource:*rawSource]; @@ -232,7 +236,7 @@ static NSURL *MGLStyleURL_emerald; - (NS_ARRAY_OF(__kindof MGLStyleLayer *) *)layers { - auto layers = self.mapView.mbglMap->getLayers(); + auto layers = self.rawStyle->getLayers(); NS_MUTABLE_ARRAY_OF(__kindof MGLStyleLayer *) *styleLayers = [NSMutableArray arrayWithCapacity:layers.size()]; for (auto layer : layers) { MGLStyleLayer *styleLayer = [self layerFromMBGLLayer:layer]; @@ -252,12 +256,12 @@ static NSURL *MGLStyleURL_emerald; - (NSUInteger)countOfLayers { - return self.mapView.mbglMap->getLayers().size(); + return self.rawStyle->getLayers().size(); } - (MGLStyleLayer *)objectInLayersAtIndex:(NSUInteger)index { - auto layers = self.mapView.mbglMap->getLayers(); + auto layers = self.rawStyle->getLayers(); if (index >= layers.size()) { [NSException raise:NSRangeException format:@"No style layer at index %lu.", (unsigned long)index]; @@ -269,7 +273,7 @@ static NSURL *MGLStyleURL_emerald; - (void)getLayers:(MGLStyleLayer **)buffer range:(NSRange)inRange { - auto layers = self.mapView.mbglMap->getLayers(); + auto layers = self.rawStyle->getLayers(); if (NSMaxRange(inRange) > layers.size()) { [NSException raise:NSRangeException format:@"Style layer range %@ is out of bounds.", NSStringFromRange(inRange)]; @@ -289,21 +293,21 @@ static NSURL *MGLStyleURL_emerald; @"Make sure the style layer was created as a member of a concrete subclass of MGLStyleLayer.", styleLayer]; } - auto layers = self.mapView.mbglMap->getLayers(); + auto layers = self.rawStyle->getLayers(); if (index > layers.size()) { [NSException raise:NSRangeException format:@"Cannot insert style layer at out-of-bounds index %lu.", (unsigned long)index]; } else if (index == 0) { try { MGLStyleLayer *sibling = layers.size() ? [self layerFromMBGLLayer:layers.at(0)] : nil; - [styleLayer addToMapView:self.mapView belowLayer:sibling]; + [styleLayer addToStyle:self belowLayer:sibling]; } catch (const std::runtime_error & err) { [NSException raise:@"MGLRedundantLayerIdentifierException" format:@"%s", err.what()]; } } else { try { MGLStyleLayer *sibling = [self layerFromMBGLLayer:layers.at(index)]; - [styleLayer addToMapView:self.mapView belowLayer:sibling]; + [styleLayer addToStyle:self belowLayer:sibling]; } catch (std::runtime_error & err) { [NSException raise:@"MGLRedundantLayerIdentifierException" format:@"%s", err.what()]; } @@ -312,14 +316,14 @@ static NSURL *MGLStyleURL_emerald; - (void)removeObjectFromLayersAtIndex:(NSUInteger)index { - auto layers = self.mapView.mbglMap->getLayers(); + auto layers = self.rawStyle->getLayers(); if (index >= layers.size()) { [NSException raise:NSRangeException format:@"Cannot remove style layer at out-of-bounds index %lu.", (unsigned long)index]; } auto layer = layers.at(index); MGLStyleLayer *styleLayer = [self layerFromMBGLLayer:layer]; - [styleLayer removeFromMapView:self.mapView]; + [styleLayer removeFromStyle:self]; } - (MGLStyleLayer *)layerFromMBGLLayer:(mbgl::style::Layer *)rawLayer @@ -354,7 +358,7 @@ static NSURL *MGLStyleURL_emerald; - (MGLStyleLayer *)layerWithIdentifier:(NSString *)identifier { - auto mbglLayer = self.mapView.mbglMap->getLayer(identifier.UTF8String); + auto mbglLayer = self.rawStyle->getLayer(identifier.UTF8String); return mbglLayer ? [self layerFromMBGLLayer:mbglLayer] : nil; } @@ -367,7 +371,7 @@ static NSURL *MGLStyleURL_emerald; layer]; } [self willChangeValueForKey:@"layers"]; - [layer removeFromMapView:self.mapView]; + [layer removeFromStyle:self]; [self didChangeValueForKey:@"layers"]; } @@ -381,7 +385,7 @@ static NSURL *MGLStyleURL_emerald; } [self willChangeValueForKey:@"layers"]; try { - [layer addToMapView:self.mapView belowLayer:nil]; + [layer addToStyle:self belowLayer:nil]; } catch (std::runtime_error & err) { [NSException raise:@"MGLRedundantLayerIdentifierException" format:@"%s", err.what()]; } @@ -410,7 +414,7 @@ static NSURL *MGLStyleURL_emerald; } [self willChangeValueForKey:@"layers"]; try { - [layer addToMapView:self.mapView belowLayer:sibling]; + [layer addToStyle:self belowLayer:sibling]; } catch (std::runtime_error & err) { [NSException raise:@"MGLRedundantLayerIdentifierException" format:@"%s", err.what()]; } @@ -433,7 +437,7 @@ static NSURL *MGLStyleURL_emerald; sibling]; } - auto layers = self.mapView.mbglMap->getLayers(); + auto layers = self.rawStyle->getLayers(); std::string siblingIdentifier = sibling.identifier.UTF8String; NSUInteger index = 0; for (auto layer : layers) { @@ -452,14 +456,14 @@ static NSURL *MGLStyleURL_emerald; sibling]; } else if (index + 1 == layers.size()) { try { - [layer addToMapView:self.mapView belowLayer:nil]; + [layer addToStyle:self belowLayer:nil]; } catch (std::runtime_error & err) { [NSException raise:@"MGLRedundantLayerIdentifierException" format:@"%s", err.what()]; } } else { MGLStyleLayer *sibling = [self layerFromMBGLLayer:layers.at(index + 1)]; try { - [layer addToMapView:self.mapView belowLayer:sibling]; + [layer addToStyle:self belowLayer:sibling]; } catch (std::runtime_error & err) { [NSException raise:@"MGLRedundantLayerIdentifierException" format:@"%s", err.what()]; } @@ -471,60 +475,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 @@ -540,7 +516,7 @@ static NSURL *MGLStyleURL_emerald; format:@"Cannot assign image %@ to a nil name.", image]; } - self.mapView.mbglMap->addImage([name UTF8String], image.mgl_styleImage); + self.rawStyle->addImage([image mgl_styleImageWithIdentifier:name]); } - (void)removeImageForName:(NSString *)name @@ -550,7 +526,7 @@ static NSURL *MGLStyleURL_emerald; format:@"Cannot remove image with nil name."]; } - self.mapView.mbglMap->removeImage([name UTF8String]); + self.rawStyle->removeImage([name UTF8String]); } - (MGLImage *)imageForName:(NSString *)name @@ -560,7 +536,7 @@ static NSURL *MGLStyleURL_emerald; format:@"Cannot get image with nil name."]; } - auto styleImage = self.mapView.mbglMap->getImage([name UTF8String]); + auto styleImage = self.rawStyle->getImage([name UTF8String]); return styleImage ? [[MGLImage alloc] initWithMGLStyleImage:styleImage] : nil; } @@ -568,17 +544,17 @@ static NSURL *MGLStyleURL_emerald; - (void)setTransition:(MGLTransition)transition { - auto transitionOptions = self.mapView.mbglMap->getTransitionOptions(); + auto transitionOptions = self.rawStyle->getTransitionOptions(); transitionOptions.duration = MGLDurationFromTimeInterval(transition.duration); transitionOptions.delay = MGLDurationFromTimeInterval(transition.delay); - self.mapView.mbglMap->setTransitionOptions(transitionOptions); + self.rawStyle->setTransitionOptions(transitionOptions); } - (MGLTransition)transition { MGLTransition transition; - const mbgl::style::TransitionOptions transitionOptions = self.mapView.mbglMap->getTransitionOptions(); + const mbgl::style::TransitionOptions transitionOptions = self.rawStyle->getTransitionOptions(); transition.delay = MGLTimeIntervalFromDuration(transitionOptions.delay.value_or(mbgl::Duration::zero())); transition.duration = MGLTimeIntervalFromDuration(transitionOptions.duration.value_or(mbgl::Duration::zero())); @@ -591,12 +567,12 @@ static NSURL *MGLStyleURL_emerald; - (void)setLight:(MGLLight *)light { std::unique_ptr<mbgl::style::Light> mbglLight = std::make_unique<mbgl::style::Light>([light mbglLight]); - self.mapView.mbglMap->setLight(std::move(mbglLight)); + self.rawStyle->setLight(std::move(mbglLight)); } - (MGLLight *)light { - auto mbglLight = self.mapView.mbglMap->getLight(); + auto mbglLight = self.rawStyle->getLight(); MGLLight *light = [[MGLLight alloc] initWithMBGLLight:mbglLight]; return light; } diff --git a/platform/darwin/src/MGLStyleLayer.mm b/platform/darwin/src/MGLStyleLayer.mm index 4bfaea934b..6400b8fcbf 100644 --- a/platform/darwin/src/MGLStyleLayer.mm +++ b/platform/darwin/src/MGLStyleLayer.mm @@ -1,7 +1,7 @@ #import "MGLStyleLayer_Private.h" -#import "MGLMapView_Private.h" +#import "MGLStyle_Private.h" -#include <mbgl/map/map.hpp> +#include <mbgl/style/style.hpp> #include <mbgl/style/layer.hpp> @interface MGLStyleLayer () @@ -30,26 +30,26 @@ return self; } -- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer +- (void)addToStyle:(MGLStyle *)style 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]; + "to the style more than once is invalid.", self, style]; } if (otherLayer) { const mbgl::optional<std::string> belowLayerId{otherLayer.identifier.UTF8String}; - mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId); + style.rawStyle->addLayer(std::move(_pendingLayer), belowLayerId); } else { - mapView.mbglMap->addLayer(std::move(_pendingLayer)); + style.rawStyle->addLayer(std::move(_pendingLayer)); } } -- (void)removeFromMapView:(MGLMapView *)mapView +- (void)removeFromStyle:(MGLStyle *)style { - if (self.rawLayer == mapView.mbglMap->getLayer(self.identifier.UTF8String)) { - _pendingLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String); + if (self.rawLayer == style.rawStyle->getLayer(self.identifier.UTF8String)) { + _pendingLayer = style.rawStyle->removeLayer(self.identifier.UTF8String); } } diff --git a/platform/darwin/src/MGLStyleLayer_Private.h b/platform/darwin/src/MGLStyleLayer_Private.h index ed8ec31755..9bee013c3d 100644 --- a/platform/darwin/src/MGLStyleLayer_Private.h +++ b/platform/darwin/src/MGLStyleLayer_Private.h @@ -34,7 +34,7 @@ struct LayerWrapper { } \ } while (NO); -@class MGLMapView; +@class MGLStyle; @interface MGLStyleLayer (Private) @@ -69,7 +69,7 @@ struct LayerWrapper { `mbgl::Map` and this object no longer has an active unique_ptr reference to the `mbgl::style::Layer`. */ -- (void)addToMapView:(MGLMapView *)mapView belowLayer:(nullable MGLStyleLayer *)otherLayer; +- (void)addToStyle:(MGLStyle *)style belowLayer:(nullable MGLStyleLayer *)otherLayer; /** Removes the mbgl style layer that this object represents from the mbgl map. @@ -78,7 +78,7 @@ struct LayerWrapper { to the `MGLStyleLayer` instance and the unique_ptr reference is valid again. It is safe to add the layer back to the style after it is removed. */ -- (void)removeFromMapView:(MGLMapView *)mapView; +- (void)removeFromStyle:(MGLStyle *)style; @end diff --git a/platform/darwin/src/MGLStyle_Private.h b/platform/darwin/src/MGLStyle_Private.h index 23ce8fbee0..92b08e844b 100644 --- a/platform/darwin/src/MGLStyle_Private.h +++ b/platform/darwin/src/MGLStyle_Private.h @@ -5,15 +5,22 @@ NS_ASSUME_NONNULL_BEGIN +namespace mbgl { + namespace style { + class Style; + } +} + @class MGLAttributionInfo; @class MGLMapView; @class MGLOpenGLStyleLayer; @interface MGLStyle (Private) -- (instancetype)initWithMapView:(MGLMapView *)mapView; +- (instancetype)initWithRawStyle:(mbgl::style::Style *)rawStyle mapView:(MGLMapView *)mapView; @property (nonatomic, readonly, weak) MGLMapView *mapView; +@property (nonatomic, readonly) mbgl::style::Style *rawStyle; - (nullable NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfosWithFontSize:(CGFloat)fontSize linkColor:(nullable MGLColor *)linkColor; diff --git a/platform/darwin/src/MGLSymbolStyleLayer.h b/platform/darwin/src/MGLSymbolStyleLayer.h index b6c6372324..8512870e1b 100644 --- a/platform/darwin/src/MGLSymbolStyleLayer.h +++ b/platform/darwin/src/MGLSymbolStyleLayer.h @@ -265,16 +265,6 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) { ### Example ```swift - let layer = MGLSymbolStyleLayer(identifier: "coffeeshops", source: pois) - layer.sourceLayerIdentifier = "pois" - layer.iconImageName = MGLStyleValue(rawValue: "coffee") - layer.iconScale = MGLStyleValue(rawValue: 0.5) - layer.text = MGLStyleValue(rawValue: "{name}") - layer.textTranslation = MGLStyleValue(rawValue: NSValue(cgVector: CGVector(dx: 10, dy: 0))) - layer.textJustification = MGLStyleValue(rawValue: NSValue(mglTextJustification: .left)) - layer.textAnchor = MGLStyleValue(rawValue: NSValue(mglTextAnchor: .left)) - layer.predicate = NSPredicate(format: "%K == %@", "venue-type", "coffee") - mapView.style?.addLayer(layer) ``` */ MGL_EXPORT @@ -533,7 +523,11 @@ MGL_EXPORT @property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *iconRotationAlignment; /** - Scale factor for icon. 1 is original size, 3 triples the size. + Scales the original size of the icon by the provided factor. The new point size + of the image will be the original point size multiplied by `iconSize`. 1 is the + original size; 3 triples the size of the image. + + This property is measured in factor of the original icon sizes. 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 diff --git a/platform/darwin/src/MGLVectorSource.mm b/platform/darwin/src/MGLVectorSource.mm index 5e9f4f4a6e..7265690f4d 100644 --- a/platform/darwin/src/MGLVectorSource.mm +++ b/platform/darwin/src/MGLVectorSource.mm @@ -3,6 +3,7 @@ #import "MGLFeature_Private.h" #import "MGLSource_Private.h" #import "MGLTileSource_Private.h" +#import "MGLStyle_Private.h" #import "MGLMapView_Private.h" #import "NSPredicate+MGLAdditions.h" #import "NSURL+MGLAdditions.h" @@ -62,8 +63,8 @@ } std::vector<mbgl::Feature> features; - if (self.mapView) { - features = self.mapView.mbglMap->querySourceFeatures(self.rawSource->getID(), { optionalSourceLayerIDs, optionalFilter }); + if (self.style) { + features = self.style.mapView.mbglMap->querySourceFeatures(self.rawSource->getID(), { optionalSourceLayerIDs, optionalFilter }); } return MGLFeaturesFromMBGLFeatures(features); } diff --git a/platform/darwin/src/NSValue+MGLAdditions.h b/platform/darwin/src/NSValue+MGLAdditions.h index 0aaa2a337a..f3026a389f 100644 --- a/platform/darwin/src/NSValue+MGLAdditions.h +++ b/platform/darwin/src/NSValue+MGLAdditions.h @@ -56,6 +56,20 @@ NS_ASSUME_NONNULL_BEGIN */ @property (readonly) MGLCoordinateBounds MGLCoordinateBoundsValue; +/** + Creates a new value object containing the specified Mapbox coordinate + quad structure. + + @param quad The value for the new object. + @return A new value object that contains the coordinate quad information. + */ ++ (instancetype)valueWithMGLCoordinateQuad:(MGLCoordinateQuad)quad; + +/** + The Mapbox coordinate quad structure representation of the value. + */ +- (MGLCoordinateQuad)MGLCoordinateQuadValue; + #pragma mark Working with Offline Map Values /** diff --git a/platform/darwin/src/NSValue+MGLAdditions.m b/platform/darwin/src/NSValue+MGLAdditions.m index ef894f0eb4..1383056944 100644 --- a/platform/darwin/src/NSValue+MGLAdditions.m +++ b/platform/darwin/src/NSValue+MGLAdditions.m @@ -34,6 +34,16 @@ return bounds; } ++ (instancetype)valueWithMGLCoordinateQuad:(MGLCoordinateQuad)quad { + return [self valueWithBytes:&quad objCType:@encode(MGLCoordinateQuad)]; +} + +- (MGLCoordinateQuad)MGLCoordinateQuadValue { + MGLCoordinateQuad quad; + [self getValue:&quad]; + return quad; +} + #pragma mark Offline maps + (NSValue *)valueWithMGLOfflinePackProgress:(MGLOfflinePackProgress)progress { diff --git a/platform/darwin/src/nsthread.mm b/platform/darwin/src/nsthread.mm index 6caa1be43e..458db968d8 100644 --- a/platform/darwin/src/nsthread.mm +++ b/platform/darwin/src/nsthread.mm @@ -15,7 +15,8 @@ std::string getCurrentThreadName() { } void setCurrentThreadName(const std::string& name) { - pthread_setname_np(name.c_str()); + std::string qualifiedName = "com.mapbox.mbgl." + name; + pthread_setname_np(qualifiedName.c_str()); } void makeThreadLowPriority() { diff --git a/platform/darwin/test/MGLDocumentationExampleTests.swift b/platform/darwin/test/MGLDocumentationExampleTests.swift index 48e6b17f44..ae72b35d82 100644 --- a/platform/darwin/test/MGLDocumentationExampleTests.swift +++ b/platform/darwin/test/MGLDocumentationExampleTests.swift @@ -104,6 +104,20 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate { XCTAssertNotNil(mapView.style?.source(withIdentifier: "pois")) } + func testMGLImageSource() { + //#-example-code + let coordinates = MGLCoordinateQuad( + topLeft: CLLocationCoordinate2D(latitude: 46.437, longitude: -80.425), + bottomLeft: CLLocationCoordinate2D(latitude: 37.936, longitude: -80.425), + bottomRight: CLLocationCoordinate2D(latitude: 37.936, longitude: -71.516), + topRight: CLLocationCoordinate2D(latitude: 46.437, longitude: -71.516)) + let source = MGLImageSource(identifier: "radar", coordinateQuad: coordinates, url: URL(string: "https://www.mapbox.com/mapbox-gl-js/assets/radar.gif")!) + mapView.style?.addSource(source) + //#-end-example-code + + XCTAssertNotNil(mapView.style?.source(withIdentifier: "radar")) + } + func testMGLCircleStyleLayer() { let population = MGLVectorSource(identifier: "population", configurationURL: URL(string: "https://example.com/style.json")!) mapView.style?.addSource(population) diff --git a/platform/darwin/test/MGLGeometryTests.mm b/platform/darwin/test/MGLGeometryTests.mm index 220a837643..1c85470188 100644 --- a/platform/darwin/test/MGLGeometryTests.mm +++ b/platform/darwin/test/MGLGeometryTests.mm @@ -144,4 +144,23 @@ XCTAssertEqualObjects(serializedGeoJSON, geoJSON, @"MGLPointFeature should serialize as a GeoJSON point feature."); } +- (void)testMGLCoordinateBoundsToMGLCoordinateQuad { + MGLCoordinateBounds bounds = MGLCoordinateBoundsMake(CLLocationCoordinate2DMake(37.936, -80.425), + CLLocationCoordinate2DMake(46.437, -71.516)); + + MGLCoordinateQuad quad = MGLCoordinateQuadFromCoordinateBounds(bounds); + XCTAssertEqualObjects([NSValue valueWithMGLCoordinate:bounds.sw], + [NSValue valueWithMGLCoordinate:quad.bottomLeft], + @"Bounds southwest should be bottom left of quad."); + XCTAssertEqualObjects([NSValue valueWithMGLCoordinate:bounds.ne], + [NSValue valueWithMGLCoordinate:quad.topRight], + @"Bounds northeast should be top right of quad."); + + XCTAssertEqualObjects([NSValue valueWithMGLCoordinate:CLLocationCoordinate2DMake(46.437, -80.425)], + [NSValue valueWithMGLCoordinate:quad.topLeft], + @"Quad top left should be computed correctly."); + XCTAssertEqualObjects([NSValue valueWithMGLCoordinate:CLLocationCoordinate2DMake(37.936, -71.516)], + [NSValue valueWithMGLCoordinate:quad.bottomRight], + @"Quad bottom right should be computed correctly."); +} @end diff --git a/platform/darwin/test/MGLImageSourceTests.m b/platform/darwin/test/MGLImageSourceTests.m new file mode 100644 index 0000000000..38fcd38709 --- /dev/null +++ b/platform/darwin/test/MGLImageSourceTests.m @@ -0,0 +1,42 @@ +#import <XCTest/XCTest.h> + +#import <Mapbox/Mapbox.h> + +@interface MGLImageSourceTests : XCTestCase + +@end + +@implementation MGLImageSourceTests + + +- (void)testMGLImageSourceWithImageURL { + + MGLCoordinateQuad quad = { { 80, 37}, { 81, 37}, { 81, 39}, { 80, 39}}; + MGLImageSource *source = [[MGLImageSource alloc] initWithIdentifier:@"source-id" coordinateQuad:quad URL:[NSURL URLWithString:@"http://host/image.png"]]; + + XCTAssertNotNil(source.URL); + XCTAssertEqualObjects(source.URL.absoluteString, @"http://host/image.png"); + XCTAssertNil(source.image); +} + +- (void)testMGLImageSourceWithImage { + + NSString *imageName = @"RadarImage"; +#if TARGET_OS_IPHONE + MGLImage *image = [MGLImage imageNamed:imageName + inBundle:[NSBundle bundleForClass:[self class]] + compatibleWithTraitCollection:nil]; +#else + MGLImage *image = [[NSBundle bundleForClass:[self class]] imageForResource:imageName]; +#endif + XCTAssertNotNil(image); + + MGLCoordinateQuad quad = { { 80, 37}, { 81, 37}, { 81, 39}, { 80, 39}}; + MGLImageSource *source = [[MGLImageSource alloc] initWithIdentifier:@"source-id" coordinateQuad:quad image:image]; + + XCTAssertNotNil(source.image); + XCTAssertEqualObjects(source.image, image); + XCTAssertNil(source.URL); +} + +@end diff --git a/platform/darwin/test/MGLLightTest.mm b/platform/darwin/test/MGLLightTest.mm index 8f901cbb72..de64d57851 100644 --- a/platform/darwin/test/MGLLightTest.mm +++ b/platform/darwin/test/MGLLightTest.mm @@ -18,7 +18,7 @@ @implementation MGLLightTest - (void)testProperties { - + MGLTransition defaultTransition = MGLTransitionMake(0, 0); MGLTransition transition = MGLTransitionMake(6, 3); mbgl::style::TransitionOptions transitionOptions { { MGLDurationFromTimeInterval(6) }, { MGLDurationFromTimeInterval(3) } }; @@ -35,9 +35,7 @@ XCTAssertEqual(anchorValue.MGLLightAnchorValue, MGLLightAnchorViewport); mbgl::style::PropertyValue<mbgl::style::LightAnchorType> propertyValue = { mbgl::style::LightAnchorType::Viewport }; - light.setAnchor(propertyValue); - mglLight = [[MGLLight alloc] initWithMBGLLight:&light]; lightFromMGLlight = [mglLight mbglLight]; @@ -55,14 +53,12 @@ XCTAssert(positionTransition.delay && MGLTimeIntervalFromDuration(*positionTransition.delay) == defaultTransition.delay); XCTAssert(positionTransition.duration && MGLTimeIntervalFromDuration(*positionTransition.duration) == defaultTransition.duration); - const std::array<float, 3> positionArray = { { 6, 180, 90 } }; + std::array<float, 3> positionArray = { { 6, 180, 90 } }; mbgl::style::Position position = { positionArray }; mbgl::style::PropertyValue<mbgl::style::Position> propertyValue = { position }; - light.setPosition(propertyValue); light.setPositionTransition(transitionOptions); - mglLight = [[MGLLight alloc] initWithMBGLLight:&light]; lightFromMGLlight = [mglLight mbglLight]; @@ -85,11 +81,9 @@ XCTAssert(colorTransition.duration && MGLTimeIntervalFromDuration(*colorTransition.duration) == defaultTransition.duration); mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } }; - light.setColor(propertyValue); light.setColorTransition(transitionOptions); - mglLight = [[MGLLight alloc] initWithMBGLLight:&light]; lightFromMGLlight = [mglLight mbglLight]; @@ -112,11 +106,9 @@ XCTAssert(intensityTransition.duration && MGLTimeIntervalFromDuration(*intensityTransition.duration) == defaultTransition.duration); mbgl::style::PropertyValue<float> propertyValue = { 0xff }; - light.setIntensity(propertyValue); light.setIntensityTransition(transitionOptions); - mglLight = [[MGLLight alloc] initWithMBGLLight:&light]; lightFromMGLlight = [mglLight mbglLight]; @@ -131,10 +123,10 @@ - (void)testValueAdditions { MGLSphericalPosition position = MGLSphericalPositionMake(1.15, 210, 30); - - XCTAssertEqual(@(position).MGLSphericalPositionValue.radial, position.radial); - XCTAssertEqual(@(position).MGLSphericalPositionValue.azimuthal, position.azimuthal); - XCTAssertEqual(@(position).MGLSphericalPositionValue.polar, position.polar); + + XCTAssertEqual([NSValue valueWithMGLSphericalPosition:position].MGLSphericalPositionValue.radial, position.radial); + XCTAssertEqual([NSValue valueWithMGLSphericalPosition:position].MGLSphericalPositionValue.azimuthal, position.azimuthal); + XCTAssertEqual([NSValue valueWithMGLSphericalPosition:position].MGLSphericalPositionValue.polar, position.polar); XCTAssertEqual([NSValue valueWithMGLLightAnchor:MGLLightAnchorMap].MGLLightAnchorValue, MGLLightAnchorMap); XCTAssertEqual([NSValue valueWithMGLLightAnchor:MGLLightAnchorViewport].MGLLightAnchorValue, MGLLightAnchorViewport); } diff --git a/platform/darwin/test/MGLLightTest.mm.ejs b/platform/darwin/test/MGLLightTest.mm.ejs index c1904d5ab8..5b1f27d8d1 100644 --- a/platform/darwin/test/MGLLightTest.mm.ejs +++ b/platform/darwin/test/MGLLightTest.mm.ejs @@ -22,7 +22,7 @@ @implementation MGLLightTest - (void)testProperties { - + MGLTransition defaultTransition = MGLTransitionMake(0, 0); MGLTransition transition = MGLTransitionMake(6, 3); mbgl::style::TransitionOptions transitionOptions { { MGLDurationFromTimeInterval(6) }, { MGLDurationFromTimeInterval(3) } }; @@ -48,17 +48,17 @@ <% } -%> <% if (property.type == "array") { -%> - const std::array<float, 3> positionArray = { { 6, 180, 90 } }; + std::array<float, 3> positionArray = { { 6, 180, 90 } }; mbgl::style::Position position = { positionArray }; mbgl::style::PropertyValue<mbgl::style::Position> propertyValue = { position }; <% } else { -%> mbgl::style::PropertyValue<<%- mbglType(property) %>> propertyValue = { <%- mbglTestValue(property, type) %> }; -<% } -%> +<% } -%> light.set<%- camelize(property.name) -%>(propertyValue); <% if (property.transition) { -%> light.set<%- camelize(property.name) -%>Transition(transitionOptions); -<% } -%> +<% } -%> mglLight = [[MGLLight alloc] initWithMBGLLight:&light]; lightFromMGLlight = [mglLight mbglLight]; @@ -76,7 +76,7 @@ - (void)testValueAdditions { MGLSphericalPosition position = MGLSphericalPositionMake(1.15, 210, 30); - + XCTAssertEqual([NSValue valueWithMGLSphericalPosition:position].MGLSphericalPositionValue.radial, position.radial); XCTAssertEqual([NSValue valueWithMGLSphericalPosition:position].MGLSphericalPositionValue.azimuthal, position.azimuthal); XCTAssertEqual([NSValue valueWithMGLSphericalPosition:position].MGLSphericalPositionValue.polar, position.polar); diff --git a/platform/darwin/test/MGLLineStyleLayerTests.mm b/platform/darwin/test/MGLLineStyleLayerTests.mm index 1e92959520..be7d9a6754 100644 --- a/platform/darwin/test/MGLLineStyleLayerTests.mm +++ b/platform/darwin/test/MGLLineStyleLayerTests.mm @@ -713,7 +713,7 @@ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff]; layer.lineWidth = constantStyleValue; - mbgl::style::PropertyValue<float> propertyValue = { 0xff }; + mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff }; XCTAssertEqual(rawLayer->getLineWidth(), propertyValue, @"Setting lineWidth to a constant value should update line-width."); XCTAssertEqualObjects(layer.lineWidth, constantStyleValue, @@ -730,6 +730,29 @@ XCTAssertEqualObjects(layer.lineWidth, functionStyleValue, @"lineWidth should round-trip camera functions."); + functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil]; + layer.lineWidth = functionStyleValue; + + mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 }; + propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops }; + + XCTAssertEqual(rawLayer->getLineWidth(), propertyValue, + @"Setting lineWidth to a source function should update line-width."); + XCTAssertEqualObjects(layer.lineWidth, functionStyleValue, + @"lineWidth should round-trip source functions."); + + functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil]; + layer.lineWidth = functionStyleValue; + + std::map<float, float> innerStops { {18, 0xff} }; + mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 }; + + propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops }; + + XCTAssertEqual(rawLayer->getLineWidth(), propertyValue, + @"Setting lineWidth to a composite function should update line-width."); + XCTAssertEqualObjects(layer.lineWidth, functionStyleValue, + @"lineWidth should round-trip composite functions."); layer.lineWidth = nil; @@ -737,11 +760,6 @@ @"Unsetting lineWidth should return line-width to the default value."); XCTAssertEqualObjects(layer.lineWidth, defaultStyleValue, @"lineWidth should return the default value after being unset."); - - functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil]; - XCTAssertThrowsSpecificNamed(layer.lineWidth = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it"); - functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil]; - XCTAssertThrowsSpecificNamed(layer.lineWidth = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it"); // Transition property test layer.lineWidthTransition = transitionTest; auto toptions = rawLayer->getLineWidthTransition(); diff --git a/platform/darwin/test/MGLStyleTests.mm b/platform/darwin/test/MGLStyleTests.mm index d93483ea6e..608cfdfd2d 100644 --- a/platform/darwin/test/MGLStyleTests.mm +++ b/platform/darwin/test/MGLStyleTests.mm @@ -210,9 +210,9 @@ MGLRasterSource *rasterSource = [[MGLRasterSource alloc] initWithIdentifier:@"some-identifier" tileURLTemplates:@[] options:nil]; [self.style addSource:rasterSource]; - // Attempt to remove a shape source with the same identifier as the raster source - MGLShapeSource *shapeSource = [[MGLShapeSource alloc] initWithIdentifier:@"some-identifier" shape:nil options:nil]; - [self.style removeSource:shapeSource]; + // Attempt to remove an image source with the same identifier as the raster source + MGLImageSource *imageSource = [[MGLImageSource alloc] initWithIdentifier:@"some-identifier" coordinateQuad: { } URL:[NSURL URLWithString:@"http://host/image.png"]]; + [self.style removeSource:imageSource]; // The raster source should still be added XCTAssertTrue([[self.style sourceWithIdentifier:rasterSource.identifier] isMemberOfClass:[MGLRasterSource class]]); @@ -220,16 +220,16 @@ [self.style removeSource:rasterSource]; // Add the shape source - [self.style addSource:shapeSource]; + [self.style addSource:imageSource]; // Attempt to remove a vector source with the same identifer as the shape source MGLVectorSource *vectorSource = [[MGLVectorSource alloc] initWithIdentifier:@"some-identifier" tileURLTemplates:@[] options:nil]; [self.style removeSource:vectorSource]; - // The shape source should still be added - XCTAssertTrue([[self.style sourceWithIdentifier:shapeSource.identifier] isMemberOfClass:[MGLShapeSource class]]); + // The image source should still be added + XCTAssertTrue([[self.style sourceWithIdentifier:imageSource.identifier] isMemberOfClass:[MGLImageSource class]]); - // Remove the shape source - [self.style removeSource:shapeSource]; + // Remove the image source + [self.style removeSource:imageSource]; // Add the vector source [self.style addSource:vectorSource]; @@ -237,7 +237,7 @@ // Attempt to remove the previously created raster source that has the same identifer as the shape source [self.style removeSource:rasterSource]; // The vector source should still be added - XCTAssertTrue([[self.style sourceWithIdentifier:shapeSource.identifier] isMemberOfClass:[MGLVectorSource class]]); + XCTAssertTrue([[self.style sourceWithIdentifier:imageSource.identifier] isMemberOfClass:[MGLVectorSource class]]); } - (void)testRemovingSourceInUse { diff --git a/platform/darwin/test/Media.xcassets/RadarImage.imageset/Contents.json b/platform/darwin/test/Media.xcassets/RadarImage.imageset/Contents.json new file mode 100644 index 0000000000..79be9ed970 --- /dev/null +++ b/platform/darwin/test/Media.xcassets/RadarImage.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "radar.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +}
\ No newline at end of file diff --git a/platform/darwin/test/Media.xcassets/RadarImage.imageset/radar.png b/platform/darwin/test/Media.xcassets/RadarImage.imageset/radar.png Binary files differnew file mode 100644 index 0000000000..e23697f42a --- /dev/null +++ b/platform/darwin/test/Media.xcassets/RadarImage.imageset/radar.png |