- {{^hide_name}}

{{name}}

{{/hide_name}} + {{^hide_name}}

{{name}}

{{/hide_name}} {{#declaration}}
diff --git a/platform/darwin/docs/theme/templates/footer.mustache b/platform/darwin/docs/theme/templates/footer.mustache index e72ede612..c0bd7b944 100644 --- a/platform/darwin/docs/theme/templates/footer.mustache +++ b/platform/darwin/docs/theme/templates/footer.mustache @@ -1,3 +1,3 @@ -
{{/name}} @@ -15,7 +15,7 @@ - {{name}} + {{name}} {{#default_impl_abstract}} @@ -29,9 +29,7 @@ {{/from_protocol_extension}}
-
-
{{#abstract}}
{{{abstract}}} @@ -49,13 +47,13 @@ {{#declaration}}

Declaration

-
-

{{language}}

+
+

{{language}}

{{{declaration}}}
{{#other_language_declaration}} -
-

Swift

+
+

Swift

{{{other_language_declaration}}}
{{/other_language_declaration}} @@ -80,10 +78,10 @@
{{/return}} {{#github_token_url}} -
+ {{/github_token_url}} diff --git a/platform/darwin/scripts/generate-style-code.js b/platform/darwin/scripts/generate-style-code.js index 6b54b5219..e7041ad9f 100644 --- a/platform/darwin/scripts/generate-style-code.js +++ b/platform/darwin/scripts/generate-style-code.js @@ -15,9 +15,37 @@ const suffix = 'StyleLayer'; // Rename properties and keep `original` for use with setters and getters _.forOwn(cocoaConventions, function (properties, kind) { _.forOwn(properties, function (newName, oldName) { - spec[kind][newName] = spec[kind][oldName]; - spec[kind][newName].original = oldName; + let property = spec[kind][oldName]; + if (newName.startsWith('is-')) { + property.getter = newName; + newName = newName.substr(3); + } + if (newName !== oldName) { + property.original = oldName; + } delete spec[kind][oldName]; + spec[kind][newName] = property; + + // Update requirements in other properties. + let updateRequirements = function (property, name) { + let requires = property.requires || []; + for (let i = 0; i < requires.length; i++) { + if (requires[i] === oldName) { + property.requires[i] = newName; + } + if (typeof requires[i] !== 'string') { + let prop = name; + _.forOwn(requires[i], function (values, name, require) { + if (name === oldName) { + require[newName] = values; + delete require[name]; + } + }); + } + } + }; + _.forOwn(spec[kind.replace(/^layout_/, 'paint_')], updateRequirements); + _.forOwn(spec[kind.replace(/^paint_/, 'layout_')], updateRequirements); }) }); @@ -25,12 +53,16 @@ global.objCName = function (property) { return camelizeWithLeadingLowercase(property.name); } +global.objCGetter = function (property) { + return camelizeWithLeadingLowercase(property.getter || property.name); +} + global.objCType = function (layerType, propertyName) { return `${prefix}${camelize(propertyName)}`; } global.arrayType = function (property) { - return property.type === 'array' ? property.name.split('-').pop() : false; + return property.type === 'array' ? originalPropertyName(property).split('-').pop() : false; }; global.testImplementation = function (property, layerType, isFunction) { @@ -123,7 +155,7 @@ global.propertyDoc = function (propertyName, property, layerType) { return doc.replace(/(p)ixel/gi, '$1oint').replace(/(\d)px\b/g, '$1pt'); }; -global.propertyReqs = function (property, layoutPropertiesByName, type) { +global.propertyReqs = function (property, propertiesByName, type) { return 'This property is only applied to the style if ' + property.requires.map(function (req) { if (typeof req === 'string') { return '`' + camelizeWithLeadingLowercase(req) + '` is non-`nil`'; @@ -131,7 +163,7 @@ global.propertyReqs = function (property, layoutPropertiesByName, type) { return '`' + camelizeWithLeadingLowercase(req['!']) + '` is set to `nil`'; } else { let name = Object.keys(req)[0]; - return '`' + camelizeWithLeadingLowercase(name) + '` is set to an `MGLStyleValue` object containing ' + describeValue(req[name], layoutPropertiesByName[name], type); + return '`' + camelizeWithLeadingLowercase(name) + '` is set to an `MGLStyleValue` object containing ' + describeValue(req[name], propertiesByName[name], type); } }).join(', and ') + '. Otherwise, it is ignored.'; }; @@ -292,11 +324,11 @@ global.setSourceLayer = function() { } global.mbglType = function(property) { - let mbglType = camelize(property.name) + 'Type'; - if (/-translate-anchor$/.test(property.name)) { + let mbglType = camelize(originalPropertyName(property)) + 'Type'; + if (/-translate-anchor$/.test(originalPropertyName(property))) { mbglType = 'TranslateAnchorType'; } - if (/-(rotation|pitch)-alignment$/.test(property.name)) { + if (/-(rotation|pitch)-alignment$/.test(originalPropertyName(property))) { mbglType = 'AlignmentType'; } return mbglType; @@ -304,7 +336,7 @@ global.mbglType = function(property) { const layerH = ejs.compile(fs.readFileSync('platform/darwin/src/MGLStyleLayer.h.ejs', 'utf8'), { strict: true }); const layerM = ejs.compile(fs.readFileSync('platform/darwin/src/MGLStyleLayer.mm.ejs', 'utf8'), { strict: true}); -const testLayers = ejs.compile(fs.readFileSync('platform/darwin/src/MGLRuntimeStylingTests.m.ejs', 'utf8'), { strict: true}); +const testLayers = ejs.compile(fs.readFileSync('platform/darwin/test/MGLStyleLayerTests.m.ejs', 'utf8'), { strict: true}); const categoryH = ejs.compile(fs.readFileSync('platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.h.ejs', 'utf8'), { strict: true}); const categoryM = ejs.compile(fs.readFileSync('platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.mm.ejs', 'utf8'), { strict: true}); diff --git a/platform/darwin/scripts/style-spec-cocoa-conventions-v8.json b/platform/darwin/scripts/style-spec-cocoa-conventions-v8.json index e37598406..49cf515e3 100644 --- a/platform/darwin/scripts/style-spec-cocoa-conventions-v8.json +++ b/platform/darwin/scripts/style-spec-cocoa-conventions-v8.json @@ -1,9 +1,31 @@ { "layout_symbol": { - "icon-image": "icon-image-name" + "icon-allow-overlap": "icon-allows-overlap", + "icon-image": "icon-image-name", + "icon-ignore-placement": "icon-ignores-placement", + "icon-keep-upright": "keeps-icon-upright", + "icon-optional": "is-icon-optional", + "icon-rotate": "icon-rotation", + "icon-size": "icon-scale", + "symbol-avoid-edges": "symbol-avoids-edges", + "text-allow-overlap": "text-allows-overlap", + "text-ignore-placement": "text-ignores-placement", + "text-justify": "text-justification", + "text-keep-upright": "keeps-text-upright", + "text-max-angle": "maximum-text-angle", + "text-max-width": "maximum-text-width", + "text-optional": "is-text-optional", + "text-rotate": "text-rotation" }, "paint_raster": { "raster-brightness-min": "minimum-raster-brightness", - "raster-brightness-max": "maximum-raster-brightness" + "raster-brightness-max": "maximum-raster-brightness", + "raster-hue-rotate": "raster-hue-rotation" + }, + "paint_line": { + "line-dasharray": "line-dash-pattern" + }, + "paint_fill": { + "fill-antialias": "is-fill-antialiased" } } \ No newline at end of file diff --git a/platform/darwin/scripts/style-spec-overrides-v8.json b/platform/darwin/scripts/style-spec-overrides-v8.json index ed4293513..cfda85b7f 100644 --- a/platform/darwin/scripts/style-spec-overrides-v8.json +++ b/platform/darwin/scripts/style-spec-overrides-v8.json @@ -45,6 +45,12 @@ } }, "paint_symbol": { + "icon-color": { + "doc": "The tint color to apply to the icon. The `icon-image-name` property must be set to a template image." + }, + "icon-halo-color": { + "doc": "The color of the icon’s halo. The `icon-image-name` property must be set to a template image." + }, "icon-translate": { "doc": "Distance that the icon's anchor is moved from its original placement." }, diff --git a/platform/darwin/src/MGLAttributionInfo.h b/platform/darwin/src/MGLAttributionInfo.h new file mode 100644 index 000000000..7395e3f34 --- /dev/null +++ b/platform/darwin/src/MGLAttributionInfo.h @@ -0,0 +1,62 @@ +#import +#import +#import + +#import "MGLTypes.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + Information about an attribution statement, usually a copyright or trademark + statement, associated with a map content source. + */ +@interface MGLAttributionInfo : NSObject + +/** + Returns an initialized attribution info object with the given title and URL. + + @param title The attribution statement’s title. + @param URL A URL to more information about the entity named in the attribution. + @return An initialized attribution info object. + */ +- (instancetype)initWithTitle:(NSAttributedString *)title URL:(nullable NSURL *)URL; + +/** + The attribution statement’s attributed title text. + */ +@property (nonatomic) NSAttributedString *title; + +/** + The URL to more information about the entity named in the attribution. + + If this property is set, the attribution statement should be displayed as a + hyperlink or action button. Otherwise, if it is `nil`, the attribution + statement should be displayed as plain text. + */ +@property (nonatomic, nullable) NSURL *URL; + +/** + A Boolean value indicating whether the attribution statement is a shortcut to a + feedback tool. + + If this property is set, the statement should be treated as a way for the user + to provide feedback rather than an attribution statement. + */ +@property (nonatomic, getter=isFeedbackLink) BOOL feedbackLink; + +/** + Returns a copy of the `URL` property modified to account for the given center + coordinate and zoom level. + + @param centerCoordinate The map’s center coordinate. + @param zoomLevel The map’s zoom level. See `MGLMapView`’s `zoomLevel` property + for more information. + @return A modified URL containing a fragment that points to the specified + viewport. If the `feedbackLink` property is set to `NO`, this method returns + `nil`. + */ +- (nullable NSURL *)feedbackURLAtCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel; + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLAttributionInfo.mm b/platform/darwin/src/MGLAttributionInfo.mm new file mode 100644 index 000000000..cf7b3cb22 --- /dev/null +++ b/platform/darwin/src/MGLAttributionInfo.mm @@ -0,0 +1,195 @@ +#import "MGLAttributionInfo_Private.h" + +#if TARGET_OS_IPHONE + #import +#else + #import +#endif + +#import "MGLMapCamera.h" +#import "NSArray+MGLAdditions.h" +#import "NSString+MGLAdditions.h" + +#include + +@implementation MGLAttributionInfo + ++ (NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfosFromHTMLString:(nullable NSString *)htmlString fontSize:(CGFloat)fontSize linkColor:(nullable MGLColor *)linkColor { + if (!htmlString) { + return @[]; + } + + NSDictionary *options = @{ + NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, + NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding), + }; + // Apply a bogus, easily detectable style rule to any feedback link, since + // NSAttributedString doesn’t preserve the class attribute. + NSMutableString *css = [NSMutableString stringWithString: + @".mapbox-improve-map { -webkit-text-stroke-width: 1000px; }"]; + if (fontSize) { + [css appendFormat:@"html { font-size: %.1fpx; }", fontSize]; + } + if (linkColor) { + CGFloat red; + CGFloat green; + CGFloat blue; + CGFloat alpha; +#if !TARGET_OS_IPHONE + linkColor = [linkColor colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; +#endif + [linkColor getRed:&red green:&green blue:&blue alpha:&alpha]; + [css appendFormat: + @"a:link { color: rgba(%f%%, %f%%, %f%%, %f); }", + red * 100, green * 100, blue * 100, alpha]; + } + NSString *styledHTML = [NSString stringWithFormat:@"%@", css, htmlString]; + NSData *htmlData = [styledHTML dataUsingEncoding:NSUTF8StringEncoding]; + +#if TARGET_OS_IPHONE + NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithData:htmlData + options:options + documentAttributes:nil + error:NULL]; +#else + NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithHTML:htmlData + options:options + documentAttributes:nil]; +#endif + + NSMutableArray *infos = [NSMutableArray array]; + [attributedString enumerateAttribute:NSLinkAttributeName + inRange:attributedString.mgl_wholeRange + options:0 + usingBlock: + ^(id _Nullable value, NSRange range, BOOL * _Nonnull stop) { + NSCAssert(!value || [value isKindOfClass:[NSURL class]], @"If present, URL attribute must be an NSURL."); + + // Detect feedback links by the bogus style rule applied above. + NSNumber *strokeWidth = [attributedString attribute:NSStrokeWidthAttributeName + atIndex:range.location + effectiveRange:NULL]; + BOOL isFeedbackLink = NO; + if ([strokeWidth floatValue] > 100) { + isFeedbackLink = YES; + [attributedString removeAttribute:NSStrokeWidthAttributeName range:range]; + } + + // Omit whitespace-only strings. + NSAttributedString *title = [[attributedString attributedSubstringFromRange:range] + mgl_attributedStringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + if (!title.length) { + return; + } + + MGLAttributionInfo *info = [[MGLAttributionInfo alloc] initWithTitle:title URL:value]; + info.feedbackLink = isFeedbackLink; + [infos addObject:info]; + }]; + return infos; +} + ++ (NSAttributedString *)attributedStringForAttributionInfos:(NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfos { + NSMutableArray *titles = [NSMutableArray arrayWithCapacity:attributionInfos.count]; + for (MGLAttributionInfo *info in attributionInfos) { + NSMutableAttributedString *title = info.title.mutableCopy; + if (info.URL) { + [title addAttribute:NSLinkAttributeName value:info.URL range:title.mgl_wholeRange]; + } + [titles addObject:title]; + } + return [titles mgl_attributedComponentsJoinedByString:@" "]; +} + +- (instancetype)initWithTitle:(NSAttributedString *)title URL:(NSURL *)URL { + if (self = [super init]) { + _title = title; + _URL = URL; + } + return self; +} + +- (nullable NSURL *)feedbackURLAtCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel { + if (!self.feedbackLink) { + return nil; + } + + NSURLComponents *components = [NSURLComponents componentsWithURL:self.URL resolvingAgainstBaseURL:NO]; + components.fragment = [NSString stringWithFormat:@"/%.5f/%.5f/%i", + centerCoordinate.longitude, centerCoordinate.latitude, (int)round(zoomLevel + 1)]; + return components.URL; +} + +- (BOOL)isEqual:(id)object { + return [object isKindOfClass:[self class]] && [[object title] isEqual:self.title] && [[object URL] isEqual:self.URL]; +} + +- (NSUInteger)hash { + return self.title.hash + self.URL.hash; +} + +/** + Returns whether the given attribution info object overlaps with the receiver by + its plain text title. + + @return `NSOrderedAscending` if the given object is a superset of the receiver, + `NSOrderedDescending` if it is a subset of the receiver, or `NSOrderedSame` + if there is no overlap. + */ +- (NSComparisonResult)subsetCompare:(MGLAttributionInfo *)otherInfo { + NSString *title = self.title.string; + NSString *otherTitle = otherInfo.title.string; + if ([title containsString:otherTitle]) { + return NSOrderedDescending; + } + if ([otherTitle containsString:title]) { + return NSOrderedAscending; + } + return NSOrderedSame; +} + +@end + +@implementation NSMutableArray (MGLAttributionInfoAdditions) + +- (void)growArrayByAddingAttributionInfo:(MGLAttributionInfo *)info { + __block BOOL didInsertInfo = NO; + __block BOOL shouldAddInfo = YES; + [self enumerateObjectsUsingBlock:^(MGLAttributionInfo * _Nonnull existingInfo, NSUInteger idx, BOOL * _Nonnull stop) { + switch ([info subsetCompare:existingInfo]) { + case NSOrderedDescending: + // The existing info object is a subset of the one we’re adding. + // Replace the existing object the first time we find a subset; + // remove the existing object every time after that. + if (didInsertInfo) { + [self removeObjectAtIndex:idx]; + } else { + [self replaceObjectAtIndex:idx withObject:info]; + didInsertInfo = YES; + } + break; + + case NSOrderedAscending: + // The info object we’re adding is a subset of the existing one. + // Don’t add the object and stop looking. + shouldAddInfo = NO; + *stop = YES; + break; + + default: + break; + } + }]; + if (shouldAddInfo && !didInsertInfo) { + // No overlapping infos were found, so append the info object. + [self addObject:info]; + } +} + +- (void)growArrayByAddingAttributionInfosFromArray:(NS_ARRAY_OF(MGLAttributionInfo *) *)infos { + for (MGLAttributionInfo *info in infos) { + [self growArrayByAddingAttributionInfo:info]; + } +} + +@end diff --git a/platform/darwin/src/MGLAttributionInfo_Private.h b/platform/darwin/src/MGLAttributionInfo_Private.h new file mode 100644 index 000000000..c9a428b57 --- /dev/null +++ b/platform/darwin/src/MGLAttributionInfo_Private.h @@ -0,0 +1,48 @@ +#import +#import +#import + +#import "MGLAttributionInfo.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface MGLAttributionInfo (Private) + +/** + Parses and returns the attribution infos contained in the given HTML source + code string. + + @param htmlString The HTML source code to parse. + @param fontSize The default text size in points. + @param linkColor The default link color. + */ ++ (NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfosFromHTMLString:(nullable NSString *)htmlString fontSize:(CGFloat)fontSize linkColor:(nullable MGLColor *)linkColor; + ++ (NSAttributedString *)attributedStringForAttributionInfos:(NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfos; + +@end + +@interface NSMutableArray (MGLAttributionInfoAdditions) + +/** + Adds the given attribution info object to the receiver as long as it isn’t + redundant to any object already in the receiver. Any existing object that is + redundant to the given object is replaced by the given object. + + @param info The info object to add to the receiver. + @return True if the given info object was added to the receiver. + */ +- (void)growArrayByAddingAttributionInfo:(MGLAttributionInfo *)info; + +/** + Adds each of the given attribution info objects to the receiver as long as it + isn’t redundant to any object already in the receiver. Any existing object that + is redundant to the given object is replaced by the given object. + + @param infos An array of info objects to add to the receiver. + */ +- (void)growArrayByAddingAttributionInfosFromArray:(NS_ARRAY_OF(MGLAttributionInfo *) *)infos; + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLBackgroundStyleLayer.mm b/platform/darwin/src/MGLBackgroundStyleLayer.mm index 253414852..f6a00de94 100644 --- a/platform/darwin/src/MGLBackgroundStyleLayer.mm +++ b/platform/darwin/src/MGLBackgroundStyleLayer.mm @@ -26,14 +26,24 @@ if (self = [super initWithIdentifier:identifier]) { auto layer = std::make_unique(identifier.UTF8String); _pendingLayer = std::move(layer); - _rawLayer = _pendingLayer.get(); + self.rawLayer = _pendingLayer.get(); } return self; } -#pragma mark - Adding to and removing from a map view +- (mbgl::style::BackgroundLayer *)rawLayer +{ + return (mbgl::style::BackgroundLayer *)super.rawLayer; +} -- (void)addToMapView:(MGLMapView *)mapView +- (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" @@ -41,11 +51,6 @@ "to the style more than once is invalid.", self, mapView.style]; } - [self addToMapView:mapView belowLayer:nil]; -} - -- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer -{ if (otherLayer) { const mbgl::optional belowLayerId{otherLayer.identifier.UTF8String}; mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId); @@ -57,7 +62,7 @@ - (void)removeFromMapView:(MGLMapView *)mapView { _pendingLayer = nullptr; - _rawLayer = nullptr; + self.rawLayer = nullptr; auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String); if (!removedLayer) { @@ -72,7 +77,7 @@ removedLayer.release(); _pendingLayer = std::unique_ptr(layer); - _rawLayer = _pendingLayer.get(); + self.rawLayer = _pendingLayer.get(); } #pragma mark - Accessing the Paint Attributes @@ -81,13 +86,13 @@ MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(backgroundColor); - _rawLayer->setBackgroundColor(mbglValue); + self.rawLayer->setBackgroundColor(mbglValue); } - (MGLStyleValue *)backgroundColor { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getBackgroundColor() ?: _rawLayer->getDefaultBackgroundColor(); + auto propertyValue = self.rawLayer->getBackgroundColor() ?: self.rawLayer->getDefaultBackgroundColor(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -95,13 +100,13 @@ MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(backgroundOpacity); - _rawLayer->setBackgroundOpacity(mbglValue); + self.rawLayer->setBackgroundOpacity(mbglValue); } - (MGLStyleValue *)backgroundOpacity { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getBackgroundOpacity() ?: _rawLayer->getDefaultBackgroundOpacity(); + auto propertyValue = self.rawLayer->getBackgroundOpacity() ?: self.rawLayer->getDefaultBackgroundOpacity(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -109,13 +114,13 @@ MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(backgroundPattern); - _rawLayer->setBackgroundPattern(mbglValue); + self.rawLayer->setBackgroundPattern(mbglValue); } - (MGLStyleValue *)backgroundPattern { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getBackgroundPattern() ?: _rawLayer->getDefaultBackgroundPattern(); + auto propertyValue = self.rawLayer->getBackgroundPattern() ?: self.rawLayer->getDefaultBackgroundPattern(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } diff --git a/platform/darwin/src/MGLCircleStyleLayer.mm b/platform/darwin/src/MGLCircleStyleLayer.mm index 781682d4d..e8ee2bca7 100644 --- a/platform/darwin/src/MGLCircleStyleLayer.mm +++ b/platform/darwin/src/MGLCircleStyleLayer.mm @@ -39,15 +39,26 @@ namespace mbgl { if (self = [super initWithIdentifier:identifier source:source]) { auto layer = std::make_unique(identifier.UTF8String, source.identifier.UTF8String); _pendingLayer = std::move(layer); - _rawLayer = _pendingLayer.get(); + self.rawLayer = _pendingLayer.get(); } return self; } + +- (mbgl::style::CircleLayer *)rawLayer +{ + return (mbgl::style::CircleLayer *)super.rawLayer; +} + +- (void)setRawLayer:(mbgl::style::CircleLayer *)rawLayer +{ + super.rawLayer = rawLayer; +} + - (NSString *)sourceLayerIdentifier { MGLAssertStyleLayerIsValid(); - auto layerID = _rawLayer->getSourceLayer(); + auto layerID = self.rawLayer->getSourceLayer(); return layerID.empty() ? nil : @(layerID.c_str()); } @@ -55,25 +66,26 @@ namespace mbgl { { MGLAssertStyleLayerIsValid(); - _rawLayer->setSourceLayer(sourceLayerIdentifier.UTF8String ?: ""); + self.rawLayer->setSourceLayer(sourceLayerIdentifier.UTF8String ?: ""); } - (void)setPredicate:(NSPredicate *)predicate { MGLAssertStyleLayerIsValid(); - _rawLayer->setFilter(predicate.mgl_filter); + self.rawLayer->setFilter(predicate.mgl_filter); } - (NSPredicate *)predicate { MGLAssertStyleLayerIsValid(); - return [NSPredicate mgl_predicateWithFilter:_rawLayer->getFilter()]; + return [NSPredicate mgl_predicateWithFilter:self.rawLayer->getFilter()]; } -#pragma mark - Adding to and removing from a map view -- (void)addToMapView:(MGLMapView *)mapView +#pragma mark - Adding to and removing from a map view + +- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer { if (_pendingLayer == nullptr) { [NSException raise:@"MGLRedundantLayerException" @@ -81,11 +93,6 @@ namespace mbgl { "to the style more than once is invalid.", self, mapView.style]; } - [self addToMapView:mapView belowLayer:nil]; -} - -- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer -{ if (otherLayer) { const mbgl::optional belowLayerId{otherLayer.identifier.UTF8String}; mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId); @@ -97,7 +104,7 @@ namespace mbgl { - (void)removeFromMapView:(MGLMapView *)mapView { _pendingLayer = nullptr; - _rawLayer = nullptr; + self.rawLayer = nullptr; auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String); if (!removedLayer) { @@ -112,7 +119,7 @@ namespace mbgl { removedLayer.release(); _pendingLayer = std::unique_ptr(layer); - _rawLayer = _pendingLayer.get(); + self.rawLayer = _pendingLayer.get(); } #pragma mark - Accessing the Paint Attributes @@ -121,13 +128,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(circleBlur); - _rawLayer->setCircleBlur(mbglValue); + self.rawLayer->setCircleBlur(mbglValue); } - (MGLStyleValue *)circleBlur { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getCircleBlur() ?: _rawLayer->getDefaultCircleBlur(); + auto propertyValue = self.rawLayer->getCircleBlur() ?: self.rawLayer->getDefaultCircleBlur(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -135,13 +142,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(circleColor); - _rawLayer->setCircleColor(mbglValue); + self.rawLayer->setCircleColor(mbglValue); } - (MGLStyleValue *)circleColor { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getCircleColor() ?: _rawLayer->getDefaultCircleColor(); + auto propertyValue = self.rawLayer->getCircleColor() ?: self.rawLayer->getDefaultCircleColor(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -149,13 +156,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(circleOpacity); - _rawLayer->setCircleOpacity(mbglValue); + self.rawLayer->setCircleOpacity(mbglValue); } - (MGLStyleValue *)circleOpacity { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getCircleOpacity() ?: _rawLayer->getDefaultCircleOpacity(); + auto propertyValue = self.rawLayer->getCircleOpacity() ?: self.rawLayer->getDefaultCircleOpacity(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -163,13 +170,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toEnumPropertyValue(circlePitchScale); - _rawLayer->setCirclePitchScale(mbglValue); + self.rawLayer->setCirclePitchScale(mbglValue); } - (MGLStyleValue *)circlePitchScale { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getCirclePitchScale() ?: _rawLayer->getDefaultCirclePitchScale(); + auto propertyValue = self.rawLayer->getCirclePitchScale() ?: self.rawLayer->getDefaultCirclePitchScale(); return MGLStyleValueTransformer().toEnumStyleValue(propertyValue); } @@ -177,13 +184,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(circleRadius); - _rawLayer->setCircleRadius(mbglValue); + self.rawLayer->setCircleRadius(mbglValue); } - (MGLStyleValue *)circleRadius { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getCircleRadius() ?: _rawLayer->getDefaultCircleRadius(); + auto propertyValue = self.rawLayer->getCircleRadius() ?: self.rawLayer->getDefaultCircleRadius(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -191,13 +198,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(circleStrokeColor); - _rawLayer->setCircleStrokeColor(mbglValue); + self.rawLayer->setCircleStrokeColor(mbglValue); } - (MGLStyleValue *)circleStrokeColor { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getCircleStrokeColor() ?: _rawLayer->getDefaultCircleStrokeColor(); + auto propertyValue = self.rawLayer->getCircleStrokeColor() ?: self.rawLayer->getDefaultCircleStrokeColor(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -205,13 +212,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(circleStrokeOpacity); - _rawLayer->setCircleStrokeOpacity(mbglValue); + self.rawLayer->setCircleStrokeOpacity(mbglValue); } - (MGLStyleValue *)circleStrokeOpacity { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getCircleStrokeOpacity() ?: _rawLayer->getDefaultCircleStrokeOpacity(); + auto propertyValue = self.rawLayer->getCircleStrokeOpacity() ?: self.rawLayer->getDefaultCircleStrokeOpacity(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -219,13 +226,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(circleStrokeWidth); - _rawLayer->setCircleStrokeWidth(mbglValue); + self.rawLayer->setCircleStrokeWidth(mbglValue); } - (MGLStyleValue *)circleStrokeWidth { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getCircleStrokeWidth() ?: _rawLayer->getDefaultCircleStrokeWidth(); + auto propertyValue = self.rawLayer->getCircleStrokeWidth() ?: self.rawLayer->getDefaultCircleStrokeWidth(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -233,13 +240,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer, NSValue *>().toPropertyValue(circleTranslate); - _rawLayer->setCircleTranslate(mbglValue); + self.rawLayer->setCircleTranslate(mbglValue); } - (MGLStyleValue *)circleTranslate { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getCircleTranslate() ?: _rawLayer->getDefaultCircleTranslate(); + auto propertyValue = self.rawLayer->getCircleTranslate() ?: self.rawLayer->getDefaultCircleTranslate(); return MGLStyleValueTransformer, NSValue *>().toStyleValue(propertyValue); } @@ -247,13 +254,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toEnumPropertyValue(circleTranslateAnchor); - _rawLayer->setCircleTranslateAnchor(mbglValue); + self.rawLayer->setCircleTranslateAnchor(mbglValue); } - (MGLStyleValue *)circleTranslateAnchor { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getCircleTranslateAnchor() ?: _rawLayer->getDefaultCircleTranslateAnchor(); + auto propertyValue = self.rawLayer->getCircleTranslateAnchor() ?: self.rawLayer->getDefaultCircleTranslateAnchor(); return MGLStyleValueTransformer().toEnumStyleValue(propertyValue); } diff --git a/platform/darwin/src/MGLFeature.h b/platform/darwin/src/MGLFeature.h index 384c5a073..ed4ff627b 100644 --- a/platform/darwin/src/MGLFeature.h +++ b/platform/darwin/src/MGLFeature.h @@ -19,7 +19,7 @@ NS_ASSUME_NONNULL_BEGIN using `-[MGLMapView visibleFeaturesAtPoint:]` and related methods. Each feature object associates a shape with an identifier and attributes as specified by the source. Like ordinary `MGLAnnotation` objects, some kinds of `MGLFeature` - objects can also be added to a map view using an `MGLGeoJSONSource` or + objects can also be added to a map view using an `MGLShapeSource` or `-[MGLMapView addAnnotations:]` and related methods. */ @protocol MGLFeature @@ -52,7 +52,7 @@ NS_ASSUME_NONNULL_BEGIN layer reference. Note that while it is possible to change this value on feature instances obtained from `-[MGLMapView visibleFeaturesAtPoint:]` and related methods, there will be no effect on the map. Setting this value can be useful - when the feature instance is used to initialize an `MGLGeoJSONSource` and that + when the feature instance is used to initialize an `MGLShapeSource` and that source is added to the map and styled. */ @property (nonatomic, copy, nullable) id identifier; @@ -87,7 +87,7 @@ NS_ASSUME_NONNULL_BEGIN layer references. Note that while it is possible to change this value on feature instances obtained from `-[MGLMapView visibleFeaturesAtPoint:]` and related methods, there will be no effect on the map. Setting this value can be useful - when the feature instance is used to initialize an `MGLGeoJSONSource` and that + when the feature instance is used to initialize an `MGLShapeSource` and that source is added to the map and styled. */ @property (nonatomic, copy) NS_DICTIONARY_OF(NSString *, id) *attributes; diff --git a/platform/darwin/src/MGLFeature.mm b/platform/darwin/src/MGLFeature.mm index 548343371..c1e0c312a 100644 --- a/platform/darwin/src/MGLFeature.mm +++ b/platform/darwin/src/MGLFeature.mm @@ -14,9 +14,10 @@ #import "NSExpression+MGLAdditions.h" #import +#import #import -@interface MGLPointFeature () +@interface MGLPointFeature () @end @implementation MGLPointFeature @@ -32,13 +33,13 @@ return NSDictionaryFeatureForGeometry([super geoJSONDictionary], self.attributes, self.identifier); } -- (mbgl::Feature)mbglFeature { - return mbglFeature([self featureObject], identifier, self.attributes); +- (mbgl::GeoJSON)geoJSONObject { + return mbglFeature({[self geometryObject]}, identifier, self.attributes); } @end -@interface MGLPolylineFeature () +@interface MGLPolylineFeature () @end @implementation MGLPolylineFeature @@ -54,13 +55,13 @@ return NSDictionaryFeatureForGeometry([super geoJSONDictionary], self.attributes, self.identifier); } -- (mbgl::Feature)mbglFeature { - return mbglFeature([self featureObject], identifier, self.attributes); +- (mbgl::GeoJSON)geoJSONObject { + return mbglFeature({[self geometryObject]}, identifier, self.attributes); } @end -@interface MGLPolygonFeature () +@interface MGLPolygonFeature () @end @implementation MGLPolygonFeature @@ -76,13 +77,13 @@ return NSDictionaryFeatureForGeometry([super geoJSONDictionary], self.attributes, self.identifier); } -- (mbgl::Feature)mbglFeature { - return mbglFeature([self featureObject], identifier, self.attributes); +- (mbgl::GeoJSON)geoJSONObject { + return mbglFeature({[self geometryObject]}, identifier, self.attributes); } @end -@interface MGLPointCollectionFeature () +@interface MGLPointCollectionFeature () @end @implementation MGLPointCollectionFeature @@ -98,13 +99,13 @@ return NSDictionaryFeatureForGeometry([super geoJSONDictionary], self.attributes, self.identifier); } -- (mbgl::Feature)mbglFeature { - return mbglFeature([self featureObject], identifier, self.attributes); +- (mbgl::GeoJSON)geoJSONObject { + return mbglFeature({[self geometryObject]}, identifier, self.attributes); } @end -@interface MGLMultiPolylineFeature () +@interface MGLMultiPolylineFeature () @end @implementation MGLMultiPolylineFeature @@ -120,13 +121,13 @@ return NSDictionaryFeatureForGeometry([super geoJSONDictionary], self.attributes, self.identifier); } -- (mbgl::Feature)mbglFeature { - return mbglFeature([self featureObject], identifier, self.attributes); +- (mbgl::GeoJSON)geoJSONObject { + return mbglFeature({[self geometryObject]}, identifier, self.attributes); } @end -@interface MGLMultiPolygonFeature () +@interface MGLMultiPolygonFeature () @end @implementation MGLMultiPolygonFeature @@ -142,13 +143,13 @@ return NSDictionaryFeatureForGeometry([super geoJSONDictionary], self.attributes, self.identifier); } -- (mbgl::Feature)mbglFeature { - return mbglFeature([self featureObject], identifier, self.attributes); +- (mbgl::GeoJSON)geoJSONObject { + return mbglFeature({[self geometryObject]}, identifier, self.attributes); } @end -@interface MGLShapeCollectionFeature () +@interface MGLShapeCollectionFeature () @end @implementation MGLShapeCollectionFeature @@ -170,10 +171,15 @@ return NSDictionaryFeatureForGeometry([super geoJSONDictionary], self.attributes, self.identifier); } -- (mbgl::Feature)mbglFeature { - [NSException raise:@"Method unavailable" format:@"%s is not available on %@.", __PRETTY_FUNCTION__, [self class]]; - mbgl::Polygon geometry; - return mbgl::Feature{geometry}; +- (mbgl::GeoJSON)geoJSONObject { + mbgl::FeatureCollection featureCollection; + featureCollection.reserve(self.shapes.count); + for (MGLShape *feature in self.shapes) { + auto geoJSONObject = feature.geoJSONObject; + NSAssert(geoJSONObject.is(), @"Feature collection must only contain features."); + featureCollection.push_back(geoJSONObject.get()); + } + return featureCollection; } @end @@ -185,27 +191,27 @@ template class GeometryEvaluator { public: - MGLShape * operator()(const mbgl::Point &geometry) const { + MGLShape * operator()(const mbgl::Point &geometry) const { MGLPointFeature *feature = [[MGLPointFeature alloc] init]; feature.coordinate = toLocationCoordinate2D(geometry); return feature; } - MGLShape * operator()(const mbgl::LineString &geometry) const { + MGLShape * operator()(const mbgl::LineString &geometry) const { std::vector coordinates = toLocationCoordinates2D(geometry); return [MGLPolylineFeature polylineWithCoordinates:&coordinates[0] count:coordinates.size()]; } - MGLShape * operator()(const mbgl::Polygon &geometry) const { + MGLShape * operator()(const mbgl::Polygon &geometry) const { return toShape(geometry); } - MGLShape * operator()(const mbgl::MultiPoint &geometry) const { + MGLShape * operator()(const mbgl::MultiPoint &geometry) const { std::vector coordinates = toLocationCoordinates2D(geometry); return [[MGLPointCollectionFeature alloc] initWithCoordinates:&coordinates[0] count:coordinates.size()]; } - MGLShape * operator()(const mbgl::MultiLineString &geometry) const { + MGLShape * operator()(const mbgl::MultiLineString &geometry) const { NSMutableArray *polylines = [NSMutableArray arrayWithCapacity:geometry.size()]; for (auto &lineString : geometry) { std::vector coordinates = toLocationCoordinates2D(lineString); @@ -216,7 +222,7 @@ public: return [MGLMultiPolylineFeature multiPolylineWithPolylines:polylines]; } - MGLShape * operator()(const mbgl::MultiPolygon &geometry) const { + MGLShape * operator()(const mbgl::MultiPolygon &geometry) const { NSMutableArray *polygons = [NSMutableArray arrayWithCapacity:geometry.size()]; for (auto &polygon : geometry) { [polygons addObject:toShape(polygon)]; @@ -225,11 +231,11 @@ public: return [MGLMultiPolygonFeature multiPolygonWithPolygons:polygons]; } - MGLShape * operator()(const mapbox::geometry::geometry_collection &collection) const { + MGLShape * operator()(const mapbox::geometry::geometry_collection &collection) const { NSMutableArray *shapes = [NSMutableArray arrayWithCapacity:collection.size()]; for (auto &geometry : collection) { // This is very much like the transformation that happens in MGLFeaturesFromMBGLFeatures(), but these are raw geometries with no associated feature IDs or attributes. - MGLShape *shape = mapbox::geometry::geometry::visit(geometry, *this); + MGLShape *shape = mapbox::geometry::geometry::visit(geometry, *this); [shapes addObject:shape]; } return [MGLShapeCollectionFeature shapeCollectionWithShapes:shapes]; @@ -266,27 +272,60 @@ private: } }; +template +class GeoJSONEvaluator { +public: + MGLShape * operator()(const mbgl::Geometry &geometry) const { + GeometryEvaluator evaluator; + MGLShape *shape = mapbox::geometry::geometry::visit(geometry, evaluator); + return shape; + } + + MGLShape * operator()(const mbgl::Feature &feature) const { + MGLShape *shape = (MGLShape *)MGLFeatureFromMBGLFeature(feature); + return shape; + } + + MGLShape * operator()(const mbgl::FeatureCollection &collection) const { + NSMutableArray *shapes = [NSMutableArray arrayWithCapacity:collection.size()]; + for (const auto &feature : collection) { + [shapes addObject:MGLFeatureFromMBGLFeature(feature)]; + } + return [MGLShapeCollectionFeature shapeCollectionWithShapes:shapes]; + } +}; + NS_ARRAY_OF(MGLShape *) *MGLFeaturesFromMBGLFeatures(const std::vector &features) { NSMutableArray *shapes = [NSMutableArray arrayWithCapacity:features.size()]; for (const auto &feature : features) { - NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithCapacity:feature.properties.size()]; - for (auto &pair : feature.properties) { - auto &value = pair.second; - ValueEvaluator evaluator; - attributes[@(pair.first.c_str())] = mbgl::Value::visit(value, evaluator); - } - - GeometryEvaluator evaluator; - MGLShape *shape = mapbox::geometry::geometry::visit(feature.geometry, evaluator); - if (feature.id) { - shape.identifier = mbgl::FeatureIdentifier::visit(*feature.id, ValueEvaluator()); - } - shape.attributes = attributes; - [shapes addObject:shape]; + [shapes addObject:MGLFeatureFromMBGLFeature(feature)]; } return shapes; } +id MGLFeatureFromMBGLFeature(const mbgl::Feature &feature) { + NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithCapacity:feature.properties.size()]; + for (auto &pair : feature.properties) { + auto &value = pair.second; + ValueEvaluator evaluator; + attributes[@(pair.first.c_str())] = mbgl::Value::visit(value, evaluator); + } + GeometryEvaluator evaluator; + MGLShape *shape = mapbox::geometry::geometry::visit(feature.geometry, evaluator); + if (feature.id) { + shape.identifier = mbgl::FeatureIdentifier::visit(*feature.id, ValueEvaluator()); + } + shape.attributes = attributes; + + return shape; +} + +MGLShape* MGLShapeFromGeoJSON(const mapbox::geojson::geojson &geojson) { + GeoJSONEvaluator evaluator; + MGLShape *shape = mapbox::geojson::geojson::visit(geojson, evaluator); + return shape; +} + mbgl::Feature mbglFeature(mbgl::Feature feature, id identifier, NSDictionary *attributes) { if (identifier) { diff --git a/platform/darwin/src/MGLFeature_Private.h b/platform/darwin/src/MGLFeature_Private.h index e6858c7c1..97af50989 100644 --- a/platform/darwin/src/MGLFeature_Private.h +++ b/platform/darwin/src/MGLFeature_Private.h @@ -3,6 +3,7 @@ #import #import +#import NS_ASSUME_NONNULL_BEGIN @@ -12,6 +13,17 @@ NS_ASSUME_NONNULL_BEGIN */ NS_ARRAY_OF(MGLShape *) *MGLFeaturesFromMBGLFeatures(const std::vector &features); +/** + Returns an `MGLFeature` object converted from the given mbgl::Feature + */ +id MGLFeatureFromMBGLFeature(const mbgl::Feature &feature); + +/** + Returns an `MGLShape` representing the given geojson. The shape can be + a feature, a collection of features, or a geometry. + */ +MGLShape* MGLShapeFromGeoJSON(const mapbox::geojson::geojson &geojson); + /** Takes an `mbgl::Feature` object, an identifer, and attributes dictionary and returns the feature object with converted `mbgl::FeatureIdentifier` and @@ -24,10 +36,4 @@ mbgl::Feature mbglFeature(mbgl::Feature feature, id identifier, NSDictionary *at */ NS_DICTIONARY_OF(NSString *, id) *NSDictionaryFeatureForGeometry(NSDictionary *geometry, NSDictionary *attributes, id identifier); -@protocol MGLFeaturePrivate - -- (mbgl::Feature)mbglFeature; - -@end - NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLFillStyleLayer.h b/platform/darwin/src/MGLFillStyleLayer.h index 9bbda26ce..cf8c18b5c 100644 --- a/platform/darwin/src/MGLFillStyleLayer.h +++ b/platform/darwin/src/MGLFillStyleLayer.h @@ -36,8 +36,13 @@ typedef NS_ENUM(NSUInteger, MGLFillTranslateAnchor) { Whether or not the fill should be antialiased. The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `YES`. Set this property to `nil` to reset it to the default value. + + This attribute corresponds to the fill-antialias paint property in the Mapbox Style Specification. */ -@property (nonatomic, null_resettable) MGLStyleValue *fillAntialias; +@property (nonatomic, null_resettable, getter=isFillAntialiased) MGLStyleValue *fillAntialiased; + + +@property (nonatomic, null_resettable) MGLStyleValue *fillAntialias __attribute__((unavailable("Use fillAntialiased instead."))); #if TARGET_OS_IPHONE /** @@ -69,7 +74,7 @@ typedef NS_ENUM(NSUInteger, MGLFillTranslateAnchor) { /** The outline color of the fill. Matches the value of `fillColor` if unspecified. - This property is only applied to the style if `fillPattern` is set to `nil`, and `fillAntialias` is set to an `MGLStyleValue` object containing an `NSNumber` object containing `YES`. Otherwise, it is ignored. + This property is only applied to the style if `fillPattern` is set to `nil`, and `fillAntialiased` is set to an `MGLStyleValue` object containing an `NSNumber` object containing `YES`. Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *fillOutlineColor; diff --git a/platform/darwin/src/MGLFillStyleLayer.mm b/platform/darwin/src/MGLFillStyleLayer.mm index 87a5144c6..891ab85d0 100644 --- a/platform/darwin/src/MGLFillStyleLayer.mm +++ b/platform/darwin/src/MGLFillStyleLayer.mm @@ -34,15 +34,26 @@ namespace mbgl { if (self = [super initWithIdentifier:identifier source:source]) { auto layer = std::make_unique(identifier.UTF8String, source.identifier.UTF8String); _pendingLayer = std::move(layer); - _rawLayer = _pendingLayer.get(); + self.rawLayer = _pendingLayer.get(); } return self; } + +- (mbgl::style::FillLayer *)rawLayer +{ + return (mbgl::style::FillLayer *)super.rawLayer; +} + +- (void)setRawLayer:(mbgl::style::FillLayer *)rawLayer +{ + super.rawLayer = rawLayer; +} + - (NSString *)sourceLayerIdentifier { MGLAssertStyleLayerIsValid(); - auto layerID = _rawLayer->getSourceLayer(); + auto layerID = self.rawLayer->getSourceLayer(); return layerID.empty() ? nil : @(layerID.c_str()); } @@ -50,25 +61,26 @@ namespace mbgl { { MGLAssertStyleLayerIsValid(); - _rawLayer->setSourceLayer(sourceLayerIdentifier.UTF8String ?: ""); + self.rawLayer->setSourceLayer(sourceLayerIdentifier.UTF8String ?: ""); } - (void)setPredicate:(NSPredicate *)predicate { MGLAssertStyleLayerIsValid(); - _rawLayer->setFilter(predicate.mgl_filter); + self.rawLayer->setFilter(predicate.mgl_filter); } - (NSPredicate *)predicate { MGLAssertStyleLayerIsValid(); - return [NSPredicate mgl_predicateWithFilter:_rawLayer->getFilter()]; + return [NSPredicate mgl_predicateWithFilter:self.rawLayer->getFilter()]; } -#pragma mark - Adding to and removing from a map view -- (void)addToMapView:(MGLMapView *)mapView +#pragma mark - Adding to and removing from a map view + +- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer { if (_pendingLayer == nullptr) { [NSException raise:@"MGLRedundantLayerException" @@ -76,11 +88,6 @@ namespace mbgl { "to the style more than once is invalid.", self, mapView.style]; } - [self addToMapView:mapView belowLayer:nil]; -} - -- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer -{ if (otherLayer) { const mbgl::optional belowLayerId{otherLayer.identifier.UTF8String}; mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId); @@ -92,7 +99,7 @@ namespace mbgl { - (void)removeFromMapView:(MGLMapView *)mapView { _pendingLayer = nullptr; - _rawLayer = nullptr; + self.rawLayer = nullptr; auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String); if (!removedLayer) { @@ -107,36 +114,41 @@ namespace mbgl { removedLayer.release(); _pendingLayer = std::unique_ptr(layer); - _rawLayer = _pendingLayer.get(); + self.rawLayer = _pendingLayer.get(); } #pragma mark - Accessing the Paint Attributes -- (void)setFillAntialias:(MGLStyleValue *)fillAntialias { +- (void)setFillAntialiased:(MGLStyleValue *)fillAntialiased { MGLAssertStyleLayerIsValid(); - auto mbglValue = MGLStyleValueTransformer().toPropertyValue(fillAntialias); - _rawLayer->setFillAntialias(mbglValue); + auto mbglValue = MGLStyleValueTransformer().toPropertyValue(fillAntialiased); + self.rawLayer->setFillAntialias(mbglValue); } -- (MGLStyleValue *)fillAntialias { +- (MGLStyleValue *)isFillAntialiased { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getFillAntialias() ?: _rawLayer->getDefaultFillAntialias(); + auto propertyValue = self.rawLayer->getFillAntialias() ?: self.rawLayer->getDefaultFillAntialias(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } + +- (void)setFillAntialias:(MGLStyleValue *)fillAntialias { + NSAssert(NO, @"Use -setFillAntialiased: instead."); +} + - (void)setFillColor:(MGLStyleValue *)fillColor { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(fillColor); - _rawLayer->setFillColor(mbglValue); + self.rawLayer->setFillColor(mbglValue); } - (MGLStyleValue *)fillColor { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getFillColor() ?: _rawLayer->getDefaultFillColor(); + auto propertyValue = self.rawLayer->getFillColor() ?: self.rawLayer->getDefaultFillColor(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -144,13 +156,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(fillOpacity); - _rawLayer->setFillOpacity(mbglValue); + self.rawLayer->setFillOpacity(mbglValue); } - (MGLStyleValue *)fillOpacity { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getFillOpacity() ?: _rawLayer->getDefaultFillOpacity(); + auto propertyValue = self.rawLayer->getFillOpacity() ?: self.rawLayer->getDefaultFillOpacity(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -158,13 +170,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(fillOutlineColor); - _rawLayer->setFillOutlineColor(mbglValue); + self.rawLayer->setFillOutlineColor(mbglValue); } - (MGLStyleValue *)fillOutlineColor { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getFillOutlineColor() ?: _rawLayer->getDefaultFillOutlineColor(); + auto propertyValue = self.rawLayer->getFillOutlineColor() ?: self.rawLayer->getDefaultFillOutlineColor(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -172,13 +184,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(fillPattern); - _rawLayer->setFillPattern(mbglValue); + self.rawLayer->setFillPattern(mbglValue); } - (MGLStyleValue *)fillPattern { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getFillPattern() ?: _rawLayer->getDefaultFillPattern(); + auto propertyValue = self.rawLayer->getFillPattern() ?: self.rawLayer->getDefaultFillPattern(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -186,13 +198,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer, NSValue *>().toPropertyValue(fillTranslate); - _rawLayer->setFillTranslate(mbglValue); + self.rawLayer->setFillTranslate(mbglValue); } - (MGLStyleValue *)fillTranslate { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getFillTranslate() ?: _rawLayer->getDefaultFillTranslate(); + auto propertyValue = self.rawLayer->getFillTranslate() ?: self.rawLayer->getDefaultFillTranslate(); return MGLStyleValueTransformer, NSValue *>().toStyleValue(propertyValue); } @@ -200,13 +212,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toEnumPropertyValue(fillTranslateAnchor); - _rawLayer->setFillTranslateAnchor(mbglValue); + self.rawLayer->setFillTranslateAnchor(mbglValue); } - (MGLStyleValue *)fillTranslateAnchor { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getFillTranslateAnchor() ?: _rawLayer->getDefaultFillTranslateAnchor(); + auto propertyValue = self.rawLayer->getFillTranslateAnchor() ?: self.rawLayer->getDefaultFillTranslateAnchor(); return MGLStyleValueTransformer().toEnumStyleValue(propertyValue); } diff --git a/platform/darwin/src/MGLGeoJSONSource.h b/platform/darwin/src/MGLGeoJSONSource.h deleted file mode 100644 index 30232c621..000000000 --- a/platform/darwin/src/MGLGeoJSONSource.h +++ /dev/null @@ -1,144 +0,0 @@ -#import "MGLSource.h" - -#import "MGLTypes.h" - -NS_ASSUME_NONNULL_BEGIN - -@protocol MGLFeature; - -/** - Options for `MGLGeoJSONSource` objects. - */ -typedef NSString *MGLGeoJSONSourceOption NS_STRING_ENUM; - -/** - An `NSNumber` object containing a Boolean enabling or disabling clustering. - If the `features` property contains point features, setting this option to - `YES` clusters the points by radius into groups. The default value is `NO`. - */ -extern const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionClustered; - -/** - An `NSNumber` object containing an integer; specifies the radius of each - cluster if clustering is enabled. A value of 512 produces a radius equal to - the width of a tile. The default value is 50. - */ -extern const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionClusterRadius; - -/** - An `NSNumber` object containing an integer; specifies the maximum zoom level at - which to cluster points if clustering is enabled. Defaults to one zoom level - less than the value of `MGLGeoJSONSourceOptionMaximumZoomLevel` so that, at the - maximum zoom level, the features are not clustered. - */ -extern const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionMaximumZoomLevelForClustering; - -/** - An `NSNumber` object containing an integer; specifies the maximum zoom level at - which to create vector tiles. A greater value produces greater detail at high - zoom levels. The default value is 18. - */ -extern const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionMaximumZoomLevel; - -/** - An `NSNumber` object containing an integer; specifies the size of the tile - buffer on each side. A value of 0 produces no buffer. A value of 512 produces a - buffer as wide as the tile itself. Larger values produce fewer rendering - artifacts near tile edges and slower performance. The default value is 128. - */ -extern const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionBuffer; - -/** - An `NSNumber` object containing a double; specifies the Douglas-Peucker - simplification tolerance. A greater value produces simpler geometries and - improves performance. The default value is 0.375. - */ -extern const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionSimplificationTolerance; - -/** - A GeoJSON source. - - @see The - style specification. - */ -@interface MGLGeoJSONSource : MGLSource - -#pragma mark Initializing a Source - -/** - Returns a GeoJSON source initialized with an identifier, GeoJSON data, and a - dictionary of options for the source according to the - style - specification. - - @param identifier A string that uniquely identifies the source. - @param geoJSONData An `NSData` object representing GeoJSON source code. - @param options An `NSDictionary` of options for this source. - @return An initialized GeoJSON source. - */ -- (instancetype)initWithIdentifier:(NSString *)identifier geoJSONData:(NSData *)data options:(nullable NS_DICTIONARY_OF(MGLGeoJSONSourceOption, id) *)options NS_DESIGNATED_INITIALIZER; - -/** - Returns a GeoJSON source with an identifier, URL, and dictionary of options for - the source according to the - style - specification. - - @param identifier A string that uniquely identifies the source. - @param URL An HTTP(S) URL, absolute file URL, or local file URL relative to the - current application’s resource bundle. - @param options An `NSDictionary` of options for this source. - @return An initialized GeoJSON source. - */ -- (instancetype)initWithIdentifier:(NSString *)identifier URL:(NSURL *)url options:(nullable NS_DICTIONARY_OF(MGLGeoJSONSourceOption, id) *)options NS_DESIGNATED_INITIALIZER; - -/** - Returns a GeoJSON source with an identifier, features dictionary, and dictionary - of options for the source according to the - style - specification. - - @param identifier A string that uniquely identifies the source. - @param features An array of features that conform to the `MGLFeature` protocol. - @param options An `NSDictionary` of options for this source. - @return An initialized GeoJSON source. - */ -- (instancetype)initWithIdentifier:(NSString *)identifier features:(NSArray> *)features options:(nullable NS_DICTIONARY_OF(MGLGeoJSONSourceOption, id) *)options NS_DESIGNATED_INITIALIZER; - -#pragma mark Accessing a Source’s Content - -/** - The contents of the source. - - If the receiver was initialized using `-initWithIdentifier:URL:options:`, this property - is set to `nil`. This property is unavailable until the receiver is passed into - `-[MGLStyle addSource]`. - */ -@property (nonatomic, nullable) NS_ARRAY_OF(id ) *features; - -/** - A GeoJSON representation of the contents of the source. - - Use the `features` property instead to get an object representation of the - contents. Alternatively, use `NSJSONSerialization` with the value of this - property to transform it into Foundation types. - - If the receiver was initialized using `-initWithIdentifier:URL:options` or - `-initWithIdentifier:features:options`, this property is set to `nil`. - This property is unavailable until the receiver is passed - into `-[MGLStyle addSource]`. - */ -@property (nonatomic, nullable, copy) NSData *geoJSONData; - -/** - The URL to the GeoJSON document that specifies the contents of the source. - - If the receiver was initialized using `-initWithIdentifier:geoJSONData:options`, this - property is set to `nil`. - */ -@property (nonatomic, nullable) NSURL *URL; - - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLGeoJSONSource.mm b/platform/darwin/src/MGLGeoJSONSource.mm deleted file mode 100644 index 8b37ba47c..000000000 --- a/platform/darwin/src/MGLGeoJSONSource.mm +++ /dev/null @@ -1,207 +0,0 @@ -#import "MGLGeoJSONSource_Private.h" - -#import "MGLMapView_Private.h" -#import "MGLSource_Private.h" -#import "MGLFeature_Private.h" - -#import "NSURL+MGLAdditions.h" - -#include - -const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionClustered = @"MGLGeoJSONSourceOptionClustered"; -const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionClusterRadius = @"MGLGeoJSONSourceOptionClusterRadius"; -const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionMaximumZoomLevelForClustering = @"MGLGeoJSONSourceOptionMaximumZoomLevelForClustering"; -const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionMaximumZoomLevel = @"MGLGeoJSONSourceOptionMaximumZoomLevel"; -const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionBuffer = @"MGLGeoJSONSourceOptionBuffer"; -const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionSimplificationTolerance = @"MGLGeoJSONSourceOptionSimplificationTolerance"; - -@interface MGLGeoJSONSource () - -@property (nonatomic, readwrite) NSDictionary *options; -@property (nonatomic) mbgl::style::GeoJSONSource *rawSource; - -@end - -@implementation MGLGeoJSONSource -{ - std::unique_ptr _pendingSource; -} - -- (instancetype)initWithIdentifier:(NSString *)identifier geoJSONData:(NSData *)data options:(NS_DICTIONARY_OF(NSString *, id) *)options -{ - if (self = [super initWithIdentifier:identifier]) - { - _geoJSONData = data; - _options = options; - [self commonInit]; - } - return self; -} - -- (instancetype)initWithIdentifier:(NSString *)identifier URL:(NSURL *)url options:(NS_DICTIONARY_OF(NSString *, id) *)options -{ - if (self = [super initWithIdentifier:identifier]) - { - _URL = url; - _options = options; - [self commonInit]; - } - return self; -} - -- (instancetype)initWithIdentifier:(NSString *)identifier features:(NSArray> *)features options:(NS_DICTIONARY_OF(NSString *,id) *)options { - if (self = [super initWithIdentifier:identifier]) { - _features = features; - _options = options; - [self commonInit]; - } - - return self; -} - -- (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 -{ - auto removedSource = mapView.mbglMap->removeSource(self.identifier.UTF8String); - - _pendingSource = std::move(reinterpret_cast &>(removedSource)); - self.rawSource = _pendingSource.get(); -} - -- (void)commonInit -{ - auto source = std::make_unique(self.identifier.UTF8String, self.geoJSONOptions); - - if (self.URL) { - NSURL *url = self.URL.mgl_URLByStandardizingScheme; - source->setURL(url.absoluteString.UTF8String); - _features = nil; - } else if (self.geoJSONData) { - NSString *string = [[NSString alloc] initWithData:self.geoJSONData encoding:NSUTF8StringEncoding]; - const auto geojson = mapbox::geojson::parse(string.UTF8String).get(); - source->setGeoJSON(geojson); - _features = MGLFeaturesFromMBGLFeatures(geojson); - } else { - mbgl::FeatureCollection featureCollection; - featureCollection.reserve(self.features.count); - for (id feature in self.features) { - featureCollection.push_back([feature mbglFeature]); - } - const auto geojson = mbgl::GeoJSON{featureCollection}; - source->setGeoJSON(geojson); - _features = MGLFeaturesFromMBGLFeatures(featureCollection); - } - - _pendingSource = std::move(source); - self.rawSource = _pendingSource.get(); -} - -- (mbgl::style::GeoJSONOptions)geoJSONOptions -{ - auto mbglOptions = mbgl::style::GeoJSONOptions(); - - if (id value = self.options[MGLGeoJSONSourceOptionMaximumZoomLevel]) { - [self validateValue:value]; - mbglOptions.maxzoom = [value integerValue]; - } - - if (id value = self.options[MGLGeoJSONSourceOptionBuffer]) { - [self validateValue:value]; - mbglOptions.buffer = [value integerValue]; - } - - if (id value = self.options[MGLGeoJSONSourceOptionSimplificationTolerance]) { - [self validateValue:value]; - mbglOptions.tolerance = [value doubleValue]; - } - - if (id value = self.options[MGLGeoJSONSourceOptionClusterRadius]) { - [self validateValue:value]; - mbglOptions.clusterRadius = [value integerValue]; - } - - if (id value = self.options[MGLGeoJSONSourceOptionMaximumZoomLevelForClustering]) { - [self validateValue:value]; - mbglOptions.clusterMaxZoom = [value integerValue]; - } - - if (id value = self.options[MGLGeoJSONSourceOptionClustered]) { - [self validateValue:value]; - mbglOptions.cluster = [value boolValue]; - } - - return mbglOptions; -} - -- (void)validateValue:(id)value -{ - if (! [value isKindOfClass:[NSNumber class]]) - { - [NSException raise:@"Value not handled" format:@"%@ is not an NSNumber", value]; - } -} - -- (void)setGeoJSONData:(NSData *)geoJSONData -{ - _geoJSONData = geoJSONData; - - if (self.rawSource == NULL) - { - [self commonInit]; - } - - NSString *string = [[NSString alloc] initWithData:_geoJSONData encoding:NSUTF8StringEncoding]; - const auto geojson = mapbox::geojson::parse(string.UTF8String).get(); - self.rawSource->setGeoJSON(geojson); - - _features = MGLFeaturesFromMBGLFeatures(geojson); -} - -- (void)setURL:(NSURL *)URL -{ - _URL = URL; - - if (self.rawSource == NULL) - { - [self commonInit]; - } - - NSURL *url = self.URL.mgl_URLByStandardizingScheme; - self.rawSource->setURL(url.absoluteString.UTF8String); -} - -- (void)setFeatures:(NSArray *)features -{ - if (self.rawSource == NULL) - { - [self commonInit]; - } - - mbgl::FeatureCollection featureCollection; - featureCollection.reserve(features.count); - for (id feature in features) { - featureCollection.push_back([feature mbglFeature]); - } - const auto geojson = mbgl::GeoJSON{featureCollection}; - self.rawSource->setGeoJSON(geojson); - - _features = MGLFeaturesFromMBGLFeatures(featureCollection); -} - -- (NSString *)description -{ - return [NSString stringWithFormat:@"<%@: %p; identifier = %@; URL = %@; geoJSONData = %@; features = %@>", - NSStringFromClass([self class]), (void *)self, self.identifier, self.URL, self.geoJSONData, self.features]; -} - -@end diff --git a/platform/darwin/src/MGLGeoJSONSource_Private.h b/platform/darwin/src/MGLGeoJSONSource_Private.h deleted file mode 100644 index de5bb10fa..000000000 --- a/platform/darwin/src/MGLGeoJSONSource_Private.h +++ /dev/null @@ -1,10 +0,0 @@ -#import "MGLGeoJSONSource.h" -#import "MGLGeoJSONSource_Private.h" - -#include - -@interface MGLGeoJSONSource (Private) - -- (mbgl::style::GeoJSONOptions)geoJSONOptions; - -@end diff --git a/platform/darwin/src/MGLGeometry.h b/platform/darwin/src/MGLGeometry.h index e2a4d818b..8e36b86d9 100644 --- a/platform/darwin/src/MGLGeometry.h +++ b/platform/darwin/src/MGLGeometry.h @@ -62,6 +62,14 @@ NS_INLINE BOOL MGLCoordinateBoundsEqualToCoordinateBounds(MGLCoordinateBounds bo bounds1.ne.longitude == bounds2.ne.longitude); } +/** Returns `YES` if the two coordinate bounds intersect. */ +NS_INLINE BOOL MGLCoordinateBoundsIntersectsCoordinateBounds(MGLCoordinateBounds bounds1, MGLCoordinateBounds bounds2) { + return (bounds1.ne.latitude > bounds2.sw.latitude && + bounds1.sw.latitude < bounds2.ne.latitude && + bounds1.ne.longitude > bounds2.sw.longitude && + bounds1.sw.longitude < bounds2.ne.longitude); +} + /** Returns `YES` if the coordinate is within the coordinate bounds. */ NS_INLINE BOOL MGLCoordinateInCoordinateBounds(CLLocationCoordinate2D coordinate, MGLCoordinateBounds bounds) { return (coordinate.latitude >= bounds.sw.latitude && diff --git a/platform/darwin/src/MGLLineStyleLayer.h b/platform/darwin/src/MGLLineStyleLayer.h index 74d8f7bfe..c47c7d516 100644 --- a/platform/darwin/src/MGLLineStyleLayer.h +++ b/platform/darwin/src/MGLLineStyleLayer.h @@ -141,8 +141,13 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslateAnchor) { This property is measured in line widths. This property is only applied to the style if `linePattern` is set to `nil`. Otherwise, it is ignored. + + This attribute corresponds to the line-dasharray paint property in the Mapbox Style Specification. */ -@property (nonatomic, null_resettable) MGLStyleValue *> *lineDasharray; +@property (nonatomic, null_resettable) MGLStyleValue *> *lineDashPattern; + + +@property (nonatomic, null_resettable) MGLStyleValue *> *lineDasharray __attribute__((unavailable("Use lineDashPattern instead."))); /** Draws a line casing outside of a line's actual path. Value indicates the width of the inner gap. diff --git a/platform/darwin/src/MGLLineStyleLayer.mm b/platform/darwin/src/MGLLineStyleLayer.mm index b155ec65d..48164ed0c 100644 --- a/platform/darwin/src/MGLLineStyleLayer.mm +++ b/platform/darwin/src/MGLLineStyleLayer.mm @@ -46,15 +46,26 @@ namespace mbgl { if (self = [super initWithIdentifier:identifier source:source]) { auto layer = std::make_unique(identifier.UTF8String, source.identifier.UTF8String); _pendingLayer = std::move(layer); - _rawLayer = _pendingLayer.get(); + self.rawLayer = _pendingLayer.get(); } return self; } + +- (mbgl::style::LineLayer *)rawLayer +{ + return (mbgl::style::LineLayer *)super.rawLayer; +} + +- (void)setRawLayer:(mbgl::style::LineLayer *)rawLayer +{ + super.rawLayer = rawLayer; +} + - (NSString *)sourceLayerIdentifier { MGLAssertStyleLayerIsValid(); - auto layerID = _rawLayer->getSourceLayer(); + auto layerID = self.rawLayer->getSourceLayer(); return layerID.empty() ? nil : @(layerID.c_str()); } @@ -62,25 +73,26 @@ namespace mbgl { { MGLAssertStyleLayerIsValid(); - _rawLayer->setSourceLayer(sourceLayerIdentifier.UTF8String ?: ""); + self.rawLayer->setSourceLayer(sourceLayerIdentifier.UTF8String ?: ""); } - (void)setPredicate:(NSPredicate *)predicate { MGLAssertStyleLayerIsValid(); - _rawLayer->setFilter(predicate.mgl_filter); + self.rawLayer->setFilter(predicate.mgl_filter); } - (NSPredicate *)predicate { MGLAssertStyleLayerIsValid(); - return [NSPredicate mgl_predicateWithFilter:_rawLayer->getFilter()]; + return [NSPredicate mgl_predicateWithFilter:self.rawLayer->getFilter()]; } -#pragma mark - Adding to and removing from a map view -- (void)addToMapView:(MGLMapView *)mapView +#pragma mark - Adding to and removing from a map view + +- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer { if (_pendingLayer == nullptr) { [NSException raise:@"MGLRedundantLayerException" @@ -88,11 +100,6 @@ namespace mbgl { "to the style more than once is invalid.", self, mapView.style]; } - [self addToMapView:mapView belowLayer:nil]; -} - -- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer -{ if (otherLayer) { const mbgl::optional belowLayerId{otherLayer.identifier.UTF8String}; mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId); @@ -104,7 +111,7 @@ namespace mbgl { - (void)removeFromMapView:(MGLMapView *)mapView { _pendingLayer = nullptr; - _rawLayer = nullptr; + self.rawLayer = nullptr; auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String); if (!removedLayer) { @@ -119,7 +126,7 @@ namespace mbgl { removedLayer.release(); _pendingLayer = std::unique_ptr(layer); - _rawLayer = _pendingLayer.get(); + self.rawLayer = _pendingLayer.get(); } #pragma mark - Accessing the Layout Attributes @@ -128,13 +135,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toEnumPropertyValue(lineCap); - _rawLayer->setLineCap(mbglValue); + self.rawLayer->setLineCap(mbglValue); } - (MGLStyleValue *)lineCap { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getLineCap() ?: _rawLayer->getDefaultLineCap(); + auto propertyValue = self.rawLayer->getLineCap() ?: self.rawLayer->getDefaultLineCap(); return MGLStyleValueTransformer().toEnumStyleValue(propertyValue); } @@ -142,13 +149,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toEnumPropertyValue(lineJoin); - _rawLayer->setLineJoin(mbglValue); + self.rawLayer->setLineJoin(mbglValue); } - (MGLStyleValue *)lineJoin { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getLineJoin() ?: _rawLayer->getDefaultLineJoin(); + auto propertyValue = self.rawLayer->getLineJoin() ?: self.rawLayer->getDefaultLineJoin(); return MGLStyleValueTransformer().toEnumStyleValue(propertyValue); } @@ -156,13 +163,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(lineMiterLimit); - _rawLayer->setLineMiterLimit(mbglValue); + self.rawLayer->setLineMiterLimit(mbglValue); } - (MGLStyleValue *)lineMiterLimit { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getLineMiterLimit() ?: _rawLayer->getDefaultLineMiterLimit(); + auto propertyValue = self.rawLayer->getLineMiterLimit() ?: self.rawLayer->getDefaultLineMiterLimit(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -170,13 +177,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(lineRoundLimit); - _rawLayer->setLineRoundLimit(mbglValue); + self.rawLayer->setLineRoundLimit(mbglValue); } - (MGLStyleValue *)lineRoundLimit { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getLineRoundLimit() ?: _rawLayer->getDefaultLineRoundLimit(); + auto propertyValue = self.rawLayer->getLineRoundLimit() ?: self.rawLayer->getDefaultLineRoundLimit(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -186,13 +193,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(lineBlur); - _rawLayer->setLineBlur(mbglValue); + self.rawLayer->setLineBlur(mbglValue); } - (MGLStyleValue *)lineBlur { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getLineBlur() ?: _rawLayer->getDefaultLineBlur(); + auto propertyValue = self.rawLayer->getLineBlur() ?: self.rawLayer->getDefaultLineBlur(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -200,41 +207,46 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(lineColor); - _rawLayer->setLineColor(mbglValue); + self.rawLayer->setLineColor(mbglValue); } - (MGLStyleValue *)lineColor { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getLineColor() ?: _rawLayer->getDefaultLineColor(); + auto propertyValue = self.rawLayer->getLineColor() ?: self.rawLayer->getDefaultLineColor(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } -- (void)setLineDasharray:(MGLStyleValue *> *)lineDasharray { +- (void)setLineDashPattern:(MGLStyleValue *> *)lineDashPattern { MGLAssertStyleLayerIsValid(); - auto mbglValue = MGLStyleValueTransformer, NSArray *, float>().toPropertyValue(lineDasharray); - _rawLayer->setLineDasharray(mbglValue); + auto mbglValue = MGLStyleValueTransformer, NSArray *, float>().toPropertyValue(lineDashPattern); + self.rawLayer->setLineDasharray(mbglValue); } -- (MGLStyleValue *> *)lineDasharray { +- (MGLStyleValue *> *)lineDashPattern { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getLineDasharray() ?: _rawLayer->getDefaultLineDasharray(); + auto propertyValue = self.rawLayer->getLineDasharray() ?: self.rawLayer->getDefaultLineDasharray(); return MGLStyleValueTransformer, NSArray *, float>().toStyleValue(propertyValue); } + +- (void)setLineDasharray:(MGLStyleValue *> *)lineDasharray { + NSAssert(NO, @"Use -setLineDashPattern: instead."); +} + - (void)setLineGapWidth:(MGLStyleValue *)lineGapWidth { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(lineGapWidth); - _rawLayer->setLineGapWidth(mbglValue); + self.rawLayer->setLineGapWidth(mbglValue); } - (MGLStyleValue *)lineGapWidth { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getLineGapWidth() ?: _rawLayer->getDefaultLineGapWidth(); + auto propertyValue = self.rawLayer->getLineGapWidth() ?: self.rawLayer->getDefaultLineGapWidth(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -242,13 +254,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(lineOffset); - _rawLayer->setLineOffset(mbglValue); + self.rawLayer->setLineOffset(mbglValue); } - (MGLStyleValue *)lineOffset { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getLineOffset() ?: _rawLayer->getDefaultLineOffset(); + auto propertyValue = self.rawLayer->getLineOffset() ?: self.rawLayer->getDefaultLineOffset(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -256,13 +268,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(lineOpacity); - _rawLayer->setLineOpacity(mbglValue); + self.rawLayer->setLineOpacity(mbglValue); } - (MGLStyleValue *)lineOpacity { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getLineOpacity() ?: _rawLayer->getDefaultLineOpacity(); + auto propertyValue = self.rawLayer->getLineOpacity() ?: self.rawLayer->getDefaultLineOpacity(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -270,13 +282,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(linePattern); - _rawLayer->setLinePattern(mbglValue); + self.rawLayer->setLinePattern(mbglValue); } - (MGLStyleValue *)linePattern { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getLinePattern() ?: _rawLayer->getDefaultLinePattern(); + auto propertyValue = self.rawLayer->getLinePattern() ?: self.rawLayer->getDefaultLinePattern(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -284,13 +296,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer, NSValue *>().toPropertyValue(lineTranslate); - _rawLayer->setLineTranslate(mbglValue); + self.rawLayer->setLineTranslate(mbglValue); } - (MGLStyleValue *)lineTranslate { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getLineTranslate() ?: _rawLayer->getDefaultLineTranslate(); + auto propertyValue = self.rawLayer->getLineTranslate() ?: self.rawLayer->getDefaultLineTranslate(); return MGLStyleValueTransformer, NSValue *>().toStyleValue(propertyValue); } @@ -298,13 +310,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toEnumPropertyValue(lineTranslateAnchor); - _rawLayer->setLineTranslateAnchor(mbglValue); + self.rawLayer->setLineTranslateAnchor(mbglValue); } - (MGLStyleValue *)lineTranslateAnchor { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getLineTranslateAnchor() ?: _rawLayer->getDefaultLineTranslateAnchor(); + auto propertyValue = self.rawLayer->getLineTranslateAnchor() ?: self.rawLayer->getDefaultLineTranslateAnchor(); return MGLStyleValueTransformer().toEnumStyleValue(propertyValue); } @@ -312,13 +324,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(lineWidth); - _rawLayer->setLineWidth(mbglValue); + self.rawLayer->setLineWidth(mbglValue); } - (MGLStyleValue *)lineWidth { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getLineWidth() ?: _rawLayer->getDefaultLineWidth(); + auto propertyValue = self.rawLayer->getLineWidth() ?: self.rawLayer->getDefaultLineWidth(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } diff --git a/platform/darwin/src/MGLMultiPoint.h b/platform/darwin/src/MGLMultiPoint.h index 3431fc248..ed40ee9ca 100644 --- a/platform/darwin/src/MGLMultiPoint.h +++ b/platform/darwin/src/MGLMultiPoint.h @@ -7,67 +7,133 @@ NS_ASSUME_NONNULL_BEGIN /** The `MGLMultiPoint` class is an abstract superclass used to define shapes - composed of multiple points. You should not create instances of this class + composed of multiple vertices. You should not create instances of this class directly. Instead, you should create instances of the `MGLPolyline` or `MGLPolygon` classes. However, you can use the method and properties of this - class to access information about the specific points associated with the line - or polygon. + class to access information about the vertices of the line or polygon. */ @interface MGLMultiPoint : MGLShape /** - The array of coordinates associated with the shape. + The array of vertices associated with the shape. - This C array is a pointer to a structure inside the multipoint object, - which may have a lifetime shorter than the multipoint object and will - certainly not have a longer lifetime. Therefore, you should copy the C - array if it needs to be stored outside of the memory context in which you - use this property. + This C array is a pointer to a structure inside the multipoint object, which + may have a lifetime shorter than the multipoint object and will certainly not + have a longer lifetime. Therefore, you should copy the C array if it needs to + be stored outside of the memory context in which you use this property. */ @property (nonatomic, readonly) CLLocationCoordinate2D *coordinates NS_RETURNS_INNER_POINTER; -/** The number of coordinates associated with the shape. (read-only) */ +/** The number of vertices in the shape. */ @property (nonatomic, readonly) NSUInteger pointCount; /** - Retrieves one or more coordinates associated with the shape. + Retrieves the vertices of part of the shape. - @param coords On input, you must provide a C array of structures large enough - to hold the desired number of coordinates. On output, this structure - contains the requested coordinate data. - @param range The range of points you want. The `location` field indicates the - first point you are requesting, with `0` being the first point, `1` being - the second point, and so on. The `length` field indicates the number of - points you want. The array in _`coords`_ must be large enough to accommodate - the number of requested coordinates. + @param coords On input, you must provide a C array of `CLLocationCoordinate2D` + structures large enough to hold the desired number of coordinates. On + output, this structure contains the requested coordinate data. + @param range The range of vertices you want. The `location` field indicates + the first vertex you are requesting, with `0` being the first vertex, `1` + being the second vertex, and so on. The `length` field indicates the number + of vertices you want. The array in `coords` must be large enough to + accommodate the number of requested coordinates. */ - (void)getCoordinates:(CLLocationCoordinate2D *)coords range:(NSRange)range; /** - Updates one or more coordinates for the shape, which will instantaneously - cause the shape to be redrawn if it is currently visible on the map. + Sets the shape’s vertices to the given C array of vertices. - @param range The range of points to update. The `location` field indicates the - first point you are replacing, with `0` being the first point, `1` being - the second point, and so on. The `length` field indicates the number of - points to update. The array in _`coords`_ must be equal in number to the - length of the range. If you want to append to the existing coordinates - array use `-[MGLMultiPoint appendCoordinates:count:]`. @param coords The array of coordinates defining the shape. The data in this - array is copied to the object. + array is copied to the shape’s `coordinates` property. + @param count The number of coordinates from the `coords` array. */ -- (void)replaceCoordinatesInRange:(NSRange)range withCoordinates:(const CLLocationCoordinate2D *)coords; +- (void)setCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count; /** - Appends one or more coordinates for the shape, which will instantaneously - cause the shape to be redrawn if it is currently visible on the map. + Inserts the given vertices into the shape. If the shape is currently visible on + the map, it is redrawn immediately. + + @param coords The array of coordinates to insert into the shape. The data in + this array is copied to the shape’s `coordinate` property. + @param count The number of items in the `coords` array. + @param index The zero-based index at which the first coordinate in `coords` + will appear in the `coordinates` property. + */ +- (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. @param coords The array of coordinates to add to the shape. The data in this - array is copied to the new object. + array is copied to the shape’s `coordinate` property. @param count The number of items in the `coords` array. */ - (void)appendCoordinates:(const CLLocationCoordinate2D *)coords count:(NSUInteger)count; +/** + 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. + + 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 + `-replaceCoordinatesInRange:withCoordinates:count:` method. + + If `range` extends beyond the shape’s `coordinates` property, an + `NSRangeException` is raised. If you want to append new vertices to the shape, + use the `-appendCoordinates:count:` method. + + @param range The range of vertices to replace. The `location` field indicates + the first vertex you are replacing, with `0` being the first vertex, `1` + being the second vertex, and so on. The `length` field indicates the number + of vertices to replace. + @param coords The array of coordinates defining part of the shape. The data in + this array is copied to the shape’s `coordinate` property. + */ +- (void)replaceCoordinatesInRange:(NSRange)range withCoordinates:(const CLLocationCoordinate2D *)coords; + +/** + 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. + + 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 + than the `length` field of `range`, some vertices will effectively be removed. + + If `range` extends beyond the shape’s `coordinates` property, an + `NSRangeException` is raised. If you want to append new vertices to the shape, + use the `-appendCoordinates:count:` method. + + @param range The range of vertices to replace. The `location` field indicates + the first vertex you are replacing, with `0` being the first vertex, `1` + being the second vertex, and so on. The `length` field indicates the number + of vertices to replace. + @param coords The array of coordinates defining part of the shape. The data in + this array is copied to the shape’s `coordinates` property. + @param count The number of coordinates from the `coords` array to insert in + place of the coordinates in `range`. The sum of `range`’s length and this + count must not exceed the number of items currently in the `coordinates` + property. + */ +- (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. + + If `range` extends beyond the shape’s `coordinates` property, an + `NSRangeException` is raised. + + @param range The range of vertices to remove. The `location` field indicates + the first vertex you are removing, with `0` being the first vertex, `1` + being the second vertex, and so on. The `length` field indicates the number + of vertices to remove. + */ +- (void)removeCoordinatesInRange:(NSRange)range; + @end NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLMultiPoint.mm b/platform/darwin/src/MGLMultiPoint.mm index 57b57889f..c49e970c6 100644 --- a/platform/darwin/src/MGLMultiPoint.mm +++ b/platform/darwin/src/MGLMultiPoint.mm @@ -2,19 +2,12 @@ #import "MGLGeometry_Private.h" #import "MGLTypes.h" -#import - -mbgl::Color MGLColorObjectFromCGColorRef(CGColorRef cgColor) -{ - if (!cgColor) return { 0, 0, 0, 0 }; - NSCAssert(CGColorGetNumberOfComponents(cgColor) >= 4, @"Color must have at least 4 components"); - const CGFloat *components = CGColorGetComponents(cgColor); - return { (float)components[0], (float)components[1], (float)components[2], (float)components[3] }; -} +#include +#include @implementation MGLMultiPoint { - MGLCoordinateBounds _bounds; + mbgl::optional _bounds; std::vector _coordinates; } @@ -24,9 +17,11 @@ mbgl::Color MGLColorObjectFromCGColorRef(CGColorRef cgColor) if (self) { - NSAssert(count > 0, @"A multipoint must have coordinates"); + if (!count) { + [NSException raise:NSInvalidArgumentException + format:@"A multipoint must have at least one vertex."]; + } _coordinates = { coords, coords + count }; - [self computeBounds]; } return self; @@ -65,52 +60,87 @@ mbgl::Color MGLColorObjectFromCGColorRef(CGColorRef cgColor) std::copy(_coordinates.begin() + range.location, _coordinates.begin() + NSMaxRange(range), coords); } +- (void)setCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count { + if (!count) { + [NSException raise:NSInvalidArgumentException + format:@"A multipoint must have at least one vertex."]; + } + + [self willChangeValueForKey:@"coordinates"]; + _coordinates = { coords, coords + count }; + _bounds = {}; + [self didChangeValueForKey:@"coordinates"]; +} + +- (void)insertCoordinates:(const CLLocationCoordinate2D *)coords count:(NSUInteger)count atIndex:(NSUInteger)index { + if (!count) { + return; + } + + if (index > _coordinates.size()) { + [NSException raise:NSRangeException + format:@"Invalid index %lu for existing coordinate count %ld", + (unsigned long)index, (unsigned long)[self pointCount]]; + } + + [self willChangeValueForKey:@"coordinates"]; + _coordinates.insert(_coordinates.begin() + index, count, *coords); + _bounds = {}; + [self didChangeValueForKey:@"coordinates"]; +} + - (void)appendCoordinates:(const CLLocationCoordinate2D *)coords count:(NSUInteger)count { - [self willChangeValueForKey:@"coordinates"]; - _coordinates.insert(_coordinates.end(), count, *coords); - [self computeBounds]; - [self didChangeValueForKey:@"coordinates"]; + [self insertCoordinates:coords count:count atIndex:_coordinates.size()]; } - (void)replaceCoordinatesInRange:(NSRange)range withCoordinates:(const CLLocationCoordinate2D *)coords { - if (range.length == 0) - { + [self replaceCoordinatesInRange:range withCoordinates:coords count:range.length]; +} + +- (void)replaceCoordinatesInRange:(NSRange)range withCoordinates:(const CLLocationCoordinate2D *)coords count:(NSUInteger)count { + if (!count && !range.length) { return; } - if (NSMaxRange(range) > _coordinates.size()) - { + if (NSMaxRange(range) > _coordinates.size()) { [NSException raise:NSRangeException format:@"Invalid range %@ for existing coordinate count %ld", NSStringFromRange(range), (unsigned long)[self pointCount]]; } [self willChangeValueForKey:@"coordinates"]; - std::copy(coords, coords + range.length, _coordinates.begin() + range.location); - [self computeBounds]; + std::copy(coords, coords + MIN(count, range.length), _coordinates.begin() + range.location); + if (count >= range.length) { + _coordinates.insert(_coordinates.begin() + NSMaxRange(range), coords, coords + count - range.length); + } else { + _coordinates.erase(_coordinates.begin() + range.location + count, _coordinates.begin() + NSMaxRange(range)); + } + _bounds = {}; [self didChangeValueForKey:@"coordinates"]; } -- (void)computeBounds -{ - mbgl::LatLngBounds bounds = mbgl::LatLngBounds::empty(); - for (auto coordinate : _coordinates) - { - bounds.extend(mbgl::LatLng(coordinate.latitude, coordinate.longitude)); - } - _bounds = MGLCoordinateBoundsFromLatLngBounds(bounds); +- (void)removeCoordinatesInRange:(NSRange)range { + CLLocationCoordinate2D coords; + [self replaceCoordinatesInRange:range withCoordinates:&coords count:0]; } - (MGLCoordinateBounds)overlayBounds { - return _bounds; + if (!_bounds) { + mbgl::LatLngBounds bounds = mbgl::LatLngBounds::empty(); + for (auto coordinate : _coordinates) { + bounds.extend(mbgl::LatLng(coordinate.latitude, coordinate.longitude)); + } + _bounds = bounds; + } + return MGLCoordinateBoundsFromLatLngBounds(*_bounds); } - (BOOL)intersectsOverlayBounds:(MGLCoordinateBounds)overlayBounds { - return MGLLatLngBoundsFromCoordinateBounds(_bounds).intersects(MGLLatLngBoundsFromCoordinateBounds(overlayBounds)); + return MGLCoordinateBoundsIntersectsCoordinateBounds(self.overlayBounds, overlayBounds); } - (mbgl::Annotation)annotationObjectWithDelegate:(__unused id )delegate @@ -122,7 +152,8 @@ mbgl::Color MGLColorObjectFromCGColorRef(CGColorRef cgColor) - (NSString *)description { return [NSString stringWithFormat:@"<%@: %p; count = %lu; bounds = %@>", - NSStringFromClass([self class]), (void *)self, (unsigned long)[self pointCount], MGLStringFromCoordinateBounds(_bounds)]; + NSStringFromClass([self class]), (void *)self, (unsigned long)[self pointCount], + MGLStringFromCoordinateBounds(self.overlayBounds)]; } @end diff --git a/platform/darwin/src/MGLOpenGLStyleLayer.h b/platform/darwin/src/MGLOpenGLStyleLayer.h new file mode 100644 index 000000000..7cb6b147c --- /dev/null +++ b/platform/darwin/src/MGLOpenGLStyleLayer.h @@ -0,0 +1,34 @@ +#import +#import + +#import "MGLStyleValue.h" +#import "MGLStyleLayer.h" + +NS_ASSUME_NONNULL_BEGIN + +@class MGLMapView; + +typedef struct MGLStyleLayerDrawingContext { + CGSize size; + CLLocationCoordinate2D centerCoordinate; + double zoomLevel; + CLLocationDirection direction; + CGFloat pitch; + CGFloat perspectiveSkew; +} MGLStyleLayerDrawingContext; + +@interface MGLOpenGLStyleLayer : MGLStyleLayer + +@property (nonatomic, weak, readonly) MGLMapView *mapView; + +- (void)didMoveToMapView:(MGLMapView *)mapView; + +- (void)willMoveFromMapView:(MGLMapView *)mapView; + +- (void)drawInMapView:(MGLMapView *)mapView withContext:(MGLStyleLayerDrawingContext)context; + +- (void)setNeedsDisplay; + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLOpenGLStyleLayer.mm b/platform/darwin/src/MGLOpenGLStyleLayer.mm new file mode 100644 index 000000000..f109ea85b --- /dev/null +++ b/platform/darwin/src/MGLOpenGLStyleLayer.mm @@ -0,0 +1,209 @@ +#import "MGLOpenGLStyleLayer.h" + +#import "MGLMapView_Private.h" +#import "MGLStyle_Private.h" +#import "MGLStyleLayer_Private.h" + +#include +#include + +/** + Runs the preparation handler block contained in the given context, which is + implicitly an instance of `MGLOpenGLStyleLayer`. + + @param context An `MGLOpenGLStyleLayer` instance that was provided as context + when creating an OpenGL style layer. + */ +void MGLPrepareCustomStyleLayer(void *context) { + MGLOpenGLStyleLayer *layer = (__bridge MGLOpenGLStyleLayer *)context; + [layer didMoveToMapView:layer.mapView]; +} + +/** + Runs the drawing handler block contained in the given context, which is + implicitly an instance of `MGLOpenGLStyleLayer`. + + @param context An `MGLOpenGLStyleLayer` instance that was provided as context + when creating an OpenGL style layer. + */ +void MGLDrawCustomStyleLayer(void *context, const mbgl::style::CustomLayerRenderParameters ¶ms) { + MGLOpenGLStyleLayer *layer = (__bridge MGLOpenGLStyleLayer *)context; + MGLStyleLayerDrawingContext drawingContext = { + .size = CGSizeMake(params.width, params.height), + .centerCoordinate = CLLocationCoordinate2DMake(params.latitude, params.longitude), + .zoomLevel = params.zoom, + .direction = mbgl::util::wrap(params.bearing, 0., 360.), + .pitch = static_cast(params.pitch), + .perspectiveSkew = static_cast(params.altitude), + }; + [layer drawInMapView:layer.mapView withContext:drawingContext]; +} + +/** + Runs the completion handler block contained in the given context, which is + implicitly an instance of `MGLOpenGLStyleLayer`. + + @param context An `MGLOpenGLStyleLayer` instance that was provided as context + when creating an OpenGL style layer. + */ +void MGLFinishCustomStyleLayer(void *context) { + MGLOpenGLStyleLayer *layer = (__bridge MGLOpenGLStyleLayer *)context; + [layer willMoveFromMapView:layer.mapView]; +} + +/** + An `MGLOpenGLStyleLayer` is a style layer that is rendered by OpenGL code in + Objective-C blocks or Swift closures that you specify. You may initialize a new + OpenGL style layer to add to an `MGLStyle` or obtain one from an `MGLMapView`’s + current style using the `-[MGLStyle layerWithIdentifier:]` method. + + @warning This API is undocumented and therefore unsupported. It may change at + any time without notice. + */ +@interface MGLOpenGLStyleLayer () + +@property (nonatomic) mbgl::style::CustomLayer *rawLayer; + +/** + The map view whose style currently contains the layer. + + If the layer is not currently part of any map view’s style, this property is + set to `nil`. + */ +@property (nonatomic, weak, readwrite) MGLMapView *mapView; + +@end + +@implementation MGLOpenGLStyleLayer { + std::unique_ptr _pendingLayer; +} + +/** + Returns an OpenGL style layer object initialized with the given 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 layer in the style to + which it is added. + @return An initialized OpenGL style layer. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier { + if (self = [super initWithIdentifier:identifier]) { + auto layer = std::make_unique(identifier.UTF8String, + MGLPrepareCustomStyleLayer, + MGLDrawCustomStyleLayer, + MGLFinishCustomStyleLayer, + (__bridge void *)self); + _pendingLayer = std::move(layer); + self.rawLayer = _pendingLayer.get(); + } + return self; +} + +- (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 { + if (_mapView && mapView) { + [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; +} + +- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer { + self.mapView = mapView; + if (otherLayer) { + const mbgl::optional belowLayerId{ otherLayer.identifier.UTF8String }; + mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId); + } else { + mapView.mbglMap->addLayer(std::move(_pendingLayer)); + } +} + +- (void)removeFromMapView:(MGLMapView *)mapView { + auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String); + self.mapView = nil; + if (!removedLayer) { + return; + } + _pendingLayer = std::move(reinterpret_cast &>(removedLayer)); + self.rawLayer = _pendingLayer.get(); +} + +/** + Called immediately after a layer is added to a map view’s style. + + This method is intended to be overridden in a subclass. You can use this method + to perform any setup work before the layer is used to draw a frame. For + example, you might use this method to compile an OpenGL shader. The default + implementation of this method does nothing. + + Any resource acquired in this method must be released in + `-willMoveFromMapView:`. + + @param mapView The map view to whose style the layer has been added. + */ +- (void)didMoveToMapView:(MGLMapView *)mapView { + +} + +/** + Called immediately before a layer is removed from a map view’s style. + + This method is intended to be overridden in a subclass. You can use this method + to perform any teardown work once the layer has drawn its last frame and is + about to be removed from the style. The default implementation of this method + does nothing. + + This method may be called even if `-didMoveToMapView:` has not been called. + + @param mapView The map view from whose style the layer is about to be removed. + */ +- (void)willMoveFromMapView:(MGLMapView *)mapView { + +} + +/** + Called each time the layer needs to draw a new frame in a map view. + + This method is intended to be overridden in a subclass. You can use this method + to draw the layer’s content. The default implementation of this method does + nothing. + + Your implementation should not make any assumptions about the OpenGL state, + other than that the current OpenGL context is active. It may make changes to + the OpenGL state. It is not required to reset values such as the depth mask, + stencil mask, or corresponding test flags to their original values. + + Be sure to draw your fragments with a z value of 1 to take advantage + of the opaque fragment culling, in case the style contains any opaque layers + above this layer. + + @param mapView The map view to which the layer draws. + @param context A context structure with information defining the frame to draw. + */ +- (void)drawInMapView:(MGLMapView *)mapView withContext:(MGLStyleLayerDrawingContext)context { + +} + +/** + Forces the map view associated with this style to redraw the receiving layer, + causing the `-drawInMapView:withContext:` method to be called. + */ +- (void)setNeedsDisplay { + [self.mapView setNeedsGLDisplay]; +} + +@end diff --git a/platform/darwin/src/MGLOverlay.h b/platform/darwin/src/MGLOverlay.h index 48d10d9de..1066a86d1 100644 --- a/platform/darwin/src/MGLOverlay.h +++ b/platform/darwin/src/MGLOverlay.h @@ -17,14 +17,6 @@ NS_ASSUME_NONNULL_BEGIN example, you could use an overlay to show the boundaries of a national park or trace a bus route along city streets. This SDK defines several concrete classes that conform to this protocol and define standard shapes. - - Because overlays are also annotations, they have similar usage pattern to - annotations. When added to a map view using the `-addOverlay:` method, that - view detects whenever the overlay’s defined region intersects the visible - portion of the map. At that point, the map view asks its delegate to provide a - special overlay view to draw the visual representation of the overlay. If you - add an overlay to a map view as an annotation instead, it is treated as an - annotation with a single point. */ @protocol MGLOverlay diff --git a/platform/darwin/src/MGLPointAnnotation.mm b/platform/darwin/src/MGLPointAnnotation.mm index ce8e4a235..d2e87f07d 100644 --- a/platform/darwin/src/MGLPointAnnotation.mm +++ b/platform/darwin/src/MGLPointAnnotation.mm @@ -24,10 +24,10 @@ @"coordinates": @[@(self.coordinate.longitude), @(self.coordinate.latitude)]}; } -- (mbgl::Feature)featureObject +- (mbgl::Geometry)geometryObject { mbgl::Point point = { self.coordinate.longitude, self.coordinate.latitude }; - return mbgl::Feature {point}; + return point; } @end diff --git a/platform/darwin/src/MGLPointCollection.h b/platform/darwin/src/MGLPointCollection.h index ce3e95a16..95af9dae5 100644 --- a/platform/darwin/src/MGLPointCollection.h +++ b/platform/darwin/src/MGLPointCollection.h @@ -11,7 +11,7 @@ @note `MGLPointCollection` objects cannot be added to a map view using `-[MGLMapView addAnnotations:]` and related methods. However, when used in a - `MGLPointCollectionFeature` to initialize a `MGLGeoJSONSource` that is added + `MGLPointCollectionFeature` to initialize a `MGLShapeSource` that is added to the map view's style, the point collection represents as a group of distinct annotations. */ diff --git a/platform/darwin/src/MGLPointCollection.mm b/platform/darwin/src/MGLPointCollection.mm index ab4a9c978..387a575b2 100644 --- a/platform/darwin/src/MGLPointCollection.mm +++ b/platform/darwin/src/MGLPointCollection.mm @@ -1,17 +1,19 @@ #import "MGLPointCollection_Private.h" #import "MGLGeometry_Private.h" +#import #import -#import NS_ASSUME_NONNULL_BEGIN @implementation MGLPointCollection { - MGLCoordinateBounds _bounds; + MGLCoordinateBounds _overlayBounds; std::vector _coordinates; } +@synthesize overlayBounds = _overlayBounds; + + (instancetype)pointCollectionWithCoordinates:(const CLLocationCoordinate2D *)coords count:(NSUInteger)count { return [[self alloc] initWithCoordinates:coords count:count]; @@ -28,7 +30,7 @@ NS_ASSUME_NONNULL_BEGIN { bounds.extend(mbgl::LatLng(coordinate.latitude, coordinate.longitude)); } - _bounds = MGLCoordinateBoundsFromLatLngBounds(bounds); + _overlayBounds = MGLCoordinateBoundsFromLatLngBounds(bounds); } return self; } @@ -61,17 +63,12 @@ NS_ASSUME_NONNULL_BEGIN std::copy(_coordinates.begin() + range.location, _coordinates.begin() + NSMaxRange(range), coords); } -- (MGLCoordinateBounds)overlayBounds -{ - return _bounds; -} - - (BOOL)intersectsOverlayBounds:(MGLCoordinateBounds)overlayBounds { - return MGLLatLngBoundsFromCoordinateBounds(_bounds).intersects(MGLLatLngBoundsFromCoordinateBounds(overlayBounds)); + return MGLCoordinateBoundsIntersectsCoordinateBounds(_overlayBounds, overlayBounds); } -- (mbgl::Feature)featureObject +- (mbgl::Geometry)geometryObject { mbgl::MultiPoint multiPoint; multiPoint.reserve(self.pointCount); @@ -79,7 +76,7 @@ NS_ASSUME_NONNULL_BEGIN { multiPoint.push_back(mbgl::Point(self.coordinates[i].longitude, self.coordinates[i].latitude)); } - return mbgl::Feature {multiPoint}; + return multiPoint; } - (NSDictionary *)geoJSONDictionary diff --git a/platform/darwin/src/MGLPolygon.mm b/platform/darwin/src/MGLPolygon.mm index 7562db6e6..393bd31d0 100644 --- a/platform/darwin/src/MGLPolygon.mm +++ b/platform/darwin/src/MGLPolygon.mm @@ -5,6 +5,8 @@ #import "MGLPolygon+MGLAdditions.h" +#import + @implementation MGLPolygon @dynamic overlayBounds; @@ -38,23 +40,22 @@ return result; } -- (mbgl::Feature)featureObject { +- (mbgl::Polygon)polygon { mbgl::Polygon geometry; geometry.push_back(self.ring); for (MGLPolygon *polygon in self.interiorPolygons) { geometry.push_back(polygon.ring); } - return mbgl::Feature{geometry}; + return geometry; +} + +- (mbgl::Geometry)geometryObject { + return [self polygon]; } - (mbgl::Annotation)annotationObjectWithDelegate:(id )delegate { - mbgl::Polygon geometry; - geometry.push_back(self.ring); - for (MGLPolygon *polygon in self.interiorPolygons) { - geometry.push_back(polygon.ring); - } - - mbgl::FillAnnotation annotation { geometry }; + + mbgl::FillAnnotation annotation { [self polygon] }; annotation.opacity = { static_cast([delegate alphaForShapeAnnotation:self]) }; annotation.outlineColor = { [delegate strokeColorForShapeAnnotation:self] }; annotation.color = { [delegate fillColorForPolygonAnnotation:self] }; @@ -100,10 +101,10 @@ } - (BOOL)intersectsOverlayBounds:(MGLCoordinateBounds)overlayBounds { - return MGLLatLngBoundsFromCoordinateBounds(_overlayBounds).intersects(MGLLatLngBoundsFromCoordinateBounds(overlayBounds)); + return MGLCoordinateBoundsIntersectsCoordinateBounds(_overlayBounds, overlayBounds); } -- (mbgl::Feature)featureObject { +- (mbgl::Geometry)geometryObject { mbgl::MultiPolygon multiPolygon; multiPolygon.reserve(self.polygons.count); for (MGLPolygon *polygon in self.polygons) { @@ -114,7 +115,7 @@ } multiPolygon.push_back(geometry); } - return mbgl::Feature {multiPolygon}; + return multiPolygon; } - (NSDictionary *)geoJSONDictionary { diff --git a/platform/darwin/src/MGLPolyline.mm b/platform/darwin/src/MGLPolyline.mm index 1801dfd44..0baeb68e1 100644 --- a/platform/darwin/src/MGLPolyline.mm +++ b/platform/darwin/src/MGLPolyline.mm @@ -5,6 +5,8 @@ #import "MGLPolyline+MGLAdditions.h" +#import + @implementation MGLPolyline @dynamic overlayBounds; @@ -37,8 +39,8 @@ return annotation; } -- (mbgl::Feature)featureObject { - return mbgl::Feature {[self lineString]}; +- (mbgl::Geometry)geometryObject { + return [self lineString]; } - (NSDictionary *)geoJSONDictionary { @@ -79,16 +81,16 @@ } - (BOOL)intersectsOverlayBounds:(MGLCoordinateBounds)overlayBounds { - return MGLLatLngBoundsFromCoordinateBounds(_overlayBounds).intersects(MGLLatLngBoundsFromCoordinateBounds(overlayBounds)); + return MGLCoordinateBoundsIntersectsCoordinateBounds(_overlayBounds, overlayBounds); } -- (mbgl::Feature)featureObject { +- (mbgl::Geometry)geometryObject { mbgl::MultiLineString multiLineString; multiLineString.reserve(self.polylines.count); for (MGLPolyline *polyline in self.polylines) { multiLineString.push_back([polyline lineString]); } - return mbgl::Feature {multiLineString}; + return multiLineString; } - (NSDictionary *)geoJSONDictionary { diff --git a/platform/darwin/src/MGLRasterSource.h b/platform/darwin/src/MGLRasterSource.h index 78f5af8a6..262e8f2ce 100644 --- a/platform/darwin/src/MGLRasterSource.h +++ b/platform/darwin/src/MGLRasterSource.h @@ -1,88 +1,94 @@ -#import "MGLSource.h" -#import "MGLTypes.h" +#import "MGLTileSource.h" #import -@class MGLTileSet; - NS_ASSUME_NONNULL_BEGIN /** - A raster tile source. + An `NSNumber` object containing a floating-point number that specifies the + width and height (measured in points) at which the map displays each raster + image tile when the map’s zoom level is an integer. The raster source scales + its images up or down when the map’s zoom level falls between two integers. - @see The - style specification. + The default value for this option is 512. Version 4 of the + Mapbox Maps API + requires a value of 256, as do many third-party tile servers, so consult your + provider’s documentation for the correct value. + + This option is only applicable to `MGLRasterSource` objects; it is ignored when + initializing `MGLVectorSource` objects. */ -@interface MGLRasterSource : MGLSource +extern const MGLTileSourceOption MGLTileSourceOptionTileSize; + +/** + `MGLRasterSource` is a map content source that supplies raster image tiles to + be shown on the map. The location of and metadata about the tiles are defined + either by an option dictionary or by an external file that conforms to the + TileJSON specification. + A raster 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 raster source. + + Each + raster + source defined by the style JSON file is represented at runtime by an + `MGLRasterSource` 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:]`. + */ +@interface MGLRasterSource : MGLTileSource #pragma mark Initializing a Source /** - Returns a raster source initialized with an identifier, TileJSON configuration - URL, and tile size. + Returns a raster 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://`). The URL should + point to a JSON file that conforms to the + TileJSON specification. + + If a Mapbox URL is specified, this source uses a tile size of 256. For all + other tile sets, the default value is 512. (See the + `MGLTileSourceOptionTileSize` documentation for more information about tile + sizes.) If you need to use a tile size other than the default, use the + `-initWithIdentifier:configurationURL:tileSize:` method. + @param identifier A string that uniquely identifies the source in the style to which it is added. - @param url A URL to a TileJSON configuration file describing the source’s - contents and other metadata. - @param tileSize The height and width (measured in points) at which to display - each tile in this source when the map’s zoom level is an integer. + @param configurationURL A URL to a TileJSON configuration file describing the + source’s contents and other metadata. @return An initialized raster source. */ -- (instancetype)initWithIdentifier:(NSString *)identifier URL:(NSURL *)url tileSize:(CGFloat)tileSize NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithIdentifier:(NSString *)identifier configurationURL:(NSURL *)configurationURL; /** - Returns a raster source initialized with the given identifier, tile size, and - tile set. + Returns a raster source initialized with an identifier, configuration URL, and + tile size. 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://`). The URL should + point to a JSON file that conforms to the + TileJSON specification. + @param identifier A string that uniquely identifies the source in the style to which it is added. - @param tileSet A tile set describing the source’s contents and other metadata. - @param tileSize The height and width (measured in points) at which to display - each tile in this source when the map’s zoom level is an integer. + @param configurationURL A URL to a TileJSON configuration file describing the + source’s contents and other metadata. + @param tileSize The width and height (measured in points) of each tiled image + in the raster source. See the `MGLTileSourceOptionTileSize` documentation + for details. @return An initialized raster source. */ -- (instancetype)initWithIdentifier:(NSString *)identifier tileSet:(MGLTileSet *)tileSet tileSize:(CGFloat)tileSize NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithIdentifier:(NSString *)identifier configurationURL:(NSURL *)configurationURL tileSize:(CGFloat)tileSize NS_DESIGNATED_INITIALIZER; -#pragma mark Accessing a Source’s Content - -/** - A URL to a TileJSON configuration file describing the source’s contents and - other metadata. - - The URL may be a full HTTP or HTTPS URL or a Mapbox URL indicating the tile - set’s map ID (`mapbox://`). - - @see The - TileJSON specification. - */ -@property (nonatomic, readonly, copy) NSURL *URL; - -/** - The height and width (measured in points) at which to display each tile in this - source when the map’s zoom level is an integer. - - A tile may be scaled up or down when the zoom level is between two integers. - - The default value of this property is 512 points. - */ -@property (nonatomic, readonly, assign) NSUInteger tileSize; - -/** - The tile set used to locate and download tiles. - - A tile set holds the raster tile URL template strings and associated - configuration for those strings. It can be passed in place of the URL - to TileJSON in order to create a source configured to download tiles - from ordinary web URLs. - */ -@property (nonatomic, readonly, nullable) MGLTileSet *tileSet; +- (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 62472050e..edca8bced 100644 --- a/platform/darwin/src/MGLRasterSource.mm +++ b/platform/darwin/src/MGLRasterSource.mm @@ -1,90 +1,103 @@ -#import "MGLRasterSource.h" +#import "MGLRasterSource_Private.h" #import "MGLMapView_Private.h" #import "MGLSource_Private.h" -#import "MGLTileSet_Private.h" +#import "MGLTileSource_Private.h" #import "NSURL+MGLAdditions.h" #include +const MGLTileSourceOption MGLTileSourceOptionTileSize = @"MGLTileSourceOptionTileSize"; + +static const CGFloat MGLRasterSourceClassicTileSize = 256; +static const CGFloat MGLRasterSourceRetinaTileSize = 512; + @interface MGLRasterSource () +- (instancetype)initWithRawSource:(mbgl::style::RasterSource *)rawSource NS_DESIGNATED_INITIALIZER; + @property (nonatomic) mbgl::style::RasterSource *rawSource; @end -@implementation MGLRasterSource -{ +@implementation MGLRasterSource { std::unique_ptr _pendingSource; } -- (instancetype)initWithIdentifier:(NSString *)identifier URL:(NSURL *)url tileSize:(CGFloat)tileSize -{ - if (self = [super initWithIdentifier:identifier]) { - _URL = url; - _tileSize = tileSize; - [self commonInit]; +- (instancetype)initWithIdentifier:(NSString *)identifier configurationURL:(NSURL *)configurationURL { + // The style specification default is 512, but 256 is the expected value for + // any tile set that would be accessed through a mapbox: URL and therefore + // any tile URL that this option currently affects. + BOOL isMapboxURL = ([configurationURL.scheme isEqualToString:@"mapbox"] + && [configurationURL.host containsString:@"."] + && (!configurationURL.path.length || [configurationURL.path isEqualToString:@"/"])); + CGFloat tileSize = isMapboxURL ? MGLRasterSourceClassicTileSize : MGLRasterSourceRetinaTileSize; + return [self initWithIdentifier:identifier configurationURL:configurationURL tileSize:tileSize]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier configurationURL:(NSURL *)configurationURL tileSize:(CGFloat)tileSize { + if (self = [super initWithIdentifier:identifier configurationURL:configurationURL]) { + auto source = std::make_unique(identifier.UTF8String, + configurationURL.mgl_URLByStandardizingScheme.absoluteString.UTF8String, + uint16_t(round(tileSize))); + _pendingSource = std::move(source); + self.rawSource = _pendingSource.get(); } return self; } -- (instancetype)initWithIdentifier:(NSString *)identifier tileSet:(MGLTileSet *)tileSet tileSize:(CGFloat)tileSize; -{ - if (self = [super initWithIdentifier:identifier]) - { - _tileSet = tileSet; - _tileSize = tileSize; - [self commonInit]; +- (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; + if (NSNumber *tileSizeNumber = options[MGLTileSourceOptionTileSize]) { + if (![tileSizeNumber isKindOfClass:[NSNumber class]]) { + [NSException raise:NSInvalidArgumentException + format:@"MGLTileSourceOptionTileSize must be set to an NSNumber."]; + } + tileSize = static_cast(round(tileSizeNumber.doubleValue)); + } + + auto source = std::make_unique(identifier.UTF8String, tileSet, tileSize); + _pendingSource = std::move(source); + self.rawSource = _pendingSource.get(); } return self; } -- (void)commonInit -{ - std::unique_ptr source; - - if (self.URL) - { - source = std::make_unique(self.identifier.UTF8String, - self.URL.mgl_URLByStandardizingScheme.absoluteString.UTF8String, - uint16_t(self.tileSize)); - } - else - { - source = std::make_unique(self.identifier.UTF8String, - self.tileSet.mbglTileset, - uint16_t(self.tileSize)); - } - - _pendingSource = std::move(source); - self.rawSource = _pendingSource.get(); +- (instancetype)initWithRawSource:(mbgl::style::RasterSource *)rawSource { + return [super initWithRawSource:rawSource]; } -- (void)addToMapView:(MGLMapView *)mapView -{ +- (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]; + @"to the style more than once is invalid.", self, mapView.style]; } mapView.mbglMap->addSource(std::move(_pendingSource)); } -- (void)removeFromMapView:(MGLMapView *)mapView -{ +- (void)removeFromMapView:(MGLMapView *)mapView { auto removedSource = mapView.mbglMap->removeSource(self.identifier.UTF8String); _pendingSource = std::move(reinterpret_cast &>(removedSource)); self.rawSource = _pendingSource.get(); } -- (NSString *)description -{ - return [NSString stringWithFormat: - @"<%@: %p; identifier = %@; URL = %@; tileSet = %@; tileSize = %lu>", - NSStringFromClass([self class]), (void *)self, self.identifier, self.URL, - self.tileSet, (unsigned long)self.tileSize]; +- (mbgl::style::RasterSource *)rawSource { + return (mbgl::style::RasterSource *)super.rawSource; +} + +- (void)setRawSource:(mbgl::style::RasterSource *)rawSource { + super.rawSource = rawSource; +} + +- (NSString *)attributionHTMLString { + auto attribution = self.rawSource->getAttribution(); + return attribution ? @(attribution->c_str()) : nil; } @end diff --git a/platform/darwin/src/MGLRasterSource_Private.h b/platform/darwin/src/MGLRasterSource_Private.h new file mode 100644 index 000000000..47b1c1351 --- /dev/null +++ b/platform/darwin/src/MGLRasterSource_Private.h @@ -0,0 +1,17 @@ +#import "MGLRasterSource.h" + +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 68b187a90..def5221d6 100644 --- a/platform/darwin/src/MGLRasterStyleLayer.h +++ b/platform/darwin/src/MGLRasterStyleLayer.h @@ -20,16 +20,26 @@ NS_ASSUME_NONNULL_BEGIN Increase or reduce the brightness of the image. The value is the maximum brightness. 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. + + This attribute corresponds to the raster-brightness-max paint property in the Mapbox Style Specification. */ @property (nonatomic, null_resettable) MGLStyleValue *maximumRasterBrightness; + +@property (nonatomic, null_resettable) MGLStyleValue *rasterBrightnessMax __attribute__((unavailable("Use maximumRasterBrightness instead."))); + /** Increase or reduce the brightness of the image. The value is the minimum brightness. 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 attribute corresponds to the raster-brightness-min paint property in the Mapbox Style Specification. */ @property (nonatomic, null_resettable) MGLStyleValue *minimumRasterBrightness; + +@property (nonatomic, null_resettable) MGLStyleValue *rasterBrightnessMin __attribute__((unavailable("Use minimumRasterBrightness instead."))); + /** Increase or reduce the contrast of the image. @@ -52,8 +62,13 @@ NS_ASSUME_NONNULL_BEGIN This property is measured in degrees. 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 attribute corresponds to the raster-hue-rotate paint property in the Mapbox Style Specification. */ -@property (nonatomic, null_resettable) MGLStyleValue *rasterHueRotate; +@property (nonatomic, null_resettable) MGLStyleValue *rasterHueRotation; + + +@property (nonatomic, null_resettable) MGLStyleValue *rasterHueRotate __attribute__((unavailable("Use rasterHueRotation instead."))); /** The opacity at which the image will be drawn. diff --git a/platform/darwin/src/MGLRasterStyleLayer.mm b/platform/darwin/src/MGLRasterStyleLayer.mm index 3b2c3bd83..e61532773 100644 --- a/platform/darwin/src/MGLRasterStyleLayer.mm +++ b/platform/darwin/src/MGLRasterStyleLayer.mm @@ -26,13 +26,24 @@ if (self = [super initWithIdentifier:identifier source:source]) { auto layer = std::make_unique(identifier.UTF8String, source.identifier.UTF8String); _pendingLayer = std::move(layer); - _rawLayer = _pendingLayer.get(); + self.rawLayer = _pendingLayer.get(); } return self; } -#pragma mark - Adding to and removing from a map view -- (void)addToMapView:(MGLMapView *)mapView +- (mbgl::style::RasterLayer *)rawLayer +{ + return (mbgl::style::RasterLayer *)super.rawLayer; +} + +- (void)setRawLayer:(mbgl::style::RasterLayer *)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" @@ -40,11 +51,6 @@ "to the style more than once is invalid.", self, mapView.style]; } - [self addToMapView:mapView belowLayer:nil]; -} - -- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer -{ if (otherLayer) { const mbgl::optional belowLayerId{otherLayer.identifier.UTF8String}; mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId); @@ -56,7 +62,7 @@ - (void)removeFromMapView:(MGLMapView *)mapView { _pendingLayer = nullptr; - _rawLayer = nullptr; + self.rawLayer = nullptr; auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String); if (!removedLayer) { @@ -71,7 +77,7 @@ removedLayer.release(); _pendingLayer = std::unique_ptr(layer); - _rawLayer = _pendingLayer.get(); + self.rawLayer = _pendingLayer.get(); } #pragma mark - Accessing the Paint Attributes @@ -80,41 +86,51 @@ MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(maximumRasterBrightness); - _rawLayer->setRasterBrightnessMax(mbglValue); + self.rawLayer->setRasterBrightnessMax(mbglValue); } - (MGLStyleValue *)maximumRasterBrightness { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getRasterBrightnessMax() ?: _rawLayer->getDefaultRasterBrightnessMax(); + auto propertyValue = self.rawLayer->getRasterBrightnessMax() ?: self.rawLayer->getDefaultRasterBrightnessMax(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } + +- (void)setRasterBrightnessMax:(MGLStyleValue *)rasterBrightnessMax { + NSAssert(NO, @"Use -setMaximumRasterBrightness: instead."); +} + - (void)setMinimumRasterBrightness:(MGLStyleValue *)minimumRasterBrightness { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(minimumRasterBrightness); - _rawLayer->setRasterBrightnessMin(mbglValue); + self.rawLayer->setRasterBrightnessMin(mbglValue); } - (MGLStyleValue *)minimumRasterBrightness { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getRasterBrightnessMin() ?: _rawLayer->getDefaultRasterBrightnessMin(); + auto propertyValue = self.rawLayer->getRasterBrightnessMin() ?: self.rawLayer->getDefaultRasterBrightnessMin(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } + +- (void)setRasterBrightnessMin:(MGLStyleValue *)rasterBrightnessMin { + NSAssert(NO, @"Use -setMinimumRasterBrightness: instead."); +} + - (void)setRasterContrast:(MGLStyleValue *)rasterContrast { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(rasterContrast); - _rawLayer->setRasterContrast(mbglValue); + self.rawLayer->setRasterContrast(mbglValue); } - (MGLStyleValue *)rasterContrast { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getRasterContrast() ?: _rawLayer->getDefaultRasterContrast(); + auto propertyValue = self.rawLayer->getRasterContrast() ?: self.rawLayer->getDefaultRasterContrast(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -122,41 +138,46 @@ MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(rasterFadeDuration); - _rawLayer->setRasterFadeDuration(mbglValue); + self.rawLayer->setRasterFadeDuration(mbglValue); } - (MGLStyleValue *)rasterFadeDuration { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getRasterFadeDuration() ?: _rawLayer->getDefaultRasterFadeDuration(); + auto propertyValue = self.rawLayer->getRasterFadeDuration() ?: self.rawLayer->getDefaultRasterFadeDuration(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } +- (void)setRasterHueRotation:(MGLStyleValue *)rasterHueRotation { + MGLAssertStyleLayerIsValid(); + + auto mbglValue = MGLStyleValueTransformer().toPropertyValue(rasterHueRotation); + self.rawLayer->setRasterHueRotate(mbglValue); +} + +- (MGLStyleValue *)rasterHueRotation { + MGLAssertStyleLayerIsValid(); + + auto propertyValue = self.rawLayer->getRasterHueRotate() ?: self.rawLayer->getDefaultRasterHueRotate(); + return MGLStyleValueTransformer().toStyleValue(propertyValue); +} + + - (void)setRasterHueRotate:(MGLStyleValue *)rasterHueRotate { - MGLAssertStyleLayerIsValid(); - - auto mbglValue = MGLStyleValueTransformer().toPropertyValue(rasterHueRotate); - _rawLayer->setRasterHueRotate(mbglValue); -} - -- (MGLStyleValue *)rasterHueRotate { - MGLAssertStyleLayerIsValid(); - - auto propertyValue = _rawLayer->getRasterHueRotate() ?: _rawLayer->getDefaultRasterHueRotate(); - return MGLStyleValueTransformer().toStyleValue(propertyValue); + NSAssert(NO, @"Use -setRasterHueRotation: instead."); } - (void)setRasterOpacity:(MGLStyleValue *)rasterOpacity { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(rasterOpacity); - _rawLayer->setRasterOpacity(mbglValue); + self.rawLayer->setRasterOpacity(mbglValue); } - (MGLStyleValue *)rasterOpacity { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getRasterOpacity() ?: _rawLayer->getDefaultRasterOpacity(); + auto propertyValue = self.rawLayer->getRasterOpacity() ?: self.rawLayer->getDefaultRasterOpacity(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -164,13 +185,13 @@ MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(rasterSaturation); - _rawLayer->setRasterSaturation(mbglValue); + self.rawLayer->setRasterSaturation(mbglValue); } - (MGLStyleValue *)rasterSaturation { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getRasterSaturation() ?: _rawLayer->getDefaultRasterSaturation(); + auto propertyValue = self.rawLayer->getRasterSaturation() ?: self.rawLayer->getDefaultRasterSaturation(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } diff --git a/platform/darwin/src/MGLShape.h b/platform/darwin/src/MGLShape.h index ce9375c91..af815da0e 100644 --- a/platform/darwin/src/MGLShape.h +++ b/platform/darwin/src/MGLShape.h @@ -13,6 +13,30 @@ NS_ASSUME_NONNULL_BEGIN */ @interface MGLShape : NSObject +#pragma mark Creating a Shape + +/** + Returns an `MGLShape` object initialized with the given data interpreted as a + string containing a GeoJSON object. + + If the GeoJSON object is a geometry, the returned value is a kind of + `MGLShape`. If it is a feature object, the returned value is a kind of + `MGLShape` that conforms to the `MGLFeature` protocol. If it is a feature + collection object, the returned value is an instance of + `MGLShapeCollectionFeature`. + + @param data String data containing GeoJSON source code. + @param encoding The encoding used by `data`. + @param outError Upon return, if an error has occurred, a pointer to an + `NSError` object describing the error. Pass in `NULL` to ignore any error. + @return An `MGLShape` object representation of `data`, or `nil` if `data` could + not be parsed as valid GeoJSON source code. If `nil`, `outError` contains an + `NSError` object describing the problem. + */ ++ (nullable MGLShape *)shapeWithData:(NSData *)data encoding:(NSStringEncoding)encoding error:(NSError * _Nullable *)outError; + +#pragma mark Accessing the Shape Attributes + /** The title of the shape annotation. The default value of this property is `nil`. */ @@ -34,6 +58,17 @@ NS_ASSUME_NONNULL_BEGIN #endif +#pragma mark Creating GeoJSON Data + +/** + Returns the GeoJSON string representation of the shape encapsulated in a data + object. + + @param encoding The string encoding to use. + @return A data object containing the shape’s GeoJSON string representation. + */ +- (NSData *)geoJSONDataUsingEncoding:(NSStringEncoding)encoding; + @end NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLShape.mm b/platform/darwin/src/MGLShape.mm index e3d92c38c..889ef8b3d 100644 --- a/platform/darwin/src/MGLShape.mm +++ b/platform/darwin/src/MGLShape.mm @@ -1,14 +1,52 @@ -#import "MGLShape.h" +#import "MGLShape_Private.h" + +#import "MGLFeature_Private.h" @implementation MGLShape -- (CLLocationCoordinate2D)coordinate -{ - [[NSException exceptionWithName:@"MGLAbstractClassException" - reason:@"MGLShape is an abstract class" - userInfo:nil] raise]; ++ (nullable MGLShape *)shapeWithData:(NSData *)data encoding:(NSStringEncoding)encoding error:(NSError * _Nullable *)outError { + NSString *string = [[NSString alloc] initWithData:data encoding:encoding]; + if (!string) { + if (outError) { + *outError = [NSError errorWithDomain:MGLErrorDomain code:MGLErrorCodeUnknown userInfo:nil]; + } + return nil; + } + + try { + const auto geojson = mapbox::geojson::parse(string.UTF8String); + return MGLShapeFromGeoJSON(geojson); + } catch (std::runtime_error &err) { + if (outError) { + *outError = [NSError errorWithDomain:MGLErrorDomain code:MGLErrorCodeUnknown userInfo:@{ + NSLocalizedFailureReasonErrorKey: @(err.what()), + }]; + } + return nil; + } +} - return CLLocationCoordinate2DMake(MAXFLOAT, MAXFLOAT); +- (mbgl::GeoJSON)geoJSONObject { + return self.geometryObject; +} + +- (mbgl::Geometry)geometryObject { + [NSException raise:@"MGLAbstractClassException" + format:@"MGLShape is an abstract class"]; + return mbgl::Point(); +} + +- (NSData *)geoJSONDataUsingEncoding:(NSStringEncoding)encoding { + auto geometry = self.geoJSONObject; + NSString *string = @(mapbox::geojson::stringify(geometry).c_str()); + return [string dataUsingEncoding:NSUTF8StringEncoding]; +} + +- (CLLocationCoordinate2D)coordinate { + [NSException raise:@"MGLAbstractClassException" + format:@"MGLShape is an abstract class"]; + + return kCLLocationCoordinate2DInvalid; } @end diff --git a/platform/darwin/src/MGLShapeCollection.m b/platform/darwin/src/MGLShapeCollection.mm similarity index 73% rename from platform/darwin/src/MGLShapeCollection.m rename to platform/darwin/src/MGLShapeCollection.mm index 0f011bfd2..e317a443f 100644 --- a/platform/darwin/src/MGLShapeCollection.m +++ b/platform/darwin/src/MGLShapeCollection.mm @@ -1,5 +1,9 @@ #import "MGLShapeCollection.h" +#import "MGLShape_Private.h" + +#import + @implementation MGLShapeCollection + (instancetype)shapeCollectionWithShapes:(NS_ARRAY_OF(MGLShape *) *)shapes { @@ -32,4 +36,13 @@ return [geometries copy]; } +- (mbgl::Geometry)geometryObject { + mapbox::geojson::geometry_collection collection; + collection.reserve(self.shapes.count); + for (MGLShape *shape in self.shapes) { + collection.push_back([shape geometryObject]); + } + return collection; +} + @end diff --git a/platform/darwin/src/MGLShapeSource.h b/platform/darwin/src/MGLShapeSource.h new file mode 100644 index 000000000..68cb40a83 --- /dev/null +++ b/platform/darwin/src/MGLShapeSource.h @@ -0,0 +1,135 @@ +#import "MGLSource.h" + +#import "MGLTypes.h" +#import "MGLShape.h" + +NS_ASSUME_NONNULL_BEGIN + +@protocol MGLFeature; + +/** + Options for `MGLShapeSource` objects. + */ +typedef NSString *MGLShapeSourceOption NS_STRING_ENUM; + +/** + An `NSNumber` object containing a Boolean enabling or disabling clustering. + If the `shape` property contains point shapes, setting this option to + `YES` clusters the points by radius into groups. The default value is `NO`. + */ +extern const MGLShapeSourceOption MGLShapeSourceOptionClustered; + +/** + An `NSNumber` object containing an integer; specifies the radius of each + cluster if clustering is enabled. A value of 512 produces a radius equal to + the width of a tile. The default value is 50. + */ +extern const MGLShapeSourceOption MGLShapeSourceOptionClusterRadius; + +/** + An `NSNumber` object containing an integer; specifies the maximum zoom level at + which to cluster points if clustering is enabled. Defaults to one zoom level + less than the value of `MGLShapeSourceOptionMaximumZoomLevel` so that, at the + maximum zoom level, the shapes are not clustered. + */ +extern const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevelForClustering; + +/** + An `NSNumber` object containing an integer; specifies the maximum zoom level at + which to create vector tiles. A greater value produces greater detail at high + zoom levels. The default value is 18. + */ +extern const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevel; + +/** + An `NSNumber` object containing an integer; specifies the size of the tile + buffer on each side. A value of 0 produces no buffer. A value of 512 produces a + buffer as wide as the tile itself. Larger values produce fewer rendering + artifacts near tile edges and slower performance. The default value is 128. + */ +extern const MGLShapeSourceOption MGLShapeSourceOptionBuffer; + +/** + An `NSNumber` object containing a double; specifies the Douglas-Peucker + simplification tolerance. A greater value produces simpler geometries and + improves performance. The default value is 0.375. + */ +extern const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance; + +/** + `MGLShapeSource` is a map content source that supplies vector shapes to be + shown on the map. The shapes may be instances of `MGLShape` or `MGLFeature`, + or they may be defined by local or external + GeoJSON code. A shape source is added to an + `MGLStyle` object along with an `MGLVectorStyleLayer` object. The vector style + layer defines the appearance of any content supplied by the shape source. + + Each + geojson + source defined by the style JSON file is represented at runtime by an + `MGLShapeSource` object that you can use to refine the map’s content and + initialize new style layers. You can also add and remove sources dynamically + using methods such as `-[MGLStyle addSource:]` and + `-[MGLStyle sourceWithIdentifier:]`. + + Any vector style layer initialized with a shape source should have a `nil` + value in its `sourceLayerIdentifier` property. + */ +@interface MGLShapeSource : MGLSource + +#pragma mark Initializing a Source + +/** + Returns a shape source with an identifier, URL, and dictionary of options for + the source. + + @param identifier A string that uniquely identifies the source. + @param URL An HTTP(S) URL, absolute file URL, or local file URL relative to the + current application’s resource bundle. + @param options An `NSDictionary` of options for this source. + @return An initialized shape source. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier URL:(NSURL *)url options:(nullable NS_DICTIONARY_OF(MGLShapeSourceOption, id) *)options NS_DESIGNATED_INITIALIZER; + +/** + Returns a shape source with an identifier, a shape, and dictionary of options + for the source. + + To specify attributes about the shape, use an instance of an `MGLShape` + subclass that conforms to the `MGLFeature` protocol, such as `MGLPointFeature`. + To include multiple shapes in the source, use an `MGLShapeCollection` or + `MGLShapeCollectionFeature` object. + + To create a shape from GeoJSON source code, use the + `+[MGLShape shapeWithData:encoding:error:]` method. + + @param identifier A string that uniquely identifies the source. + @param shape A concrete subclass of `MGLShape` + @param options An `NSDictionary` of options for this source. + @return An initialized shape source. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier shape:(nullable MGLShape *)shape options:(nullable NS_DICTIONARY_OF(MGLShapeSourceOption, id) *)options NS_DESIGNATED_INITIALIZER; + +#pragma mark Accessing a Source’s Content + +/** + The contents of the source. A shape can represent a GeoJSON geometry, a + feature, or a collection of features. + + If the receiver was initialized using `-initWithIdentifier:URL:options:`, this + property is set to `nil`. This property is unavailable until the receiver is + passed into `-[MGLStyle addSource:]`. + */ +@property (nonatomic, copy, nullable) MGLShape *shape; + +/** + The URL to the GeoJSON document that specifies the contents of the source. + + If the receiver was initialized using `-initWithIdentifier:shape:options:`, + this property is set to `nil`. + */ +@property (nonatomic, copy, nullable) NSURL *URL; + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLShapeSource.mm b/platform/darwin/src/MGLShapeSource.mm new file mode 100644 index 000000000..d062e656c --- /dev/null +++ b/platform/darwin/src/MGLShapeSource.mm @@ -0,0 +1,165 @@ +#import "MGLShapeSource_Private.h" + +#import "MGLMapView_Private.h" +#import "MGLSource_Private.h" +#import "MGLFeature_Private.h" +#import "MGLShape_Private.h" + +#import "NSURL+MGLAdditions.h" + +#include + +const MGLShapeSourceOption MGLShapeSourceOptionClustered = @"MGLShapeSourceOptionClustered"; +const MGLShapeSourceOption MGLShapeSourceOptionClusterRadius = @"MGLShapeSourceOptionClusterRadius"; +const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevelForClustering = @"MGLShapeSourceOptionMaximumZoomLevelForClustering"; +const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevel = @"MGLShapeSourceOptionMaximumZoomLevel"; +const MGLShapeSourceOption MGLShapeSourceOptionBuffer = @"MGLShapeSourceOptionBuffer"; +const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance = @"MGLShapeSourceOptionSimplificationTolerance"; + +@interface MGLShapeSource () + +- (instancetype)initWithRawSource:(mbgl::style::GeoJSONSource *)rawSource NS_DESIGNATED_INITIALIZER; + +@property (nonatomic, readwrite) NSDictionary *options; +@property (nonatomic) mbgl::style::GeoJSONSource *rawSource; + +@end + +@implementation MGLShapeSource { + std::unique_ptr _pendingSource; +} + +- (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(identifier.UTF8String, geoJSONOptions); + + _pendingSource = std::move(source); + self.rawSource = _pendingSource.get(); + + 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(identifier.UTF8String, geoJSONOptions); + + _pendingSource = std::move(source); + self.rawSource = _pendingSource.get(); + + self.shape = shape; + } + return self; +} + +- (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 { + auto removedSource = mapView.mbglMap->removeSource(self.identifier.UTF8String); + + _pendingSource = std::move(reinterpret_cast &>(removedSource)); + 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; +} + +- (void)setURL:(NSURL *)url { + if (url) { + self.rawSource->setURL(url.mgl_URLByStandardizingScheme.absoluteString.UTF8String); + _shape = nil; + } else { + self.shape = nil; + } +} + +- (void)setShape:(MGLShape *)shape { + self.rawSource->setGeoJSON({ shape.geoJSONObject }); + _shape = shape; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@: %p; identifier = %@; URL = %@; shape = %@>", + NSStringFromClass([self class]), (void *)self, self.identifier, self.URL, self.shape]; +} + +@end + +mbgl::style::GeoJSONOptions MGLGeoJSONOptionsFromDictionary(NS_DICTIONARY_OF(MGLShapeSourceOption, id) *options) { + auto geoJSONOptions = mbgl::style::GeoJSONOptions(); + + if (NSNumber *value = options[MGLShapeSourceOptionMaximumZoomLevel]) { + if (![value isKindOfClass:[NSNumber class]]) { + [NSException raise:NSInvalidArgumentException + format:@"MGLShapeSourceOptionMaximumZoomLevel must be an NSNumber."]; + } + geoJSONOptions.maxzoom = value.integerValue; + } + + if (NSNumber *value = options[MGLShapeSourceOptionBuffer]) { + if (![value isKindOfClass:[NSNumber class]]) { + [NSException raise:NSInvalidArgumentException + format:@"MGLShapeSourceOptionBuffer must be an NSNumber."]; + } + geoJSONOptions.buffer = value.integerValue; + } + + if (NSNumber *value = options[MGLShapeSourceOptionSimplificationTolerance]) { + if (![value isKindOfClass:[NSNumber class]]) { + [NSException raise:NSInvalidArgumentException + format:@"MGLShapeSourceOptionSimplificationTolerance must be an NSNumber."]; + } + geoJSONOptions.tolerance = value.doubleValue; + } + + if (NSNumber *value = options[MGLShapeSourceOptionClusterRadius]) { + if (![value isKindOfClass:[NSNumber class]]) { + [NSException raise:NSInvalidArgumentException + format:@"MGLShapeSourceOptionClusterRadius must be an NSNumber."]; + } + geoJSONOptions.clusterRadius = value.integerValue; + } + + if (NSNumber *value = options[MGLShapeSourceOptionMaximumZoomLevelForClustering]) { + if (![value isKindOfClass:[NSNumber class]]) { + [NSException raise:NSInvalidArgumentException + format:@"MGLShapeSourceOptionMaximumZoomLevelForClustering must be an NSNumber."]; + } + geoJSONOptions.clusterMaxZoom = value.integerValue; + } + + if (NSNumber *value = options[MGLShapeSourceOptionClustered]) { + if (![value isKindOfClass:[NSNumber class]]) { + [NSException raise:NSInvalidArgumentException + format:@"MGLShapeSourceOptionClustered must be an NSNumber."]; + } + geoJSONOptions.cluster = value.boolValue; + } + + return geoJSONOptions; +} diff --git a/platform/darwin/src/MGLShapeSource_Private.h b/platform/darwin/src/MGLShapeSource_Private.h new file mode 100644 index 000000000..584a5a4b3 --- /dev/null +++ b/platform/darwin/src/MGLShapeSource_Private.h @@ -0,0 +1,21 @@ +#import "MGLShapeSource.h" +#import "MGLShapeSource_Private.h" + +NS_ASSUME_NONNULL_BEGIN + +namespace mbgl { + namespace style { + class GeoJSONOptions; + struct GeoJSONSource; + } +} + +@interface MGLShapeSource (Private) + +- (instancetype)initWithRawSource:(mbgl::style::GeoJSONSource *)rawSource; + +@end + +mbgl::style::GeoJSONOptions MGLGeoJSONOptionsFromDictionary(NS_DICTIONARY_OF(MGLShapeSourceOption, id) *options); + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLShape_Private.h b/platform/darwin/src/MGLShape_Private.h index a8ee12c20..15d1c1eb9 100644 --- a/platform/darwin/src/MGLShape_Private.h +++ b/platform/darwin/src/MGLShape_Private.h @@ -1,13 +1,19 @@ #import "MGLShape.h" -#import +#import +#import @interface MGLShape (Private) /** - Returns an `mbgl::Feature` representation of the `MGLShape`. + Returns an `mbgl::GeoJSON` representation of the `MGLShape`. */ -- (mbgl::Feature)featureObject; +- (mbgl::GeoJSON)geoJSONObject; + +/** + Returns an `mbgl::Geometry` representation of the `MGLShape`. + */ +- (mbgl::Geometry)geometryObject; /** Returns a dictionary with the GeoJSON geometry member object. diff --git a/platform/darwin/src/MGLSource.h b/platform/darwin/src/MGLSource.h index ec3733bf0..6b381fca1 100644 --- a/platform/darwin/src/MGLSource.h +++ b/platform/darwin/src/MGLSource.h @@ -1,17 +1,29 @@ #import +NS_ASSUME_NONNULL_BEGIN + /** - A source supplies data to be shown on the map. Sources don't contain styling - details like color or width. Use subclasses of `MGLStyleLayer` to give visual - representation to sources. + `MGLSource` is an abstract base class for map content sources. A map content + source supplies content to be shown on the map. A source is added to an + `MGLStyle` object along with an `MGLForegroundStyleLayer` object. The + foreground style layer defines the appearance of any content supplied by the + source. - You should use the concrete subclasses of `MGLSource` to create vector, - raster, GeoJSON, and other source types. + Each source defined by the style JSON file is represented at runtime by an + `MGLSource` object that you can use to refine the map’s content. You can also + add and remove sources dynamically using methods such as + `-[MGLStyle addSource:]` and `-[MGLStyle sourceWithIdentifier:]`. + + Do not create instances of this class directly, and do not create your own + subclasses of this class. Instead, create instances of `MGLShapeSource` and the + concrete subclasses of `MGLTileSource`. */ @interface MGLSource : NSObject #pragma mark Initializing a Source +- (instancetype)init __attribute__((unavailable("Use -initWithIdentifier: instead."))); + /** Returns a source initialized with an identifier. @@ -32,3 +44,5 @@ @property (nonatomic, copy) NSString *identifier; @end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLSource.mm b/platform/darwin/src/MGLSource.mm index 2fa580df8..c96b6c41c 100644 --- a/platform/darwin/src/MGLSource.mm +++ b/platform/darwin/src/MGLSource.mm @@ -20,6 +20,14 @@ return self; } +- (instancetype)initWithRawSource:(mbgl::style::Source *)rawSource { + NSString *identifier = @(rawSource->getID().c_str()); + if (self = [self initWithIdentifier:identifier]) { + _rawSource = rawSource; + } + return self; +} + - (void)addToMapView:(MGLMapView *)mapView { [NSException raise:NSInvalidArgumentException format: @"The source %@ cannot be added to the style. " diff --git a/platform/darwin/src/MGLSource_Private.h b/platform/darwin/src/MGLSource_Private.h index 5f63f1fb1..6e1d2e379 100644 --- a/platform/darwin/src/MGLSource_Private.h +++ b/platform/darwin/src/MGLSource_Private.h @@ -1,11 +1,22 @@ #import "MGLSource.h" -#include +NS_ASSUME_NONNULL_BEGIN + +namespace mbgl { + namespace style { + class Source; + } +} @class MGLMapView; @interface MGLSource (Private) +/** + Initializes and returns a source with a raw pointer to the backing store. + */ +- (instancetype)initWithRawSource:(mbgl::style::Source *)rawSource; + /** 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, @@ -37,3 +48,5 @@ - (void)removeFromMapView:(MGLMapView *)mapView; @end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLStyle.h b/platform/darwin/src/MGLStyle.h index 54ca267ba..96dd502c3 100644 --- a/platform/darwin/src/MGLStyle.h +++ b/platform/darwin/src/MGLStyle.h @@ -30,14 +30,24 @@ NS_ASSUME_NONNULL_BEGIN static const NSInteger MGLStyleDefaultVersion = 9; /** - The proxy object for the current map style for customization purposes and a - set of convenience methods for creating style URLs of default styles provided - by Mapbox. + The proxy object for the current map style. + + MGLStyle provides a set of convenience methods for changing Mapbox + default styles using `-[MGLMapView styleURL]`. Learn more about Mapbox default styles. + + 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 `MGLMapViewDelegate` methods `-mapViewDidFinishLoadingMap:` + or `-mapView:didFinishLoadingStyle:` as indicators that it's safe + to modify the map's style. */ @interface MGLStyle : NSObject -#pragma mark Accessing Common Styles +#pragma mark Accessing Default Styles /** Returns the URL to version 8 of the @@ -199,11 +209,11 @@ static const NSInteger MGLStyleDefaultVersion = 9; /** Adds a new source to the current style. - - @note Adding the same source instance more than once will result in a + + @note Adding the same source instance more than once will result in a `MGLRedundantSourceException`. Reusing the same source identifier, even with different source instances, will result in a - `MGLRedundantSourceIdentiferException`. + `MGLRedundantSourceIdentifierException`. @param source The source to add to the current style. */ @@ -251,7 +261,7 @@ static const NSInteger MGLStyleDefaultVersion = 9; /** Adds a new layer on top of existing layers. - + @note Adding the same layer instance more than once will result in a `MGLRedundantLayerException`. Reusing the same layer identifer, even with different layer instances, will also result in an exception. @@ -371,11 +381,29 @@ static const NSInteger MGLStyleDefaultVersion = 9; #pragma mark Managing a Style’s Images +/** + Returns the image associated with the given name in the style. + + @note Names and their associated images 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 image name changes that will + occur in the default style over time. + + @param name The name associated with the image you want to obtain. + @return The image associated with the given name, or `nil` if no image is + associated with that name. + */ +- (nullable MGLImage *)imageForName:(NSString *)name; + /** Adds or overrides an image used by the style’s layers. To use an image in a style layer, give it a unique name using this method, then - set the `iconImage` property of an `MGLSymbolStyleLayer` object to that name. + set the `iconImageName` property of an `MGLSymbolStyleLayer` object to that + name. @param image The image for the name. @param name The name of the image to set to the style. diff --git a/platform/darwin/src/MGLStyle.mm b/platform/darwin/src/MGLStyle.mm index 7d7ca73a5..9ea9e760f 100644 --- a/platform/darwin/src/MGLStyle.mm +++ b/platform/darwin/src/MGLStyle.mm @@ -1,4 +1,4 @@ -#import "MGLStyle.h" +#import "MGLStyle_Private.h" #import "MGLMapView_Private.h" #import "MGLStyleLayer.h" @@ -8,6 +8,7 @@ #import "MGLSymbolStyleLayer.h" #import "MGLRasterStyleLayer.h" #import "MGLBackgroundStyleLayer.h" +#import "MGLOpenGLStyleLayer.h" #import "MGLStyle_Private.h" #import "MGLStyleLayer_Private.h" @@ -16,9 +17,12 @@ #import "NSDate+MGLAdditions.h" #import "MGLSource.h" +#import "MGLTileSource_Private.h" #import "MGLVectorSource.h" #import "MGLRasterSource.h" -#import "MGLGeoJSONSource.h" +#import "MGLShapeSource.h" + +#import "MGLAttributionInfo_Private.h" #include #include @@ -28,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -42,6 +47,7 @@ @property (nonatomic, readwrite, weak) MGLMapView *mapView; @property (readonly, copy, nullable) NSURL *URL; +@property (nonatomic, readwrite, strong) NS_MUTABLE_DICTIONARY_OF(NSString *, MGLOpenGLStyleLayer *) *openGLLayers; @end @@ -108,6 +114,7 @@ static NSURL *MGLStyleURL_emerald; - (instancetype)initWithMapView:(MGLMapView *)mapView { if (self = [super init]) { _mapView = mapView; + _openGLLayers = [NSMutableDictionary dictionary]; } return self; } @@ -157,25 +164,18 @@ static NSURL *MGLStyleURL_emerald; return rawSource ? [self sourceFromMBGLSource:rawSource] : nil; } -- (MGLSource *)sourceFromMBGLSource:(mbgl::style::Source *)mbglSource { - NSString *identifier = @(mbglSource->getID().c_str()); - +- (MGLSource *)sourceFromMBGLSource:(mbgl::style::Source *)source { // TODO: Fill in options specific to the respective source classes // https://github.com/mapbox/mapbox-gl-native/issues/6584 - MGLSource *source; - if (mbglSource->is()) { - source = [[MGLVectorSource alloc] initWithIdentifier:identifier]; - } else if (mbglSource->is()) { - source = [[MGLGeoJSONSource alloc] initWithIdentifier:identifier]; - } else if (mbglSource->is()) { - source = [[MGLRasterSource alloc] initWithIdentifier:identifier]; + if (auto vectorSource = source->as()) { + return [[MGLVectorSource alloc] initWithRawSource:vectorSource]; + } else if (auto geoJSONSource = source->as()) { + return [[MGLShapeSource alloc] initWithRawSource:geoJSONSource]; + } else if (auto rasterSource = source->as()) { + return [[MGLRasterSource alloc] initWithRawSource:rasterSource]; } else { - source = [[MGLSource alloc] initWithIdentifier:identifier]; + return [[MGLSource alloc] initWithRawSource:source]; } - - source.rawSource = mbglSource; - - return source; } - (void)addSource:(MGLSource *)source @@ -190,7 +190,7 @@ static NSURL *MGLStyleURL_emerald; try { [source addToMapView:self.mapView]; } catch (std::runtime_error & err) { - [NSException raise:@"MGLRedundantSourceIdentiferException" format:@"%s", err.what()]; + [NSException raise:@"MGLRedundantSourceIdentifierException" format:@"%s", err.what()]; } } @@ -205,6 +205,24 @@ static NSURL *MGLStyleURL_emerald; [source removeFromMapView:self.mapView]; } +- (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(); + NSMutableArray *infos = [NSMutableArray arrayWithCapacity:rawSources.size()]; + for (auto rawSource = rawSources.begin(); rawSource != rawSources.end(); ++rawSource) { + MGLTileSource *source = (MGLTileSource *)[self sourceFromMBGLSource:*rawSource]; + if (![source isKindOfClass:[MGLTileSource class]]) { + continue; + } + + NSArray *tileSetInfos = [source attributionInfosWithFontSize:fontSize linkColor:linkColor]; + [infos growArrayByAddingAttributionInfosFromArray:tileSetInfos]; + } + return infos; +} + #pragma mark Style layers - (NS_MUTABLE_ARRAY_OF(MGLStyleLayer *) *)layers @@ -272,7 +290,7 @@ static NSURL *MGLStyleURL_emerald; format:@"Cannot insert style layer at out-of-bounds index %lu.", (unsigned long)index]; } else if (index == 0) { try { - [styleLayer addToMapView:self.mapView]; + [styleLayer addToMapView:self.mapView belowLayer:nil]; } catch (const std::runtime_error & err) { [NSException raise:@"MGLRedundantLayerIdentifierException" format:@"%s", err.what()]; } @@ -294,7 +312,8 @@ static NSURL *MGLStyleURL_emerald; format:@"Cannot remove style layer at out-of-bounds index %lu.", (unsigned long)index]; } auto layer = layers.at(layers.size() - 1 - index); - self.mapView.mbglMap->removeLayer(layer->getID()); + MGLStyleLayer *styleLayer = [self layerFromMBGLLayer:layer]; + [styleLayer removeFromMapView:self.mapView]; } - (MGLStyleLayer *)layerFromMBGLLayer:(mbgl::style::Layer *)mbglLayer @@ -318,8 +337,15 @@ static NSURL *MGLStyleURL_emerald; } else if (auto circleLayer = mbglLayer->as()) { MGLSource *source = [self sourceWithIdentifier:@(circleLayer->getSourceID().c_str())]; styleLayer = [[MGLCircleStyleLayer alloc] initWithIdentifier:identifier source:source]; - } else if (mbglLayer->as()) { + } else if (mbglLayer->is()) { styleLayer = [[MGLBackgroundStyleLayer alloc] initWithIdentifier:identifier]; + } else if (auto customLayer = mbglLayer->as()) { + styleLayer = self.openGLLayers[identifier]; + if (styleLayer) { + NSAssert(styleLayer.rawLayer == customLayer, @"%@ wraps a CustomLayer that differs from the one associated with the underlying style.", styleLayer); + return styleLayer; + } + styleLayer = [[MGLOpenGLStyleLayer alloc] initWithIdentifier:identifier]; } else { NSAssert(NO, @"Unrecognized layer type"); return nil; @@ -359,7 +385,7 @@ static NSURL *MGLStyleURL_emerald; } [self willChangeValueForKey:@"layers"]; try { - [layer addToMapView:self.mapView]; + [layer addToMapView:self.mapView belowLayer:nil]; } catch (std::runtime_error & err) { [NSException raise:@"MGLRedundantLayerIdentifierException" format:@"%s", err.what()]; } @@ -430,7 +456,7 @@ static NSURL *MGLStyleURL_emerald; sibling]; } else if (index + 1 == layers.size()) { try { - [layer addToMapView:self.mapView]; + [layer addToMapView:self.mapView belowLayer:nil]; } catch (std::runtime_error & err) { [NSException raise:@"MGLRedundantLayerIdentifierException" format:@"%s", err.what()]; } @@ -509,19 +535,39 @@ static NSURL *MGLStyleURL_emerald; - (void)setImage:(MGLImage *)image forName:(NSString *)name { - NSAssert(image, @"image is null"); - NSAssert(name, @"name is null"); + if (!image) { + [NSException raise:NSInvalidArgumentException + format:@"Cannot assign nil image to “%@”.", name]; + } + if (!name) { + [NSException raise:NSInvalidArgumentException + format:@"Cannot assign image %@ to a nil name.", image]; + } self.mapView.mbglMap->addImage([name UTF8String], image.mgl_spriteImage); } - (void)removeImageForName:(NSString *)name { - NSAssert(name, @"name is null"); + if (!name) { + [NSException raise:NSInvalidArgumentException + format:@"Cannot remove image with nil name."]; + } self.mapView.mbglMap->removeImage([name UTF8String]); } +- (MGLImage *)imageForName:(NSString *)name +{ + if (!name) { + [NSException raise:NSInvalidArgumentException + format:@"Cannot get image with nil name."]; + } + + auto spriteImage = self.mapView.mbglMap->getImage([name UTF8String]); + return spriteImage ? [[MGLImage alloc] initWithMGLSpriteImage:spriteImage] : nil; +} + - (NSString *)description { return [NSString stringWithFormat:@"<%@: %p; name = %@, URL = %@>", diff --git a/platform/darwin/src/MGLStyleLayer.h.ejs b/platform/darwin/src/MGLStyleLayer.h.ejs index b97d070b9..3b576e766 100644 --- a/platform/darwin/src/MGLStyleLayer.h.ejs +++ b/platform/darwin/src/MGLStyleLayer.h.ejs @@ -90,10 +90,18 @@ typedef NS_ENUM(NSUInteger, MGL<%- camelize(property.name) %>) { <% } if (property.requires) { -%> <%- propertyReqs(property, layoutPropertiesByName, type) %> +<% } -%> +<% if (property.original) { -%> + + This attribute corresponds to the <%- property.original -%> layout property in the Mapbox Style Specification. <% } -%> */ -@property (nonatomic<% if (!property.required) { %>, null_resettable<% } %>) MGLStyleValue<<%- propertyType(property, true) %>> *<%- camelizeWithLeadingLowercase(property.name) %>; +@property (nonatomic<% if (!property.required) { %>, null_resettable<% } if (property.getter) { %>, getter=<%- objCGetter(property) -%><% } %>) MGLStyleValue<<%- propertyType(property, true) %>> *<%- camelizeWithLeadingLowercase(property.name) %>; +<% if (property.original) { %> +@property (nonatomic<% if (!property.required) { %>, null_resettable<% } %>) MGLStyleValue<<%- propertyType(property, true) %>> *<%- camelizeWithLeadingLowercase(originalPropertyName(property)) %> __attribute__((unavailable("Use <%- camelizeWithLeadingLowercase(property.name) %> instead."))); + +<% } -%> <% } -%> <% } -%> <% if (paintProperties.length) { -%> @@ -108,10 +116,18 @@ typedef NS_ENUM(NSUInteger, MGL<%- camelize(property.name) %>) { <% } if (property.requires) { -%> <%- propertyReqs(property, paintPropertiesByName, type) %> +<% } -%> +<% if (property.original) { -%> + + This attribute corresponds to the <%- property.original -%> paint property in the Mapbox Style Specification. <% } -%> */ -@property (nonatomic<% if (!property.required) { %>, null_resettable<% } %>) MGLStyleValue<<%- propertyType(property, true) %>> *<%- camelizeWithLeadingLowercase(property.name) %>; +@property (nonatomic<% if (!property.required) { %>, null_resettable<% } if (property.getter) { %>, getter=<%- objCGetter(property) -%><% } %>) MGLStyleValue<<%- propertyType(property, true) %>> *<%- camelizeWithLeadingLowercase(property.name) %>; +<% if (property.original) { %> +@property (nonatomic<% if (!property.required) { %>, null_resettable<% } %>) MGLStyleValue<<%- propertyType(property, true) %>> *<%- camelizeWithLeadingLowercase(originalPropertyName(property)) %> __attribute__((unavailable("Use <%- camelizeWithLeadingLowercase(property.name) %> instead."))); + +<% } -%> <% } -%> <% } -%> @end diff --git a/platform/darwin/src/MGLStyleLayer.mm b/platform/darwin/src/MGLStyleLayer.mm index 6d9dabf25..97f8f86b2 100644 --- a/platform/darwin/src/MGLStyleLayer.mm +++ b/platform/darwin/src/MGLStyleLayer.mm @@ -3,6 +3,12 @@ #include +@interface MGLStyleLayer () + +@property (nonatomic) mbgl::style::Layer *rawLayer; + +@end + @implementation MGLStyleLayer - (instancetype)initWithIdentifier:(NSString *)identifier diff --git a/platform/darwin/src/MGLStyleLayer.mm.ejs b/platform/darwin/src/MGLStyleLayer.mm.ejs index 82d8a2561..baeed3b88 100644 --- a/platform/darwin/src/MGLStyleLayer.mm.ejs +++ b/platform/darwin/src/MGLStyleLayer.mm.ejs @@ -21,9 +21,9 @@ namespace mbgl { <% if (layoutProperties.length) { -%> <% for (const property of layoutProperties) { -%> <% if (property.type == "enum") { -%> - MBGL_DEFINE_ENUM(MGL<%- camelize(originalPropertyName(property)) %>, { + MBGL_DEFINE_ENUM(MGL<%- camelize(property.name) %>, { <% for (const value in property.values) { -%> - { MGL<%- camelize(originalPropertyName(property)) %><%- camelize(value) %>, "<%-value%>" }, + { MGL<%- camelize(property.name) %><%- camelize(value) %>, "<%-value%>" }, <% } -%> }); @@ -33,9 +33,9 @@ namespace mbgl { <% if (paintProperties.length) { -%> <% for (const property of paintProperties) { -%> <% if (property.type == "enum") { -%> - MBGL_DEFINE_ENUM(MGL<%- camelize(originalPropertyName(property)) %>, { + MBGL_DEFINE_ENUM(MGL<%- camelize(property.name) %>, { <% for (const value in property.values) { -%> - { MGL<%- camelize(originalPropertyName(property)) %><%- camelize(value) %>, "<%-value%>" }, + { MGL<%- camelize(property.name) %><%- camelize(value) %>, "<%-value%>" }, <% } -%> }); @@ -62,7 +62,7 @@ namespace mbgl { if (self = [super initWithIdentifier:identifier]) { auto layer = std::make_uniqueLayer>(identifier.UTF8String); _pendingLayer = std::move(layer); - _rawLayer = _pendingLayer.get(); + self.rawLayer = _pendingLayer.get(); } return self; } @@ -73,17 +73,28 @@ namespace mbgl { if (self = [super initWithIdentifier:identifier source:source]) { auto layer = std::make_uniqueLayer>(identifier.UTF8String, source.identifier.UTF8String); _pendingLayer = std::move(layer); - _rawLayer = _pendingLayer.get(); + self.rawLayer = _pendingLayer.get(); } return self; } + <% } -%> +- (mbgl::style::<%- camelize(type) %>Layer *)rawLayer +{ + return (mbgl::style::<%- camelize(type) %>Layer *)super.rawLayer; +} + +- (void)setRawLayer:(mbgl::style::<%- camelize(type) %>Layer *)rawLayer +{ + super.rawLayer = rawLayer; +} + <% if (type !== 'background' && type !== 'raster') { -%> - (NSString *)sourceLayerIdentifier { MGLAssertStyleLayerIsValid(); - auto layerID = _rawLayer->getSourceLayer(); + auto layerID = self.rawLayer->getSourceLayer(); return layerID.empty() ? nil : @(layerID.c_str()); } @@ -91,26 +102,27 @@ namespace mbgl { { MGLAssertStyleLayerIsValid(); - _rawLayer->setSourceLayer(sourceLayerIdentifier.UTF8String ?: ""); + self.rawLayer->setSourceLayer(sourceLayerIdentifier.UTF8String ?: ""); } - (void)setPredicate:(NSPredicate *)predicate { MGLAssertStyleLayerIsValid(); - _rawLayer->setFilter(predicate.mgl_filter); + self.rawLayer->setFilter(predicate.mgl_filter); } - (NSPredicate *)predicate { MGLAssertStyleLayerIsValid(); - return [NSPredicate mgl_predicateWithFilter:_rawLayer->getFilter()]; + return [NSPredicate mgl_predicateWithFilter:self.rawLayer->getFilter()]; } -<% } -%> -#pragma mark - Adding to and removing from a map view -- (void)addToMapView:(MGLMapView *)mapView +<% } -%> +#pragma mark - Adding to and removing from a map view + +- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer { if (_pendingLayer == nullptr) { [NSException raise:@"MGLRedundantLayerException" @@ -118,11 +130,6 @@ namespace mbgl { "to the style more than once is invalid.", self, mapView.style]; } - [self addToMapView:mapView belowLayer:nil]; -} - -- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer -{ if (otherLayer) { const mbgl::optional belowLayerId{otherLayer.identifier.UTF8String}; mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId); @@ -134,7 +141,7 @@ namespace mbgl { - (void)removeFromMapView:(MGLMapView *)mapView { _pendingLayer = nullptr; - _rawLayer = nullptr; + self.rawLayer = nullptr; auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String); if (!removedLayer) { @@ -149,7 +156,7 @@ namespace mbgl { removedLayer.release(); _pendingLayer = std::unique_ptrLayer>(layer); - _rawLayer = _pendingLayer.get(); + self.rawLayer = _pendingLayer.get(); } <% if (layoutProperties.length) { -%> @@ -160,25 +167,35 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); <% if (property.type == "enum") { -%> - auto mbglValue = MGLStyleValueTransformer, NSValue *, mbgl::style::<%- mbglType(property) %>, MGL<%- camelize(originalPropertyName(property)) %>>().toEnumPropertyValue(<%- objCName(property) %>); - _rawLayer->set<%- camelize(originalPropertyName(property)) %>(mbglValue); + auto mbglValue = MGLStyleValueTransformer, NSValue *, mbgl::style::<%- mbglType(property) %>, MGL<%- camelize(property.name) %>>().toEnumPropertyValue(<%- objCName(property) %>); + self.rawLayer->set<%- camelize(originalPropertyName(property)) %>(mbglValue); <% } else { -%> auto mbglValue = MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toPropertyValue(<%- objCName(property) %>); - _rawLayer->set<%- camelize(originalPropertyName(property)) %>(mbglValue); + self.rawLayer->set<%- camelize(originalPropertyName(property)) %>(mbglValue); <% } -%> } -- (MGLStyleValue<<%- propertyType(property, true) %>> *)<%- objCName(property) %> { +- (MGLStyleValue<<%- propertyType(property, true) %>> *)<%- objCGetter(property) %> { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->get<%- camelize(originalPropertyName(property)) %>() ?: _rawLayer->getDefault<%- camelize(originalPropertyName(property)) %>(); + auto propertyValue = self.rawLayer->get<%- camelize(originalPropertyName(property)) %>() ?: self.rawLayer->getDefault<%- camelize(originalPropertyName(property)) %>(); <% if (property.type == "enum") { -%> - return MGLStyleValueTransformer, NSValue *, mbgl::style::<%- mbglType(property) %>, MGL<%- camelize(originalPropertyName(property)) %>>().toEnumStyleValue(propertyValue); + return MGLStyleValueTransformer, NSValue *, mbgl::style::<%- mbglType(property) %>, MGL<%- camelize(property.name) %>>().toEnumStyleValue(propertyValue); <% } else { -%> return MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toStyleValue(propertyValue); <% } -%> } +<% if (property.original) { %> +- (void)set<%- camelize(originalPropertyName(property)) %>:(MGLStyleValue<<%- propertyType(property, true) %>> *)<%- camelizeWithLeadingLowercase(originalPropertyName(property)) %> { + self.<%- camelizeWithLeadingLowercase(property.name) %> = <%- camelizeWithLeadingLowercase(originalPropertyName(property)) %>; +} + +- (MGLStyleValue<<%- propertyType(property, true) %>> *)<%- camelizeWithLeadingLowercase(originalPropertyName(property)) %> { + return self.<%- objCGetter(property) %>; +} + +<% } -%> <% } -%> <% } -%> <% if (paintProperties.length) { -%> @@ -189,25 +206,31 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); <% if (property.type == "enum") { -%> - auto mbglValue = MGLStyleValueTransformer, NSValue *, mbgl::style::<%- mbglType(property) %>, MGL<%- camelize(originalPropertyName(property)) %>>().toEnumPropertyValue(<%- objCName(property) %>); - _rawLayer->set<%- camelize(originalPropertyName(property)) %>(mbglValue); + auto mbglValue = MGLStyleValueTransformer, NSValue *, mbgl::style::<%- mbglType(property) %>, MGL<%- camelize(property.name) %>>().toEnumPropertyValue(<%- objCName(property) %>); + self.rawLayer->set<%- camelize(originalPropertyName(property)) %>(mbglValue); <% } else { -%> auto mbglValue = MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toPropertyValue(<%- objCName(property) %>); - _rawLayer->set<%- camelize(originalPropertyName(property)) %>(mbglValue); + self.rawLayer->set<%- camelize(originalPropertyName(property)) %>(mbglValue); <% } -%> } -- (MGLStyleValue<<%- propertyType(property, true) %>> *)<%- objCName(property) %> { +- (MGLStyleValue<<%- propertyType(property, true) %>> *)<%- objCGetter(property) %> { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->get<%- camelize(originalPropertyName(property)) %>() ?: _rawLayer->getDefault<%- camelize(originalPropertyName(property)) %>(); + auto propertyValue = self.rawLayer->get<%- camelize(originalPropertyName(property)) %>() ?: self.rawLayer->getDefault<%- camelize(originalPropertyName(property)) %>(); <% if (property.type == "enum") { -%> - return MGLStyleValueTransformer, NSValue *, mbgl::style::<%- mbglType(property) %>, MGL<%- camelize(originalPropertyName(property)) %>>().toEnumStyleValue(propertyValue); + return MGLStyleValueTransformer, NSValue *, mbgl::style::<%- mbglType(property) %>, MGL<%- camelize(property.name) %>>().toEnumStyleValue(propertyValue); <% } else { -%> return MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toStyleValue(propertyValue); <% } -%> } +<% if (property.original) { %> +- (void)set<%- camelize(originalPropertyName(property)) %>:(MGLStyleValue<<%- propertyType(property, true) %>> *)<%- camelizeWithLeadingLowercase(originalPropertyName(property)) %> { + NSAssert(NO, @"Use -set<%- camelize(property.name) %>: instead."); +} + +<% } -%> <% } -%> <% } -%> diff --git a/platform/darwin/src/MGLStyleLayer_Private.h b/platform/darwin/src/MGLStyleLayer_Private.h index e723c8cf1..8f1cdfb4a 100644 --- a/platform/darwin/src/MGLStyleLayer_Private.h +++ b/platform/darwin/src/MGLStyleLayer_Private.h @@ -5,6 +5,8 @@ #include +NS_ASSUME_NONNULL_BEGIN + /** Assert that the style layer is valid. @@ -19,7 +21,7 @@ @"-[MGLStyle removeLayer:] has been called " \ @"with this instance but another style layer instance was added with the same identifer. It is an " \ @"error to send any message to this layer since it cannot be recovered after removal due to the " \ - @"identifer collision. Use unique identifiers for all layer instances including layers of " \ + @"identifier collision. Use unique identifiers for all layer instances including layers of " \ @"different types."]; \ } \ } while (NO); @@ -40,13 +42,14 @@ @property (nonatomic) mbgl::style::Layer *rawLayer; /** - Adds the mbgl style layer that this object represents to the mbgl map. - + Adds the mbgl style layer that this object represents to the mbgl map below the + specified `otherLayer`. + Once a mbgl style layer 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::Layer`. */ -- (void)addToMapView:(MGLMapView *)mapView; +- (void)addToMapView:(MGLMapView *)mapView belowLayer:(nullable MGLStyleLayer *)otherLayer; /** Removes the mbgl style layer that this object represents from the mbgl map. @@ -57,13 +60,6 @@ */ - (void)removeFromMapView:(MGLMapView *)mapView; -/** - Adds the mbgl style layer that this object represents to the mbgl map below the specified `otherLayer`. - - Once a mbgl style layer 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::Layer`. - */ -- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer; - @end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLStyleValue.mm b/platform/darwin/src/MGLStyleValue.mm index 43b51d678..6ced819cd 100644 --- a/platform/darwin/src/MGLStyleValue.mm +++ b/platform/darwin/src/MGLStyleValue.mm @@ -63,6 +63,10 @@ - (instancetype)initWithBase:(CGFloat)base stops:(NSDictionary *)stops { if (self = [super init]) { + if (!stops.count) + { + [NSException raise:NSInvalidArgumentException format:@"%@ requires at least one stop.", self]; + } _base = base; _stops = stops; } diff --git a/platform/darwin/src/MGLStyle_Private.h b/platform/darwin/src/MGLStyle_Private.h index 002be884e..23ce8fbee 100644 --- a/platform/darwin/src/MGLStyle_Private.h +++ b/platform/darwin/src/MGLStyle_Private.h @@ -2,7 +2,12 @@ #import "MGLStyleLayer.h" #import "MGLFillStyleLayer.h" -#import + +NS_ASSUME_NONNULL_BEGIN + +@class MGLAttributionInfo; +@class MGLMapView; +@class MGLOpenGLStyleLayer; @interface MGLStyle (Private) @@ -10,6 +15,12 @@ @property (nonatomic, readonly, weak) MGLMapView *mapView; +- (nullable NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfosWithFontSize:(CGFloat)fontSize linkColor:(nullable MGLColor *)linkColor; + +@property (nonatomic, readonly, strong) NS_MUTABLE_DICTIONARY_OF(NSString *, MGLOpenGLStyleLayer *) *openGLLayers; + - (void)setStyleClasses:(NS_ARRAY_OF(NSString *) *)appliedClasses transitionDuration:(NSTimeInterval)transitionDuration; @end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLSymbolStyleLayer.h b/platform/darwin/src/MGLSymbolStyleLayer.h index dbb966b4e..5a216e035 100644 --- a/platform/darwin/src/MGLSymbolStyleLayer.h +++ b/platform/darwin/src/MGLSymbolStyleLayer.h @@ -113,21 +113,21 @@ typedef NS_ENUM(NSUInteger, MGLTextAnchor) { /** Text justification options. - Values of this type are used in the `textJustify` property of `MGLSymbolStyleLayer`. + Values of this type are used in the `textJustification` property of `MGLSymbolStyleLayer`. */ -typedef NS_ENUM(NSUInteger, MGLTextJustify) { +typedef NS_ENUM(NSUInteger, MGLTextJustification) { /** The text is aligned to the left. */ - MGLTextJustifyLeft, + MGLTextJustificationLeft, /** The text is centered. */ - MGLTextJustifyCenter, + MGLTextJustificationCenter, /** The text is aligned to the right. */ - MGLTextJustifyRight, + MGLTextJustificationRight, }; /** @@ -237,39 +237,45 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `NO`. Set this property to `nil` to reset it to the default value. - This property is only applied to the style if `iconImage` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. + + This attribute corresponds to the icon-allow-overlap layout property in the Mapbox Style Specification. */ -@property (nonatomic, null_resettable) MGLStyleValue *iconAllowOverlap; +@property (nonatomic, null_resettable) MGLStyleValue *iconAllowsOverlap; + + +@property (nonatomic, null_resettable) MGLStyleValue *iconAllowOverlap __attribute__((unavailable("Use iconAllowsOverlap instead."))); /** If true, other symbols can be visible even if they collide with the icon. The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `NO`. Set this property to `nil` to reset it to the default value. - This property is only applied to the style if `iconImage` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. + + This attribute corresponds to the icon-ignore-placement layout property in the Mapbox Style Specification. */ -@property (nonatomic, null_resettable) MGLStyleValue *iconIgnorePlacement; +@property (nonatomic, null_resettable) MGLStyleValue *iconIgnoresPlacement; + + +@property (nonatomic, null_resettable) MGLStyleValue *iconIgnorePlacement __attribute__((unavailable("Use iconIgnoresPlacement instead."))); /** A string with {tokens} replaced, referencing the data property to pull from. + + This attribute corresponds to the icon-image layout property in the Mapbox Style Specification. */ @property (nonatomic, null_resettable) MGLStyleValue *iconImageName; -/** - If true, the icon may be flipped to prevent it from being rendered upside-down. - - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `NO`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `iconImage` is non-`nil`, and `iconRotationAlignment` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLIconRotationAlignmentMap`, and `symbolPlacement` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLSymbolPlacementLine`. Otherwise, it is ignored. - */ -@property (nonatomic, null_resettable) MGLStyleValue *iconKeepUpright; + +@property (nonatomic, null_resettable) MGLStyleValue *iconImage __attribute__((unavailable("Use iconImageName instead."))); /** Offset distance of icon from its anchor. The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing a `CGVector` struct set to 0 from the left and 0 from the top. Set this property to `nil` to reset it to the default value. - This property is only applied to the style if `iconImage` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *iconOffset; @@ -278,9 +284,9 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `NO`. Set this property to `nil` to reset it to the default value. - This property is only applied to the style if `iconImage` is non-`nil`, and `textField` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`, and `textField` is non-`nil`. Otherwise, it is ignored. */ -@property (nonatomic, null_resettable) MGLStyleValue *iconOptional; +@property (nonatomic, null_resettable, getter=isIconOptional) MGLStyleValue *iconOptional; /** Size of the additional area around the icon bounding box used for detecting symbol collisions. @@ -289,7 +295,7 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `2`. Set this property to `nil` to reset it to the default value. - This property is only applied to the style if `iconImage` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *iconPadding; @@ -300,16 +306,21 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { 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 `iconImage` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. + + This attribute corresponds to the icon-rotate layout property in the Mapbox Style Specification. */ -@property (nonatomic, null_resettable) MGLStyleValue *iconRotate; +@property (nonatomic, null_resettable) MGLStyleValue *iconRotation; + + +@property (nonatomic, null_resettable) MGLStyleValue *iconRotate __attribute__((unavailable("Use iconRotation instead."))); /** In combination with `symbolPlacement`, determines the rotation behavior of icons. The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLIconRotationAlignmentAuto`. Set this property to `nil` to reset it to the default value. - This property is only applied to the style if `iconImage` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *iconRotationAlignment; @@ -318,16 +329,21 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { 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. - This property is only applied to the style if `iconImage` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. + + This attribute corresponds to the icon-size layout property in the Mapbox Style Specification. */ -@property (nonatomic, null_resettable) MGLStyleValue *iconSize; +@property (nonatomic, null_resettable) MGLStyleValue *iconScale; + + +@property (nonatomic, null_resettable) MGLStyleValue *iconSize __attribute__((unavailable("Use iconScale instead."))); /** Scales the icon to fit around the associated text. The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLIconTextFitNone`. Set this property to `nil` to reset it to the default value. - This property is only applied to the style if `iconImage` is non-`nil`, and `textField` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`, and `textField` is non-`nil`. Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *iconTextFit; @@ -338,16 +354,81 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `NSEdgeInsetsZero` or `UIEdgeInsetsZero`. Set this property to `nil` to reset it to the default value. - This property is only applied to the style if `iconImage` is non-`nil`, and `textField` is non-`nil`, and `iconTextFit` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLIconTextFitBoth`, `MGLIconTextFitWidth`, or `MGLIconTextFitHeight`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`, and `textField` is non-`nil`, and `iconTextFit` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLIconTextFitBoth`, `MGLIconTextFitWidth`, or `MGLIconTextFitHeight`. Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *iconTextFitPadding; +/** + If true, the icon may be flipped to prevent it from being rendered upside-down. + + The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `NO`. Set this property to `nil` to reset it to the default value. + + This property is only applied to the style if `iconImageName` is non-`nil`, and `iconRotationAlignment` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLIconRotationAlignmentMap`, and `symbolPlacement` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLSymbolPlacementLine`. Otherwise, it is ignored. + + This attribute corresponds to the icon-keep-upright layout property in the Mapbox Style Specification. + */ +@property (nonatomic, null_resettable) MGLStyleValue *keepsIconUpright; + + +@property (nonatomic, null_resettable) MGLStyleValue *iconKeepUpright __attribute__((unavailable("Use keepsIconUpright instead."))); + +/** + If true, the text may be flipped vertically to prevent it from being rendered upside-down. + + The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `YES`. Set this property to `nil` to reset it to the default value. + + This property is only applied to the style if `textField` is non-`nil`, and `textRotationAlignment` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLTextRotationAlignmentMap`, and `symbolPlacement` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLSymbolPlacementLine`. Otherwise, it is ignored. + + This attribute corresponds to the text-keep-upright layout property in the Mapbox Style Specification. + */ +@property (nonatomic, null_resettable) MGLStyleValue *keepsTextUpright; + + +@property (nonatomic, null_resettable) MGLStyleValue *textKeepUpright __attribute__((unavailable("Use keepsTextUpright instead."))); + +/** + Maximum angle change between adjacent characters. + + This property is measured in degrees. + + The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `45`. Set this property to `nil` to reset it to the default value. + + This property is only applied to the style if `textField` is non-`nil`, and `symbolPlacement` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLSymbolPlacementLine`. Otherwise, it is ignored. + + This attribute corresponds to the text-max-angle layout property in the Mapbox Style Specification. + */ +@property (nonatomic, null_resettable) MGLStyleValue *maximumTextAngle; + + +@property (nonatomic, null_resettable) MGLStyleValue *textMaxAngle __attribute__((unavailable("Use maximumTextAngle instead."))); + +/** + The maximum line width for text wrapping. + + This property is measured in ems. + + The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `10`. Set this property to `nil` to reset it to the default value. + + This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored. + + This attribute corresponds to the text-max-width layout property in the Mapbox Style Specification. + */ +@property (nonatomic, null_resettable) MGLStyleValue *maximumTextWidth; + + +@property (nonatomic, null_resettable) MGLStyleValue *textMaxWidth __attribute__((unavailable("Use maximumTextWidth instead."))); + /** If true, the symbols will not cross tile edges to avoid mutual collisions. Recommended in layers that don't have enough padding in the vector tile to prevent collisions, or if it is a point symbol layer placed after a line symbol layer. The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `NO`. Set this property to `nil` to reset it to the default value. + + This attribute corresponds to the symbol-avoid-edges layout property in the Mapbox Style Specification. */ -@property (nonatomic, null_resettable) MGLStyleValue *symbolAvoidEdges; +@property (nonatomic, null_resettable) MGLStyleValue *symbolAvoidsEdges; + + +@property (nonatomic, null_resettable) MGLStyleValue *symbolAvoidEdges __attribute__((unavailable("Use symbolAvoidsEdges instead."))); /** Label placement relative to its geometry. @@ -373,8 +454,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `NO`. Set this property to `nil` to reset it to the default value. This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored. + + This attribute corresponds to the text-allow-overlap layout property in the Mapbox Style Specification. */ -@property (nonatomic, null_resettable) MGLStyleValue *textAllowOverlap; +@property (nonatomic, null_resettable) MGLStyleValue *textAllowsOverlap; + + +@property (nonatomic, null_resettable) MGLStyleValue *textAllowOverlap __attribute__((unavailable("Use textAllowsOverlap instead."))); /** Part of the text placed closest to the anchor. @@ -407,26 +493,27 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `NO`. Set this property to `nil` to reset it to the default value. This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored. + + This attribute corresponds to the text-ignore-placement layout property in the Mapbox Style Specification. */ -@property (nonatomic, null_resettable) MGLStyleValue *textIgnorePlacement; +@property (nonatomic, null_resettable) MGLStyleValue *textIgnoresPlacement; + + +@property (nonatomic, null_resettable) MGLStyleValue *textIgnorePlacement __attribute__((unavailable("Use textIgnoresPlacement instead."))); /** Text justification options. - The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLTextJustifyCenter`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLTextJustificationCenter`. Set this property to `nil` to reset it to the default value. This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored. + + This attribute corresponds to the text-justify layout property in the Mapbox Style Specification. */ -@property (nonatomic, null_resettable) MGLStyleValue *textJustify; +@property (nonatomic, null_resettable) MGLStyleValue *textJustification; -/** - If true, the text may be flipped vertically to prevent it from being rendered upside-down. - - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `YES`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `textField` is non-`nil`, and `textRotationAlignment` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLTextRotationAlignmentMap`, and `symbolPlacement` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLSymbolPlacementLine`. Otherwise, it is ignored. - */ -@property (nonatomic, null_resettable) MGLStyleValue *textKeepUpright; + +@property (nonatomic, null_resettable) MGLStyleValue *textJustify __attribute__((unavailable("Use textJustification instead."))); /** Text tracking amount. @@ -450,28 +537,6 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { */ @property (nonatomic, null_resettable) MGLStyleValue *textLineHeight; -/** - Maximum angle change between adjacent characters. - - This property is measured in degrees. - - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `45`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `textField` is non-`nil`, and `symbolPlacement` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLSymbolPlacementLine`. Otherwise, it is ignored. - */ -@property (nonatomic, null_resettable) MGLStyleValue *textMaxAngle; - -/** - The maximum line width for text wrapping. - - This property is measured in ems. - - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `10`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored. - */ -@property (nonatomic, null_resettable) MGLStyleValue *textMaxWidth; - /** Offset distance of text from its anchor. @@ -488,9 +553,9 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `NO`. Set this property to `nil` to reset it to the default value. - This property is only applied to the style if `textField` is non-`nil`, and `iconImage` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `textField` is non-`nil`, and `iconImageName` is non-`nil`. Otherwise, it is ignored. */ -@property (nonatomic, null_resettable) MGLStyleValue *textOptional; +@property (nonatomic, null_resettable, getter=isTextOptional) MGLStyleValue *textOptional; /** Size of the additional area around the text bounding box used for detecting symbol collisions. @@ -520,8 +585,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { 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 `textField` is non-`nil`. Otherwise, it is ignored. + + This attribute corresponds to the text-rotate layout property in the Mapbox Style Specification. */ -@property (nonatomic, null_resettable) MGLStyleValue *textRotate; +@property (nonatomic, null_resettable) MGLStyleValue *textRotation; + + +@property (nonatomic, null_resettable) MGLStyleValue *textRotate __attribute__((unavailable("Use textRotation instead."))); /** In combination with `symbolPlacement`, determines the rotation behavior of the individual glyphs forming the text. @@ -556,20 +626,20 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { #if TARGET_OS_IPHONE /** - The color of the icon. This can only be used with sdf icons. + The tint color to apply to the icon. The `iconImageName` property must be set to a template image. 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 `iconImage` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *iconColor; #else /** - The color of the icon. This can only be used with sdf icons. + The tint color to apply to the icon. The `iconImageName` property must be set to a template image. 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 `iconImage` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *iconColor; #endif @@ -581,26 +651,26 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { 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 `iconImage` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *iconHaloBlur; #if TARGET_OS_IPHONE /** - The color of the icon's halo. Icon halos can only be used with SDF icons. + The color of the icon’s halo. The `iconImageName` property must be set to a template image. The default value of this property is an `MGLStyleValue` object containing `UIColor.clearColor`. Set this property to `nil` to reset it to the default value. - This property is only applied to the style if `iconImage` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *iconHaloColor; #else /** - The color of the icon's halo. Icon halos can only be used with SDF icons. + The color of the icon’s halo. The `iconImageName` property must be set to a template image. The default value of this property is an `MGLStyleValue` object containing `NSColor.clearColor`. Set this property to `nil` to reset it to the default value. - This property is only applied to the style if `iconImage` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *iconHaloColor; #endif @@ -612,7 +682,7 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { 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 `iconImage` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *iconHaloWidth; @@ -621,7 +691,7 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { 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. - This property is only applied to the style if `iconImage` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *iconOpacity; @@ -632,7 +702,7 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing a `CGVector` struct set to 0 points from the left and 0 points from the top. Set this property to `nil` to reset it to the default value. - This property is only applied to the style if `iconImage` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *iconTranslate; @@ -641,7 +711,7 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLIconTranslateAnchorMap`. Set this property to `nil` to reset it to the default value. - This property is only applied to the style if `iconImage` is non-`nil`, and `iconTranslate` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`, and `iconTranslate` is non-`nil`. Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *iconTranslateAnchor; diff --git a/platform/darwin/src/MGLSymbolStyleLayer.mm b/platform/darwin/src/MGLSymbolStyleLayer.mm index d1d66f8ff..31c584b47 100644 --- a/platform/darwin/src/MGLSymbolStyleLayer.mm +++ b/platform/darwin/src/MGLSymbolStyleLayer.mm @@ -41,10 +41,10 @@ namespace mbgl { { MGLTextAnchorBottomRight, "bottom-right" }, }); - MBGL_DEFINE_ENUM(MGLTextJustify, { - { MGLTextJustifyLeft, "left" }, - { MGLTextJustifyCenter, "center" }, - { MGLTextJustifyRight, "right" }, + MBGL_DEFINE_ENUM(MGLTextJustification, { + { MGLTextJustificationLeft, "left" }, + { MGLTextJustificationCenter, "center" }, + { MGLTextJustificationRight, "right" }, }); MBGL_DEFINE_ENUM(MGLTextPitchAlignment, { @@ -93,15 +93,26 @@ namespace mbgl { if (self = [super initWithIdentifier:identifier source:source]) { auto layer = std::make_unique(identifier.UTF8String, source.identifier.UTF8String); _pendingLayer = std::move(layer); - _rawLayer = _pendingLayer.get(); + self.rawLayer = _pendingLayer.get(); } return self; } + +- (mbgl::style::SymbolLayer *)rawLayer +{ + return (mbgl::style::SymbolLayer *)super.rawLayer; +} + +- (void)setRawLayer:(mbgl::style::SymbolLayer *)rawLayer +{ + super.rawLayer = rawLayer; +} + - (NSString *)sourceLayerIdentifier { MGLAssertStyleLayerIsValid(); - auto layerID = _rawLayer->getSourceLayer(); + auto layerID = self.rawLayer->getSourceLayer(); return layerID.empty() ? nil : @(layerID.c_str()); } @@ -109,25 +120,26 @@ namespace mbgl { { MGLAssertStyleLayerIsValid(); - _rawLayer->setSourceLayer(sourceLayerIdentifier.UTF8String ?: ""); + self.rawLayer->setSourceLayer(sourceLayerIdentifier.UTF8String ?: ""); } - (void)setPredicate:(NSPredicate *)predicate { MGLAssertStyleLayerIsValid(); - _rawLayer->setFilter(predicate.mgl_filter); + self.rawLayer->setFilter(predicate.mgl_filter); } - (NSPredicate *)predicate { MGLAssertStyleLayerIsValid(); - return [NSPredicate mgl_predicateWithFilter:_rawLayer->getFilter()]; + return [NSPredicate mgl_predicateWithFilter:self.rawLayer->getFilter()]; } -#pragma mark - Adding to and removing from a map view -- (void)addToMapView:(MGLMapView *)mapView +#pragma mark - Adding to and removing from a map view + +- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer { if (_pendingLayer == nullptr) { [NSException raise:@"MGLRedundantLayerException" @@ -135,11 +147,6 @@ namespace mbgl { "to the style more than once is invalid.", self, mapView.style]; } - [self addToMapView:mapView belowLayer:nil]; -} - -- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer -{ if (otherLayer) { const mbgl::optional belowLayerId{otherLayer.identifier.UTF8String}; mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId); @@ -151,7 +158,7 @@ namespace mbgl { - (void)removeFromMapView:(MGLMapView *)mapView { _pendingLayer = nullptr; - _rawLayer = nullptr; + self.rawLayer = nullptr; auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String); if (!removedLayer) { @@ -166,78 +173,91 @@ namespace mbgl { removedLayer.release(); _pendingLayer = std::unique_ptr(layer); - _rawLayer = _pendingLayer.get(); + self.rawLayer = _pendingLayer.get(); } #pragma mark - Accessing the Layout Attributes -- (void)setIconAllowOverlap:(MGLStyleValue *)iconAllowOverlap { +- (void)setIconAllowsOverlap:(MGLStyleValue *)iconAllowsOverlap { MGLAssertStyleLayerIsValid(); - auto mbglValue = MGLStyleValueTransformer().toPropertyValue(iconAllowOverlap); - _rawLayer->setIconAllowOverlap(mbglValue); + auto mbglValue = MGLStyleValueTransformer().toPropertyValue(iconAllowsOverlap); + self.rawLayer->setIconAllowOverlap(mbglValue); +} + +- (MGLStyleValue *)iconAllowsOverlap { + MGLAssertStyleLayerIsValid(); + + auto propertyValue = self.rawLayer->getIconAllowOverlap() ?: self.rawLayer->getDefaultIconAllowOverlap(); + return MGLStyleValueTransformer().toStyleValue(propertyValue); +} + + +- (void)setIconAllowOverlap:(MGLStyleValue *)iconAllowOverlap { + self.iconAllowsOverlap = iconAllowOverlap; } - (MGLStyleValue *)iconAllowOverlap { + return self.iconAllowsOverlap; +} + +- (void)setIconIgnoresPlacement:(MGLStyleValue *)iconIgnoresPlacement { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getIconAllowOverlap() ?: _rawLayer->getDefaultIconAllowOverlap(); + auto mbglValue = MGLStyleValueTransformer().toPropertyValue(iconIgnoresPlacement); + self.rawLayer->setIconIgnorePlacement(mbglValue); +} + +- (MGLStyleValue *)iconIgnoresPlacement { + MGLAssertStyleLayerIsValid(); + + auto propertyValue = self.rawLayer->getIconIgnorePlacement() ?: self.rawLayer->getDefaultIconIgnorePlacement(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } -- (void)setIconIgnorePlacement:(MGLStyleValue *)iconIgnorePlacement { - MGLAssertStyleLayerIsValid(); - auto mbglValue = MGLStyleValueTransformer().toPropertyValue(iconIgnorePlacement); - _rawLayer->setIconIgnorePlacement(mbglValue); +- (void)setIconIgnorePlacement:(MGLStyleValue *)iconIgnorePlacement { + self.iconIgnoresPlacement = iconIgnorePlacement; } - (MGLStyleValue *)iconIgnorePlacement { - MGLAssertStyleLayerIsValid(); - - auto propertyValue = _rawLayer->getIconIgnorePlacement() ?: _rawLayer->getDefaultIconIgnorePlacement(); - return MGLStyleValueTransformer().toStyleValue(propertyValue); + return self.iconIgnoresPlacement; } - (void)setIconImageName:(MGLStyleValue *)iconImageName { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(iconImageName); - _rawLayer->setIconImage(mbglValue); + self.rawLayer->setIconImage(mbglValue); } - (MGLStyleValue *)iconImageName { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getIconImage() ?: _rawLayer->getDefaultIconImage(); + auto propertyValue = self.rawLayer->getIconImage() ?: self.rawLayer->getDefaultIconImage(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } -- (void)setIconKeepUpright:(MGLStyleValue *)iconKeepUpright { - MGLAssertStyleLayerIsValid(); - auto mbglValue = MGLStyleValueTransformer().toPropertyValue(iconKeepUpright); - _rawLayer->setIconKeepUpright(mbglValue); +- (void)setIconImage:(MGLStyleValue *)iconImage { + self.iconImageName = iconImage; } -- (MGLStyleValue *)iconKeepUpright { - MGLAssertStyleLayerIsValid(); - - auto propertyValue = _rawLayer->getIconKeepUpright() ?: _rawLayer->getDefaultIconKeepUpright(); - return MGLStyleValueTransformer().toStyleValue(propertyValue); +- (MGLStyleValue *)iconImage { + return self.iconImageName; } - (void)setIconOffset:(MGLStyleValue *)iconOffset { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer, NSValue *>().toPropertyValue(iconOffset); - _rawLayer->setIconOffset(mbglValue); + self.rawLayer->setIconOffset(mbglValue); } - (MGLStyleValue *)iconOffset { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getIconOffset() ?: _rawLayer->getDefaultIconOffset(); + auto propertyValue = self.rawLayer->getIconOffset() ?: self.rawLayer->getDefaultIconOffset(); return MGLStyleValueTransformer, NSValue *>().toStyleValue(propertyValue); } @@ -245,13 +265,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(iconOptional); - _rawLayer->setIconOptional(mbglValue); + self.rawLayer->setIconOptional(mbglValue); } -- (MGLStyleValue *)iconOptional { +- (MGLStyleValue *)isIconOptional { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getIconOptional() ?: _rawLayer->getDefaultIconOptional(); + auto propertyValue = self.rawLayer->getIconOptional() ?: self.rawLayer->getDefaultIconOptional(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -259,69 +279,87 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(iconPadding); - _rawLayer->setIconPadding(mbglValue); + self.rawLayer->setIconPadding(mbglValue); } - (MGLStyleValue *)iconPadding { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getIconPadding() ?: _rawLayer->getDefaultIconPadding(); + auto propertyValue = self.rawLayer->getIconPadding() ?: self.rawLayer->getDefaultIconPadding(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } -- (void)setIconRotate:(MGLStyleValue *)iconRotate { +- (void)setIconRotation:(MGLStyleValue *)iconRotation { MGLAssertStyleLayerIsValid(); - auto mbglValue = MGLStyleValueTransformer().toPropertyValue(iconRotate); - _rawLayer->setIconRotate(mbglValue); + auto mbglValue = MGLStyleValueTransformer().toPropertyValue(iconRotation); + self.rawLayer->setIconRotate(mbglValue); +} + +- (MGLStyleValue *)iconRotation { + MGLAssertStyleLayerIsValid(); + + auto propertyValue = self.rawLayer->getIconRotate() ?: self.rawLayer->getDefaultIconRotate(); + return MGLStyleValueTransformer().toStyleValue(propertyValue); +} + + +- (void)setIconRotate:(MGLStyleValue *)iconRotate { + self.iconRotation = iconRotate; } - (MGLStyleValue *)iconRotate { - MGLAssertStyleLayerIsValid(); - - auto propertyValue = _rawLayer->getIconRotate() ?: _rawLayer->getDefaultIconRotate(); - return MGLStyleValueTransformer().toStyleValue(propertyValue); + return self.iconRotation; } - (void)setIconRotationAlignment:(MGLStyleValue *)iconRotationAlignment { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toEnumPropertyValue(iconRotationAlignment); - _rawLayer->setIconRotationAlignment(mbglValue); + self.rawLayer->setIconRotationAlignment(mbglValue); } - (MGLStyleValue *)iconRotationAlignment { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getIconRotationAlignment() ?: _rawLayer->getDefaultIconRotationAlignment(); + auto propertyValue = self.rawLayer->getIconRotationAlignment() ?: self.rawLayer->getDefaultIconRotationAlignment(); return MGLStyleValueTransformer().toEnumStyleValue(propertyValue); } -- (void)setIconSize:(MGLStyleValue *)iconSize { +- (void)setIconScale:(MGLStyleValue *)iconScale { MGLAssertStyleLayerIsValid(); - auto mbglValue = MGLStyleValueTransformer().toPropertyValue(iconSize); - _rawLayer->setIconSize(mbglValue); + auto mbglValue = MGLStyleValueTransformer().toPropertyValue(iconScale); + self.rawLayer->setIconSize(mbglValue); +} + +- (MGLStyleValue *)iconScale { + MGLAssertStyleLayerIsValid(); + + auto propertyValue = self.rawLayer->getIconSize() ?: self.rawLayer->getDefaultIconSize(); + return MGLStyleValueTransformer().toStyleValue(propertyValue); +} + + +- (void)setIconSize:(MGLStyleValue *)iconSize { + self.iconScale = iconSize; } - (MGLStyleValue *)iconSize { - MGLAssertStyleLayerIsValid(); - - auto propertyValue = _rawLayer->getIconSize() ?: _rawLayer->getDefaultIconSize(); - return MGLStyleValueTransformer().toStyleValue(propertyValue); + return self.iconScale; } - (void)setIconTextFit:(MGLStyleValue *)iconTextFit { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toEnumPropertyValue(iconTextFit); - _rawLayer->setIconTextFit(mbglValue); + self.rawLayer->setIconTextFit(mbglValue); } - (MGLStyleValue *)iconTextFit { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getIconTextFit() ?: _rawLayer->getDefaultIconTextFit(); + auto propertyValue = self.rawLayer->getIconTextFit() ?: self.rawLayer->getDefaultIconTextFit(); return MGLStyleValueTransformer().toEnumStyleValue(propertyValue); } @@ -329,41 +367,142 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer, NSValue *>().toPropertyValue(iconTextFitPadding); - _rawLayer->setIconTextFitPadding(mbglValue); + self.rawLayer->setIconTextFitPadding(mbglValue); } - (MGLStyleValue *)iconTextFitPadding { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getIconTextFitPadding() ?: _rawLayer->getDefaultIconTextFitPadding(); + auto propertyValue = self.rawLayer->getIconTextFitPadding() ?: self.rawLayer->getDefaultIconTextFitPadding(); return MGLStyleValueTransformer, NSValue *>().toStyleValue(propertyValue); } -- (void)setSymbolAvoidEdges:(MGLStyleValue *)symbolAvoidEdges { +- (void)setKeepsIconUpright:(MGLStyleValue *)keepsIconUpright { MGLAssertStyleLayerIsValid(); - auto mbglValue = MGLStyleValueTransformer().toPropertyValue(symbolAvoidEdges); - _rawLayer->setSymbolAvoidEdges(mbglValue); + auto mbglValue = MGLStyleValueTransformer().toPropertyValue(keepsIconUpright); + self.rawLayer->setIconKeepUpright(mbglValue); +} + +- (MGLStyleValue *)keepsIconUpright { + MGLAssertStyleLayerIsValid(); + + auto propertyValue = self.rawLayer->getIconKeepUpright() ?: self.rawLayer->getDefaultIconKeepUpright(); + return MGLStyleValueTransformer().toStyleValue(propertyValue); +} + + +- (void)setIconKeepUpright:(MGLStyleValue *)iconKeepUpright { + self.keepsIconUpright = iconKeepUpright; +} + +- (MGLStyleValue *)iconKeepUpright { + return self.keepsIconUpright; +} + +- (void)setKeepsTextUpright:(MGLStyleValue *)keepsTextUpright { + MGLAssertStyleLayerIsValid(); + + auto mbglValue = MGLStyleValueTransformer().toPropertyValue(keepsTextUpright); + self.rawLayer->setTextKeepUpright(mbglValue); +} + +- (MGLStyleValue *)keepsTextUpright { + MGLAssertStyleLayerIsValid(); + + auto propertyValue = self.rawLayer->getTextKeepUpright() ?: self.rawLayer->getDefaultTextKeepUpright(); + return MGLStyleValueTransformer().toStyleValue(propertyValue); +} + + +- (void)setTextKeepUpright:(MGLStyleValue *)textKeepUpright { + self.keepsTextUpright = textKeepUpright; +} + +- (MGLStyleValue *)textKeepUpright { + return self.keepsTextUpright; +} + +- (void)setMaximumTextAngle:(MGLStyleValue *)maximumTextAngle { + MGLAssertStyleLayerIsValid(); + + auto mbglValue = MGLStyleValueTransformer().toPropertyValue(maximumTextAngle); + self.rawLayer->setTextMaxAngle(mbglValue); +} + +- (MGLStyleValue *)maximumTextAngle { + MGLAssertStyleLayerIsValid(); + + auto propertyValue = self.rawLayer->getTextMaxAngle() ?: self.rawLayer->getDefaultTextMaxAngle(); + return MGLStyleValueTransformer().toStyleValue(propertyValue); +} + + +- (void)setTextMaxAngle:(MGLStyleValue *)textMaxAngle { + self.maximumTextAngle = textMaxAngle; +} + +- (MGLStyleValue *)textMaxAngle { + return self.maximumTextAngle; +} + +- (void)setMaximumTextWidth:(MGLStyleValue *)maximumTextWidth { + MGLAssertStyleLayerIsValid(); + + auto mbglValue = MGLStyleValueTransformer().toPropertyValue(maximumTextWidth); + self.rawLayer->setTextMaxWidth(mbglValue); +} + +- (MGLStyleValue *)maximumTextWidth { + MGLAssertStyleLayerIsValid(); + + auto propertyValue = self.rawLayer->getTextMaxWidth() ?: self.rawLayer->getDefaultTextMaxWidth(); + return MGLStyleValueTransformer().toStyleValue(propertyValue); +} + + +- (void)setTextMaxWidth:(MGLStyleValue *)textMaxWidth { + self.maximumTextWidth = textMaxWidth; +} + +- (MGLStyleValue *)textMaxWidth { + return self.maximumTextWidth; +} + +- (void)setSymbolAvoidsEdges:(MGLStyleValue *)symbolAvoidsEdges { + MGLAssertStyleLayerIsValid(); + + auto mbglValue = MGLStyleValueTransformer().toPropertyValue(symbolAvoidsEdges); + self.rawLayer->setSymbolAvoidEdges(mbglValue); +} + +- (MGLStyleValue *)symbolAvoidsEdges { + MGLAssertStyleLayerIsValid(); + + auto propertyValue = self.rawLayer->getSymbolAvoidEdges() ?: self.rawLayer->getDefaultSymbolAvoidEdges(); + return MGLStyleValueTransformer().toStyleValue(propertyValue); +} + + +- (void)setSymbolAvoidEdges:(MGLStyleValue *)symbolAvoidEdges { + self.symbolAvoidsEdges = symbolAvoidEdges; } - (MGLStyleValue *)symbolAvoidEdges { - MGLAssertStyleLayerIsValid(); - - auto propertyValue = _rawLayer->getSymbolAvoidEdges() ?: _rawLayer->getDefaultSymbolAvoidEdges(); - return MGLStyleValueTransformer().toStyleValue(propertyValue); + return self.symbolAvoidsEdges; } - (void)setSymbolPlacement:(MGLStyleValue *)symbolPlacement { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toEnumPropertyValue(symbolPlacement); - _rawLayer->setSymbolPlacement(mbglValue); + self.rawLayer->setSymbolPlacement(mbglValue); } - (MGLStyleValue *)symbolPlacement { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getSymbolPlacement() ?: _rawLayer->getDefaultSymbolPlacement(); + auto propertyValue = self.rawLayer->getSymbolPlacement() ?: self.rawLayer->getDefaultSymbolPlacement(); return MGLStyleValueTransformer().toEnumStyleValue(propertyValue); } @@ -371,41 +510,50 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(symbolSpacing); - _rawLayer->setSymbolSpacing(mbglValue); + self.rawLayer->setSymbolSpacing(mbglValue); } - (MGLStyleValue *)symbolSpacing { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getSymbolSpacing() ?: _rawLayer->getDefaultSymbolSpacing(); + auto propertyValue = self.rawLayer->getSymbolSpacing() ?: self.rawLayer->getDefaultSymbolSpacing(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } -- (void)setTextAllowOverlap:(MGLStyleValue *)textAllowOverlap { +- (void)setTextAllowsOverlap:(MGLStyleValue *)textAllowsOverlap { MGLAssertStyleLayerIsValid(); - auto mbglValue = MGLStyleValueTransformer().toPropertyValue(textAllowOverlap); - _rawLayer->setTextAllowOverlap(mbglValue); + auto mbglValue = MGLStyleValueTransformer().toPropertyValue(textAllowsOverlap); + self.rawLayer->setTextAllowOverlap(mbglValue); +} + +- (MGLStyleValue *)textAllowsOverlap { + MGLAssertStyleLayerIsValid(); + + auto propertyValue = self.rawLayer->getTextAllowOverlap() ?: self.rawLayer->getDefaultTextAllowOverlap(); + return MGLStyleValueTransformer().toStyleValue(propertyValue); +} + + +- (void)setTextAllowOverlap:(MGLStyleValue *)textAllowOverlap { + self.textAllowsOverlap = textAllowOverlap; } - (MGLStyleValue *)textAllowOverlap { - MGLAssertStyleLayerIsValid(); - - auto propertyValue = _rawLayer->getTextAllowOverlap() ?: _rawLayer->getDefaultTextAllowOverlap(); - return MGLStyleValueTransformer().toStyleValue(propertyValue); + return self.textAllowsOverlap; } - (void)setTextAnchor:(MGLStyleValue *)textAnchor { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toEnumPropertyValue(textAnchor); - _rawLayer->setTextAnchor(mbglValue); + self.rawLayer->setTextAnchor(mbglValue); } - (MGLStyleValue *)textAnchor { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getTextAnchor() ?: _rawLayer->getDefaultTextAnchor(); + auto propertyValue = self.rawLayer->getTextAnchor() ?: self.rawLayer->getDefaultTextAnchor(); return MGLStyleValueTransformer().toEnumStyleValue(propertyValue); } @@ -413,13 +561,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(textField); - _rawLayer->setTextField(mbglValue); + self.rawLayer->setTextField(mbglValue); } - (MGLStyleValue *)textField { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getTextField() ?: _rawLayer->getDefaultTextField(); + auto propertyValue = self.rawLayer->getTextField() ?: self.rawLayer->getDefaultTextField(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -427,69 +575,73 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer, NSArray *, std::string>().toPropertyValue(textFont); - _rawLayer->setTextFont(mbglValue); + self.rawLayer->setTextFont(mbglValue); } - (MGLStyleValue *> *)textFont { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getTextFont() ?: _rawLayer->getDefaultTextFont(); + auto propertyValue = self.rawLayer->getTextFont() ?: self.rawLayer->getDefaultTextFont(); return MGLStyleValueTransformer, NSArray *, std::string>().toStyleValue(propertyValue); } -- (void)setTextIgnorePlacement:(MGLStyleValue *)textIgnorePlacement { +- (void)setTextIgnoresPlacement:(MGLStyleValue *)textIgnoresPlacement { MGLAssertStyleLayerIsValid(); - auto mbglValue = MGLStyleValueTransformer().toPropertyValue(textIgnorePlacement); - _rawLayer->setTextIgnorePlacement(mbglValue); + auto mbglValue = MGLStyleValueTransformer().toPropertyValue(textIgnoresPlacement); + self.rawLayer->setTextIgnorePlacement(mbglValue); +} + +- (MGLStyleValue *)textIgnoresPlacement { + MGLAssertStyleLayerIsValid(); + + auto propertyValue = self.rawLayer->getTextIgnorePlacement() ?: self.rawLayer->getDefaultTextIgnorePlacement(); + return MGLStyleValueTransformer().toStyleValue(propertyValue); +} + + +- (void)setTextIgnorePlacement:(MGLStyleValue *)textIgnorePlacement { + self.textIgnoresPlacement = textIgnorePlacement; } - (MGLStyleValue *)textIgnorePlacement { - MGLAssertStyleLayerIsValid(); - - auto propertyValue = _rawLayer->getTextIgnorePlacement() ?: _rawLayer->getDefaultTextIgnorePlacement(); - return MGLStyleValueTransformer().toStyleValue(propertyValue); + return self.textIgnoresPlacement; } -- (void)setTextJustify:(MGLStyleValue *)textJustify { +- (void)setTextJustification:(MGLStyleValue *)textJustification { MGLAssertStyleLayerIsValid(); - auto mbglValue = MGLStyleValueTransformer().toEnumPropertyValue(textJustify); - _rawLayer->setTextJustify(mbglValue); + auto mbglValue = MGLStyleValueTransformer().toEnumPropertyValue(textJustification); + self.rawLayer->setTextJustify(mbglValue); +} + +- (MGLStyleValue *)textJustification { + MGLAssertStyleLayerIsValid(); + + auto propertyValue = self.rawLayer->getTextJustify() ?: self.rawLayer->getDefaultTextJustify(); + return MGLStyleValueTransformer().toEnumStyleValue(propertyValue); +} + + +- (void)setTextJustify:(MGLStyleValue *)textJustify { + self.textJustification = textJustify; } - (MGLStyleValue *)textJustify { - MGLAssertStyleLayerIsValid(); - - auto propertyValue = _rawLayer->getTextJustify() ?: _rawLayer->getDefaultTextJustify(); - return MGLStyleValueTransformer().toEnumStyleValue(propertyValue); -} - -- (void)setTextKeepUpright:(MGLStyleValue *)textKeepUpright { - MGLAssertStyleLayerIsValid(); - - auto mbglValue = MGLStyleValueTransformer().toPropertyValue(textKeepUpright); - _rawLayer->setTextKeepUpright(mbglValue); -} - -- (MGLStyleValue *)textKeepUpright { - MGLAssertStyleLayerIsValid(); - - auto propertyValue = _rawLayer->getTextKeepUpright() ?: _rawLayer->getDefaultTextKeepUpright(); - return MGLStyleValueTransformer().toStyleValue(propertyValue); + return self.textJustification; } - (void)setTextLetterSpacing:(MGLStyleValue *)textLetterSpacing { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(textLetterSpacing); - _rawLayer->setTextLetterSpacing(mbglValue); + self.rawLayer->setTextLetterSpacing(mbglValue); } - (MGLStyleValue *)textLetterSpacing { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getTextLetterSpacing() ?: _rawLayer->getDefaultTextLetterSpacing(); + auto propertyValue = self.rawLayer->getTextLetterSpacing() ?: self.rawLayer->getDefaultTextLetterSpacing(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -497,41 +649,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(textLineHeight); - _rawLayer->setTextLineHeight(mbglValue); + self.rawLayer->setTextLineHeight(mbglValue); } - (MGLStyleValue *)textLineHeight { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getTextLineHeight() ?: _rawLayer->getDefaultTextLineHeight(); - return MGLStyleValueTransformer().toStyleValue(propertyValue); -} - -- (void)setTextMaxAngle:(MGLStyleValue *)textMaxAngle { - MGLAssertStyleLayerIsValid(); - - auto mbglValue = MGLStyleValueTransformer().toPropertyValue(textMaxAngle); - _rawLayer->setTextMaxAngle(mbglValue); -} - -- (MGLStyleValue *)textMaxAngle { - MGLAssertStyleLayerIsValid(); - - auto propertyValue = _rawLayer->getTextMaxAngle() ?: _rawLayer->getDefaultTextMaxAngle(); - return MGLStyleValueTransformer().toStyleValue(propertyValue); -} - -- (void)setTextMaxWidth:(MGLStyleValue *)textMaxWidth { - MGLAssertStyleLayerIsValid(); - - auto mbglValue = MGLStyleValueTransformer().toPropertyValue(textMaxWidth); - _rawLayer->setTextMaxWidth(mbglValue); -} - -- (MGLStyleValue *)textMaxWidth { - MGLAssertStyleLayerIsValid(); - - auto propertyValue = _rawLayer->getTextMaxWidth() ?: _rawLayer->getDefaultTextMaxWidth(); + auto propertyValue = self.rawLayer->getTextLineHeight() ?: self.rawLayer->getDefaultTextLineHeight(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -539,13 +663,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer, NSValue *>().toPropertyValue(textOffset); - _rawLayer->setTextOffset(mbglValue); + self.rawLayer->setTextOffset(mbglValue); } - (MGLStyleValue *)textOffset { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getTextOffset() ?: _rawLayer->getDefaultTextOffset(); + auto propertyValue = self.rawLayer->getTextOffset() ?: self.rawLayer->getDefaultTextOffset(); return MGLStyleValueTransformer, NSValue *>().toStyleValue(propertyValue); } @@ -553,13 +677,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(textOptional); - _rawLayer->setTextOptional(mbglValue); + self.rawLayer->setTextOptional(mbglValue); } -- (MGLStyleValue *)textOptional { +- (MGLStyleValue *)isTextOptional { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getTextOptional() ?: _rawLayer->getDefaultTextOptional(); + auto propertyValue = self.rawLayer->getTextOptional() ?: self.rawLayer->getDefaultTextOptional(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -567,13 +691,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(textPadding); - _rawLayer->setTextPadding(mbglValue); + self.rawLayer->setTextPadding(mbglValue); } - (MGLStyleValue *)textPadding { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getTextPadding() ?: _rawLayer->getDefaultTextPadding(); + auto propertyValue = self.rawLayer->getTextPadding() ?: self.rawLayer->getDefaultTextPadding(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -581,41 +705,50 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toEnumPropertyValue(textPitchAlignment); - _rawLayer->setTextPitchAlignment(mbglValue); + self.rawLayer->setTextPitchAlignment(mbglValue); } - (MGLStyleValue *)textPitchAlignment { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getTextPitchAlignment() ?: _rawLayer->getDefaultTextPitchAlignment(); + auto propertyValue = self.rawLayer->getTextPitchAlignment() ?: self.rawLayer->getDefaultTextPitchAlignment(); return MGLStyleValueTransformer().toEnumStyleValue(propertyValue); } -- (void)setTextRotate:(MGLStyleValue *)textRotate { +- (void)setTextRotation:(MGLStyleValue *)textRotation { MGLAssertStyleLayerIsValid(); - auto mbglValue = MGLStyleValueTransformer().toPropertyValue(textRotate); - _rawLayer->setTextRotate(mbglValue); + auto mbglValue = MGLStyleValueTransformer().toPropertyValue(textRotation); + self.rawLayer->setTextRotate(mbglValue); +} + +- (MGLStyleValue *)textRotation { + MGLAssertStyleLayerIsValid(); + + auto propertyValue = self.rawLayer->getTextRotate() ?: self.rawLayer->getDefaultTextRotate(); + return MGLStyleValueTransformer().toStyleValue(propertyValue); +} + + +- (void)setTextRotate:(MGLStyleValue *)textRotate { + self.textRotation = textRotate; } - (MGLStyleValue *)textRotate { - MGLAssertStyleLayerIsValid(); - - auto propertyValue = _rawLayer->getTextRotate() ?: _rawLayer->getDefaultTextRotate(); - return MGLStyleValueTransformer().toStyleValue(propertyValue); + return self.textRotation; } - (void)setTextRotationAlignment:(MGLStyleValue *)textRotationAlignment { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toEnumPropertyValue(textRotationAlignment); - _rawLayer->setTextRotationAlignment(mbglValue); + self.rawLayer->setTextRotationAlignment(mbglValue); } - (MGLStyleValue *)textRotationAlignment { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getTextRotationAlignment() ?: _rawLayer->getDefaultTextRotationAlignment(); + auto propertyValue = self.rawLayer->getTextRotationAlignment() ?: self.rawLayer->getDefaultTextRotationAlignment(); return MGLStyleValueTransformer().toEnumStyleValue(propertyValue); } @@ -623,13 +756,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(textSize); - _rawLayer->setTextSize(mbglValue); + self.rawLayer->setTextSize(mbglValue); } - (MGLStyleValue *)textSize { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getTextSize() ?: _rawLayer->getDefaultTextSize(); + auto propertyValue = self.rawLayer->getTextSize() ?: self.rawLayer->getDefaultTextSize(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -637,13 +770,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toEnumPropertyValue(textTransform); - _rawLayer->setTextTransform(mbglValue); + self.rawLayer->setTextTransform(mbglValue); } - (MGLStyleValue *)textTransform { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getTextTransform() ?: _rawLayer->getDefaultTextTransform(); + auto propertyValue = self.rawLayer->getTextTransform() ?: self.rawLayer->getDefaultTextTransform(); return MGLStyleValueTransformer().toEnumStyleValue(propertyValue); } @@ -653,13 +786,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(iconColor); - _rawLayer->setIconColor(mbglValue); + self.rawLayer->setIconColor(mbglValue); } - (MGLStyleValue *)iconColor { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getIconColor() ?: _rawLayer->getDefaultIconColor(); + auto propertyValue = self.rawLayer->getIconColor() ?: self.rawLayer->getDefaultIconColor(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -667,13 +800,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(iconHaloBlur); - _rawLayer->setIconHaloBlur(mbglValue); + self.rawLayer->setIconHaloBlur(mbglValue); } - (MGLStyleValue *)iconHaloBlur { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getIconHaloBlur() ?: _rawLayer->getDefaultIconHaloBlur(); + auto propertyValue = self.rawLayer->getIconHaloBlur() ?: self.rawLayer->getDefaultIconHaloBlur(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -681,13 +814,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(iconHaloColor); - _rawLayer->setIconHaloColor(mbglValue); + self.rawLayer->setIconHaloColor(mbglValue); } - (MGLStyleValue *)iconHaloColor { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getIconHaloColor() ?: _rawLayer->getDefaultIconHaloColor(); + auto propertyValue = self.rawLayer->getIconHaloColor() ?: self.rawLayer->getDefaultIconHaloColor(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -695,13 +828,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(iconHaloWidth); - _rawLayer->setIconHaloWidth(mbglValue); + self.rawLayer->setIconHaloWidth(mbglValue); } - (MGLStyleValue *)iconHaloWidth { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getIconHaloWidth() ?: _rawLayer->getDefaultIconHaloWidth(); + auto propertyValue = self.rawLayer->getIconHaloWidth() ?: self.rawLayer->getDefaultIconHaloWidth(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -709,13 +842,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(iconOpacity); - _rawLayer->setIconOpacity(mbglValue); + self.rawLayer->setIconOpacity(mbglValue); } - (MGLStyleValue *)iconOpacity { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getIconOpacity() ?: _rawLayer->getDefaultIconOpacity(); + auto propertyValue = self.rawLayer->getIconOpacity() ?: self.rawLayer->getDefaultIconOpacity(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -723,13 +856,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer, NSValue *>().toPropertyValue(iconTranslate); - _rawLayer->setIconTranslate(mbglValue); + self.rawLayer->setIconTranslate(mbglValue); } - (MGLStyleValue *)iconTranslate { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getIconTranslate() ?: _rawLayer->getDefaultIconTranslate(); + auto propertyValue = self.rawLayer->getIconTranslate() ?: self.rawLayer->getDefaultIconTranslate(); return MGLStyleValueTransformer, NSValue *>().toStyleValue(propertyValue); } @@ -737,13 +870,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toEnumPropertyValue(iconTranslateAnchor); - _rawLayer->setIconTranslateAnchor(mbglValue); + self.rawLayer->setIconTranslateAnchor(mbglValue); } - (MGLStyleValue *)iconTranslateAnchor { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getIconTranslateAnchor() ?: _rawLayer->getDefaultIconTranslateAnchor(); + auto propertyValue = self.rawLayer->getIconTranslateAnchor() ?: self.rawLayer->getDefaultIconTranslateAnchor(); return MGLStyleValueTransformer().toEnumStyleValue(propertyValue); } @@ -751,13 +884,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(textColor); - _rawLayer->setTextColor(mbglValue); + self.rawLayer->setTextColor(mbglValue); } - (MGLStyleValue *)textColor { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getTextColor() ?: _rawLayer->getDefaultTextColor(); + auto propertyValue = self.rawLayer->getTextColor() ?: self.rawLayer->getDefaultTextColor(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -765,13 +898,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(textHaloBlur); - _rawLayer->setTextHaloBlur(mbglValue); + self.rawLayer->setTextHaloBlur(mbglValue); } - (MGLStyleValue *)textHaloBlur { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getTextHaloBlur() ?: _rawLayer->getDefaultTextHaloBlur(); + auto propertyValue = self.rawLayer->getTextHaloBlur() ?: self.rawLayer->getDefaultTextHaloBlur(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -779,13 +912,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(textHaloColor); - _rawLayer->setTextHaloColor(mbglValue); + self.rawLayer->setTextHaloColor(mbglValue); } - (MGLStyleValue *)textHaloColor { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getTextHaloColor() ?: _rawLayer->getDefaultTextHaloColor(); + auto propertyValue = self.rawLayer->getTextHaloColor() ?: self.rawLayer->getDefaultTextHaloColor(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -793,13 +926,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(textHaloWidth); - _rawLayer->setTextHaloWidth(mbglValue); + self.rawLayer->setTextHaloWidth(mbglValue); } - (MGLStyleValue *)textHaloWidth { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getTextHaloWidth() ?: _rawLayer->getDefaultTextHaloWidth(); + auto propertyValue = self.rawLayer->getTextHaloWidth() ?: self.rawLayer->getDefaultTextHaloWidth(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -807,13 +940,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toPropertyValue(textOpacity); - _rawLayer->setTextOpacity(mbglValue); + self.rawLayer->setTextOpacity(mbglValue); } - (MGLStyleValue *)textOpacity { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getTextOpacity() ?: _rawLayer->getDefaultTextOpacity(); + auto propertyValue = self.rawLayer->getTextOpacity() ?: self.rawLayer->getDefaultTextOpacity(); return MGLStyleValueTransformer().toStyleValue(propertyValue); } @@ -821,13 +954,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer, NSValue *>().toPropertyValue(textTranslate); - _rawLayer->setTextTranslate(mbglValue); + self.rawLayer->setTextTranslate(mbglValue); } - (MGLStyleValue *)textTranslate { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getTextTranslate() ?: _rawLayer->getDefaultTextTranslate(); + auto propertyValue = self.rawLayer->getTextTranslate() ?: self.rawLayer->getDefaultTextTranslate(); return MGLStyleValueTransformer, NSValue *>().toStyleValue(propertyValue); } @@ -835,13 +968,13 @@ namespace mbgl { MGLAssertStyleLayerIsValid(); auto mbglValue = MGLStyleValueTransformer().toEnumPropertyValue(textTranslateAnchor); - _rawLayer->setTextTranslateAnchor(mbglValue); + self.rawLayer->setTextTranslateAnchor(mbglValue); } - (MGLStyleValue *)textTranslateAnchor { MGLAssertStyleLayerIsValid(); - auto propertyValue = _rawLayer->getTextTranslateAnchor() ?: _rawLayer->getDefaultTextTranslateAnchor(); + auto propertyValue = self.rawLayer->getTextTranslateAnchor() ?: self.rawLayer->getDefaultTextTranslateAnchor(); return MGLStyleValueTransformer().toEnumStyleValue(propertyValue); } diff --git a/platform/darwin/src/MGLTileSet.h b/platform/darwin/src/MGLTileSet.h deleted file mode 100644 index 08a34338b..000000000 --- a/platform/darwin/src/MGLTileSet.h +++ /dev/null @@ -1,78 +0,0 @@ -#import -#import "MGLTypes.h" - -NS_ASSUME_NONNULL_BEGIN - -/** These constants represent the scheme that the tile URL templates will use. */ -typedef NS_ENUM(NSUInteger, MGLTileSetScheme) { - MGLTileSetSchemeXYZ = 0, - MGLTileSetSchemeTMS -}; - -/** - The `MGLTileSet` class holds the tile URL template strings and associated - configuration for those strings. It can be passed to an `MGLVectorSource` or - `MGLRasterSource` instead of an `NSURL` representing a TileJSON URL to create a - source. - */ -@interface MGLTileSet : NSObject - -/** - An `NSArray` of `NSString` objects that represent the tile templates. - */ -@property (nonatomic, copy) NS_ARRAY_OF(NSString *) *tileURLTemplates; - -/** - An `NSNumber` object containing an integer; specifies the minimum zoom level at - which the source will display tiles. The value should be in the range of 0 to - 22. The default value is 0 and the source will use the default value - if `minimumZoomLevel` is nil. - */ -@property (nonatomic, nullable) NSNumber *minimumZoomLevel; - -/** - An `NSNumber` object containing an integer; specifies the maximum zoom level at - which to display tiles. The value should be in the range of 0 to 22 and greater - than `minimumZoomLevel`. The default value is 22 and the source will use the - default value if `maximumZoomLevel` is nil. - */ -@property (nonatomic, nullable) NSNumber *maximumZoomLevel; - -/** - An `NSString` object that contains an attribution to be displayed when the map - is shown to a user. The default value is `nil`. - */ -@property (nonatomic, copy, nullable) NSString *attribution; - -/** - An `MGLTileSetScheme` value that contains an enumeration (either - `MGLTileSetSchemeXYZ` or `MGLTileSetSchemeTMS`) that influences the y direction - of the tile coordinates. The default is `MGLTileSetSchemeXYZ`. - */ -@property (nonatomic) MGLTileSetScheme scheme; - -/** - Initializes and returns a new tile set object. - - @param tileURLTemplates An `NSArray` of `NSString` objects that represent the - tile templates. - @return The initialized tile set object. - */ -- (instancetype)initWithTileURLTemplates:(NS_ARRAY_OF(NSString *) *)tileURLTemplates; - -/** - Initializes and returns a new tile set object. - - @param tileURLTemplates An `NSArray` of `NSString` objects that represent the - tile templates. - @param minimumZoomLevel An `NSUInteger`; specifies the minimum zoom level at - which to display tiles. - @param maximumZoomLevel An `NSUInteger`; specifies the maximum zoom level at - which to display tiles. - @return The initialized tile set object. - */ -- (instancetype)initWithTileURLTemplates:(NS_ARRAY_OF(NSString *) *)tileURLTemplates minimumZoomLevel:(NSUInteger)minimumZoomLevel maximumZoomLevel:(NSUInteger)maximumZoomLevel; - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLTileSet.mm b/platform/darwin/src/MGLTileSet.mm deleted file mode 100644 index f795545ee..000000000 --- a/platform/darwin/src/MGLTileSet.mm +++ /dev/null @@ -1,93 +0,0 @@ -#import "MGLTileSet.h" - -#include - -@implementation MGLTileSet - -- (instancetype)initWithTileURLTemplates:(NS_ARRAY_OF(NSString *) *)tileURLTemplates -{ - if (self = [super init]) - { - _tileURLTemplates = tileURLTemplates; - } - return self; -} - -- (instancetype)initWithTileURLTemplates:(NS_ARRAY_OF(NSString *) *)tileURLTemplates minimumZoomLevel:(NSUInteger)minimumZoomLevel maximumZoomLevel:(NSUInteger)maximumZoomLevel -{ - if (minimumZoomLevel > maximumZoomLevel) - { - [[NSException exceptionWithName:@"Invalid minimumZoomLevel" - reason:@"minimumZoomLevel must be less than maximumZoomLevel" - userInfo:nil] raise]; - return nil; - } - - if (self = [super init]) - { - _tileURLTemplates = tileURLTemplates; - _minimumZoomLevel = @(minimumZoomLevel); - _maximumZoomLevel = @(maximumZoomLevel); - } - return self; -} - -- (void)setMinimumZoomLevel:(NSNumber *)minimumZoomLevel -{ - if (self.maximumZoomLevel && [minimumZoomLevel integerValue] > [self.maximumZoomLevel integerValue]) - { - [[NSException exceptionWithName:@"Invalid minimumZoomLevel" - reason:@"minimumZoomLevel must be less than maximumZoomLevel" - userInfo:nil] raise]; - return; - } - - _minimumZoomLevel = minimumZoomLevel; -} - -- (void)setMaximumZoomLevel:(NSNumber *)maximumZoomLevel -{ - if (self.maximumZoomLevel && [maximumZoomLevel integerValue] < [self.maximumZoomLevel integerValue]) - { - [[NSException exceptionWithName:@"Invalid minimumZoomLevel" - reason:@"minimumZoomLevel must be less than maximumZoomLevel" - userInfo:nil] raise]; - } - - _maximumZoomLevel = maximumZoomLevel; -} - -- (mbgl::Tileset)mbglTileset -{ - mbgl::Tileset tileset; - - for (NSString *tileURLTemplate in self.tileURLTemplates) - { - tileset.tiles.push_back(tileURLTemplate.UTF8String); - } - - // set the minimum / maximum zoom range to the values specified by this class if they - // were set. otherwise, use the core objects default values - uint8_t minimumZoomLevel = self.minimumZoomLevel ? [self.minimumZoomLevel unsignedIntegerValue] : tileset.zoomRange.min; - uint8_t maximumZoomLevel = self.minimumZoomLevel ? [self.maximumZoomLevel unsignedIntegerValue] : tileset.zoomRange.max; - tileset.zoomRange = mbgl::Range(minimumZoomLevel, maximumZoomLevel); - - if (self.attribution) - { - tileset.attribution = self.attribution.UTF8String; - } - - if (self.scheme == MGLTileSetSchemeTMS) { - tileset.scheme = mbgl::Tileset::Scheme::TMS; - } - - return tileset; -} - -- (NSString *)description -{ - return [NSString stringWithFormat:@"<%@: %p; tileURLTemplates = %@>", - NSStringFromClass([self class]), (void *)self, self.tileURLTemplates]; -} - -@end diff --git a/platform/darwin/src/MGLTileSet_Private.h b/platform/darwin/src/MGLTileSet_Private.h deleted file mode 100644 index 6a14d428d..000000000 --- a/platform/darwin/src/MGLTileSet_Private.h +++ /dev/null @@ -1,9 +0,0 @@ -#import "MGLTileSet.h" - -#include - -@interface MGLTileSet (Private) - -- (mbgl::Tileset)mbglTileset; - -@end \ No newline at end of file diff --git a/platform/darwin/src/MGLTileSource.h b/platform/darwin/src/MGLTileSource.h new file mode 100644 index 000000000..caf915637 --- /dev/null +++ b/platform/darwin/src/MGLTileSource.h @@ -0,0 +1,179 @@ +#import + +#import "MGLSource.h" +#import "MGLTypes.h" + +NS_ASSUME_NONNULL_BEGIN + +@class MGLAttributionInfo; + +/** + Options for `MGLTileSource` objects. + */ +typedef NSString *MGLTileSourceOption NS_STRING_ENUM; + +/** + An `NSNumber` object containing an unsigned integer that specifies the minimum + zoom level at which to display tiles from the source. + + The value should be between 0 and 22, inclusive, and less than + `MGLTileSourceOptionMaximumZoomLevel`, if specified. The default value for this + option is 0. + */ +extern const MGLTileSourceOption MGLTileSourceOptionMinimumZoomLevel; + +/** + An `NSNumber` object containing an unsigned integer that specifies the maximum + zoom level at which to display tiles from the source. + + The value should be between 0 and 22, inclusive, and less than + `MGLTileSourceOptionMinimumZoomLevel`, if specified. The default value for this + option is 22. + */ +extern const MGLTileSourceOption MGLTileSourceOptionMaximumZoomLevel; + +#if TARGET_OS_IPHONE +/** + An HTML string defining the buttons to be displayed in an action sheet when the + source is part of a map view’s style and the map view’s attribution button is + pressed. + + By default, no attribution statements are displayed. If the + `MGLTileSourceOptionAttributionInfos` option is specified, this option is + ignored. + */ +extern const MGLTileSourceOption MGLTileSourceOptionAttributionHTMLString; + +/** + An array of `MGLAttributionInfo` objects defining the buttons to be displayed + in an action sheet when the source is part of a map view’s style and the map + view’s attribution button is pressed. + + By default, no attribution statements are displayed. + */ +extern const MGLTileSourceOption MGLTileSourceOptionAttributionInfos; +#else +/** + An HTML string defining the buttons to be displayed in the map view’s + attribution view when the source is part of the map view’s style. + + By default, no attribution statements are displayed. If the + `MGLTileSourceOptionAttributionInfos` option is specified, this option is + ignored. + */ +extern const MGLTileSourceOption MGLTileSourceOptionAttributionHTMLString; + +/** + An array of `MGLAttributionInfo` objects defining the buttons to be displayed + in the map view’s attribution view when the source is part of the map view’s + style. + + By default, no attribution statements are displayed. + */ +extern const MGLTileSourceOption MGLTileSourceOptionAttributionInfos; +#endif + +/** + An `NSNumber` object containing an unsigned integer that specifies the tile + coordinate system for the source’s tile URLs. The integer corresponds to one of + the constants described in `MGLTileCoordinateSystem`. + + The default value for this option is `MGLTileCoordinateSystemXYZ`. + */ +extern const MGLTileSourceOption MGLTileSourceOptionTileCoordinateSystem; + +/** + Tile coordinate systems that determine how tile coordinates in tile URLs are + interpreted. + */ +typedef NS_ENUM(NSUInteger, MGLTileCoordinateSystem) { + /** + The origin is at the top-left (northwest), and `y` values increase + southwards. + + This tile coordinate system is used by Mapbox and OpenStreetMap tile + servers. + */ + MGLTileCoordinateSystemXYZ = 0, + + /** + The origin is at the bottom-left (southwest), and `y` values increase + northwards. + + This tile coordinate system is used by tile servers that conform to the + Tile Map Service Specification. + */ + MGLTileCoordinateSystemTMS +}; + +/** + `MGLTileSource` is a map content source that supplies map tiles to be shown on + the map. The location of and metadata about the tiles are defined either by an + option dictionary or by an external file that conforms to the + TileJSON specification. + A tile source is added to an `MGLStyle` object along with one or more + `MGLRasterStyleLayer` or `MGLVectorStyleLayer` objects. Use a style layer to + control the appearance of content supplied by the tile source. + + Do not create instances of this class directly, and do not create your own + subclasses of this class. Instead, create instances of `MGLRasterSource` and + `MGLVectorSource`. + */ +@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://`). The URL should + point to a JSON file that conforms to the + TileJSON specification. + + @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. + + @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. + @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 Attribution Strings + +/** + An array of `MGLAttributionInfo` objects that define the attribution + statements to be displayed when the map is shown to the user. + + By default, this array is empty. If the source is initialized with a + configuration URL, this array is also empty until the configuration JSON file + is loaded. + */ +@property (nonatomic, copy, readonly) NS_ARRAY_OF(MGLAttributionInfo *) *attributionInfos; + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLTileSource.mm b/platform/darwin/src/MGLTileSource.mm new file mode 100644 index 000000000..522675bc8 --- /dev/null +++ b/platform/darwin/src/MGLTileSource.mm @@ -0,0 +1,123 @@ +#import "MGLTileSource_Private.h" + +#import "MGLAttributionInfo_Private.h" +#import "NSString+MGLAdditions.h" + +#if TARGET_OS_IPHONE + #import +#else + #import +#endif + +#include + +const MGLTileSourceOption MGLTileSourceOptionMinimumZoomLevel = @"MGLTileSourceOptionMinimumZoomLevel"; +const MGLTileSourceOption MGLTileSourceOptionMaximumZoomLevel = @"MGLTileSourceOptionMaximumZoomLevel"; +const MGLTileSourceOption MGLTileSourceOptionAttributionHTMLString = @"MGLTileSourceOptionAttributionHTMLString"; +const MGLTileSourceOption MGLTileSourceOptionAttributionInfos = @"MGLTileSourceOptionAttributionInfos"; +const MGLTileSourceOption MGLTileSourceOptionTileCoordinateSystem = @"MGLTileSourceOptionTileCoordinateSystem"; + +@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]; +} + +- (NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfos { + return [self attributionInfosWithFontSize:0 linkColor:nil]; +} + +- (NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfosWithFontSize:(CGFloat)fontSize linkColor:(nullable MGLColor *)linkColor { + return [MGLAttributionInfo attributionInfosFromHTMLString:self.attributionHTMLString + fontSize:fontSize + linkColor:linkColor]; +} + +- (NSString *)attributionHTMLString { + [NSException raise:@"MGLAbstractClassException" + format:@"MGLTileSource is an abstract class"]; + return nil; +} + +@end + +mbgl::Tileset MGLTileSetFromTileURLTemplates(NS_ARRAY_OF(NSString *) *tileURLTemplates, NS_DICTIONARY_OF(MGLTileSourceOption, id) * _Nullable options) { + mbgl::Tileset tileSet; + + for (NSString *tileURLTemplate in tileURLTemplates) { + tileSet.tiles.push_back(tileURLTemplate.UTF8String); + } + + // set the minimum / maximum zoom range to the values specified by this class if they + // were set. otherwise, use the core objects default values + if (NSNumber *minimumZoomLevel = options[MGLTileSourceOptionMinimumZoomLevel]) { + if (![minimumZoomLevel isKindOfClass:[NSNumber class]]) { + [NSException raise:NSInvalidArgumentException + format:@"MGLTileSourceOptionMinimumZoomLevel must be set to an NSNumber."]; + } + tileSet.zoomRange.min = minimumZoomLevel.integerValue; + } + if (NSNumber *maximumZoomLevel = options[MGLTileSourceOptionMaximumZoomLevel]) { + if (![maximumZoomLevel isKindOfClass:[NSNumber class]]) { + [NSException raise:NSInvalidArgumentException + format:@"MGLTileSourceOptionMinimumZoomLevel must be set to an NSNumber."]; + } + tileSet.zoomRange.max = maximumZoomLevel.integerValue; + } + if (tileSet.zoomRange.min > tileSet.zoomRange.max) { + [NSException raise:NSInvalidArgumentException + format:@"MGLTileSourceOptionMinimumZoomLevel must be less than MGLTileSourceOptionMaximumZoomLevel."]; + } + + if (NSString *attribution = options[MGLTileSourceOptionAttributionHTMLString]) { + if (![attribution isKindOfClass:[NSString class]]) { + [NSException raise:NSInvalidArgumentException + format:@"MGLTileSourceOptionAttributionHTMLString must be set to a string."]; + } + tileSet.attribution = attribution.UTF8String; + } + + if (NSArray *attributionInfos = options[MGLTileSourceOptionAttributionInfos]) { + if (![attributionInfos isKindOfClass:[NSArray class]]) { + [NSException raise:NSInvalidArgumentException + format:@"MGLTileSourceOptionAttributionInfos must be set to a string."]; + } + + NSAttributedString *attributedString = [MGLAttributionInfo attributedStringForAttributionInfos:attributionInfos]; +#if TARGET_OS_IPHONE + static NSString * const NSExcludedElementsDocumentAttribute = @"ExcludedElements"; +#endif + NSDictionary *documentAttributes = @{ + NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, + NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding), + // The attribution string is meant to be a simple, inline fragment, not a full-fledged, validating document. + NSExcludedElementsDocumentAttribute: @[@"XML", @"DOCTYPE", @"html", @"head", @"meta", @"title", @"style", @"body", @"p"], + }; + NSData *data = [attributedString dataFromRange:attributedString.mgl_wholeRange documentAttributes:documentAttributes error:NULL]; + NSString *html = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + tileSet.attribution = html.UTF8String; + } + + if (NSNumber *tileCoordinateSystemNumber = options[MGLTileSourceOptionTileCoordinateSystem]) { + if (![tileCoordinateSystemNumber isKindOfClass:[NSValue class]]) { + [NSException raise:NSInvalidArgumentException + format:@"MGLTileSourceOptionTileCoordinateSystem must be set to an NSValue or NSNumber."]; + } + MGLTileCoordinateSystem tileCoordinateSystem; + [tileCoordinateSystemNumber getValue:&tileCoordinateSystem]; + switch (tileCoordinateSystem) { + case MGLTileCoordinateSystemXYZ: + tileSet.scheme = mbgl::Tileset::Scheme::XYZ; + break; + case MGLTileCoordinateSystemTMS: + tileSet.scheme = mbgl::Tileset::Scheme::TMS; + break; + } + } + + return tileSet; +} diff --git a/platform/darwin/src/MGLTileSource_Private.h b/platform/darwin/src/MGLTileSource_Private.h new file mode 100644 index 000000000..ca80e3d96 --- /dev/null +++ b/platform/darwin/src/MGLTileSource_Private.h @@ -0,0 +1,36 @@ +#import "MGLTileSource.h" + +#import + +NS_ASSUME_NONNULL_BEGIN + +namespace mbgl { + class Tileset; +} + +@class MGLAttributionInfo; + +@interface MGLTileSource (Private) + +/** + An HTML string to be displayed as attribution when the map is shown to a user. + + The default value is `nil`. If the source is initialized with a configuration + URL, this property is also `nil` until the configuration JSON file is loaded. + */ +@property (nonatomic, copy, nullable, readonly) NSString *attributionHTMLString; + +/** + A structured representation of the `attribution` property. The default value is + `nil`. + + @param fontSize The default text size in points, or 0 to use the default. + @param linkColor The default link color, or `nil` to use the default. + */ +- (NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfosWithFontSize:(CGFloat)fontSize linkColor:(nullable MGLColor *)linkColor; + +@end + +mbgl::Tileset MGLTileSetFromTileURLTemplates(NS_ARRAY_OF(NSString *) *tileURLTemplates, NS_DICTIONARY_OF(MGLTileSourceOption, id) * _Nullable options); + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLVectorSource.h b/platform/darwin/src/MGLVectorSource.h index 6cfab0948..f91a0cbb2 100644 --- a/platform/darwin/src/MGLVectorSource.h +++ b/platform/darwin/src/MGLVectorSource.h @@ -1,68 +1,35 @@ -#import "MGLSource.h" -#import "MGLTypes.h" - -@class MGLTileSet; +#import "MGLTileSource.h" NS_ASSUME_NONNULL_BEGIN /** - A vector tile source. Tiles must be in Mapbox Vector Tile format. + `MGLVectorSource` is a map content source that supplies tiled vector data in + Mapbox Vector Tile format to + be shown on the map. The location of and metadata about the tiles are defined + either by an option dictionary or by an external file that conforms to the + TileJSON specification. + A vector source is added to an `MGLStyle` object along with one or more + `MGLVectorStyleLayer` objects. A vector style layer defines the appearance of + any content supplied by the vector source. - @see The - style specification. + Each + vector + source defined by the style JSON file is represented at runtime by an + `MGLVectorSource` 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:]`. + + Within each vector tile, each geometric coordinate must lie between + −1 × extent and + (extent × 2) − 1, inclusive. Any vector style + layer initialized with a vector source must have a non-`nil` value in its + `sourceLayerIdentifier` property. */ -@interface MGLVectorSource : MGLSource +@interface MGLVectorSource : MGLTileSource -#pragma mark Initializing a Source +- (instancetype)initWithIdentifier:(NSString *)identifier configurationURL:(NSURL *)configurationURL NS_DESIGNATED_INITIALIZER; -/** - Returns a vector source initialized with an identifier and TileJSON URL. - - After initializing and configuring the source, add it to a map view’s style - using the `-[MGLStyle addSource:]` method. - - @param identifier A string that uniquely identifies the source in the style to - which it is added. - @param url A URL to a TileJSON configuration file describing the source’s - contents and other metadata. - @return An initialized vector source. - */ -- (instancetype)initWithIdentifier:(NSString *)identifier URL:(NSURL *)url NS_DESIGNATED_INITIALIZER; - -/** - Returns a vector source initialized an identifier and tile set. - - After initializing and configuring the source, add it to a map view’s style - using the `-[MGLStyle addSource:]` method. - - @param identifier A string that uniquely identifies the source in the style to - which it is added. - @param tileSet A tile set describing the source’s contents and other metadata. - @return An initialized vector source. - */ -- (instancetype)initWithIdentifier:(NSString *)identifier tileSet:(MGLTileSet *)tileSet NS_DESIGNATED_INITIALIZER; - -#pragma mark Accessing a Source’s Content - -/** - A URL to a TileJSON configuration file describing the source’s contents and - other metadata. - - The URL may be a full HTTP or HTTPS URL or a Mapbox URL indicating the tile - set’s map ID (`mapbox://`). - - If the receiver was initialized using `-initWithIdentifier:tileSet:`, this - property is set to `nil`. - */ -@property (nonatomic, readonly, copy) NSURL *URL; - -/** - A tile set describing the source’s contents and other metadata. - - If the receiver was initialized using `-initWithIdentifier:URL:`, this property - is set to `nil`. - */ -@property (nonatomic, readonly, nullable) MGLTileSet *tileSet; +- (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/MGLVectorSource.mm b/platform/darwin/src/MGLVectorSource.mm index ab68d45ba..0eea8dd18 100644 --- a/platform/darwin/src/MGLVectorSource.mm +++ b/platform/darwin/src/MGLVectorSource.mm @@ -1,64 +1,50 @@ -#import "MGLVectorSource.h" +#import "MGLVectorSource_Private.h" #import "MGLMapView_Private.h" #import "MGLSource_Private.h" -#import "MGLTileSet_Private.h" +#import "MGLTileSource_Private.h" #import "NSURL+MGLAdditions.h" #include @interface MGLVectorSource () +- (instancetype)initWithRawSource:(mbgl::style::VectorSource *)rawSource NS_DESIGNATED_INITIALIZER; + @property (nonatomic) mbgl::style::VectorSource *rawSource; @end -@implementation MGLVectorSource -{ +@implementation MGLVectorSource { std::unique_ptr _pendingSource; } -- (instancetype)initWithIdentifier:(NSString *)identifier URL:(NSURL *)url -{ - if (self = [super initWithIdentifier:identifier]) - { - _URL = url; - [self commonInit]; +- (instancetype)initWithIdentifier:(NSString *)identifier configurationURL:(NSURL *)configurationURL { + if (self = [super initWithIdentifier:identifier configurationURL:configurationURL]) { + auto source = std::make_unique(identifier.UTF8String, + configurationURL.mgl_URLByStandardizingScheme.absoluteString.UTF8String); + _pendingSource = std::move(source); + self.rawSource = _pendingSource.get(); } return self; } -- (instancetype)initWithIdentifier:(NSString *)identifier tileSet:(MGLTileSet *)tileSet -{ - if (self = [super initWithIdentifier:identifier]) - { - _tileSet = tileSet; - [self commonInit]; +- (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(identifier.UTF8String, tileSet); + _pendingSource = std::move(source); + self.rawSource = _pendingSource.get(); } return self; } -- (void)commonInit -{ - std::unique_ptr source; - - if (self.URL) - { - source = std::make_unique(self.identifier.UTF8String, - self.URL.mgl_URLByStandardizingScheme.absoluteString.UTF8String); - } - else - { - source = std::make_unique(self.identifier.UTF8String, - self.tileSet.mbglTileset); - } - - _pendingSource = std::move(source); - self.rawSource = _pendingSource.get(); +- (instancetype)initWithRawSource:(mbgl::style::VectorSource *)rawSource { + return [super initWithRawSource:rawSource]; } -- (void)addToMapView:(MGLMapView *)mapView -{ +- (void)addToMapView:(MGLMapView *)mapView { if (_pendingSource == nullptr) { [NSException raise:@"MGLRedundantSourceException" format:@"This instance %@ was already added to %@. Adding the same source instance " \ @@ -68,18 +54,24 @@ mapView.mbglMap->addSource(std::move(_pendingSource)); } -- (void)removeFromMapView:(MGLMapView *)mapView -{ +- (void)removeFromMapView:(MGLMapView *)mapView { auto removedSource = mapView.mbglMap->removeSource(self.identifier.UTF8String); _pendingSource = std::move(reinterpret_cast &>(removedSource)); self.rawSource = _pendingSource.get(); } -- (NSString *)description -{ - return [NSString stringWithFormat:@"<%@: %p; identifier = %@; URL = %@; tileSet = %@>", - NSStringFromClass([self class]), (void *)self, self.identifier, self.URL, self.tileSet]; +- (mbgl::style::VectorSource *)rawSource { + return (mbgl::style::VectorSource *)super.rawSource; +} + +- (void)setRawSource:(mbgl::style::VectorSource *)rawSource { + super.rawSource = rawSource; +} + +- (NSString *)attributionHTMLString { + auto attribution = self.rawSource->getAttribution(); + return attribution ? @(attribution->c_str()) : nil; } @end diff --git a/platform/darwin/src/MGLVectorSource_Private.h b/platform/darwin/src/MGLVectorSource_Private.h new file mode 100644 index 000000000..12fcd8201 --- /dev/null +++ b/platform/darwin/src/MGLVectorSource_Private.h @@ -0,0 +1,17 @@ +#import "MGLVectorSource.h" + +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/MGLVectorStyleLayer.h b/platform/darwin/src/MGLVectorStyleLayer.h index e2a755083..1197d7680 100644 --- a/platform/darwin/src/MGLVectorStyleLayer.h +++ b/platform/darwin/src/MGLVectorStyleLayer.h @@ -6,7 +6,7 @@ NS_ASSUME_NONNULL_BEGIN /** `MGLVectorStyleLayer` is an abstract superclass for style layers whose content - is defined by an `MGLGeoJSONSource` or `MGLVectorSource` object. + is defined by an `MGLShapeSource` or `MGLVectorSource` object. Do not create instances of this class directly, and do not create your own subclasses of this class. Instead, create instances of the following concrete @@ -122,6 +122,12 @@ NS_ASSUME_NONNULL_BEGIN value specified in the predicate. Also, operator modifiers `c`, `d`, and the combined `cd` for case and diacritic insensitivity are unsupported for comparison and aggregate operators that are used in the predicate. + + It is possible to create expressions that contain special characters in the + predicate format syntax. This includes the `$` in the `$id` and `$type` special + style attributes and also `hyphen-minus` and `tag:subtag`. However, you must use + `%K` in the format string to represent these variables: + `@"%K == 'LineString'", @"$type"`. */ @property (nonatomic, nullable) NSPredicate *predicate; diff --git a/platform/darwin/src/NSArray+MGLAdditions.h b/platform/darwin/src/NSArray+MGLAdditions.h index 6871f1548..eb1cfb7c4 100644 --- a/platform/darwin/src/NSArray+MGLAdditions.h +++ b/platform/darwin/src/NSArray+MGLAdditions.h @@ -6,4 +6,7 @@ - (std::vector)mgl_vector; +/** Returns a string resulting from inserting a separator between each attributed string in the array */ +- (NSAttributedString *)mgl_attributedComponentsJoinedByString:(NSString *)separator; + @end diff --git a/platform/darwin/src/NSArray+MGLAdditions.mm b/platform/darwin/src/NSArray+MGLAdditions.mm index 976eda704..b2799c46e 100644 --- a/platform/darwin/src/NSArray+MGLAdditions.mm +++ b/platform/darwin/src/NSArray+MGLAdditions.mm @@ -23,4 +23,19 @@ return vector; } +- (NSAttributedString *)mgl_attributedComponentsJoinedByString:(NSString *)separator { + NSAttributedString *attributedSeparator = [[NSAttributedString alloc] initWithString:separator]; + NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] init]; + BOOL isSubsequentItem = NO; + for (NSAttributedString *component in self) { + NSAssert([component isKindOfClass:[NSAttributedString class]], @"Items in array must be attributed strings."); + if (isSubsequentItem) { + [attributedString appendAttributedString:attributedSeparator]; + } + isSubsequentItem = YES; + [attributedString appendAttributedString:component]; + } + return attributedString; +} + @end diff --git a/platform/darwin/src/NSString+MGLAdditions.h b/platform/darwin/src/NSString+MGLAdditions.h index 5b549affd..45fea2558 100644 --- a/platform/darwin/src/NSString+MGLAdditions.h +++ b/platform/darwin/src/NSString+MGLAdditions.h @@ -4,9 +4,22 @@ NS_ASSUME_NONNULL_BEGIN @interface NSString (MGLAdditions) +/** Returns the range spanning the entire receiver. */ +- (NSRange)mgl_wholeRange; + /** Returns the receiver if non-empty or nil if empty. */ - (nullable NSString *)mgl_stringOrNilIfEmpty; @end +@interface NSAttributedString (MGLAdditions) + +/** Returns the range spanning the entire receiver. */ +- (NSRange)mgl_wholeRange; + +/** Returns a copy of the receiver with leading and trailing members of the given set removed. */ +- (NSAttributedString *)mgl_attributedStringByTrimmingCharactersInSet:(NSCharacterSet *)set; + +@end + NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/NSString+MGLAdditions.m b/platform/darwin/src/NSString+MGLAdditions.m index 969886651..04a65dc5e 100644 --- a/platform/darwin/src/NSString+MGLAdditions.m +++ b/platform/darwin/src/NSString+MGLAdditions.m @@ -2,9 +2,30 @@ @implementation NSString (MGLAdditions) -- (nullable NSString *)mgl_stringOrNilIfEmpty -{ +- (NSRange)mgl_wholeRange { + return NSMakeRange(0, self.length); +} + +- (nullable NSString *)mgl_stringOrNilIfEmpty { return self.length ? self : nil; } @end + +@implementation NSAttributedString (MGLAdditions) + +- (NSRange)mgl_wholeRange { + return NSMakeRange(0, self.length); +} + +- (NSAttributedString *)mgl_attributedStringByTrimmingCharactersInSet:(NSCharacterSet *)set { + NSScanner *scanner = [NSScanner scannerWithString:self.string]; + scanner.charactersToBeSkipped = nil; + NSString *prefix; + [scanner scanCharactersFromSet:set intoString:&prefix]; + + NSString *trimmedString = [self.string stringByTrimmingCharactersInSet:set]; + return [self attributedSubstringFromRange:NSMakeRange(prefix.length, trimmedString.length)]; +} + +@end diff --git a/platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.h b/platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.h index 8aa07b2a0..3387ce818 100644 --- a/platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.h +++ b/platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.h @@ -98,17 +98,17 @@ NS_ASSUME_NONNULL_BEGIN @property (readonly) MGLTextAnchor MGLTextAnchorValue; /** - Creates a new value object containing the given `MGLTextJustify` enumeration. + Creates a new value object containing the given `MGLTextJustification` enumeration. @param type The value for the new object. @return A new value object that contains the style enumeration type. */ -+ (instancetype)valueWithMGLTextJustify:(MGLTextJustify)textJustify; ++ (instancetype)valueWithMGLTextJustification:(MGLTextJustification)textJustification; /** - The `MGLTextJustify` enumeration representation of the value. + The `MGLTextJustification` enumeration representation of the value. */ -@property (readonly) MGLTextJustify MGLTextJustifyValue; +@property (readonly) MGLTextJustification MGLTextJustificationValue; /** Creates a new value object containing the given `MGLTextPitchAlignment` enumeration. diff --git a/platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.mm b/platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.mm index 89f0c07a5..db91408c5 100644 --- a/platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.mm +++ b/platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.mm @@ -65,12 +65,12 @@ return value; } -+ (NSValue *)valueWithMGLTextJustify:(MGLTextJustify)textJustify { - return [NSValue value:&textJustify withObjCType:@encode(MGLTextJustify)]; ++ (NSValue *)valueWithMGLTextJustification:(MGLTextJustification)textJustification { + return [NSValue value:&textJustification withObjCType:@encode(MGLTextJustification)]; } -- (MGLTextJustify)MGLTextJustifyValue { - MGLTextJustify value; +- (MGLTextJustification)MGLTextJustificationValue { + MGLTextJustification value; [self getValue:&value]; return value; } diff --git a/platform/darwin/test/MGLAttributionInfoTests.m b/platform/darwin/test/MGLAttributionInfoTests.m new file mode 100644 index 000000000..3cdb7adff --- /dev/null +++ b/platform/darwin/test/MGLAttributionInfoTests.m @@ -0,0 +1,115 @@ +#import +#import + +#import "MGLAttributionInfo_Private.h" + +@interface MGLAttributionInfoTests : XCTestCase + +@end + +@implementation MGLAttributionInfoTests + +- (void)testParsing { + static NSString * const htmlStrings[] = { + @"© Mapbox " + @"©️ OpenStreetMap " + @"CC BY-SA " + @"Improve this map", + }; + + NS_MUTABLE_ARRAY_OF(MGLAttributionInfo *) *infos = [NSMutableArray array]; + for (NSUInteger i = 0; i < sizeof(htmlStrings) / sizeof(htmlStrings[0]); i++) { + NSArray *subinfos = [MGLAttributionInfo attributionInfosFromHTMLString:htmlStrings[i] + fontSize:0 + linkColor:nil]; + [infos growArrayByAddingAttributionInfosFromArray:subinfos]; + } + + XCTAssertEqual(infos.count, 4); + + CLLocationCoordinate2D mapbox = CLLocationCoordinate2DMake(12.9810816, 77.6368034); + XCTAssertEqualObjects(infos[0].title.string, @"© Mapbox"); + XCTAssertEqualObjects(infos[0].URL, [NSURL URLWithString:@"https://www.mapbox.com/about/maps/"]); + XCTAssertFalse(infos[0].feedbackLink); + XCTAssertNil([infos[0] feedbackURLAtCenterCoordinate:mapbox zoomLevel:14]); + + XCTAssertEqualObjects(infos[1].title.string, @"©️ OpenStreetMap"); + XCTAssertEqualObjects(infos[1].URL, [NSURL URLWithString:@"http://www.openstreetmap.org/about/"]); + XCTAssertFalse(infos[1].feedbackLink); + XCTAssertNil([infos[1] feedbackURLAtCenterCoordinate:mapbox zoomLevel:14]); + + XCTAssertEqualObjects(infos[2].title.string, @"CC\u00a0BY-SA"); + XCTAssertNil(infos[2].URL); + XCTAssertFalse(infos[2].feedbackLink); + XCTAssertNil([infos[2] feedbackURLAtCenterCoordinate:mapbox zoomLevel:14]); + + XCTAssertEqualObjects(infos[3].title.string, @"Improve this map"); + XCTAssertEqualObjects(infos[3].URL, [NSURL URLWithString:@"https://www.mapbox.com/map-feedback/"]); + XCTAssertTrue(infos[3].feedbackLink); + XCTAssertEqualObjects([infos[3] feedbackURLAtCenterCoordinate:mapbox zoomLevel:14], + [NSURL URLWithString:@"https://www.mapbox.com/map-feedback/#/77.63680/12.98108/15"]); +} + +- (void)testStyle { + static NSString * const htmlStrings[] = { + @"Mapbox", + }; + + CGFloat fontSize = 72; + MGLColor *color = [MGLColor redColor]; + NS_MUTABLE_ARRAY_OF(MGLAttributionInfo *) *infos = [NSMutableArray array]; + for (NSUInteger i = 0; i < sizeof(htmlStrings) / sizeof(htmlStrings[0]); i++) { + NSArray *subinfos = [MGLAttributionInfo attributionInfosFromHTMLString:htmlStrings[i] + fontSize:72 + linkColor:color]; + [infos growArrayByAddingAttributionInfosFromArray:subinfos]; + } + + XCTAssertEqual(infos.count, 1); + + XCTAssertEqualObjects(infos[0].title.string, @"Mapbox"); + XCTAssertEqualObjects([infos[0].title attribute:NSLinkAttributeName atIndex:0 effectiveRange:nil], [NSURL URLWithString:@"https://www.mapbox.com/"]); + XCTAssertEqualObjects([infos[0].title attribute:NSUnderlineStyleAttributeName atIndex:0 effectiveRange:nil], @(NSUnderlineStyleSingle)); + +#if TARGET_OS_IPHONE + UIFont *font; +#else + NSFont *font; +#endif + font = [infos[0].title attribute:NSFontAttributeName atIndex:0 effectiveRange:nil]; + XCTAssertEqual(font.pointSize, fontSize); + + CGFloat r, g, b, a; + [color getRed:&r green:&g blue:&b alpha:&a]; + MGLColor *linkColor = [infos[0].title attribute:NSForegroundColorAttributeName atIndex:0 effectiveRange:nil]; + CGFloat linkR, linkG, linkB, linkA; + [linkColor getRed:&linkR green:&linkG blue:&linkB alpha:&linkA]; + XCTAssertEqual(r, linkR); + XCTAssertEqual(g, linkG); + XCTAssertEqual(b, linkB); + XCTAssertEqual(a, linkA); +} + +- (void)testDedupe { + static NSString * const htmlStrings[] = { + @"World", + @"Hello World", + @"Another Source", + @"Hello", + @"Hello World", + }; + + NS_MUTABLE_ARRAY_OF(MGLAttributionInfo *) *infos = [NSMutableArray array]; + for (NSUInteger i = 0; i < sizeof(htmlStrings) / sizeof(htmlStrings[0]); i++) { + NSArray *subinfos = [MGLAttributionInfo attributionInfosFromHTMLString:htmlStrings[i] + fontSize:0 + linkColor:nil]; + [infos growArrayByAddingAttributionInfosFromArray:subinfos]; + } + + XCTAssertEqual(infos.count, 2); + XCTAssertEqualObjects(infos[0].title.string, @"Hello World"); + XCTAssertEqualObjects(infos[1].title.string, @"Another Source"); +} + +@end diff --git a/platform/darwin/test/MGLBackgroundStyleLayerTests.m b/platform/darwin/test/MGLBackgroundStyleLayerTests.m index 09bed7665..934021d6b 100644 --- a/platform/darwin/test/MGLBackgroundStyleLayerTests.m +++ b/platform/darwin/test/MGLBackgroundStyleLayerTests.m @@ -8,6 +8,10 @@ @implementation MGLBackgroundLayerTests ++ (NSString *)layerType { + return @"background"; +} + - (void)testBackgroundLayer { MGLBackgroundStyleLayer *layer = [[MGLBackgroundStyleLayer alloc] initWithIdentifier:@"layerID"]; [self.mapView.style addLayer:layer]; @@ -31,4 +35,10 @@ XCTAssertEqualObjects(gLayer.backgroundPattern, [MGLRuntimeStylingHelper testStringFunction]); } +- (void)testPropertyNames { + [self testPropertyName:@"background-color" isBoolean:NO]; + [self testPropertyName:@"background-opacity" isBoolean:NO]; + [self testPropertyName:@"background-pattern" isBoolean:NO]; +} + @end diff --git a/platform/darwin/test/MGLCircleStyleLayerTests.m b/platform/darwin/test/MGLCircleStyleLayerTests.m index 6f90f2c24..ce17d9355 100644 --- a/platform/darwin/test/MGLCircleStyleLayerTests.m +++ b/platform/darwin/test/MGLCircleStyleLayerTests.m @@ -8,10 +8,14 @@ @implementation MGLCircleLayerTests ++ (NSString *)layerType { + return @"circle"; +} + - (void)testCircleLayer { NSString *filePath = [[NSBundle bundleForClass:self.class] pathForResource:@"amsterdam" ofType:@"geojson"]; NSURL *url = [NSURL fileURLWithPath:filePath]; - MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"sourceID" URL:url options:nil]; + MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" URL:url options:nil]; [self.mapView.style addSource:source]; MGLCircleStyleLayer *layer = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"layerID" source:source]; [self.mapView.style addLayer:layer]; @@ -65,4 +69,17 @@ XCTAssertEqualObjects(gLayer.circleTranslateAnchor, [MGLRuntimeStylingHelper testEnumFunction:MGLCircleTranslateAnchorViewport type:@encode(MGLCircleTranslateAnchor)]); } +- (void)testPropertyNames { + [self testPropertyName:@"circle-blur" isBoolean:NO]; + [self testPropertyName:@"circle-color" isBoolean:NO]; + [self testPropertyName:@"circle-opacity" isBoolean:NO]; + [self testPropertyName:@"circle-pitch-scale" isBoolean:NO]; + [self testPropertyName:@"circle-radius" isBoolean:NO]; + [self testPropertyName:@"circle-stroke-color" isBoolean:NO]; + [self testPropertyName:@"circle-stroke-opacity" isBoolean:NO]; + [self testPropertyName:@"circle-stroke-width" isBoolean:NO]; + [self testPropertyName:@"circle-translate" isBoolean:NO]; + [self testPropertyName:@"circle-translate-anchor" isBoolean:NO]; +} + @end diff --git a/platform/darwin/test/MGLFeatureTests.mm b/platform/darwin/test/MGLFeatureTests.mm index 66b752a73..efc30d307 100644 --- a/platform/darwin/test/MGLFeatureTests.mm +++ b/platform/darwin/test/MGLFeatureTests.mm @@ -159,7 +159,7 @@ } - (void)testPointFeatureGeoJSONDictionary { - MGLPointFeature *pointFeature = (MGLPointFeature *)[[MGLPointFeature alloc] init]; + MGLPointFeature *pointFeature = [[MGLPointFeature alloc] init]; CLLocationCoordinate2D coordinate = { 10, 10 }; pointFeature.coordinate = coordinate; diff --git a/platform/darwin/test/MGLFillStyleLayerTests.m b/platform/darwin/test/MGLFillStyleLayerTests.m index 87846302e..7d51c15cf 100644 --- a/platform/darwin/test/MGLFillStyleLayerTests.m +++ b/platform/darwin/test/MGLFillStyleLayerTests.m @@ -8,15 +8,19 @@ @implementation MGLFillLayerTests ++ (NSString *)layerType { + return @"fill"; +} + - (void)testFillLayer { NSString *filePath = [[NSBundle bundleForClass:self.class] pathForResource:@"amsterdam" ofType:@"geojson"]; NSURL *url = [NSURL fileURLWithPath:filePath]; - MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"sourceID" URL:url options:nil]; + MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" URL:url options:nil]; [self.mapView.style addSource:source]; MGLFillStyleLayer *layer = [[MGLFillStyleLayer alloc] initWithIdentifier:@"layerID" source:source]; [self.mapView.style addLayer:layer]; - layer.fillAntialias = [MGLRuntimeStylingHelper testBool]; + layer.fillAntialiased = [MGLRuntimeStylingHelper testBool]; layer.fillColor = [MGLRuntimeStylingHelper testColor]; layer.fillOpacity = [MGLRuntimeStylingHelper testNumber]; layer.fillOutlineColor = [MGLRuntimeStylingHelper testColor]; @@ -26,7 +30,7 @@ MGLFillStyleLayer *gLayer = (MGLFillStyleLayer *)[self.mapView.style layerWithIdentifier:@"layerID"]; XCTAssertTrue([gLayer isKindOfClass:[MGLFillStyleLayer class]]); - XCTAssertEqualObjects(gLayer.fillAntialias, [MGLRuntimeStylingHelper testBool]); + XCTAssertEqualObjects(gLayer.fillAntialiased, [MGLRuntimeStylingHelper testBool]); XCTAssertEqualObjects(gLayer.fillColor, [MGLRuntimeStylingHelper testColor]); XCTAssertEqualObjects(gLayer.fillOpacity, [MGLRuntimeStylingHelper testNumber]); XCTAssertEqualObjects(gLayer.fillOutlineColor, [MGLRuntimeStylingHelper testColor]); @@ -35,7 +39,7 @@ XCTAssert([gLayer.fillTranslateAnchor isKindOfClass:[MGLStyleConstantValue class]]); XCTAssertEqualObjects(gLayer.fillTranslateAnchor, [MGLRuntimeStylingHelper testEnum:MGLFillTranslateAnchorViewport type:@encode(MGLFillTranslateAnchor)]); - layer.fillAntialias = [MGLRuntimeStylingHelper testBoolFunction]; + layer.fillAntialiased = [MGLRuntimeStylingHelper testBoolFunction]; layer.fillColor = [MGLRuntimeStylingHelper testColorFunction]; layer.fillOpacity = [MGLRuntimeStylingHelper testNumberFunction]; layer.fillOutlineColor = [MGLRuntimeStylingHelper testColorFunction]; @@ -43,7 +47,7 @@ layer.fillTranslate = [MGLRuntimeStylingHelper testOffsetFunction]; layer.fillTranslateAnchor = [MGLRuntimeStylingHelper testEnumFunction:MGLFillTranslateAnchorViewport type:@encode(MGLFillTranslateAnchor)]; - XCTAssertEqualObjects(gLayer.fillAntialias, [MGLRuntimeStylingHelper testBoolFunction]); + XCTAssertEqualObjects(gLayer.fillAntialiased, [MGLRuntimeStylingHelper testBoolFunction]); XCTAssertEqualObjects(gLayer.fillColor, [MGLRuntimeStylingHelper testColorFunction]); XCTAssertEqualObjects(gLayer.fillOpacity, [MGLRuntimeStylingHelper testNumberFunction]); XCTAssertEqualObjects(gLayer.fillOutlineColor, [MGLRuntimeStylingHelper testColorFunction]); @@ -52,4 +56,14 @@ XCTAssertEqualObjects(gLayer.fillTranslateAnchor, [MGLRuntimeStylingHelper testEnumFunction:MGLFillTranslateAnchorViewport type:@encode(MGLFillTranslateAnchor)]); } +- (void)testPropertyNames { + [self testPropertyName:@"is-fill-antialiased" isBoolean:YES]; + [self testPropertyName:@"fill-color" isBoolean:NO]; + [self testPropertyName:@"fill-opacity" isBoolean:NO]; + [self testPropertyName:@"fill-outline-color" isBoolean:NO]; + [self testPropertyName:@"fill-pattern" isBoolean:NO]; + [self testPropertyName:@"fill-translate" isBoolean:NO]; + [self testPropertyName:@"fill-translate-anchor" isBoolean:NO]; +} + @end diff --git a/platform/darwin/test/MGLFilterTests.mm b/platform/darwin/test/MGLFilterTests.mm index b18400f83..e688d5058 100644 --- a/platform/darwin/test/MGLFilterTests.mm +++ b/platform/darwin/test/MGLFilterTests.mm @@ -5,7 +5,7 @@ @interface MGLFilterTests : MGLStyleLayerTests { - MGLGeoJSONSource *source; + MGLShapeSource *source; MGLLineStyleLayer *layer; } @end @@ -18,7 +18,11 @@ NSString *filePath = [[NSBundle bundleForClass:self.class] pathForResource:@"amsterdam" ofType:@"geojson"]; NSURL *url = [NSURL fileURLWithPath:filePath]; NSData *geoJSONData = [NSData dataWithContentsOfURL:url]; - source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"test-source" geoJSONData:geoJSONData options:nil]; + NSError *error; + MGLShape *shape = [MGLShape shapeWithData:geoJSONData encoding:NSUTF8StringEncoding error:&error]; + XCTAssertNil(error); + XCTAssertNotNil(shape); + source = [[MGLShapeSource alloc] initWithIdentifier:@"test-source" shape:shape options:nil]; [self.mapView.style addSource:source]; layer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"test-layer" source:source]; } diff --git a/platform/darwin/test/MGLGeometryTests.mm b/platform/darwin/test/MGLGeometryTests.mm index b15916e6f..0ffc27b29 100644 --- a/platform/darwin/test/MGLGeometryTests.mm +++ b/platform/darwin/test/MGLGeometryTests.mm @@ -99,4 +99,49 @@ XCTAssertFalse(MGLCoordinateInCoordinateBounds(kCLLocationCoordinate2DInvalid, wyoming)); } +- (void)testGeoJSONDeserialization { + NSData *data = [@"{\"type\": \"Feature\", \"geometry\": {\"type\": \"Point\", \"coordinates\": [0, 0]}, \"properties\": {}}" dataUsingEncoding:NSUTF8StringEncoding]; + NSError *error; + MGLPointFeature *feature = (MGLPointFeature *)[MGLShape shapeWithData:data encoding:NSUTF8StringEncoding error:&error]; + XCTAssertNil(error, @"Valid GeoJSON data should produce no error on deserialization."); + XCTAssertNotNil(feature, @"Valid GeoJSON data should produce an object on deserialization."); + XCTAssertTrue([feature isKindOfClass:[MGLPointFeature class]], @"Valid GeoJSON point feature data should produce an MGLPointFeature."); + XCTAssertEqual(feature.attributes.count, 0); + XCTAssertEqual(feature.coordinate.latitude, 0); + XCTAssertEqual(feature.coordinate.longitude, 0); + + data = [@"{\"type\": \"Feature\", \"feature\": {\"type\": \"Point\", \"coordinates\": [0, 0]}}" dataUsingEncoding:NSUTF8StringEncoding]; + error = nil; + MGLShape *shape = [MGLShape shapeWithData:data encoding:NSUTF8StringEncoding error:&error]; + XCTAssertNotNil(error, @"Invalid GeoJSON data should produce an error on deserialization."); + XCTAssertNil(shape, @"Invalid GeoJSON data should produce no object on deserialization."); +} + +- (void)testGeoJSONSerialization { + MGLPointFeature *feature = [[MGLPointFeature alloc] init]; + feature.identifier = @504; + feature.coordinate = CLLocationCoordinate2DMake(29.95, -90.066667); + + NSData *data = [feature geoJSONDataUsingEncoding:NSUTF8StringEncoding]; + XCTAssertNotNil(data, @"MGLPointFeature should serialize as an UTF-8 string data object."); + NSError *error; + NSDictionary *serializedGeoJSON = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; + XCTAssertNil(error, @"Serialized GeoJSON data should be deserializable JSON."); + XCTAssertNotNil(serializedGeoJSON, @"Serialized GeoJSON data should be valid JSON."); + XCTAssertTrue([serializedGeoJSON isKindOfClass:[NSDictionary class]], @"Serialized GeoJSON data should be a JSON object."); + NSDictionary *geoJSON = @{ + @"type": @"Feature", + @"id": @504, + @"geometry": @{ + @"type": @"Point", + @"coordinates": @[ + @(-90.066667), + @29.95, + ], + }, + @"properties": @{}, + }; + XCTAssertEqualObjects(serializedGeoJSON, geoJSON, @"MGLPointFeature should serialize as a GeoJSON point feature."); +} + @end diff --git a/platform/darwin/test/MGLLineStyleLayerTests.m b/platform/darwin/test/MGLLineStyleLayerTests.m index 95983b1f5..e877c1d57 100644 --- a/platform/darwin/test/MGLLineStyleLayerTests.m +++ b/platform/darwin/test/MGLLineStyleLayerTests.m @@ -8,10 +8,14 @@ @implementation MGLLineLayerTests ++ (NSString *)layerType { + return @"line"; +} + - (void)testLineLayer { NSString *filePath = [[NSBundle bundleForClass:self.class] pathForResource:@"amsterdam" ofType:@"geojson"]; NSURL *url = [NSURL fileURLWithPath:filePath]; - MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"sourceID" URL:url options:nil]; + MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" URL:url options:nil]; [self.mapView.style addSource:source]; MGLLineStyleLayer *layer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"layerID" source:source]; [self.mapView.style addLayer:layer]; @@ -22,7 +26,7 @@ layer.lineRoundLimit = [MGLRuntimeStylingHelper testNumber]; layer.lineBlur = [MGLRuntimeStylingHelper testNumber]; layer.lineColor = [MGLRuntimeStylingHelper testColor]; - layer.lineDasharray = [MGLRuntimeStylingHelper testDashArray]; + layer.lineDashPattern = [MGLRuntimeStylingHelper testDashArray]; layer.lineGapWidth = [MGLRuntimeStylingHelper testNumber]; layer.lineOffset = [MGLRuntimeStylingHelper testNumber]; layer.lineOpacity = [MGLRuntimeStylingHelper testNumber]; @@ -41,7 +45,7 @@ XCTAssertEqualObjects(gLayer.lineRoundLimit, [MGLRuntimeStylingHelper testNumber]); XCTAssertEqualObjects(gLayer.lineBlur, [MGLRuntimeStylingHelper testNumber]); XCTAssertEqualObjects(gLayer.lineColor, [MGLRuntimeStylingHelper testColor]); - XCTAssertEqualObjects(gLayer.lineDasharray, [MGLRuntimeStylingHelper testDashArray]); + XCTAssertEqualObjects(gLayer.lineDashPattern, [MGLRuntimeStylingHelper testDashArray]); XCTAssertEqualObjects(gLayer.lineGapWidth, [MGLRuntimeStylingHelper testNumber]); XCTAssertEqualObjects(gLayer.lineOffset, [MGLRuntimeStylingHelper testNumber]); XCTAssertEqualObjects(gLayer.lineOpacity, [MGLRuntimeStylingHelper testNumber]); @@ -57,7 +61,7 @@ layer.lineRoundLimit = [MGLRuntimeStylingHelper testNumberFunction]; layer.lineBlur = [MGLRuntimeStylingHelper testNumberFunction]; layer.lineColor = [MGLRuntimeStylingHelper testColorFunction]; - layer.lineDasharray = [MGLRuntimeStylingHelper testDashArrayFunction]; + layer.lineDashPattern = [MGLRuntimeStylingHelper testDashArrayFunction]; layer.lineGapWidth = [MGLRuntimeStylingHelper testNumberFunction]; layer.lineOffset = [MGLRuntimeStylingHelper testNumberFunction]; layer.lineOpacity = [MGLRuntimeStylingHelper testNumberFunction]; @@ -72,7 +76,7 @@ XCTAssertEqualObjects(gLayer.lineRoundLimit, [MGLRuntimeStylingHelper testNumberFunction]); XCTAssertEqualObjects(gLayer.lineBlur, [MGLRuntimeStylingHelper testNumberFunction]); XCTAssertEqualObjects(gLayer.lineColor, [MGLRuntimeStylingHelper testColorFunction]); - XCTAssertEqualObjects(gLayer.lineDasharray, [MGLRuntimeStylingHelper testDashArrayFunction]); + XCTAssertEqualObjects(gLayer.lineDashPattern, [MGLRuntimeStylingHelper testDashArrayFunction]); XCTAssertEqualObjects(gLayer.lineGapWidth, [MGLRuntimeStylingHelper testNumberFunction]); XCTAssertEqualObjects(gLayer.lineOffset, [MGLRuntimeStylingHelper testNumberFunction]); XCTAssertEqualObjects(gLayer.lineOpacity, [MGLRuntimeStylingHelper testNumberFunction]); @@ -82,4 +86,21 @@ XCTAssertEqualObjects(gLayer.lineWidth, [MGLRuntimeStylingHelper testNumberFunction]); } +- (void)testPropertyNames { + [self testPropertyName:@"line-cap" isBoolean:NO]; + [self testPropertyName:@"line-join" isBoolean:NO]; + [self testPropertyName:@"line-miter-limit" isBoolean:NO]; + [self testPropertyName:@"line-round-limit" isBoolean:NO]; + [self testPropertyName:@"line-blur" isBoolean:NO]; + [self testPropertyName:@"line-color" isBoolean:NO]; + [self testPropertyName:@"line-dash-pattern" isBoolean:NO]; + [self testPropertyName:@"line-gap-width" isBoolean:NO]; + [self testPropertyName:@"line-offset" isBoolean:NO]; + [self testPropertyName:@"line-opacity" isBoolean:NO]; + [self testPropertyName:@"line-pattern" isBoolean:NO]; + [self testPropertyName:@"line-translate" isBoolean:NO]; + [self testPropertyName:@"line-translate-anchor" isBoolean:NO]; + [self testPropertyName:@"line-width" isBoolean:NO]; +} + @end diff --git a/platform/darwin/test/MGLRasterStyleLayerTests.m b/platform/darwin/test/MGLRasterStyleLayerTests.m index 84fd0fe3e..f8de191da 100644 --- a/platform/darwin/test/MGLRasterStyleLayerTests.m +++ b/platform/darwin/test/MGLRasterStyleLayerTests.m @@ -8,10 +8,14 @@ @implementation MGLRasterLayerTests ++ (NSString *)layerType { + return @"raster"; +} + - (void)testRasterLayer { NSString *filePath = [[NSBundle bundleForClass:self.class] pathForResource:@"amsterdam" ofType:@"geojson"]; NSURL *url = [NSURL fileURLWithPath:filePath]; - MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"sourceID" URL:url options:nil]; + MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" URL:url options:nil]; [self.mapView.style addSource:source]; MGLRasterStyleLayer *layer = [[MGLRasterStyleLayer alloc] initWithIdentifier:@"layerID" source:source]; [self.mapView.style addLayer:layer]; @@ -20,7 +24,7 @@ layer.minimumRasterBrightness = [MGLRuntimeStylingHelper testNumber]; layer.rasterContrast = [MGLRuntimeStylingHelper testNumber]; layer.rasterFadeDuration = [MGLRuntimeStylingHelper testNumber]; - layer.rasterHueRotate = [MGLRuntimeStylingHelper testNumber]; + layer.rasterHueRotation = [MGLRuntimeStylingHelper testNumber]; layer.rasterOpacity = [MGLRuntimeStylingHelper testNumber]; layer.rasterSaturation = [MGLRuntimeStylingHelper testNumber]; @@ -30,7 +34,7 @@ XCTAssertEqualObjects(gLayer.minimumRasterBrightness, [MGLRuntimeStylingHelper testNumber]); XCTAssertEqualObjects(gLayer.rasterContrast, [MGLRuntimeStylingHelper testNumber]); XCTAssertEqualObjects(gLayer.rasterFadeDuration, [MGLRuntimeStylingHelper testNumber]); - XCTAssertEqualObjects(gLayer.rasterHueRotate, [MGLRuntimeStylingHelper testNumber]); + XCTAssertEqualObjects(gLayer.rasterHueRotation, [MGLRuntimeStylingHelper testNumber]); XCTAssertEqualObjects(gLayer.rasterOpacity, [MGLRuntimeStylingHelper testNumber]); XCTAssertEqualObjects(gLayer.rasterSaturation, [MGLRuntimeStylingHelper testNumber]); @@ -38,7 +42,7 @@ layer.minimumRasterBrightness = [MGLRuntimeStylingHelper testNumberFunction]; layer.rasterContrast = [MGLRuntimeStylingHelper testNumberFunction]; layer.rasterFadeDuration = [MGLRuntimeStylingHelper testNumberFunction]; - layer.rasterHueRotate = [MGLRuntimeStylingHelper testNumberFunction]; + layer.rasterHueRotation = [MGLRuntimeStylingHelper testNumberFunction]; layer.rasterOpacity = [MGLRuntimeStylingHelper testNumberFunction]; layer.rasterSaturation = [MGLRuntimeStylingHelper testNumberFunction]; @@ -46,9 +50,19 @@ XCTAssertEqualObjects(gLayer.minimumRasterBrightness, [MGLRuntimeStylingHelper testNumberFunction]); XCTAssertEqualObjects(gLayer.rasterContrast, [MGLRuntimeStylingHelper testNumberFunction]); XCTAssertEqualObjects(gLayer.rasterFadeDuration, [MGLRuntimeStylingHelper testNumberFunction]); - XCTAssertEqualObjects(gLayer.rasterHueRotate, [MGLRuntimeStylingHelper testNumberFunction]); + XCTAssertEqualObjects(gLayer.rasterHueRotation, [MGLRuntimeStylingHelper testNumberFunction]); XCTAssertEqualObjects(gLayer.rasterOpacity, [MGLRuntimeStylingHelper testNumberFunction]); XCTAssertEqualObjects(gLayer.rasterSaturation, [MGLRuntimeStylingHelper testNumberFunction]); } +- (void)testPropertyNames { + [self testPropertyName:@"maximum-raster-brightness" isBoolean:NO]; + [self testPropertyName:@"minimum-raster-brightness" isBoolean:NO]; + [self testPropertyName:@"raster-contrast" isBoolean:NO]; + [self testPropertyName:@"raster-fade-duration" isBoolean:NO]; + [self testPropertyName:@"raster-hue-rotation" isBoolean:NO]; + [self testPropertyName:@"raster-opacity" isBoolean:NO]; + [self testPropertyName:@"raster-saturation" isBoolean:NO]; +} + @end diff --git a/platform/darwin/test/MGLGeoJSONSourceTests.mm b/platform/darwin/test/MGLShapeSourceTests.mm similarity index 60% rename from platform/darwin/test/MGLGeoJSONSourceTests.mm rename to platform/darwin/test/MGLShapeSourceTests.mm index be8bb143c..efff4b393 100644 --- a/platform/darwin/test/MGLGeoJSONSourceTests.mm +++ b/platform/darwin/test/MGLShapeSourceTests.mm @@ -2,28 +2,25 @@ #import #import "MGLFeature_Private.h" -#import "MGLGeoJSONSource_Private.h" +#import "MGLShapeSource_Private.h" #import "MGLSource_Private.h" #include -@interface MGLGeoJSONSourceTests : XCTestCase +@interface MGLShapeSourceTests : XCTestCase @end -@implementation MGLGeoJSONSourceTests +@implementation MGLShapeSourceTests -- (void)testMGLGeoJSONSourceWithOptions { - NSURL *url = [NSURL URLWithString:@"http://www.mapbox.com/source"]; +- (void)testGeoJSONOptionsFromDictionary { + NSDictionary *options = @{MGLShapeSourceOptionClustered: @YES, + MGLShapeSourceOptionClusterRadius: @42, + MGLShapeSourceOptionMaximumZoomLevelForClustering: @98, + MGLShapeSourceOptionMaximumZoomLevel: @99, + MGLShapeSourceOptionBuffer: @1976, + MGLShapeSourceOptionSimplificationTolerance: @0.42}; - NSDictionary *options = @{MGLGeoJSONSourceOptionClustered: @YES, - MGLGeoJSONSourceOptionClusterRadius: @42, - MGLGeoJSONSourceOptionMaximumZoomLevelForClustering: @98, - MGLGeoJSONSourceOptionMaximumZoomLevel: @99, - MGLGeoJSONSourceOptionBuffer: @1976, - MGLGeoJSONSourceOptionSimplificationTolerance: @0.42}; - MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"source-id" URL:url options:options]; - - auto mbglOptions = [source geoJSONOptions]; + auto mbglOptions = MGLGeoJSONOptionsFromDictionary(options); XCTAssertTrue(mbglOptions.cluster); XCTAssertEqual(mbglOptions.clusterRadius, 42); XCTAssertEqual(mbglOptions.clusterMaxZoom, 98); @@ -31,34 +28,68 @@ XCTAssertEqual(mbglOptions.buffer, 1976); XCTAssertEqual(mbglOptions.tolerance, 0.42); - options = @{MGLGeoJSONSourceOptionClustered: @"number 1"}; - XCTAssertThrows([[MGLGeoJSONSource alloc] initWithIdentifier:@"source-id" URL:url options:options]); + options = @{MGLShapeSourceOptionClustered: @"number 1"}; + XCTAssertThrows(MGLGeoJSONOptionsFromDictionary(options)); } -- (void)testMGLGeoJSONSourceWithData { +- (void)testNilShape { + MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"id" shape:nil options:nil]; + XCTAssertNil(source.shape); +} + +- (void)testMGLShapeSourceWithDataMultipleFeatures { NSString *geoJSON = @"{\"type\": \"FeatureCollection\",\"features\": [{\"type\": \"Feature\",\"properties\": {},\"geometry\": {\"type\": \"LineString\",\"coordinates\": [[-107.75390625,40.329795743702064],[-104.34814453125,37.64903402157866]]}}]}"; NSData *data = [geoJSON dataUsingEncoding:NSUTF8StringEncoding]; - MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"source-id" geoJSONData:data options:nil]; + NSError *error; + MGLShape *shape = [MGLShape shapeWithData:data encoding:NSUTF8StringEncoding error:&error]; + XCTAssertNil(error); + XCTAssertNotNil(shape); + MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"source-id" shape:shape options:nil]; - XCTAssertNotNil(source.features); - XCTAssertEqual(source.features.count, 1); - XCTAssertTrue([source.features.firstObject isMemberOfClass:[MGLPolylineFeature class]]); + MGLShapeCollection *collection = (MGLShapeCollection *)source.shape; + XCTAssertNotNil(collection); + XCTAssertEqual(collection.shapes.count, 1); + XCTAssertTrue([collection.shapes.firstObject isMemberOfClass:[MGLPolylineFeature class]]); } -- (void)testMGLGeoJSONSourceWithPolylineFeatures { +- (void)testMGLShapeSourceWithSingleGeometry { + NSData *data = [@"{\"type\": \"Point\", \"coordinates\": [0, 0]}" dataUsingEncoding:NSUTF8StringEncoding]; + NSError *error; + MGLShape *shape = [MGLShape shapeWithData:data encoding:NSUTF8StringEncoding error:&error]; + XCTAssertNil(error); + XCTAssertNotNil(shape); + MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"geojson" shape:shape options:nil]; + XCTAssertNotNil(source.shape); + XCTAssert([source.shape isKindOfClass:[MGLPointAnnotation class]]); +} + +- (void)testMGLGeoJSONSourceWithSingleFeature { + NSString *geoJSON = @"{\"type\": \"Feature\", \"properties\": {\"color\": \"green\"}, \"geometry\": { \"type\": \"Point\", \"coordinates\": [ -114.06847000122069, 51.050459433092655 ] }}"; + NSData *data = [geoJSON dataUsingEncoding:NSUTF8StringEncoding]; + NSError *error; + MGLShape *shape = [MGLShape shapeWithData:data encoding:NSUTF8StringEncoding error:&error]; + XCTAssertNil(error); + XCTAssertNotNil(shape); + MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"geojson" shape:shape options:nil]; + XCTAssertNotNil(source.shape); + XCTAssert([source.shape isKindOfClass:[MGLPointFeature class]]); + MGLPointFeature *feature = (MGLPointFeature *)source.shape; + XCTAssert([feature.attributes.allKeys containsObject:@"color"]); +} + +- (void)testMGLShapeSourceWithPolylineFeatures { CLLocationCoordinate2D coordinates[] = { CLLocationCoordinate2DMake(0, 0), CLLocationCoordinate2DMake(10, 10)}; MGLPolylineFeature *polylineFeature = [MGLPolylineFeature polylineWithCoordinates:coordinates count:2]; - MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"source-id" features:@[polylineFeature] options:nil]; + MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"source-id" shape:polylineFeature options:nil]; - XCTAssertNotNil(source.features); - XCTAssertEqual(source.features.count, 1); - XCTAssertTrue([source.features.firstObject isMemberOfClass:[MGLPolylineFeature class]]); + XCTAssertNotNil(source.shape); + XCTAssertTrue([source.shape isMemberOfClass:[MGLPolylineFeature class]]); } -- (void)testMGLGeoJSONSourceWithPolygonFeatures { +- (void)testMGLShapeSourceWithPolygonFeatures { CLLocationCoordinate2D coordinates[] = { CLLocationCoordinate2DMake(100.0, 0.0), CLLocationCoordinate2DMake(101.0, 0.0), @@ -66,7 +97,7 @@ CLLocationCoordinate2DMake(100.0, 1.0), CLLocationCoordinate2DMake(100.0, 0.0)}; - MGLPolygonFeature *polygonFeature = (MGLPolygonFeature *)[MGLPolygonFeature polygonWithCoordinates:coordinates count:5]; + MGLPolygonFeature *polygonFeature = [MGLPolygonFeature polygonWithCoordinates:coordinates count:5]; polygonFeature.identifier = @"feature-id"; NSString *stringAttribute = @"string"; NSNumber *boolAttribute = [NSNumber numberWithBool:YES]; @@ -88,11 +119,11 @@ @"array-of-array-attribute": arrayOfArrays, @"array-of-dictionary-attribute": arrayOfDictionaries}; - MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"source-id" features:@[polygonFeature] options:nil]; + MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"source-id" shape:polygonFeature options:nil]; - XCTAssertNotNil(source.features); - XCTAssertEqual(source.features.count, 1); - MGLPolygonFeature *expectedPolygonFeature = (MGLPolygonFeature *)source.features.firstObject; + XCTAssertNotNil(source.shape); + MGLPolygonFeature *expectedPolygonFeature = (MGLPolygonFeature *)source.shape; + XCTAssertEqualObjects(expectedPolygonFeature.identifier, polygonFeature.identifier); XCTAssertTrue([expectedPolygonFeature isMemberOfClass:[MGLPolygonFeature class]]); XCTAssertEqualObjects(expectedPolygonFeature.identifier, polygonFeature.identifier); XCTAssertEqualObjects(expectedPolygonFeature.attributes[@"name"], stringAttribute); @@ -104,7 +135,7 @@ XCTAssertEqualObjects(expectedPolygonFeature.attributes[@"array-of-dictionary-attribute"], arrayOfDictionaries); } -- (void)testMGLGeoJSONSourceWithPolygonFeaturesInculdingInteriorPolygons { +- (void)testMGLShapeSourceWithPolygonFeaturesInculdingInteriorPolygons { CLLocationCoordinate2D coordinates[] = { CLLocationCoordinate2DMake(100.0, 0.0), CLLocationCoordinate2DMake(101.0, 0.0), @@ -123,29 +154,26 @@ MGLPolygonFeature *polygonFeature = [MGLPolygonFeature polygonWithCoordinates:coordinates count:5 interiorPolygons:@[polygon]]; - MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"source-id" features:@[polygonFeature] options:nil]; - + MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"source-id" shape:polygonFeature options:nil]; - XCTAssertNotNil(source.features); - XCTAssertEqual(source.features.count, 1); - XCTAssertTrue([source.features.firstObject isMemberOfClass:[MGLPolygonFeature class]]); + XCTAssertNotNil(source.shape); + XCTAssertTrue([source.shape isMemberOfClass:[MGLPolygonFeature class]]); } -- (void)testMGLGeoJSONSourceWithMultiPolylineFeatures { +- (void)testMGLShapeSourceWithMultiPolylineFeatures { CLLocationCoordinate2D firstCoordinates[] = { CLLocationCoordinate2DMake(0, 0), CLLocationCoordinate2DMake(10, 10)}; MGLPolylineFeature *firstPolylineFeature = [MGLPolylineFeature polylineWithCoordinates:firstCoordinates count:2]; CLLocationCoordinate2D secondCoordinates[] = { CLLocationCoordinate2DMake(0, 0), CLLocationCoordinate2DMake(10, 10)}; MGLPolylineFeature *secondPolylineFeature = [MGLPolylineFeature polylineWithCoordinates:secondCoordinates count:2]; MGLMultiPolylineFeature *multiPolylineFeature = [MGLMultiPolylineFeature multiPolylineWithPolylines:@[firstPolylineFeature, secondPolylineFeature]]; - MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"source-id" features:@[multiPolylineFeature] options:nil]; + MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"source-id" shape:multiPolylineFeature options:nil]; - XCTAssertNotNil(source.features); - XCTAssertEqual(source.features.count, 1); - XCTAssertTrue([source.features.firstObject isMemberOfClass:[MGLMultiPolylineFeature class]]); + XCTAssertNotNil(source.shape); + XCTAssertTrue([source.shape isMemberOfClass:[MGLMultiPolylineFeature class]]); } -- (void)testMGLGeoJSONSourceWithMultiPolygonFeatures { +- (void)testMGLShapeSourceWithMultiPolygonFeatures { CLLocationCoordinate2D coordinates[] = { CLLocationCoordinate2DMake(100.0, 0.0), CLLocationCoordinate2DMake(101.0, 0.0), @@ -167,26 +195,23 @@ MGLMultiPolygonFeature *multiPolygonFeature = [MGLMultiPolygonFeature multiPolygonWithPolygons:@[firstPolygon, secondPolygon]]; - MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"source-id" features:@[multiPolygonFeature] options:nil]; + MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"source-id" shape:multiPolygonFeature options:nil]; - XCTAssertNotNil(source.features); - XCTAssertEqual(source.features.count, 1); - XCTAssertTrue([source.features.firstObject isMemberOfClass:[MGLMultiPolygonFeature class]]); - + XCTAssertNotNil(source.shape); + XCTAssertTrue([source.shape isMemberOfClass:[MGLMultiPolygonFeature class]]); } -- (void)testMGLGeoJSONSourceWithPointFeature { +- (void)testMGLShapeSourceWithPointFeature { MGLPointFeature *pointFeature = [MGLPointFeature new]; pointFeature.coordinate = CLLocationCoordinate2DMake(100.2, 0.2); - MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"souce-id" features:@[pointFeature] options:nil]; + MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"souce-id" shape:pointFeature options:nil]; - XCTAssertNotNil(source.features); - XCTAssertEqual(source.features.count, 1); - XCTAssertTrue([source.features.firstObject isMemberOfClass:[MGLPointFeature class]]); + XCTAssertNotNil(source.shape); + XCTAssertTrue([source.shape isMemberOfClass:[MGLPointFeature class]]); } -- (void)testMGLGeoJSONSourceWithPointCollectionFeature { +- (void)testMGLShapeSourceWithPointCollectionFeature { CLLocationCoordinate2D coordinates[] = { CLLocationCoordinate2DMake(100.0, 0.0), CLLocationCoordinate2DMake(101.0, 0.0), @@ -194,14 +219,13 @@ CLLocationCoordinate2DMake(100.0, 1.0), CLLocationCoordinate2DMake(100.0, 0.0)}; MGLPointCollectionFeature *pointCollectionFeature = [MGLPointCollectionFeature pointCollectionWithCoordinates:coordinates count:5]; - MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"souce-id" features:@[pointCollectionFeature] options:nil]; + MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"souce-id" shape:pointCollectionFeature options:nil]; - XCTAssertNotNil(source.features); - XCTAssertEqual(source.features.count, 1); - XCTAssertTrue([source.features.firstObject isMemberOfClass:[MGLPointCollectionFeature class]]); + XCTAssertNotNil(source.shape); + XCTAssertTrue([source.shape isMemberOfClass:[MGLPointCollectionFeature class]]); } -- (void)testMGLGeoJSONSourceWithShapeCollectionFeatures { +- (void)testMGLShapeSourceWithShapeCollectionFeatures { CLLocationCoordinate2D coordinates[] = { CLLocationCoordinate2DMake(100.0, 0.0), CLLocationCoordinate2DMake(101.0, 0.0), @@ -234,9 +258,11 @@ MGLShapeCollectionFeature *shapeCollectionFeature = [MGLShapeCollectionFeature shapeCollectionWithShapes:@[polygonFeature, polylineFeature, multiPolygonFeature, multiPolylineFeature, pointCollectionFeature, pointFeature]]; - MGLShapeCollectionFeature *shapeCollectionFeature_1 = [MGLShapeCollectionFeature shapeCollectionWithShapes:@[polygonFeature, polylineFeature, multiPolygonFeature, multiPolylineFeature, pointCollectionFeature, pointFeature, shapeCollectionFeature]]; - - XCTAssertThrowsSpecificNamed([[MGLGeoJSONSource alloc] initWithIdentifier:@"source-id" features:@[shapeCollectionFeature_1] options:nil], NSException, @"Method unavailable"); + MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"source-id" shape:shapeCollectionFeature options:nil]; + + MGLShapeCollectionFeature *shape = (MGLShapeCollectionFeature *)source.shape; + XCTAssertNotNil(shape); + XCTAssert(shape.shapes.count == 6, @"Shape collection should contain 6 shapes"); } @end diff --git a/platform/darwin/test/MGLStyleLayerTests.h b/platform/darwin/test/MGLStyleLayerTests.h index f81e075e0..74ce62e89 100644 --- a/platform/darwin/test/MGLStyleLayerTests.h +++ b/platform/darwin/test/MGLStyleLayerTests.h @@ -6,5 +6,15 @@ @property (nonatomic) IBOutlet MGLMapView *mapView; @property (nonatomic) XCTestExpectation *expectation; +@property (nonatomic, copy, readonly, class) NSString *layerType; + +- (void)testPropertyName:(NSString *)name isBoolean:(BOOL)isBoolean; + +@end + +@interface NSString (MGLStyleLayerTestAdditions) + +@property (nonatomic, readonly, copy) NS_ARRAY_OF(NSString *) *lexicalClasses; +@property (nonatomic, readonly, copy) NSString *lemma; @end diff --git a/platform/darwin/test/MGLStyleLayerTests.m b/platform/darwin/test/MGLStyleLayerTests.m index 74c6b2f90..590d6eda7 100644 --- a/platform/darwin/test/MGLStyleLayerTests.m +++ b/platform/darwin/test/MGLStyleLayerTests.m @@ -1,7 +1,13 @@ #import "MGLStyleLayerTests.h" +#import "NSString+MGLAdditions.h" + +#define TEST_STRICT_NAMING_CONVENTIONS 0 + @implementation MGLStyleLayerTests +@dynamic layerType; + - (void)setUp { [super setUp]; #if TARGET_OS_IPHONE @@ -19,4 +25,65 @@ #endif } +- (void)testPropertyName:(NSString *)name isBoolean:(BOOL)isBoolean { + NS_MUTABLE_ARRAY_OF(NSString *) *components = [name componentsSeparatedByString:@"-"].mutableCopy; + if (isBoolean) { + if ([components.firstObject isEqualToString:@"is"]) { + [components removeObjectAtIndex:0]; + if (![components.lastObject.lexicalClasses containsObject:NSLinguisticTagAdjective]) { + XCTAssertTrue([components.lastObject.lexicalClasses containsObject:NSLinguisticTagVerb], + @"Boolean getter %@ that starts with “is” should contain an adjective, past participle, or verb.", name); + XCTAssertNotEqualObjects(components.lastObject.lemma, components.lastObject, + @"Boolean getter %@ should not have infinitive, imperative, or present tense verb.", name); + } + } else { + if ([components.firstObject isEqualToString:[self class].layerType] + || [components.firstObject isEqualToString:@"icon"] || [components.firstObject isEqualToString:@"text"]) { + [components removeObjectAtIndex:0]; + } +#if TEST_STRICT_NAMING_CONVENTIONS + XCTAssertTrue([components.firstObject.lexicalClasses containsObject:NSLinguisticTagVerb], + @"Boolean getter %@ that doesn’t start with “is” should contain a verb.", name); + XCTAssertNotEqualObjects(components.firstObject.lemma, components.lastObject); +#endif + } + } else { + XCTAssertFalse([components.firstObject isEqualToString:@"is"]); +#if TEST_STRICT_NAMING_CONVENTIONS + XCTAssertTrue([components.lastObject.lexicalClasses containsObject:NSLinguisticTagNoun], + @"Non-Boolean getter %@ should contain a noun.", name); +#endif + } +} + +@end + +@implementation NSString (MGLStyleLayerTestAdditions) + +- (NS_ARRAY_OF(NSString *) *)lexicalClasses { + NSOrthography *orthography = [NSOrthography orthographyWithDominantScript:@"Latn" + languageMap:@{@"Latn": @[@"en"]}]; + NSLinguisticTaggerOptions options = (NSLinguisticTaggerOmitPunctuation + | NSLinguisticTaggerOmitWhitespace + | NSLinguisticTaggerOmitOther); + return [self linguisticTagsInRange:self.mgl_wholeRange + scheme:NSLinguisticTagSchemeLexicalClass + options:options + orthography:orthography + tokenRanges:NULL]; +} + +- (NSString *)lemma { + NSOrthography *orthography = [NSOrthography orthographyWithDominantScript:@"Latn" + languageMap:@{@"Latn": @[@"en"]}]; + NSLinguisticTaggerOptions options = (NSLinguisticTaggerOmitPunctuation + | NSLinguisticTaggerOmitWhitespace + | NSLinguisticTaggerOmitOther); + return [self linguisticTagsInRange:self.mgl_wholeRange + scheme:NSLinguisticTagSchemeLemma + options:options + orthography:orthography + tokenRanges:NULL].firstObject; +} + @end diff --git a/platform/darwin/src/MGLRuntimeStylingTests.m.ejs b/platform/darwin/test/MGLStyleLayerTests.m.ejs similarity index 78% rename from platform/darwin/src/MGLRuntimeStylingTests.m.ejs rename to platform/darwin/test/MGLStyleLayerTests.m.ejs index 720ee4547..6b7bfe2f1 100644 --- a/platform/darwin/src/MGLRuntimeStylingTests.m.ejs +++ b/platform/darwin/test/MGLStyleLayerTests.m.ejs @@ -13,13 +13,17 @@ @implementation MGL<%- camelize(type) %>LayerTests ++ (NSString *)layerType { + return @"<%- type %>"; +} + - (void)test<%- camelize(type) %>Layer { <% if (type === 'background') { -%> MGL<%- camelize(type) %>StyleLayer *layer = [[MGL<%- camelize(type) %>StyleLayer alloc] initWithIdentifier:@"layerID"]; <% } else { -%> NSString *filePath = [[NSBundle bundleForClass:self.class] pathForResource:@"amsterdam" ofType:@"geojson"]; NSURL *url = [NSURL fileURLWithPath:filePath]; - MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"sourceID" URL:url options:nil]; + MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" URL:url options:nil]; [self.mapView.style addSource:source]; MGL<%- camelize(type) %>StyleLayer *layer = [[MGL<%- camelize(type) %>StyleLayer alloc] initWithIdentifier:@"layerID" source:source]; <% } -%> @@ -56,4 +60,13 @@ <% } -%> } +- (void)testPropertyNames { +<% for (const property of layoutProperties) { -%> + [self testPropertyName:@"<%- property.getter || property.name %>" isBoolean:<%- property.type === 'boolean' ? 'YES' : 'NO' %>]; +<% } -%> +<% for (const property of paintProperties) { -%> + [self testPropertyName:@"<%- property.getter || property.name %>" isBoolean:<%- property.type === 'boolean' ? 'YES' : 'NO' %>]; +<% } -%> +} + @end diff --git a/platform/darwin/test/MGLStyleTests.mm b/platform/darwin/test/MGLStyleTests.mm index 5231d2dcf..e9ba4a9af 100644 --- a/platform/darwin/test/MGLStyleTests.mm +++ b/platform/darwin/test/MGLStyleTests.mm @@ -1,10 +1,7 @@ #import "MGLMapView.h" #import "MGLStyle_Private.h" -#if TARGET_OS_IPHONE -#import "MGLMapView+MGLCustomStyleLayerAdditions.h" -#endif -#import "MGLGeoJSONSource.h" +#import "MGLShapeSource.h" #import "MGLRasterSource.h" #import "MGLVectorSource.h" @@ -12,6 +9,7 @@ #import "MGLCircleStyleLayer.h" #import "MGLFillStyleLayer.h" #import "MGLLineStyleLayer.h" +#import "MGLOpenGLStyleLayer.h" #import "MGLRasterStyleLayer.h" #import "MGLSymbolStyleLayer.h" @@ -20,6 +18,11 @@ #import #import +#if TARGET_OS_IPHONE + #import +#else + #import +#endif #import @interface MGLStyleTests : XCTestCase @@ -119,29 +122,29 @@ } - (void)testAddingSourcesTwice { - MGLGeoJSONSource *geoJSONSource = [[MGLGeoJSONSource alloc] initWithIdentifier:@"geoJSONSource" features:@[] options:nil]; - [self.style addSource:geoJSONSource]; - XCTAssertThrowsSpecificNamed([self.style addSource:geoJSONSource], NSException, @"MGLRedundantSourceException"); + MGLShapeSource *shapeSource = [[MGLShapeSource alloc] initWithIdentifier:@"shapeSource" shape:nil options:nil]; + [self.style addSource:shapeSource]; + XCTAssertThrowsSpecificNamed([self.style addSource:shapeSource], NSException, @"MGLRedundantSourceException"); - MGLRasterSource *rasterSource = [[MGLRasterSource alloc] initWithIdentifier:@"rasterSource" URL:[NSURL new] tileSize:42]; + MGLRasterSource *rasterSource = [[MGLRasterSource alloc] initWithIdentifier:@"rasterSource" configurationURL:[NSURL URLWithString:@".json"] tileSize:42]; [self.style addSource:rasterSource]; XCTAssertThrowsSpecificNamed([self.style addSource:rasterSource], NSException, @"MGLRedundantSourceException"); - MGLVectorSource *vectorSource = [[MGLVectorSource alloc] initWithIdentifier:@"vectorSource" URL:[NSURL new]]; + MGLVectorSource *vectorSource = [[MGLVectorSource alloc] initWithIdentifier:@"vectorSource" configurationURL:[NSURL URLWithString:@".json"]]; [self.style addSource:vectorSource]; XCTAssertThrowsSpecificNamed([self.style addSource:vectorSource], NSException, @"MGLRedundantSourceException"); } - (void)testAddingSourcesWithDuplicateIdentifiers { - MGLVectorSource *source1 = [[MGLVectorSource alloc] initWithIdentifier:@"my-source" URL:[NSURL URLWithString:@"mapbox://mapbox.mapbox-terrain-v2"]]; - MGLVectorSource *source2 = [[MGLVectorSource alloc] initWithIdentifier:@"my-source" URL:[NSURL URLWithString:@"mapbox://mapbox.mapbox-terrain-v2"]]; + MGLVectorSource *source1 = [[MGLVectorSource alloc] initWithIdentifier:@"my-source" configurationURL:[NSURL URLWithString:@"mapbox://mapbox.mapbox-terrain-v2"]]; + MGLVectorSource *source2 = [[MGLVectorSource alloc] initWithIdentifier:@"my-source" configurationURL:[NSURL URLWithString:@"mapbox://mapbox.mapbox-terrain-v2"]]; [self.style addSource: source1]; - XCTAssertThrowsSpecificNamed([self.style addSource: source2], NSException, @"MGLRedundantSourceIdentiferException"); + XCTAssertThrowsSpecificNamed([self.style addSource: source2], NSException, @"MGLRedundantSourceIdentifierException"); } - (void)testAddingLayersTwice { - MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"geoJSONSource" features:@[] options:nil]; + MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"shapeSource" shape:nil options:nil]; MGLBackgroundStyleLayer *backgroundLayer = [[MGLBackgroundStyleLayer alloc] initWithIdentifier:@"backgroundLayer"]; [self.style addLayer:backgroundLayer]; @@ -170,7 +173,7 @@ - (void)testAddingLayersWithDuplicateIdentifiers { //Just some source - MGLVectorSource *source = [[MGLVectorSource alloc] initWithIdentifier:@"my-source" URL:[NSURL URLWithString:@"mapbox://mapbox.mapbox-terrain-v2"]]; + MGLVectorSource *source = [[MGLVectorSource alloc] initWithIdentifier:@"my-source" configurationURL:[NSURL URLWithString:@"mapbox://mapbox.mapbox-terrain-v2"]]; [self.mapView.style addSource: source]; //Add initial layer @@ -182,14 +185,7 @@ XCTAssertThrowsSpecificNamed([self.mapView.style insertLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source] belowLayer:initial],NSException, @"MGLRedundantLayerIdentifierException"); XCTAssertThrowsSpecificNamed([self.mapView.style insertLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source] aboveLayer:initial], NSException, @"MGLRedundantLayerIdentifierException"); XCTAssertThrowsSpecificNamed([self.mapView.style insertLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source] atIndex:0], NSException, @"MGLRedundantLayerIdentifierException"); - -#if TARGET_OS_IPHONE - //Try to insert a duplicate custom layer - MGLCustomStyleLayerDrawingHandler drawingHandler = ^(CGSize size, CLLocationCoordinate2D centerCoordinate, double zoomLevel, CLLocationDirection direction, CGFloat pitch, CGFloat perspectiveSkew) { - }; - - XCTAssertThrowsSpecific([self.mapView insertCustomStyleLayerWithIdentifier:@"my-layer" preparationHandler:^{} drawingHandler:drawingHandler completionHandler: ^{} belowStyleLayerWithIdentifier:nil], NSException); -#endif + XCTAssertThrowsSpecificNamed([self.mapView.style insertLayer:[[MGLOpenGLStyleLayer alloc] initWithIdentifier:@"my-layer"] atIndex:0], NSException, @"MGLRedundantLayerIdentifierException"); } - (NSString *)stringWithContentsOfStyleHeader { @@ -202,4 +198,23 @@ return styleHeader; } +- (void)testImages { + NSString *imageName = @"TrackingLocationMask"; +#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); + + [self.mapView.style setImage:image forName:imageName]; + MGLImage *styleImage = [self.mapView.style imageForName:imageName]; + + XCTAssertNotNil(styleImage); + XCTAssertEqual(image.size.width, styleImage.size.width); + XCTAssertEqual(image.size.height, styleImage.size.height); +} + @end diff --git a/platform/darwin/test/MGLStyleValueTests.h b/platform/darwin/test/MGLStyleValueTests.h new file mode 100644 index 000000000..a563de39f --- /dev/null +++ b/platform/darwin/test/MGLStyleValueTests.h @@ -0,0 +1,4 @@ +#import + +@interface MGLStyleValueTests : XCTestCase +@end diff --git a/platform/darwin/test/MGLStyleValueTests.m b/platform/darwin/test/MGLStyleValueTests.m new file mode 100644 index 000000000..fe6096584 --- /dev/null +++ b/platform/darwin/test/MGLStyleValueTests.m @@ -0,0 +1,13 @@ +#import +#import + +@interface MGLStyleValueTests : XCTestCase +@end + +@implementation MGLStyleValueTests + +- (void)testStoplessFunction { + XCTAssertThrowsSpecificNamed([MGLStyleValue valueWithStops:@{}], NSException, NSInvalidArgumentException, @"Stopless function should raise an exception"); +} + +@end diff --git a/platform/darwin/test/MGLStyleValueTests.swift b/platform/darwin/test/MGLStyleValueTests.swift index f7bf34385..bf0143511 100644 --- a/platform/darwin/test/MGLStyleValueTests.swift +++ b/platform/darwin/test/MGLStyleValueTests.swift @@ -1,14 +1,16 @@ import XCTest import Mapbox -class MGLStyleValueTests: XCTestCase { + +extension MGLStyleValueTests { + func testConstantValues() { - let geoJSONSource = MGLGeoJSONSource(identifier: "test", features: [], options: nil) - let symbolStyleLayer = MGLSymbolStyleLayer(identifier: "test", source: geoJSONSource) + let shapeSource = MGLShapeSource(identifier: "test", shape: nil, options: nil) + let symbolStyleLayer = MGLSymbolStyleLayer(identifier: "test", source: shapeSource) // Boolean - symbolStyleLayer.iconAllowOverlap = MGLStyleConstantValue(rawValue: true) - XCTAssertEqual((symbolStyleLayer.iconAllowOverlap as! MGLStyleConstantValue).rawValue, true) + symbolStyleLayer.iconAllowsOverlap = MGLStyleConstantValue(rawValue: true) + XCTAssertEqual((symbolStyleLayer.iconAllowsOverlap as! MGLStyleConstantValue).rawValue, true) // Number symbolStyleLayer.iconHaloWidth = MGLStyleConstantValue(rawValue: 3) @@ -20,8 +22,8 @@ class MGLStyleValueTests: XCTestCase { } func testFunctions() { - let geoJSONSource = MGLGeoJSONSource(identifier: "test", features: [], options: nil) - let symbolStyleLayer = MGLSymbolStyleLayer(identifier: "test", source: geoJSONSource) + let shapeSource = MGLShapeSource(identifier: "test", shape: nil, options: nil) + let symbolStyleLayer = MGLSymbolStyleLayer(identifier: "test", source: shapeSource) // Boolean let stops: [NSNumber: MGLStyleValue] = [ @@ -29,8 +31,8 @@ class MGLStyleValueTests: XCTestCase { 2: MGLStyleValue(rawValue: false), 3: MGLStyleValue(rawValue: true), 4: MGLStyleValue(rawValue: false), - ] - symbolStyleLayer.iconAllowOverlap = MGLStyleFunction(base: 1, stops: stops) - XCTAssertEqual((symbolStyleLayer.iconAllowOverlap as! MGLStyleFunction), MGLStyleFunction(base: 1, stops: stops)) + ] + symbolStyleLayer.iconAllowsOverlap = MGLStyleFunction(base: 1, stops: stops) + XCTAssertEqual((symbolStyleLayer.iconAllowsOverlap as! MGLStyleFunction), MGLStyleFunction(base: 1, stops: stops)) } } diff --git a/platform/darwin/test/MGLSymbolStyleLayerTests.m b/platform/darwin/test/MGLSymbolStyleLayerTests.m index e77c4f6f3..40250a8c7 100644 --- a/platform/darwin/test/MGLSymbolStyleLayerTests.m +++ b/platform/darwin/test/MGLSymbolStyleLayerTests.m @@ -8,45 +8,49 @@ @implementation MGLSymbolLayerTests ++ (NSString *)layerType { + return @"symbol"; +} + - (void)testSymbolLayer { NSString *filePath = [[NSBundle bundleForClass:self.class] pathForResource:@"amsterdam" ofType:@"geojson"]; NSURL *url = [NSURL fileURLWithPath:filePath]; - MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"sourceID" URL:url options:nil]; + MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" URL:url options:nil]; [self.mapView.style addSource:source]; MGLSymbolStyleLayer *layer = [[MGLSymbolStyleLayer alloc] initWithIdentifier:@"layerID" source:source]; [self.mapView.style addLayer:layer]; - layer.iconAllowOverlap = [MGLRuntimeStylingHelper testBool]; - layer.iconIgnorePlacement = [MGLRuntimeStylingHelper testBool]; + layer.iconAllowsOverlap = [MGLRuntimeStylingHelper testBool]; + layer.iconIgnoresPlacement = [MGLRuntimeStylingHelper testBool]; layer.iconImageName = [MGLRuntimeStylingHelper testString]; - layer.iconKeepUpright = [MGLRuntimeStylingHelper testBool]; layer.iconOffset = [MGLRuntimeStylingHelper testOffset]; layer.iconOptional = [MGLRuntimeStylingHelper testBool]; layer.iconPadding = [MGLRuntimeStylingHelper testNumber]; - layer.iconRotate = [MGLRuntimeStylingHelper testNumber]; + layer.iconRotation = [MGLRuntimeStylingHelper testNumber]; layer.iconRotationAlignment = [MGLRuntimeStylingHelper testEnum:MGLIconRotationAlignmentAuto type:@encode(MGLIconRotationAlignment)]; - layer.iconSize = [MGLRuntimeStylingHelper testNumber]; + layer.iconScale = [MGLRuntimeStylingHelper testNumber]; layer.iconTextFit = [MGLRuntimeStylingHelper testEnum:MGLIconTextFitBoth type:@encode(MGLIconTextFit)]; layer.iconTextFitPadding = [MGLRuntimeStylingHelper testPadding]; - layer.symbolAvoidEdges = [MGLRuntimeStylingHelper testBool]; + layer.keepsIconUpright = [MGLRuntimeStylingHelper testBool]; + layer.keepsTextUpright = [MGLRuntimeStylingHelper testBool]; + layer.maximumTextAngle = [MGLRuntimeStylingHelper testNumber]; + layer.maximumTextWidth = [MGLRuntimeStylingHelper testNumber]; + layer.symbolAvoidsEdges = [MGLRuntimeStylingHelper testBool]; layer.symbolPlacement = [MGLRuntimeStylingHelper testEnum:MGLSymbolPlacementLine type:@encode(MGLSymbolPlacement)]; layer.symbolSpacing = [MGLRuntimeStylingHelper testNumber]; - layer.textAllowOverlap = [MGLRuntimeStylingHelper testBool]; + layer.textAllowsOverlap = [MGLRuntimeStylingHelper testBool]; layer.textAnchor = [MGLRuntimeStylingHelper testEnum:MGLTextAnchorBottomRight type:@encode(MGLTextAnchor)]; layer.textField = [MGLRuntimeStylingHelper testString]; layer.textFont = [MGLRuntimeStylingHelper testFont]; - layer.textIgnorePlacement = [MGLRuntimeStylingHelper testBool]; - layer.textJustify = [MGLRuntimeStylingHelper testEnum:MGLTextJustifyRight type:@encode(MGLTextJustify)]; - layer.textKeepUpright = [MGLRuntimeStylingHelper testBool]; + layer.textIgnoresPlacement = [MGLRuntimeStylingHelper testBool]; + layer.textJustification = [MGLRuntimeStylingHelper testEnum:MGLTextJustificationRight type:@encode(MGLTextJustification)]; layer.textLetterSpacing = [MGLRuntimeStylingHelper testNumber]; layer.textLineHeight = [MGLRuntimeStylingHelper testNumber]; - layer.textMaxAngle = [MGLRuntimeStylingHelper testNumber]; - layer.textMaxWidth = [MGLRuntimeStylingHelper testNumber]; layer.textOffset = [MGLRuntimeStylingHelper testOffset]; layer.textOptional = [MGLRuntimeStylingHelper testBool]; layer.textPadding = [MGLRuntimeStylingHelper testNumber]; layer.textPitchAlignment = [MGLRuntimeStylingHelper testEnum:MGLTextPitchAlignmentAuto type:@encode(MGLTextPitchAlignment)]; - layer.textRotate = [MGLRuntimeStylingHelper testNumber]; + layer.textRotation = [MGLRuntimeStylingHelper testNumber]; layer.textRotationAlignment = [MGLRuntimeStylingHelper testEnum:MGLTextRotationAlignmentAuto type:@encode(MGLTextRotationAlignment)]; layer.textSize = [MGLRuntimeStylingHelper testNumber]; layer.textTransform = [MGLRuntimeStylingHelper testEnum:MGLTextTransformLowercase type:@encode(MGLTextTransform)]; @@ -67,43 +71,43 @@ MGLSymbolStyleLayer *gLayer = (MGLSymbolStyleLayer *)[self.mapView.style layerWithIdentifier:@"layerID"]; XCTAssertTrue([gLayer isKindOfClass:[MGLSymbolStyleLayer class]]); - XCTAssertEqualObjects(gLayer.iconAllowOverlap, [MGLRuntimeStylingHelper testBool]); - XCTAssertEqualObjects(gLayer.iconIgnorePlacement, [MGLRuntimeStylingHelper testBool]); + XCTAssertEqualObjects(gLayer.iconAllowsOverlap, [MGLRuntimeStylingHelper testBool]); + XCTAssertEqualObjects(gLayer.iconIgnoresPlacement, [MGLRuntimeStylingHelper testBool]); XCTAssertEqualObjects(gLayer.iconImageName, [MGLRuntimeStylingHelper testString]); - XCTAssertEqualObjects(gLayer.iconKeepUpright, [MGLRuntimeStylingHelper testBool]); XCTAssertEqualObjects(gLayer.iconOffset, [MGLRuntimeStylingHelper testOffset]); XCTAssertEqualObjects(gLayer.iconOptional, [MGLRuntimeStylingHelper testBool]); XCTAssertEqualObjects(gLayer.iconPadding, [MGLRuntimeStylingHelper testNumber]); - XCTAssertEqualObjects(gLayer.iconRotate, [MGLRuntimeStylingHelper testNumber]); + XCTAssertEqualObjects(gLayer.iconRotation, [MGLRuntimeStylingHelper testNumber]); XCTAssert([gLayer.iconRotationAlignment isKindOfClass:[MGLStyleConstantValue class]]); XCTAssertEqualObjects(gLayer.iconRotationAlignment, [MGLRuntimeStylingHelper testEnum:MGLIconRotationAlignmentAuto type:@encode(MGLIconRotationAlignment)]); - XCTAssertEqualObjects(gLayer.iconSize, [MGLRuntimeStylingHelper testNumber]); + XCTAssertEqualObjects(gLayer.iconScale, [MGLRuntimeStylingHelper testNumber]); XCTAssert([gLayer.iconTextFit isKindOfClass:[MGLStyleConstantValue class]]); XCTAssertEqualObjects(gLayer.iconTextFit, [MGLRuntimeStylingHelper testEnum:MGLIconTextFitBoth type:@encode(MGLIconTextFit)]); XCTAssertEqualObjects(gLayer.iconTextFitPadding, [MGLRuntimeStylingHelper testPadding]); - XCTAssertEqualObjects(gLayer.symbolAvoidEdges, [MGLRuntimeStylingHelper testBool]); + XCTAssertEqualObjects(gLayer.keepsIconUpright, [MGLRuntimeStylingHelper testBool]); + XCTAssertEqualObjects(gLayer.keepsTextUpright, [MGLRuntimeStylingHelper testBool]); + XCTAssertEqualObjects(gLayer.maximumTextAngle, [MGLRuntimeStylingHelper testNumber]); + XCTAssertEqualObjects(gLayer.maximumTextWidth, [MGLRuntimeStylingHelper testNumber]); + XCTAssertEqualObjects(gLayer.symbolAvoidsEdges, [MGLRuntimeStylingHelper testBool]); XCTAssert([gLayer.symbolPlacement isKindOfClass:[MGLStyleConstantValue class]]); XCTAssertEqualObjects(gLayer.symbolPlacement, [MGLRuntimeStylingHelper testEnum:MGLSymbolPlacementLine type:@encode(MGLSymbolPlacement)]); XCTAssertEqualObjects(gLayer.symbolSpacing, [MGLRuntimeStylingHelper testNumber]); - XCTAssertEqualObjects(gLayer.textAllowOverlap, [MGLRuntimeStylingHelper testBool]); + XCTAssertEqualObjects(gLayer.textAllowsOverlap, [MGLRuntimeStylingHelper testBool]); XCTAssert([gLayer.textAnchor isKindOfClass:[MGLStyleConstantValue class]]); XCTAssertEqualObjects(gLayer.textAnchor, [MGLRuntimeStylingHelper testEnum:MGLTextAnchorBottomRight type:@encode(MGLTextAnchor)]); XCTAssertEqualObjects(gLayer.textField, [MGLRuntimeStylingHelper testString]); XCTAssertEqualObjects(gLayer.textFont, [MGLRuntimeStylingHelper testFont]); - XCTAssertEqualObjects(gLayer.textIgnorePlacement, [MGLRuntimeStylingHelper testBool]); - XCTAssert([gLayer.textJustify isKindOfClass:[MGLStyleConstantValue class]]); - XCTAssertEqualObjects(gLayer.textJustify, [MGLRuntimeStylingHelper testEnum:MGLTextJustifyRight type:@encode(MGLTextJustify)]); - XCTAssertEqualObjects(gLayer.textKeepUpright, [MGLRuntimeStylingHelper testBool]); + XCTAssertEqualObjects(gLayer.textIgnoresPlacement, [MGLRuntimeStylingHelper testBool]); + XCTAssert([gLayer.textJustification isKindOfClass:[MGLStyleConstantValue class]]); + XCTAssertEqualObjects(gLayer.textJustification, [MGLRuntimeStylingHelper testEnum:MGLTextJustificationRight type:@encode(MGLTextJustification)]); XCTAssertEqualObjects(gLayer.textLetterSpacing, [MGLRuntimeStylingHelper testNumber]); XCTAssertEqualObjects(gLayer.textLineHeight, [MGLRuntimeStylingHelper testNumber]); - XCTAssertEqualObjects(gLayer.textMaxAngle, [MGLRuntimeStylingHelper testNumber]); - XCTAssertEqualObjects(gLayer.textMaxWidth, [MGLRuntimeStylingHelper testNumber]); XCTAssertEqualObjects(gLayer.textOffset, [MGLRuntimeStylingHelper testOffset]); XCTAssertEqualObjects(gLayer.textOptional, [MGLRuntimeStylingHelper testBool]); XCTAssertEqualObjects(gLayer.textPadding, [MGLRuntimeStylingHelper testNumber]); XCTAssert([gLayer.textPitchAlignment isKindOfClass:[MGLStyleConstantValue class]]); XCTAssertEqualObjects(gLayer.textPitchAlignment, [MGLRuntimeStylingHelper testEnum:MGLTextPitchAlignmentAuto type:@encode(MGLTextPitchAlignment)]); - XCTAssertEqualObjects(gLayer.textRotate, [MGLRuntimeStylingHelper testNumber]); + XCTAssertEqualObjects(gLayer.textRotation, [MGLRuntimeStylingHelper testNumber]); XCTAssert([gLayer.textRotationAlignment isKindOfClass:[MGLStyleConstantValue class]]); XCTAssertEqualObjects(gLayer.textRotationAlignment, [MGLRuntimeStylingHelper testEnum:MGLTextRotationAlignmentAuto type:@encode(MGLTextRotationAlignment)]); XCTAssertEqualObjects(gLayer.textSize, [MGLRuntimeStylingHelper testNumber]); @@ -126,37 +130,37 @@ XCTAssert([gLayer.textTranslateAnchor isKindOfClass:[MGLStyleConstantValue class]]); XCTAssertEqualObjects(gLayer.textTranslateAnchor, [MGLRuntimeStylingHelper testEnum:MGLTextTranslateAnchorViewport type:@encode(MGLTextTranslateAnchor)]); - layer.iconAllowOverlap = [MGLRuntimeStylingHelper testBoolFunction]; - layer.iconIgnorePlacement = [MGLRuntimeStylingHelper testBoolFunction]; + layer.iconAllowsOverlap = [MGLRuntimeStylingHelper testBoolFunction]; + layer.iconIgnoresPlacement = [MGLRuntimeStylingHelper testBoolFunction]; layer.iconImageName = [MGLRuntimeStylingHelper testStringFunction]; - layer.iconKeepUpright = [MGLRuntimeStylingHelper testBoolFunction]; layer.iconOffset = [MGLRuntimeStylingHelper testOffsetFunction]; layer.iconOptional = [MGLRuntimeStylingHelper testBoolFunction]; layer.iconPadding = [MGLRuntimeStylingHelper testNumberFunction]; - layer.iconRotate = [MGLRuntimeStylingHelper testNumberFunction]; + layer.iconRotation = [MGLRuntimeStylingHelper testNumberFunction]; layer.iconRotationAlignment = [MGLRuntimeStylingHelper testEnumFunction:MGLIconRotationAlignmentAuto type:@encode(MGLIconRotationAlignment)]; - layer.iconSize = [MGLRuntimeStylingHelper testNumberFunction]; + layer.iconScale = [MGLRuntimeStylingHelper testNumberFunction]; layer.iconTextFit = [MGLRuntimeStylingHelper testEnumFunction:MGLIconTextFitBoth type:@encode(MGLIconTextFit)]; layer.iconTextFitPadding = [MGLRuntimeStylingHelper testPaddingFunction]; - layer.symbolAvoidEdges = [MGLRuntimeStylingHelper testBoolFunction]; + layer.keepsIconUpright = [MGLRuntimeStylingHelper testBoolFunction]; + layer.keepsTextUpright = [MGLRuntimeStylingHelper testBoolFunction]; + layer.maximumTextAngle = [MGLRuntimeStylingHelper testNumberFunction]; + layer.maximumTextWidth = [MGLRuntimeStylingHelper testNumberFunction]; + layer.symbolAvoidsEdges = [MGLRuntimeStylingHelper testBoolFunction]; layer.symbolPlacement = [MGLRuntimeStylingHelper testEnumFunction:MGLSymbolPlacementLine type:@encode(MGLSymbolPlacement)]; layer.symbolSpacing = [MGLRuntimeStylingHelper testNumberFunction]; - layer.textAllowOverlap = [MGLRuntimeStylingHelper testBoolFunction]; + layer.textAllowsOverlap = [MGLRuntimeStylingHelper testBoolFunction]; layer.textAnchor = [MGLRuntimeStylingHelper testEnumFunction:MGLTextAnchorBottomRight type:@encode(MGLTextAnchor)]; layer.textField = [MGLRuntimeStylingHelper testStringFunction]; layer.textFont = [MGLRuntimeStylingHelper testFontFunction]; - layer.textIgnorePlacement = [MGLRuntimeStylingHelper testBoolFunction]; - layer.textJustify = [MGLRuntimeStylingHelper testEnumFunction:MGLTextJustifyRight type:@encode(MGLTextJustify)]; - layer.textKeepUpright = [MGLRuntimeStylingHelper testBoolFunction]; + layer.textIgnoresPlacement = [MGLRuntimeStylingHelper testBoolFunction]; + layer.textJustification = [MGLRuntimeStylingHelper testEnumFunction:MGLTextJustificationRight type:@encode(MGLTextJustification)]; layer.textLetterSpacing = [MGLRuntimeStylingHelper testNumberFunction]; layer.textLineHeight = [MGLRuntimeStylingHelper testNumberFunction]; - layer.textMaxAngle = [MGLRuntimeStylingHelper testNumberFunction]; - layer.textMaxWidth = [MGLRuntimeStylingHelper testNumberFunction]; layer.textOffset = [MGLRuntimeStylingHelper testOffsetFunction]; layer.textOptional = [MGLRuntimeStylingHelper testBoolFunction]; layer.textPadding = [MGLRuntimeStylingHelper testNumberFunction]; layer.textPitchAlignment = [MGLRuntimeStylingHelper testEnumFunction:MGLTextPitchAlignmentAuto type:@encode(MGLTextPitchAlignment)]; - layer.textRotate = [MGLRuntimeStylingHelper testNumberFunction]; + layer.textRotation = [MGLRuntimeStylingHelper testNumberFunction]; layer.textRotationAlignment = [MGLRuntimeStylingHelper testEnumFunction:MGLTextRotationAlignmentAuto type:@encode(MGLTextRotationAlignment)]; layer.textSize = [MGLRuntimeStylingHelper testNumberFunction]; layer.textTransform = [MGLRuntimeStylingHelper testEnumFunction:MGLTextTransformLowercase type:@encode(MGLTextTransform)]; @@ -175,37 +179,37 @@ layer.textTranslate = [MGLRuntimeStylingHelper testOffsetFunction]; layer.textTranslateAnchor = [MGLRuntimeStylingHelper testEnumFunction:MGLTextTranslateAnchorViewport type:@encode(MGLTextTranslateAnchor)]; - XCTAssertEqualObjects(gLayer.iconAllowOverlap, [MGLRuntimeStylingHelper testBoolFunction]); - XCTAssertEqualObjects(gLayer.iconIgnorePlacement, [MGLRuntimeStylingHelper testBoolFunction]); + XCTAssertEqualObjects(gLayer.iconAllowsOverlap, [MGLRuntimeStylingHelper testBoolFunction]); + XCTAssertEqualObjects(gLayer.iconIgnoresPlacement, [MGLRuntimeStylingHelper testBoolFunction]); XCTAssertEqualObjects(gLayer.iconImageName, [MGLRuntimeStylingHelper testStringFunction]); - XCTAssertEqualObjects(gLayer.iconKeepUpright, [MGLRuntimeStylingHelper testBoolFunction]); XCTAssertEqualObjects(gLayer.iconOffset, [MGLRuntimeStylingHelper testOffsetFunction]); XCTAssertEqualObjects(gLayer.iconOptional, [MGLRuntimeStylingHelper testBoolFunction]); XCTAssertEqualObjects(gLayer.iconPadding, [MGLRuntimeStylingHelper testNumberFunction]); - XCTAssertEqualObjects(gLayer.iconRotate, [MGLRuntimeStylingHelper testNumberFunction]); + XCTAssertEqualObjects(gLayer.iconRotation, [MGLRuntimeStylingHelper testNumberFunction]); XCTAssertEqualObjects(gLayer.iconRotationAlignment, [MGLRuntimeStylingHelper testEnumFunction:MGLIconRotationAlignmentAuto type:@encode(MGLIconRotationAlignment)]); - XCTAssertEqualObjects(gLayer.iconSize, [MGLRuntimeStylingHelper testNumberFunction]); + XCTAssertEqualObjects(gLayer.iconScale, [MGLRuntimeStylingHelper testNumberFunction]); XCTAssertEqualObjects(gLayer.iconTextFit, [MGLRuntimeStylingHelper testEnumFunction:MGLIconTextFitBoth type:@encode(MGLIconTextFit)]); XCTAssertEqualObjects(gLayer.iconTextFitPadding, [MGLRuntimeStylingHelper testPaddingFunction]); - XCTAssertEqualObjects(gLayer.symbolAvoidEdges, [MGLRuntimeStylingHelper testBoolFunction]); + XCTAssertEqualObjects(gLayer.keepsIconUpright, [MGLRuntimeStylingHelper testBoolFunction]); + XCTAssertEqualObjects(gLayer.keepsTextUpright, [MGLRuntimeStylingHelper testBoolFunction]); + XCTAssertEqualObjects(gLayer.maximumTextAngle, [MGLRuntimeStylingHelper testNumberFunction]); + XCTAssertEqualObjects(gLayer.maximumTextWidth, [MGLRuntimeStylingHelper testNumberFunction]); + XCTAssertEqualObjects(gLayer.symbolAvoidsEdges, [MGLRuntimeStylingHelper testBoolFunction]); XCTAssertEqualObjects(gLayer.symbolPlacement, [MGLRuntimeStylingHelper testEnumFunction:MGLSymbolPlacementLine type:@encode(MGLSymbolPlacement)]); XCTAssertEqualObjects(gLayer.symbolSpacing, [MGLRuntimeStylingHelper testNumberFunction]); - XCTAssertEqualObjects(gLayer.textAllowOverlap, [MGLRuntimeStylingHelper testBoolFunction]); + XCTAssertEqualObjects(gLayer.textAllowsOverlap, [MGLRuntimeStylingHelper testBoolFunction]); XCTAssertEqualObjects(gLayer.textAnchor, [MGLRuntimeStylingHelper testEnumFunction:MGLTextAnchorBottomRight type:@encode(MGLTextAnchor)]); XCTAssertEqualObjects(gLayer.textField, [MGLRuntimeStylingHelper testStringFunction]); XCTAssertEqualObjects(gLayer.textFont, [MGLRuntimeStylingHelper testFontFunction]); - XCTAssertEqualObjects(gLayer.textIgnorePlacement, [MGLRuntimeStylingHelper testBoolFunction]); - XCTAssertEqualObjects(gLayer.textJustify, [MGLRuntimeStylingHelper testEnumFunction:MGLTextJustifyRight type:@encode(MGLTextJustify)]); - XCTAssertEqualObjects(gLayer.textKeepUpright, [MGLRuntimeStylingHelper testBoolFunction]); + XCTAssertEqualObjects(gLayer.textIgnoresPlacement, [MGLRuntimeStylingHelper testBoolFunction]); + XCTAssertEqualObjects(gLayer.textJustification, [MGLRuntimeStylingHelper testEnumFunction:MGLTextJustificationRight type:@encode(MGLTextJustification)]); XCTAssertEqualObjects(gLayer.textLetterSpacing, [MGLRuntimeStylingHelper testNumberFunction]); XCTAssertEqualObjects(gLayer.textLineHeight, [MGLRuntimeStylingHelper testNumberFunction]); - XCTAssertEqualObjects(gLayer.textMaxAngle, [MGLRuntimeStylingHelper testNumberFunction]); - XCTAssertEqualObjects(gLayer.textMaxWidth, [MGLRuntimeStylingHelper testNumberFunction]); XCTAssertEqualObjects(gLayer.textOffset, [MGLRuntimeStylingHelper testOffsetFunction]); XCTAssertEqualObjects(gLayer.textOptional, [MGLRuntimeStylingHelper testBoolFunction]); XCTAssertEqualObjects(gLayer.textPadding, [MGLRuntimeStylingHelper testNumberFunction]); XCTAssertEqualObjects(gLayer.textPitchAlignment, [MGLRuntimeStylingHelper testEnumFunction:MGLTextPitchAlignmentAuto type:@encode(MGLTextPitchAlignment)]); - XCTAssertEqualObjects(gLayer.textRotate, [MGLRuntimeStylingHelper testNumberFunction]); + XCTAssertEqualObjects(gLayer.textRotation, [MGLRuntimeStylingHelper testNumberFunction]); XCTAssertEqualObjects(gLayer.textRotationAlignment, [MGLRuntimeStylingHelper testEnumFunction:MGLTextRotationAlignmentAuto type:@encode(MGLTextRotationAlignment)]); XCTAssertEqualObjects(gLayer.textSize, [MGLRuntimeStylingHelper testNumberFunction]); XCTAssertEqualObjects(gLayer.textTransform, [MGLRuntimeStylingHelper testEnumFunction:MGLTextTransformLowercase type:@encode(MGLTextTransform)]); @@ -225,4 +229,55 @@ XCTAssertEqualObjects(gLayer.textTranslateAnchor, [MGLRuntimeStylingHelper testEnumFunction:MGLTextTranslateAnchorViewport type:@encode(MGLTextTranslateAnchor)]); } +- (void)testPropertyNames { + [self testPropertyName:@"icon-allows-overlap" isBoolean:YES]; + [self testPropertyName:@"icon-ignores-placement" isBoolean:YES]; + [self testPropertyName:@"icon-image-name" isBoolean:NO]; + [self testPropertyName:@"icon-offset" isBoolean:NO]; + [self testPropertyName:@"is-icon-optional" isBoolean:YES]; + [self testPropertyName:@"icon-padding" isBoolean:NO]; + [self testPropertyName:@"icon-rotation" isBoolean:NO]; + [self testPropertyName:@"icon-rotation-alignment" isBoolean:NO]; + [self testPropertyName:@"icon-scale" isBoolean:NO]; + [self testPropertyName:@"icon-text-fit" isBoolean:NO]; + [self testPropertyName:@"icon-text-fit-padding" isBoolean:NO]; + [self testPropertyName:@"keeps-icon-upright" isBoolean:YES]; + [self testPropertyName:@"keeps-text-upright" isBoolean:YES]; + [self testPropertyName:@"maximum-text-angle" isBoolean:NO]; + [self testPropertyName:@"maximum-text-width" isBoolean:NO]; + [self testPropertyName:@"symbol-avoids-edges" isBoolean:YES]; + [self testPropertyName:@"symbol-placement" isBoolean:NO]; + [self testPropertyName:@"symbol-spacing" isBoolean:NO]; + [self testPropertyName:@"text-allows-overlap" isBoolean:YES]; + [self testPropertyName:@"text-anchor" isBoolean:NO]; + [self testPropertyName:@"text-field" isBoolean:NO]; + [self testPropertyName:@"text-font" isBoolean:NO]; + [self testPropertyName:@"text-ignores-placement" isBoolean:YES]; + [self testPropertyName:@"text-justification" isBoolean:NO]; + [self testPropertyName:@"text-letter-spacing" isBoolean:NO]; + [self testPropertyName:@"text-line-height" isBoolean:NO]; + [self testPropertyName:@"text-offset" isBoolean:NO]; + [self testPropertyName:@"is-text-optional" isBoolean:YES]; + [self testPropertyName:@"text-padding" isBoolean:NO]; + [self testPropertyName:@"text-pitch-alignment" isBoolean:NO]; + [self testPropertyName:@"text-rotation" isBoolean:NO]; + [self testPropertyName:@"text-rotation-alignment" isBoolean:NO]; + [self testPropertyName:@"text-size" isBoolean:NO]; + [self testPropertyName:@"text-transform" isBoolean:NO]; + [self testPropertyName:@"icon-color" isBoolean:NO]; + [self testPropertyName:@"icon-halo-blur" isBoolean:NO]; + [self testPropertyName:@"icon-halo-color" isBoolean:NO]; + [self testPropertyName:@"icon-halo-width" isBoolean:NO]; + [self testPropertyName:@"icon-opacity" isBoolean:NO]; + [self testPropertyName:@"icon-translate" isBoolean:NO]; + [self testPropertyName:@"icon-translate-anchor" isBoolean:NO]; + [self testPropertyName:@"text-color" isBoolean:NO]; + [self testPropertyName:@"text-halo-blur" isBoolean:NO]; + [self testPropertyName:@"text-halo-color" isBoolean:NO]; + [self testPropertyName:@"text-halo-width" isBoolean:NO]; + [self testPropertyName:@"text-opacity" isBoolean:NO]; + [self testPropertyName:@"text-translate" isBoolean:NO]; + [self testPropertyName:@"text-translate-anchor" isBoolean:NO]; +} + @end diff --git a/platform/darwin/test/MGLTileSetTests.mm b/platform/darwin/test/MGLTileSetTests.mm index d77046928..06901a0e9 100644 --- a/platform/darwin/test/MGLTileSetTests.mm +++ b/platform/darwin/test/MGLTileSetTests.mm @@ -1,7 +1,7 @@ #import #import -#import "MGLTileSet_Private.h" +#import "MGLTileSource_Private.h" #include @@ -11,72 +11,91 @@ @implementation MGLTileSetTests -- (void)testTileSet { +- (void)testTileSetFromTileURLTemplates { // a tile set that provides an mbgl tile set - MGLTileSet *tileSet = [[MGLTileSet alloc] initWithTileURLTemplates:@[@"tile.1", - @"tile.2", - @"tile.3"]]; - mbgl::Tileset mbglTileset = [tileSet mbglTileset]; + NSArray *tileURLTemplates = @[@"tile.1", @"tile.2", @"tile.3"]; + mbgl::Tileset tileSet = MGLTileSetFromTileURLTemplates(tileURLTemplates, nil); // has the correct URL templates - XCTAssertEqual(mbglTileset.tiles.size(), 3); - XCTAssertEqual(mbglTileset.tiles[0], "tile.1"); - XCTAssertEqual(mbglTileset.tiles[1], "tile.2"); - XCTAssertEqual(mbglTileset.tiles[2], "tile.3"); + XCTAssertEqual(tileSet.tiles.size(), 3); + XCTAssertEqual(tileSet.tiles[0], "tile.1"); + XCTAssertEqual(tileSet.tiles[1], "tile.2"); + XCTAssertEqual(tileSet.tiles[2], "tile.3"); // has the default scheme - XCTAssertEqual(mbglTileset.scheme, mbgl::Tileset::Scheme::XYZ); + XCTAssertEqual(tileSet.scheme, mbgl::Tileset::Scheme::XYZ); // when the tile set has no min or max zoom level set - tileSet.minimumZoomLevel = nil; - tileSet.maximumZoomLevel = nil; - // the mbgl object has default values for min and max zoom level - XCTAssertEqual([tileSet mbglTileset].zoomRange.min, 0); - XCTAssertEqual([tileSet mbglTileset].zoomRange.max, 22); + XCTAssertEqual(tileSet.zoomRange.min, 0); + XCTAssertEqual(tileSet.zoomRange.max, 22); // when the tile set has min and/or max zoom level set - tileSet.minimumZoomLevel = @(1); - tileSet.maximumZoomLevel = @(2); + tileSet = MGLTileSetFromTileURLTemplates(@[@"tile.1"], @{ + MGLTileSourceOptionMinimumZoomLevel: @1, + MGLTileSourceOptionMaximumZoomLevel: @2, + }); // the mbgl object reflects the set values for min and max zoom level - XCTAssertEqual([tileSet mbglTileset].zoomRange.min, 1); - XCTAssertEqual([tileSet mbglTileset].zoomRange.max, 2); + XCTAssertEqual(tileSet.zoomRange.min, 1); + XCTAssertEqual(tileSet.zoomRange.max, 2); // when the tile set has an attribution - tileSet.attribution = @"my tileset © ©️🎈"; + NSString *attribution = @"my tileset © ©️🎈"; + tileSet = MGLTileSetFromTileURLTemplates(tileURLTemplates, @{ + MGLTileSourceOptionAttributionHTMLString: attribution, + }); // the attribution is reflected by the mbgl tileset - XCTAssertEqual([tileSet mbglTileset].attribution, tileSet.attribution.UTF8String); + XCTAssertEqual(tileSet.attribution, attribution.UTF8String); - // when the scheme is changed - tileSet.scheme = MGLTileSetSchemeTMS; + // when the tile set has attribution infos + MGLAttributionInfo *mapboxInfo = [[MGLAttributionInfo alloc] initWithTitle:[[NSAttributedString alloc] initWithString:@"Mapbox"] + URL:[NSURL URLWithString:@"https://www.mapbox.com/"]]; + NSAttributedString *gl = [[NSAttributedString alloc] initWithString:@"GL" attributes:@{ + NSBackgroundColorAttributeName: [MGLColor redColor], + }]; + MGLAttributionInfo *glInfo = [[MGLAttributionInfo alloc] initWithTitle:gl URL:nil]; + tileSet = MGLTileSetFromTileURLTemplates(tileURLTemplates, @{ + MGLTileSourceOptionAttributionInfos: @[mapboxInfo, glInfo], + }); + + // the attribution is reflected by the mbgl tileset +#if TARGET_OS_IPHONE + NSString *html = (@"" + @"Mapbox " + @"GL\n"); +#else + NSString *html = (@"" + @"Mapbox " + @"GL\n"); +#endif + XCTAssertEqualObjects(@(tileSet.attribution.c_str()), html); + + // when the tile coordinate system is changed using an NSNumber + tileSet = MGLTileSetFromTileURLTemplates(tileURLTemplates, @{ + MGLTileSourceOptionTileCoordinateSystem: @(MGLTileCoordinateSystemTMS), + }); // the scheme is reflected by the mbgl tileset - XCTAssertEqual([tileSet mbglTileset].scheme , mbgl::Tileset::Scheme::TMS); + XCTAssertEqual(tileSet.scheme, mbgl::Tileset::Scheme::TMS); - // a tile set that provides an mbgl tile set and minimum and maximum zoom levels - tileSet = [[MGLTileSet alloc] initWithTileURLTemplates:@[@"tile.1"] minimumZoomLevel:15 maximumZoomLevel:20]; + // when the tile coordinate system is changed using an NSValue + MGLTileCoordinateSystem tms = MGLTileCoordinateSystemTMS; + tileSet = MGLTileSetFromTileURLTemplates(tileURLTemplates, @{ + MGLTileSourceOptionTileCoordinateSystem: [NSValue value:&tms withObjCType:@encode(MGLTileCoordinateSystem)], + }); - // the zoom levels are reflected by the mbgl tileset - XCTAssertEqual([tileSet mbglTileset].zoomRange.min, 15); - XCTAssertEqual([tileSet mbglTileset].zoomRange.max, 20); + // the scheme is reflected by the mbgl tileset + XCTAssertEqual(tileSet.scheme, mbgl::Tileset::Scheme::TMS); } - (void)testInvalidTileSet { // a tile set that provides an mbgl tile set and invalid (crossed) minimum and maximum zoom levels throws an exception - XCTAssertThrowsSpecificNamed([[MGLTileSet alloc] initWithTileURLTemplates:@[@"tile.1"] minimumZoomLevel:10 maximumZoomLevel:9], NSException, @"Invalid minimumZoomLevel"); - - // a tile set that provides an mbgl tile set - MGLTileSet *tileSet = [[MGLTileSet alloc] initWithTileURLTemplates:@[@"tile.1"]]; - tileSet.maximumZoomLevel = @(10); - - // when the minimum zoom level is set higher than the maximum zoom level - XCTAssertThrowsSpecificNamed(tileSet.minimumZoomLevel = @(11), NSException, @"Invalid minimumZoomLevel"); - - // when the maximum zoom level is set lower than the minimum zoom level - tileSet.minimumZoomLevel = @(5); - XCTAssertThrowsSpecificNamed(tileSet.maximumZoomLevel = @(4), NSException, @"Invalid minimumZoomLevel"); + XCTAssertThrowsSpecificNamed(MGLTileSetFromTileURLTemplates(@[@"tile.1"], @{ + MGLTileSourceOptionMinimumZoomLevel: @10, + MGLTileSourceOptionMaximumZoomLevel: @9, + }), NSException, NSInvalidArgumentException); } @end diff --git a/platform/darwin/test/Media.xcassets/Contents.json b/platform/darwin/test/Media.xcassets/Contents.json new file mode 100644 index 000000000..da4a164c9 --- /dev/null +++ b/platform/darwin/test/Media.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/platform/darwin/test/Media.xcassets/TrackingLocationMask.imageset/Contents.json b/platform/darwin/test/Media.xcassets/TrackingLocationMask.imageset/Contents.json new file mode 100644 index 000000000..08cd551fc --- /dev/null +++ b/platform/darwin/test/Media.xcassets/TrackingLocationMask.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "TrackingLocationMask.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "TrackingLocationMask@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "TrackingLocationMask@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "template-rendering-intent" : "template" + } +} \ No newline at end of file diff --git a/platform/darwin/test/Media.xcassets/TrackingLocationMask.imageset/TrackingLocationMask.png b/platform/darwin/test/Media.xcassets/TrackingLocationMask.imageset/TrackingLocationMask.png new file mode 100644 index 000000000..bb7348c48 Binary files /dev/null and b/platform/darwin/test/Media.xcassets/TrackingLocationMask.imageset/TrackingLocationMask.png differ diff --git a/platform/darwin/test/Media.xcassets/TrackingLocationMask.imageset/TrackingLocationMask@2x.png b/platform/darwin/test/Media.xcassets/TrackingLocationMask.imageset/TrackingLocationMask@2x.png new file mode 100644 index 000000000..35c5a293e Binary files /dev/null and b/platform/darwin/test/Media.xcassets/TrackingLocationMask.imageset/TrackingLocationMask@2x.png differ diff --git a/platform/darwin/test/Media.xcassets/TrackingLocationMask.imageset/TrackingLocationMask@3x.png b/platform/darwin/test/Media.xcassets/TrackingLocationMask.imageset/TrackingLocationMask@3x.png new file mode 100644 index 000000000..af523975a Binary files /dev/null and b/platform/darwin/test/Media.xcassets/TrackingLocationMask.imageset/TrackingLocationMask@3x.png differ diff --git a/platform/darwin/test/test-Bridging-Header.h b/platform/darwin/test/test-Bridging-Header.h index e11d920b1..5d23e9d6c 100644 --- a/platform/darwin/test/test-Bridging-Header.h +++ b/platform/darwin/test/test-Bridging-Header.h @@ -1,3 +1,4 @@ // // Use this file to import your target's public headers that you would like to expose to Swift. // +#import "MGLStyleValueTests.h" diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index c43a5f24a..9105afce6 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -21,7 +21,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT * A new runtime styling API allows you to adjust the style and content of the base map dynamically. All the options available in [Mapbox Studio](https://www.mapbox.com/studio/) are now exposed via MGLStyle and subclasses of MGLStyleLayer and MGLSource. ([#5727](https://github.com/mapbox/mapbox-gl-native/pull/5727)) * MGLMapView’s `styleURL` property can now be set to an absolute file URL. ([#6026](https://github.com/mapbox/mapbox-gl-native/pull/6026)) -* GeoJSON sources specified by the stylesheet at design time now support `cluster`, `clusterMaxZoom`, and `clusterRadius` attributes for clustering point features on the base map. ([#5724](https://github.com/mapbox/mapbox-gl-native/pull/5724)) +* MGLShapeSource objects, as well as GeoJSON sources specified by the stylesheet at design time, now support `cluster`, `clusterMaxZoom`, and `clusterRadius` attributes for clustering point features on the base map. ([#5724](https://github.com/mapbox/mapbox-gl-native/pull/5724)) * Added [quadkey](https://msdn.microsoft.com/en-us/library/bb259689.aspx) support and limited WMS support in raster tile URL templates. ([#5628](https://github.com/mapbox/mapbox-gl-native/pull/5628)) * TileJSON manifests can now specify `"scheme": "tms"` to indicate the use of [TMS](https://en.wikipedia.org/wiki/Tile_Map_Service) coordinates. ([#2270](https://github.com/mapbox/mapbox-gl-native/pull/2270)) * Fixed an issue causing abstract MGLMultiPointFeature objects to be returned in feature query results. Now concrete MGLPointCollectionFeature objects are returned. ([#6742](https://github.com/mapbox/mapbox-gl-native/pull/6742)) @@ -29,6 +29,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT * `-[MGLMapView resetPosition]` now resets to the current style’s default center coordinates, zoom level, direction, and pitch, if specified. ([#6127](https://github.com/mapbox/mapbox-gl-native/pull/6127)) * Fixed an issue where feature querying sometimes failed to return the expected features when the map was tilted. ([#6773](https://github.com/mapbox/mapbox-gl-native/pull/6773)) * MGLFeature’s `attributes` and `identifier` properties are now writable. ([#6728](https://github.com/mapbox/mapbox-gl-native/pull/6728)) +* The action sheet that appears when tapping the information button in the bottom-right corner now lists the correct attribution for the current style. ([#5999](https://github.com/mapbox/mapbox-gl-native/pull/5999)) * The `text-pitch-alignment` property is now supported in stylesheets for improved street label legibility on a tilted map. ([#5288](https://github.com/mapbox/mapbox-gl-native/pull/5288)) * The `icon-text-fit` and `icon-text-fit-padding` properties are now supported in stylesheets, allowing the background of a shield to automatically resize to fit the shield’s text. ([#5334](https://github.com/mapbox/mapbox-gl-native/pull/5334)) * The `circle-pitch-scale` property is now supported in stylesheets, allowing circle features in a tilted base map to scale or remain the same size as the viewing distance changes. ([#5576](https://github.com/mapbox/mapbox-gl-native/pull/5576)) @@ -53,12 +54,13 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT ### Annotations -* Added new methods to MGLMultiPoint for changing or appending vertices along polyline annotations and the exteriors of polygon annotations. ([#6565](https://github.com/mapbox/mapbox-gl-native/pull/6565)) +* Added new methods to MGLMultiPoint for changing the vertices along a polyline annotation or the exterior of a polygon annotation. ([#6565](https://github.com/mapbox/mapbox-gl-native/pull/6565)) * Added new APIs to MGLMapView to query for visible annotations. Combined with `-[MGLMapView viewForAnnotation:]`, these APIs can be used to access all visible annotation views. ([6061](https://github.com/mapbox/mapbox-gl-native/pull/6061)) * Fixed an issue causing offscreen annotation views to be updated even when they were in the reuse queue. ([#5987](https://github.com/mapbox/mapbox-gl-native/pull/5987)) * Fixed an issue preventing MGLAnnotationView from animating when its coordinate changes. ([#6215](https://github.com/mapbox/mapbox-gl-native/pull/6215)) * Fixed an issue causing the wrong annotation view to be selected when tapping an annotation view with a center offset applied. ([#5931](https://github.com/mapbox/mapbox-gl-native/pull/5931)) * Fixed an issue that assigned annotation views to polyline and polygon annotations. ([#5770](https://github.com/mapbox/mapbox-gl-native/pull/5770)) +* Fixed an issue causing the callout view to be dismissed when panning around. ([#6676](https://github.com/mapbox/mapbox-gl-native/pull/6676)) * Per documentation, the first and last coordinates in an MGLPolygon must be identical in order for the polygon to draw correctly. The same is true for an MGLPolygon’s interior polygon. ([#5514](https://github.com/mapbox/mapbox-gl-native/pull/5514)) * To make an MGLPolyline or MGLPolygon span the antimeridian, specify coordinates with longitudes greater than 180° or less than −180°. ([#6088](https://github.com/mapbox/mapbox-gl-native/pull/6088)) * Deprecated `-[MGLMapViewDelegate mapView:alphaForShapeAnnotation:]` in favor of specifying an alpha component via `-[MGLMapViewDelegate mapView:strokeColorForShapeAnnotation:]` or `-[MGLMapViewDelegate mapView:fillColorForPolygonAnnotation:]`. ([#6706](https://github.com/mapbox/mapbox-gl-native/pull/6706)) @@ -88,6 +90,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT * MGLMapDebugOverdrawVisualizationMask no longer has any effect in Release builds of the SDK. This debug mask has been disabled for performance reasons. ([#5555](https://github.com/mapbox/mapbox-gl-native/pull/5555)) * Fixed a typo in the documentation for the MGLCompassDirectionFormatter class. ([#5879](https://github.com/mapbox/mapbox-gl-native/pull/5879)) * The UITapGestureRecognizer on MGLMapView that is used for selecting annotations now fails if a tap does not select an annotation. ([#7246](https://github.com/mapbox/mapbox-gl-native/pull/7246)) +* Fixed issues related to the visibility of sources in viewports less than 512 pixels wide or tall. ([#7438](https://github.com/mapbox/mapbox-gl-native/pull/7438)) ## 3.3.7 - November 17, 2016 diff --git a/platform/ios/Mapbox-iOS-SDK-symbols.podspec b/platform/ios/Mapbox-iOS-SDK-symbols.podspec index 3ec0fb387..2cf3695af 100644 --- a/platform/ios/Mapbox-iOS-SDK-symbols.podspec +++ b/platform/ios/Mapbox-iOS-SDK-symbols.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |m| m.name = 'Mapbox-iOS-SDK' - m.version = '3.4.0-beta.4-symbols' + m.version = '3.4.0-beta.5-symbols' m.summary = 'Open source vector map solution for iOS with full styling capabilities.' m.description = 'Open source, OpenGL-based vector map solution for iOS with full styling capabilities and Cocoa Touch APIs.' diff --git a/platform/ios/Mapbox-iOS-SDK.podspec b/platform/ios/Mapbox-iOS-SDK.podspec index be6322187..8bc963f91 100644 --- a/platform/ios/Mapbox-iOS-SDK.podspec +++ b/platform/ios/Mapbox-iOS-SDK.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |m| m.name = 'Mapbox-iOS-SDK' - m.version = '3.4.0-beta.4' + m.version = '3.4.0-beta.5' m.summary = 'Open source vector map solution for iOS with full styling capabilities.' m.description = 'Open source, OpenGL-based vector map solution for iOS with full styling capabilities and Cocoa Touch APIs.' diff --git a/platform/ios/app/Assets.xcassets/AppIcon.appiconset/Contents.json b/platform/ios/app/Assets.xcassets/AppIcon.appiconset/Contents.json index c1b88669e..e1bc22272 100644 --- a/platform/ios/app/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/platform/ios/app/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,5 +1,15 @@ { "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, { "size" : "29x29", "idiom" : "iphone", @@ -36,6 +46,16 @@ "filename" : "Icon-60@3x.png", "scale" : "3x" }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, { "size" : "29x29", "idiom" : "ipad", diff --git a/platform/ios/app/MBXViewController.m b/platform/ios/app/MBXViewController.m index 8a2ccee41..05c2f9169 100644 --- a/platform/ios/app/MBXViewController.m +++ b/platform/ios/app/MBXViewController.m @@ -54,7 +54,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsRuntimeStylingRows) { MBXSettingsRuntimeStylingWater = 0, MBXSettingsRuntimeStylingRoads, MBXSettingsRuntimeStylingRaster, - MBXSettingsRuntimeStylingGeoJSON, + MBXSettingsRuntimeStylingShape, MBXSettingsRuntimeStylingSymbols, MBXSettingsRuntimeStylingBuildings, MBXSettingsRuntimeStylingFerry, @@ -65,9 +65,9 @@ typedef NS_ENUM(NSInteger, MBXSettingsRuntimeStylingRows) { MBXSettingsRuntimeStylingStyleQuery, MBXSettingsRuntimeStylingFeatureSource, MBXSettingsRuntimeStylingPointCollection, - MBXSettingsRuntimeStylingUpdateGeoJSONSourceData, - MBXSettingsRuntimeStylingUpdateGeoJSONSourceURL, - MBXSettingsRuntimeStylingUpdateGeoJSONSourceFeatures, + MBXSettingsRuntimeStylingUpdateShapeSourceData, + MBXSettingsRuntimeStylingUpdateShapeSourceURL, + MBXSettingsRuntimeStylingUpdateShapeSourceFeatures, MBXSettingsRuntimeStylingVectorSource, MBXSettingsRuntimeStylingRasterSource, MBXSettingsRuntimeStylingCountryLabels, @@ -316,7 +316,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { @"Style Water With Function", @"Style Roads With Function", @"Add Raster & Apply Function", - @"Add GeoJSON & Apply Fill", + @"Add Shapes & Apply Fill", @"Style Symbol Color", @"Style Building Fill Color", @"Style Ferry Line Color", @@ -324,12 +324,12 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { @"Style Fill With Filter", @"Style Lines With Filter", @"Style Fill With Numeric Filter", - @"Style Query For GeoJSON", + @"Query and Style Features", @"Style Feature", @"Style Dynamic Point Collection", - @"Update GeoJSON Source: Data", - @"Update GeoJSON Source: URL", - @"Update GeoJSON Source: Features", + @"Update Shape Source: Data", + @"Update Shape Source: URL", + @"Update Shape Source: Features", @"Style Vector Source", @"Style Raster Source", [NSString stringWithFormat:@"Label Countries in %@", (_usingLocaleBasedCountryLabels ? @"Local Language" : [[NSLocale currentLocale] displayNameForKey:NSLocaleIdentifier value:[self bestLanguageForUser]])], @@ -441,8 +441,8 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { case MBXSettingsRuntimeStylingRaster: [self styleRasterLayer]; break; - case MBXSettingsRuntimeStylingGeoJSON: - [self styleGeoJSONSource]; + case MBXSettingsRuntimeStylingShape: + [self styleShapeSource]; break; case MBXSettingsRuntimeStylingSymbols: [self styleSymbolLayer]; @@ -474,14 +474,14 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { case MBXSettingsRuntimeStylingPointCollection: [self styleDynamicPointCollection]; break; - case MBXSettingsRuntimeStylingUpdateGeoJSONSourceURL: - [self updateGeoJSONSourceURL]; + case MBXSettingsRuntimeStylingUpdateShapeSourceURL: + [self updateShapeSourceURL]; break; - case MBXSettingsRuntimeStylingUpdateGeoJSONSourceData: - [self updateGeoJSONSourceData]; + case MBXSettingsRuntimeStylingUpdateShapeSourceData: + [self updateShapeSourceData]; break; - case MBXSettingsRuntimeStylingUpdateGeoJSONSourceFeatures: - [self updateGeoJSONSourceFeatures]; + case MBXSettingsRuntimeStylingUpdateShapeSourceFeatures: + [self updateShapeSourceFeatures]; break; case MBXSettingsRuntimeStylingVectorSource: [self styleVectorSource]; @@ -719,21 +719,26 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { }]; waterLayer.fillColor = waterColorFunction; - MGLStyleValue *fillAntialias = [MGLStyleValue valueWithStops:@{ + MGLStyleValue *fillAntialiasedFunction = [MGLStyleValue valueWithStops:@{ @11: [MGLStyleValue valueWithRawValue:@YES], @12: [MGLStyleValue valueWithRawValue:@NO], @13: [MGLStyleValue valueWithRawValue:@YES], @14: [MGLStyleValue valueWithRawValue:@NO], @15: [MGLStyleValue valueWithRawValue:@YES], }]; - waterLayer.fillAntialias = fillAntialias; + waterLayer.fillAntialiased = fillAntialiasedFunction; } - (void)styleRoadLayer { MGLLineStyleLayer *roadLayer = (MGLLineStyleLayer *)[self.mapView.style layerWithIdentifier:@"road-primary"]; roadLayer.lineColor = [MGLStyleValue valueWithRawValue:[UIColor blackColor]]; - MGLStyleValue *lineWidthFunction = [MGLStyleValue valueWithStops:@{}]; + + MGLStyleValue *lineWidthFunction = [MGLStyleValue valueWithStops:@{ + @5: [MGLStyleValue valueWithRawValue:@5], + @10: [MGLStyleValue valueWithRawValue:@15], + @15: [MGLStyleValue valueWithRawValue:@30], + }]; MGLStyleValue *roadLineColor = [MGLStyleValue valueWithStops:@{ @10: [MGLStyleValue valueWithRawValue:[UIColor purpleColor]], @@ -752,7 +757,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { - (void)styleRasterLayer { NSURL *rasterURL = [NSURL URLWithString:@"mapbox://mapbox.satellite"]; - MGLRasterSource *rasterSource = [[MGLRasterSource alloc] initWithIdentifier:@"my-raster-source" URL:rasterURL tileSize:512]; + MGLRasterSource *rasterSource = [[MGLRasterSource alloc] initWithIdentifier:@"my-raster-source" configurationURL:rasterURL tileSize:512]; [self.mapView.style addSource:rasterSource]; MGLRasterStyleLayer *rasterLayer = [[MGLRasterStyleLayer alloc] initWithIdentifier:@"my-raster-layer" source:rasterSource]; @@ -764,11 +769,11 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { [self.mapView.style addLayer:rasterLayer]; } -- (void)styleGeoJSONSource +- (void)styleShapeSource { NSString *filePath = [[NSBundle bundleForClass:self.class] pathForResource:@"amsterdam" ofType:@"geojson"]; NSURL *geoJSONURL = [NSURL fileURLWithPath:filePath]; - MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"ams" URL:geoJSONURL options:nil]; + MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"ams" URL:geoJSONURL options:nil]; [self.mapView.style addSource:source]; MGLFillStyleLayer *fillLayer = [[MGLFillStyleLayer alloc] initWithIdentifier:@"test" source:source]; @@ -877,7 +882,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { - (void)styleQuery { CGRect queryRect = CGRectInset(self.mapView.bounds, 100, 200); - NSArray *features = [self.mapView visibleFeaturesInRect:queryRect]; + NSArray *visibleFeatures = [self.mapView visibleFeaturesInRect:queryRect]; NSString *querySourceID = @"query-source-id"; NSString *queryLayerID = @"query-layer-id"; @@ -895,9 +900,9 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { [self.mapView.style removeSource:source]; } - dispatch_async(dispatch_get_main_queue(), ^{ - MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:querySourceID features:features options:nil]; + MGLShapeCollectionFeature *features = [MGLShapeCollectionFeature shapeCollectionWithShapes:visibleFeatures]; + MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:querySourceID shape:features options:nil]; [self.mapView.style addSource:source]; MGLFillStyleLayer *fillLayer = [[MGLFillStyleLayer alloc] initWithIdentifier:queryLayerID source:source]; @@ -913,61 +918,90 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { self.mapView.centerCoordinate = CLLocationCoordinate2DMake(51.068585180672635, -114.06074523925781); CLLocationCoordinate2D leafCoords[] = { - CLLocationCoordinate2DMake(50.9683733218221,-114.07035827636719), - CLLocationCoordinate2DMake(51.02325750523972,-114.06967163085938), - CLLocationCoordinate2DMake(51.009434536947786,-114.14245605468749), - CLLocationCoordinate2DMake(51.030599281184124,-114.12597656249999), - CLLocationCoordinate2DMake(51.060386316691016,-114.21043395996094), - CLLocationCoordinate2DMake(51.063838646941576,-114.17816162109375), - CLLocationCoordinate2DMake(51.08152779888779,-114.19876098632812), - CLLocationCoordinate2DMake(51.08066507029602,-114.16854858398438), - CLLocationCoordinate2DMake(51.09662294502995,-114.17472839355469), - CLLocationCoordinate2DMake(51.07764539352731,-114.114990234375), - CLLocationCoordinate2DMake(51.13670896949613,-114.12391662597656), - CLLocationCoordinate2DMake(51.13369295212583,-114.09576416015624), - CLLocationCoordinate2DMake(51.17546878815025,-114.07585144042969), - CLLocationCoordinate2DMake(51.140155605265896,-114.04632568359375), - CLLocationCoordinate2DMake(51.15049396880196,-114.01542663574219), - CLLocationCoordinate2DMake(51.088860342359965,-114.00924682617186), - CLLocationCoordinate2DMake(51.12205789681453,-113.94813537597656), - CLLocationCoordinate2DMake(51.106539930027225,-113.94882202148438), - CLLocationCoordinate2DMake(51.117747873223344,-113.92616271972656), - CLLocationCoordinate2DMake(51.10093493903458,-113.92616271972656), - CLLocationCoordinate2DMake(51.10697105503078,-113.90625), - CLLocationCoordinate2DMake(51.09144802136697,-113.9117431640625), - CLLocationCoordinate2DMake(51.04916446529361,-113.97010803222655), - CLLocationCoordinate2DMake(51.045279344649146,-113.9398956298828), - CLLocationCoordinate2DMake(51.022825599852496,-114.06211853027344), - CLLocationCoordinate2DMake(51.045279344649146,-113.9398956298828), - CLLocationCoordinate2DMake(51.022825599852496,-114.06211853027344), - CLLocationCoordinate2DMake(51.022825599852496,-114.06280517578125), - CLLocationCoordinate2DMake(50.968805734317804,-114.06280517578125), - CLLocationCoordinate2DMake(50.9683733218221,-114.07035827636719), + {50.9683733218221,-114.07035827636719}, + {51.02325750523972,-114.06967163085938}, + {51.009434536947786,-114.14245605468749}, + {51.030599281184124,-114.12597656249999}, + {51.060386316691016,-114.21043395996094}, + {51.063838646941576,-114.17816162109375}, + {51.08152779888779,-114.19876098632812}, + {51.08066507029602,-114.16854858398438}, + {51.09662294502995,-114.17472839355469}, + {51.07764539352731,-114.114990234375}, + {51.13670896949613,-114.12391662597656}, + {51.13369295212583,-114.09576416015624}, + {51.17546878815025,-114.07585144042969}, + {51.140155605265896,-114.04632568359375}, + {51.15049396880196,-114.01542663574219}, + {51.088860342359965,-114.00924682617186}, + {51.12205789681453,-113.94813537597656}, + {51.106539930027225,-113.94882202148438}, + {51.117747873223344,-113.92616271972656}, + {51.10093493903458,-113.92616271972656}, + {51.10697105503078,-113.90625}, + {51.09144802136697,-113.9117431640625}, + {51.04916446529361,-113.97010803222655}, + {51.045279344649146,-113.9398956298828}, + {51.022825599852496,-114.06211853027344}, + {51.045279344649146,-113.9398956298828}, + {51.022825599852496,-114.06211853027344}, + {51.022825599852496,-114.06280517578125}, + {50.968805734317804,-114.06280517578125}, + {50.9683733218221,-114.07035827636719}, }; NSUInteger coordsCount = sizeof(leafCoords) / sizeof(leafCoords[0]); MGLPolygonFeature *feature = [MGLPolygonFeature polygonWithCoordinates:leafCoords count:coordsCount]; feature.identifier = @"leaf-feature"; feature.attributes = @{@"color": @"red"}; - - MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"leaf-source" features:@[feature] options:nil]; + + MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"leaf-source" shape:feature options:nil]; [self.mapView.style addSource:source]; MGLFillStyleLayer *layer = [[MGLFillStyleLayer alloc] initWithIdentifier:@"leaf-fill-layer" source:source]; - layer.predicate = [NSPredicate predicateWithFormat:@"color = %@", @"red"]; + layer.predicate = [NSPredicate predicateWithFormat:@"color = 'red'"]; MGLStyleValue *fillColor = [MGLStyleValue valueWithRawValue:[UIColor redColor]]; layer.fillColor = fillColor; [self.mapView.style addLayer:layer]; + + NSString *geoJSON = @"{\"type\": \"Feature\", \"properties\": {\"color\": \"green\"}, \"geometry\": { \"type\": \"Point\", \"coordinates\": [ -114.06847000122069, 51.050459433092655 ] }}"; + + NSData *data = [geoJSON dataUsingEncoding:NSUTF8StringEncoding]; + MGLShape *shape = [MGLShape shapeWithData:data encoding:NSUTF8StringEncoding error:NULL]; + MGLShapeSource *pointSource = [[MGLShapeSource alloc] initWithIdentifier:@"leaf-point-source" shape:shape options:nil]; + [self.mapView.style addSource:pointSource]; + + MGLCircleStyleLayer *circleLayer = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"leaf-circle-layer" source:pointSource]; + circleLayer.circleColor = [MGLStyleValue valueWithRawValue:[UIColor greenColor]]; + circleLayer.predicate = [NSPredicate predicateWithFormat:@"color = 'green'"]; + [self.mapView.style addLayer:circleLayer]; + + + CLLocationCoordinate2D squareCoords[] = { + {51.056070541830934, -114.0274429321289}, + {51.07937094724242, -114.0274429321289}, + {51.07937094724242, -113.98761749267578}, + {51.05607054183093, -113.98761749267578}, + {51.056070541830934, -114.0274429321289}, + }; + MGLPolygon *polygon = [MGLPolygon polygonWithCoordinates:squareCoords count:sizeof(squareCoords)/sizeof(squareCoords[0])]; + MGLShapeSource *plainShapeSource = [[MGLShapeSource alloc] initWithIdentifier:@"leaf-plain-shape-source" shape:polygon options:nil]; + [self.mapView.style addSource:plainShapeSource]; + + MGLFillStyleLayer *plainFillLayer = [[MGLFillStyleLayer alloc] initWithIdentifier:@"leaf-plain-fill-layer" source:plainShapeSource]; + plainFillLayer.fillColor = [MGLStyleValue valueWithRawValue:[UIColor yellowColor]]; + [self.mapView.style addLayer:plainFillLayer]; } -- (void)updateGeoJSONSourceData +- (void)updateShapeSourceData { [self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(40.329795743702064, -107.75390625) zoomLevel:11 animated:NO]; NSString *geoJSON = @"{\"type\": \"FeatureCollection\",\"features\": [{\"type\": \"Feature\",\"properties\": {},\"geometry\": {\"type\": \"LineString\",\"coordinates\": [[-107.75390625,40.329795743702064],[-104.34814453125,37.64903402157866]]}}]}"; NSData *data = [geoJSON dataUsingEncoding:NSUTF8StringEncoding]; - MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"mutable-data-source-id" geoJSONData:data options:nil]; + MGLShape *shape = [MGLShape shapeWithData:data encoding:NSUTF8StringEncoding error:NULL]; + MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"mutable-data-source-id" shape:shape options:nil]; [self.mapView.style addSource:source]; MGLLineStyleLayer *layer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"mutable-data-layer-id" source:source]; @@ -976,18 +1010,18 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSString *geoJSON = @"{\"type\": \"FeatureCollection\",\"features\": [{\"type\": \"Feature\",\"properties\": {},\"geometry\": {\"type\": \"LineString\",\"coordinates\": [[-107.75390625,40.329795743702064],[-109.34814453125,37.64903402157866]]}}]}"; NSData *data = [geoJSON dataUsingEncoding:NSUTF8StringEncoding]; - - source.geoJSONData = data; + MGLShape *shape = [MGLShape shapeWithData:data encoding:NSUTF8StringEncoding error:NULL]; + source.shape = shape; }); } -- (void)updateGeoJSONSourceURL +- (void)updateShapeSourceURL { [self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(48.668731, -122.857151) zoomLevel:11 animated:NO]; NSString *filePath = [[NSBundle bundleForClass:self.class] pathForResource:@"polyline" ofType:@"geojson"]; NSURL *geoJSONURL = [NSURL fileURLWithPath:filePath]; - MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"mutable-data-source-url-id" URL:geoJSONURL options:nil]; + MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"mutable-data-source-url-id" URL:geoJSONURL options:nil]; [self.mapView.style addSource:source]; MGLLineStyleLayer *layer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"mutable-data-layer-url-id" source:source]; @@ -1003,7 +1037,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { }); } -- (void)updateGeoJSONSourceFeatures +- (void)updateShapeSourceFeatures { [self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(-41.1520, 288.6592) zoomLevel:10 animated:NO]; @@ -1026,7 +1060,9 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { MGLPolygonFeature *smallBoxFeature = [MGLPolygonFeature polygonWithCoordinates:smallBox count:sizeof(smallBox)/sizeof(smallBox[0])]; MGLPolygonFeature *largeBoxFeature = [MGLPolygonFeature polygonWithCoordinates:largeBox count:sizeof(largeBox)/sizeof(largeBox[0])]; - MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"mutable-data-source-features-id" features:@[smallBoxFeature] options:nil]; + MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"mutable-data-source-features-id" + shape:smallBoxFeature + options:nil]; [self.mapView.style addSource:source]; MGLFillStyleLayer *layer = [[MGLFillStyleLayer alloc] initWithIdentifier:@"mutable-data-layer-features-id" source:source]; @@ -1035,7 +1071,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { [self.mapView.style addLayer:layer]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - source.features = @[largeBoxFeature]; + source.shape = largeBoxFeature; }); } @@ -1049,7 +1085,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { {36.99508088541243, -109.04007911682129}, }; MGLPointCollectionFeature *feature = [MGLPointCollectionFeature pointCollectionWithCoordinates:coordinates count:4]; - MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"wiggle-source" features:@[feature] options:nil]; + MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"wiggle-source" shape:feature options:nil]; [self.mapView.style addSource:source]; MGLCircleStyleLayer *layer = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"wiggle-layer" source:source]; @@ -1059,7 +1095,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { - (void)styleVectorSource { NSURL *url = [[NSURL alloc] initWithString:@"mapbox://mapbox.mapbox-terrain-v2"]; - MGLVectorSource *vectorSource = [[MGLVectorSource alloc] initWithIdentifier:@"style-vector-source-id" URL:url]; + MGLVectorSource *vectorSource = [[MGLVectorSource alloc] initWithIdentifier:@"style-vector-source-id" configurationURL:url]; [self.mapView.style addSource:vectorSource]; MGLBackgroundStyleLayer *backgroundLayer = [[MGLBackgroundStyleLayer alloc] initWithIdentifier:@"style-vector-background-layer-id"]; @@ -1080,8 +1116,10 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { - (void)styleRasterSource { // 3rd party raster source requires NSAppTransportSecurity exception for stamen.com - MGLTileSet *rasterTileSet = [[MGLTileSet alloc] initWithTileURLTemplates:@[@"http://a.tile.stamen.com/terrain-background/{z}/{x}/{y}.jpg"]]; - MGLRasterSource *rasterSource = [[MGLRasterSource alloc] initWithIdentifier:@"style-raster-source-id" tileSet:rasterTileSet tileSize:256]; + NSArray *tileURLTemplates = @[@"http://a.tile.stamen.com/terrain-background/{z}/{x}/{y}.jpg"]; + MGLRasterSource *rasterSource = [[MGLRasterSource alloc] initWithIdentifier:@"style-raster-source-id" tileURLTemplates:tileURLTemplates options:@{ + MGLTileSourceOptionTileSize: @256, + }]; [self.mapView.style addSource:rasterSource]; MGLRasterStyleLayer *rasterLayer = [[MGLRasterStyleLayer alloc] initWithIdentifier:@"style-raster-layer-id" source:rasterSource]; @@ -1116,7 +1154,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { MGLPolylineFeature *routeLine = [MGLPolylineFeature polylineWithCoordinates:coords count:count]; - MGLGeoJSONSource *routeSource = [[MGLGeoJSONSource alloc] initWithIdentifier:@"style-route-source" features:@[routeLine] options:nil]; + MGLShapeSource *routeSource = [[MGLShapeSource alloc] initWithIdentifier:@"style-route-source" shape:routeLine options:nil]; [self.mapView.style addSource:routeSource]; MGLLineStyleLayer *baseRouteLayer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"style-base-route-layer" source:routeSource]; @@ -1127,7 +1165,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { baseRouteLayer.lineJoin = [MGLStyleConstantValue valueWithRawValue:[NSValue valueWithMGLLineJoin:MGLLineJoinRound]]; [self.mapView.style addLayer:baseRouteLayer]; - MGLLineStyleLayer *routeLayer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"style-base-route-layer" source:routeSource]; + MGLLineStyleLayer *routeLayer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"style-route-layer" source:routeSource]; routeLayer.lineColor = [MGLStyleConstantValue valueWithRawValue:[UIColor whiteColor]]; routeLayer.lineWidth = [MGLStyleConstantValue valueWithRawValue:@15]; routeLayer.lineOpacity = [MGLStyleConstantValue valueWithRawValue:@0.8]; @@ -1176,7 +1214,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { NSString *bestLanguage; for (NSString *language in preferredLanguages) { - NSString *thisLanguage = [NSLocale localeWithLocaleIdentifier:language].languageCode; + NSString *thisLanguage = [[NSLocale localeWithLocaleIdentifier:language] objectForKey:NSLocaleLanguageCode]; if ([supportedLanguages containsObject:thisLanguage]) { bestLanguage = thisLanguage; break; diff --git a/platform/ios/docs/install_docs.sh b/platform/ios/docs/install_docs.sh deleted file mode 100755 index c5093cb5e..000000000 --- a/platform/ios/docs/install_docs.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env bash - -if [ -z `which appledoc` ]; then - echo "Unable to find appledoc. See https://github.com/mapbox/mapbox-gl-native/blob/master/docs/BUILD_IOS_OSX.md" - exit 1 -fi - -OUTPUT="/tmp/`uuidgen`" - -DOCS_VERSION=$( git tag | grep ^ios | sed 's/^ios-//' | sort -r | grep -v '\-rc.' | grep -v '\-pre.' | sed -n '1p' | sed 's/^v//' ) -echo "Creating new docs for ${DOCS_VERSION}..." -echo - -rm -rf /tmp/mbgl -mkdir -p /tmp/mbgl/ -README=/tmp/mbgl/GL-README.md -cat ./pod-README.md > ${README} -echo >> ${README} -echo -n "#" >> ${README} -cat ../../CHANGELOG.md | sed -n "/^## iOS ${DOCS_VERSION}/,/^##/p" | sed '$d' >> ${README} -# Copy headers to a temporary location where we can substitute macros that appledoc doesn't understand. -cp -r ../../platform/ios/include /tmp/mbgl -perl \ - -pi \ - -e 's/NS_(?:(MUTABLE)_)?(ARRAY|SET|DICTIONARY)_OF\(\s*(.+?)\s*\)/NS\L\u$1\u$2\E <$3>/g' \ - /tmp/mbgl/ios/*.h -appledoc \ - --output ${OUTPUT} \ - --project-name "Mapbox iOS SDK ${DOCS_VERSION}" \ - --project-company Mapbox \ - --create-docset \ - --company-id com.mapbox \ - --index-desc ${README} \ - /tmp/mbgl/ios diff --git a/platform/ios/docs/remove_docs.sh b/platform/ios/docs/remove_docs.sh deleted file mode 100755 index 747ca0a3a..000000000 --- a/platform/ios/docs/remove_docs.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash - -echo -echo "Removing docs from ~/Library/Developer/Shared/Documentation/DocSets..." -echo - -rm -rfv ~/Library/Developer/Shared/Documentation/DocSets/com.mapbox.Mapbox-GL-* diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj index 85cd723a9..c606c74ea 100644 --- a/platform/ios/ios.xcodeproj/project.pbxproj +++ b/platform/ios/ios.xcodeproj/project.pbxproj @@ -76,10 +76,10 @@ 354B839C1D2E9B48005D9406 /* MBXUserLocationAnnotationView.m in Sources */ = {isa = PBXBuildFile; fileRef = 354B839B1D2E9B48005D9406 /* MBXUserLocationAnnotationView.m */; }; 35599DED1D46F14E0048254D /* MGLStyleValue.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35599DEA1D46F14E0048254D /* MGLStyleValue.mm */; }; 35599DEE1D46F14E0048254D /* MGLStyleValue.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35599DEA1D46F14E0048254D /* MGLStyleValue.mm */; }; - 3566C7661D4A77BA008152BC /* MGLGeoJSONSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 3566C7641D4A77BA008152BC /* MGLGeoJSONSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3566C7671D4A77BA008152BC /* MGLGeoJSONSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 3566C7641D4A77BA008152BC /* MGLGeoJSONSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3566C7681D4A77BA008152BC /* MGLGeoJSONSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3566C7651D4A77BA008152BC /* MGLGeoJSONSource.mm */; }; - 3566C7691D4A77BA008152BC /* MGLGeoJSONSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3566C7651D4A77BA008152BC /* MGLGeoJSONSource.mm */; }; + 3566C7661D4A77BA008152BC /* MGLShapeSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 3566C7641D4A77BA008152BC /* MGLShapeSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3566C7671D4A77BA008152BC /* MGLShapeSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 3566C7641D4A77BA008152BC /* MGLShapeSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3566C7681D4A77BA008152BC /* MGLShapeSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3566C7651D4A77BA008152BC /* MGLShapeSource.mm */; }; + 3566C7691D4A77BA008152BC /* MGLShapeSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3566C7651D4A77BA008152BC /* MGLShapeSource.mm */; }; 3566C76C1D4A8DFA008152BC /* MGLRasterSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 3566C76A1D4A8DFA008152BC /* MGLRasterSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3566C76D1D4A8DFA008152BC /* MGLRasterSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 3566C76A1D4A8DFA008152BC /* MGLRasterSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3566C76E1D4A8DFA008152BC /* MGLRasterSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3566C76B1D4A8DFA008152BC /* MGLRasterSource.mm */; }; @@ -93,6 +93,7 @@ 357579891D502B06000B822E /* MGLCircleStyleLayerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 357579881D502B06000B822E /* MGLCircleStyleLayerTests.m */; }; 3575798B1D502B0C000B822E /* MGLBackgroundStyleLayerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3575798A1D502B0C000B822E /* MGLBackgroundStyleLayerTests.m */; }; 3575798E1D502EC7000B822E /* MGLRuntimeStylingHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 3575798D1D502EC7000B822E /* MGLRuntimeStylingHelper.m */; }; + 3599A3E61DF708BC00E77FB2 /* MGLStyleValueTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3599A3E51DF708BC00E77FB2 /* MGLStyleValueTests.m */; }; 359F57461D2FDDA6005217F1 /* MGLUserLocationAnnotationView_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 359F57451D2FDBD5005217F1 /* MGLUserLocationAnnotationView_Private.h */; }; 35B82BF81D6C5F8400B1B721 /* NSPredicate+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 35B82BF61D6C5F8400B1B721 /* NSPredicate+MGLAdditions.h */; }; 35B82BF91D6C5F8400B1B721 /* NSPredicate+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 35B82BF61D6C5F8400B1B721 /* NSPredicate+MGLAdditions.h */; }; @@ -137,12 +138,12 @@ 4049C29F1DB6CD6C00B3F799 /* MGLPointCollection.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4049C29C1DB6CD6C00B3F799 /* MGLPointCollection.mm */; }; 4049C2A01DB6CD6C00B3F799 /* MGLPointCollection.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4049C29C1DB6CD6C00B3F799 /* MGLPointCollection.mm */; }; 4049C2AC1DB6E05500B3F799 /* MGLPointCollection_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4049C2AB1DB6E05500B3F799 /* MGLPointCollection_Private.h */; }; - 404C26E21D89B877000AA13D /* MGLTileSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 404C26E01D89B877000AA13D /* MGLTileSet.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 404C26E31D89B877000AA13D /* MGLTileSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 404C26E01D89B877000AA13D /* MGLTileSet.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 404C26E41D89B877000AA13D /* MGLTileSet.mm in Sources */ = {isa = PBXBuildFile; fileRef = 404C26E11D89B877000AA13D /* MGLTileSet.mm */; }; - 404C26E51D89B877000AA13D /* MGLTileSet.mm in Sources */ = {isa = PBXBuildFile; fileRef = 404C26E11D89B877000AA13D /* MGLTileSet.mm */; }; - 404C26E71D89C55D000AA13D /* MGLTileSet_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 404C26E61D89C515000AA13D /* MGLTileSet_Private.h */; }; - 404C26E81D89C55D000AA13D /* MGLTileSet_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 404C26E61D89C515000AA13D /* MGLTileSet_Private.h */; }; + 404C26E21D89B877000AA13D /* MGLTileSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 404C26E01D89B877000AA13D /* MGLTileSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 404C26E31D89B877000AA13D /* MGLTileSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 404C26E01D89B877000AA13D /* MGLTileSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 404C26E41D89B877000AA13D /* MGLTileSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 404C26E11D89B877000AA13D /* MGLTileSource.mm */; }; + 404C26E51D89B877000AA13D /* MGLTileSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 404C26E11D89B877000AA13D /* MGLTileSource.mm */; }; + 404C26E71D89C55D000AA13D /* MGLTileSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 404C26E61D89C515000AA13D /* MGLTileSource_Private.h */; }; + 404C26E81D89C55D000AA13D /* MGLTileSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 404C26E61D89C515000AA13D /* MGLTileSource_Private.h */; }; 40599F0C1DEE1B7600182B5D /* api_mapbox_staging.der in Resources */ = {isa = PBXBuildFile; fileRef = 40599F001DEE1B2400182B5D /* api_mapbox_staging.der */; }; 40599F0D1DEE1B7A00182B5D /* api_mapbox_com-digicert.der in Resources */ = {isa = PBXBuildFile; fileRef = 40599F011DEE1B2400182B5D /* api_mapbox_com-digicert.der */; }; 40599F0E1DEE1B7E00182B5D /* api_mapbox_com-geotrust.der in Resources */ = {isa = PBXBuildFile; fileRef = 40599F021DEE1B2400182B5D /* api_mapbox_com-geotrust.der */; }; @@ -154,12 +155,12 @@ 408AA8581DAEDA1E00022900 /* NSDictionary+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 408AA8561DAEDA0800022900 /* NSDictionary+MGLAdditions.mm */; }; 408AA8591DAEDA1E00022900 /* NSDictionary+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 408AA8561DAEDA0800022900 /* NSDictionary+MGLAdditions.mm */; }; 40CF6DBB1DAC3C6600A4D18B /* MGLShape_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 40CF6DBA1DAC3C1800A4D18B /* MGLShape_Private.h */; }; - 40CFA6511D7875BB008103BD /* MGLGeoJSONSourceTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 40CFA6501D787579008103BD /* MGLGeoJSONSourceTests.mm */; }; + 40CFA6511D7875BB008103BD /* MGLShapeSourceTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 40CFA6501D787579008103BD /* MGLShapeSourceTests.mm */; }; 40EDA1C01CFE0E0200D9EA68 /* MGLAnnotationContainerView.h in Headers */ = {isa = PBXBuildFile; fileRef = 40EDA1BD1CFE0D4A00D9EA68 /* MGLAnnotationContainerView.h */; }; 40EDA1C11CFE0E0500D9EA68 /* MGLAnnotationContainerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EDA1BE1CFE0D4A00D9EA68 /* MGLAnnotationContainerView.m */; }; 40EDA1C21CFE0E0500D9EA68 /* MGLAnnotationContainerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EDA1BE1CFE0D4A00D9EA68 /* MGLAnnotationContainerView.m */; }; - 40F887701D7A1E58008ECB67 /* MGLGeoJSONSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 40F8876F1D7A1DB8008ECB67 /* MGLGeoJSONSource_Private.h */; }; - 40F887711D7A1E59008ECB67 /* MGLGeoJSONSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 40F8876F1D7A1DB8008ECB67 /* MGLGeoJSONSource_Private.h */; }; + 40F887701D7A1E58008ECB67 /* MGLShapeSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 40F8876F1D7A1DB8008ECB67 /* MGLShapeSource_Private.h */; }; + 40F887711D7A1E59008ECB67 /* MGLShapeSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 40F8876F1D7A1DB8008ECB67 /* MGLShapeSource_Private.h */; }; 40FDA76B1CCAAA6800442548 /* MBXAnnotationView.m in Sources */ = {isa = PBXBuildFile; fileRef = 40FDA76A1CCAAA6800442548 /* MBXAnnotationView.m */; }; 554180421D2E97DE00012372 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 554180411D2E97DE00012372 /* OpenGLES.framework */; }; 55D8C9961D0F18CE00F42F10 /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 55D8C9951D0F18CE00F42F10 /* libsqlite3.tbd */; }; @@ -171,6 +172,10 @@ 7E016D851D9E890300A29A21 /* MGLPolygon+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E016D821D9E890300A29A21 /* MGLPolygon+MGLAdditions.h */; }; 7E016D861D9E890300A29A21 /* MGLPolygon+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E016D831D9E890300A29A21 /* MGLPolygon+MGLAdditions.m */; }; 7E016D871D9E890300A29A21 /* MGLPolygon+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E016D831D9E890300A29A21 /* MGLPolygon+MGLAdditions.m */; }; + DA00FC8E1D5EEB0D009AABC8 /* MGLAttributionInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DA00FC8C1D5EEB0D009AABC8 /* MGLAttributionInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DA00FC8F1D5EEB0D009AABC8 /* MGLAttributionInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DA00FC8C1D5EEB0D009AABC8 /* MGLAttributionInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DA00FC901D5EEB0D009AABC8 /* MGLAttributionInfo.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA00FC8D1D5EEB0D009AABC8 /* MGLAttributionInfo.mm */; }; + DA00FC911D5EEB0D009AABC8 /* MGLAttributionInfo.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA00FC8D1D5EEB0D009AABC8 /* MGLAttributionInfo.mm */; }; DA0CD5901CF56F6A00A5F5A5 /* MGLFeatureTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA0CD58F1CF56F6A00A5F5A5 /* MGLFeatureTests.mm */; }; DA17BE301CC4BAC300402C41 /* MGLMapView_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA17BE2F1CC4BAC300402C41 /* MGLMapView_Private.h */; }; DA17BE311CC4BDAA00402C41 /* MGLMapView_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA17BE2F1CC4BAC300402C41 /* MGLMapView_Private.h */; }; @@ -188,6 +193,7 @@ DA25D5C01CCD9F8400607828 /* Root.plist in Resources */ = {isa = PBXBuildFile; fileRef = DA25D5BF1CCD9F8400607828 /* Root.plist */; }; DA25D5C61CCDA06800607828 /* Root.strings in Resources */ = {isa = PBXBuildFile; fileRef = DA25D5C41CCDA06800607828 /* Root.strings */; }; DA25D5CD1CCDA11500607828 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = DA25D5B91CCD9EDE00607828 /* Settings.bundle */; }; + DA2784FC1DF02FF4001D5B8D /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DA2784FB1DF02FF4001D5B8D /* Media.xcassets */; }; DA27C24E1CBB3811000B0ECD /* GLKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA27C24D1CBB3811000B0ECD /* GLKit.framework */; }; DA27C24F1CBB4C11000B0ECD /* MGLAccountManager_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8847FF1CBAFA6200AB86E3 /* MGLAccountManager_Private.h */; }; DA2DBBCE1D51E80400D38FF9 /* MGLStyleLayerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA2DBBCD1D51E80400D38FF9 /* MGLStyleLayerTests.m */; }; @@ -220,6 +226,10 @@ DA6408DC1DA4E7D300908C90 /* MGLVectorStyleLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = DA6408D91DA4E7D300908C90 /* MGLVectorStyleLayer.h */; settings = {ATTRIBUTES = (Public, ); }; }; DA6408DD1DA4E7D300908C90 /* MGLVectorStyleLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6408DA1DA4E7D300908C90 /* MGLVectorStyleLayer.m */; }; DA6408DE1DA4E7D300908C90 /* MGLVectorStyleLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6408DA1DA4E7D300908C90 /* MGLVectorStyleLayer.m */; }; + DA72620B1DEEE3480043BB89 /* MGLOpenGLStyleLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = DA7262091DEEE3480043BB89 /* MGLOpenGLStyleLayer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DA72620C1DEEE3480043BB89 /* MGLOpenGLStyleLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = DA7262091DEEE3480043BB89 /* MGLOpenGLStyleLayer.h */; }; + DA72620D1DEEE3480043BB89 /* MGLOpenGLStyleLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA72620A1DEEE3480043BB89 /* MGLOpenGLStyleLayer.mm */; }; + DA72620E1DEEE3480043BB89 /* MGLOpenGLStyleLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA72620A1DEEE3480043BB89 /* MGLOpenGLStyleLayer.mm */; }; DA737EE11D056A4E005BDA16 /* MGLMapViewDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = DA737EE01D056A4E005BDA16 /* MGLMapViewDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; DA737EE21D056A4E005BDA16 /* MGLMapViewDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = DA737EE01D056A4E005BDA16 /* MGLMapViewDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; DA821D061CCC6D59007508D4 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DA821D041CCC6D59007508D4 /* LaunchScreen.storyboard */; }; @@ -271,7 +281,6 @@ DA88483B1CBAFB8500AB86E3 /* MGLCalloutView.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848351CBAFB8500AB86E3 /* MGLCalloutView.h */; settings = {ATTRIBUTES = (Public, ); }; }; DA88483C1CBAFB8500AB86E3 /* MGLMapView.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848361CBAFB8500AB86E3 /* MGLMapView.h */; settings = {ATTRIBUTES = (Public, ); }; }; DA88483D1CBAFB8500AB86E3 /* MGLMapView+IBAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848371CBAFB8500AB86E3 /* MGLMapView+IBAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; - DA88483E1CBAFB8500AB86E3 /* MGLMapView+MGLCustomStyleLayerAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848381CBAFB8500AB86E3 /* MGLMapView+MGLCustomStyleLayerAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; DA88483F1CBAFB8500AB86E3 /* MGLUserLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848391CBAFB8500AB86E3 /* MGLUserLocation.h */; settings = {ATTRIBUTES = (Public, ); }; }; DA88484F1CBAFB9800AB86E3 /* MGLAnnotationImage_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848401CBAFB9800AB86E3 /* MGLAnnotationImage_Private.h */; }; DA8848501CBAFB9800AB86E3 /* MGLAnnotationImage.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8848411CBAFB9800AB86E3 /* MGLAnnotationImage.m */; }; @@ -385,7 +394,6 @@ DABFB86E1CBE9A0F00D62B32 /* MGLCalloutView.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848351CBAFB8500AB86E3 /* MGLCalloutView.h */; settings = {ATTRIBUTES = (Public, ); }; }; DABFB86F1CBE9A0F00D62B32 /* MGLMapView.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848361CBAFB8500AB86E3 /* MGLMapView.h */; settings = {ATTRIBUTES = (Public, ); }; }; DABFB8701CBE9A0F00D62B32 /* MGLMapView+IBAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848371CBAFB8500AB86E3 /* MGLMapView+IBAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; - DABFB8711CBE9A0F00D62B32 /* MGLMapView+MGLCustomStyleLayerAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848381CBAFB8500AB86E3 /* MGLMapView+MGLCustomStyleLayerAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; DABFB8721CBE9A0F00D62B32 /* MGLUserLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848391CBAFB8500AB86E3 /* MGLUserLocation.h */; settings = {ATTRIBUTES = (Public, ); }; }; DABFB8731CBE9A9900D62B32 /* Mapbox.h in Headers */ = {isa = PBXBuildFile; fileRef = DA88485E1CBAFC2E00AB86E3 /* Mapbox.h */; settings = {ATTRIBUTES = (Public, ); }; }; DAC49C5C1CD02BC9009E1AA3 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = DAC49C5F1CD02BC9009E1AA3 /* Localizable.stringsdict */; }; @@ -397,12 +405,19 @@ DAD165711CF41981001FF4B9 /* MGLFeature.mm in Sources */ = {isa = PBXBuildFile; fileRef = DAD1656B1CF41981001FF4B9 /* MGLFeature.mm */; }; DAD165781CF4CDFF001FF4B9 /* MGLShapeCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = DAD165761CF4CDFF001FF4B9 /* MGLShapeCollection.h */; settings = {ATTRIBUTES = (Public, ); }; }; DAD165791CF4CDFF001FF4B9 /* MGLShapeCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = DAD165761CF4CDFF001FF4B9 /* MGLShapeCollection.h */; settings = {ATTRIBUTES = (Public, ); }; }; - DAD1657A1CF4CDFF001FF4B9 /* MGLShapeCollection.m in Sources */ = {isa = PBXBuildFile; fileRef = DAD165771CF4CDFF001FF4B9 /* MGLShapeCollection.m */; }; - DAD1657B1CF4CDFF001FF4B9 /* MGLShapeCollection.m in Sources */ = {isa = PBXBuildFile; fileRef = DAD165771CF4CDFF001FF4B9 /* MGLShapeCollection.m */; }; + DAD1657A1CF4CDFF001FF4B9 /* MGLShapeCollection.mm in Sources */ = {isa = PBXBuildFile; fileRef = DAD165771CF4CDFF001FF4B9 /* MGLShapeCollection.mm */; }; + DAD1657B1CF4CDFF001FF4B9 /* MGLShapeCollection.mm in Sources */ = {isa = PBXBuildFile; fileRef = DAD165771CF4CDFF001FF4B9 /* MGLShapeCollection.mm */; }; DAED38631D62D0FC00D7640F /* NSURL+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = DAED38611D62D0FC00D7640F /* NSURL+MGLAdditions.h */; }; DAED38641D62D0FC00D7640F /* NSURL+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = DAED38611D62D0FC00D7640F /* NSURL+MGLAdditions.h */; }; DAED38651D62D0FC00D7640F /* NSURL+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = DAED38621D62D0FC00D7640F /* NSURL+MGLAdditions.m */; }; DAED38661D62D0FC00D7640F /* NSURL+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = DAED38621D62D0FC00D7640F /* NSURL+MGLAdditions.m */; }; + DAEDC4341D603417000224FF /* MGLAttributionInfoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DAEDC4331D603417000224FF /* MGLAttributionInfoTests.m */; }; + DAF0D8101DFE0EA000B28378 /* MGLRasterSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DAF0D80F1DFE0EA000B28378 /* MGLRasterSource_Private.h */; }; + DAF0D8111DFE0EA000B28378 /* MGLRasterSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DAF0D80F1DFE0EA000B28378 /* MGLRasterSource_Private.h */; }; + DAF0D8131DFE0EC500B28378 /* MGLVectorSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DAF0D8121DFE0EC500B28378 /* MGLVectorSource_Private.h */; }; + DAF0D8141DFE0EC500B28378 /* MGLVectorSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DAF0D8121DFE0EC500B28378 /* MGLVectorSource_Private.h */; }; + DAF0D8181DFE6B2800B28378 /* MGLAttributionInfo_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DAF0D8171DFE6B2800B28378 /* MGLAttributionInfo_Private.h */; }; + DAF0D8191DFE6B2800B28378 /* MGLAttributionInfo_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DAF0D8171DFE6B2800B28378 /* MGLAttributionInfo_Private.h */; }; DD0902A91DB1929D00C5BDCE /* MGLNetworkConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = DD0902A21DB18DE700C5BDCE /* MGLNetworkConfiguration.m */; }; DD0902AA1DB1929D00C5BDCE /* MGLNetworkConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = DD0902A21DB18DE700C5BDCE /* MGLNetworkConfiguration.m */; }; DD0902AB1DB192A800C5BDCE /* MGLNetworkConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = DD0902A41DB18F1B00C5BDCE /* MGLNetworkConfiguration.h */; }; @@ -532,8 +547,8 @@ 354B839A1D2E9B48005D9406 /* MBXUserLocationAnnotationView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MBXUserLocationAnnotationView.h; sourceTree = ""; }; 354B839B1D2E9B48005D9406 /* MBXUserLocationAnnotationView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MBXUserLocationAnnotationView.m; sourceTree = ""; }; 35599DEA1D46F14E0048254D /* MGLStyleValue.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLStyleValue.mm; sourceTree = ""; }; - 3566C7641D4A77BA008152BC /* MGLGeoJSONSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLGeoJSONSource.h; sourceTree = ""; }; - 3566C7651D4A77BA008152BC /* MGLGeoJSONSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLGeoJSONSource.mm; sourceTree = ""; }; + 3566C7641D4A77BA008152BC /* MGLShapeSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLShapeSource.h; sourceTree = ""; }; + 3566C7651D4A77BA008152BC /* MGLShapeSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLShapeSource.mm; sourceTree = ""; }; 3566C76A1D4A8DFA008152BC /* MGLRasterSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLRasterSource.h; sourceTree = ""; }; 3566C76B1D4A8DFA008152BC /* MGLRasterSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLRasterSource.mm; sourceTree = ""; }; 3566C7701D4A9198008152BC /* MGLSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLSource_Private.h; sourceTree = ""; }; @@ -545,6 +560,8 @@ 3575798A1D502B0C000B822E /* MGLBackgroundStyleLayerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLBackgroundStyleLayerTests.m; path = ../../darwin/test/MGLBackgroundStyleLayerTests.m; sourceTree = ""; }; 3575798C1D502EC7000B822E /* MGLRuntimeStylingHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MGLRuntimeStylingHelper.h; path = ../../darwin/test/MGLRuntimeStylingHelper.h; sourceTree = ""; }; 3575798D1D502EC7000B822E /* MGLRuntimeStylingHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLRuntimeStylingHelper.m; path = ../../darwin/test/MGLRuntimeStylingHelper.m; sourceTree = ""; }; + 357F09091DF84F3800941873 /* MGLStyleValueTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MGLStyleValueTests.h; path = ../../darwin/test/MGLStyleValueTests.h; sourceTree = ""; }; + 3599A3E51DF708BC00E77FB2 /* MGLStyleValueTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLStyleValueTests.m; path = ../../darwin/test/MGLStyleValueTests.m; sourceTree = ""; }; 359F57451D2FDBD5005217F1 /* MGLUserLocationAnnotationView_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLUserLocationAnnotationView_Private.h; sourceTree = ""; }; 35B82BF61D6C5F8400B1B721 /* NSPredicate+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSPredicate+MGLAdditions.h"; sourceTree = ""; }; 35B82BF71D6C5F8400B1B721 /* NSPredicate+MGLAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSPredicate+MGLAdditions.mm"; sourceTree = ""; }; @@ -575,9 +592,9 @@ 4049C29B1DB6CD6C00B3F799 /* MGLPointCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLPointCollection.h; sourceTree = ""; }; 4049C29C1DB6CD6C00B3F799 /* MGLPointCollection.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLPointCollection.mm; sourceTree = ""; }; 4049C2AB1DB6E05500B3F799 /* MGLPointCollection_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLPointCollection_Private.h; sourceTree = ""; }; - 404C26E01D89B877000AA13D /* MGLTileSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLTileSet.h; sourceTree = ""; }; - 404C26E11D89B877000AA13D /* MGLTileSet.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLTileSet.mm; sourceTree = ""; }; - 404C26E61D89C515000AA13D /* MGLTileSet_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLTileSet_Private.h; sourceTree = ""; }; + 404C26E01D89B877000AA13D /* MGLTileSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLTileSource.h; sourceTree = ""; }; + 404C26E11D89B877000AA13D /* MGLTileSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLTileSource.mm; sourceTree = ""; }; + 404C26E61D89C515000AA13D /* MGLTileSource_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLTileSource_Private.h; sourceTree = ""; }; 40599F001DEE1B2400182B5D /* api_mapbox_staging.der */ = {isa = PBXFileReference; lastKnownFileType = file; path = api_mapbox_staging.der; sourceTree = ""; }; 40599F011DEE1B2400182B5D /* api_mapbox_com-digicert.der */ = {isa = PBXFileReference; lastKnownFileType = file; path = "api_mapbox_com-digicert.der"; sourceTree = ""; }; 40599F021DEE1B2400182B5D /* api_mapbox_com-geotrust.der */ = {isa = PBXFileReference; lastKnownFileType = file; path = "api_mapbox_com-geotrust.der"; sourceTree = ""; }; @@ -585,10 +602,10 @@ 408AA8551DAEDA0800022900 /* NSDictionary+MGLAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+MGLAdditions.h"; sourceTree = ""; }; 408AA8561DAEDA0800022900 /* NSDictionary+MGLAdditions.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSDictionary+MGLAdditions.mm"; sourceTree = ""; }; 40CF6DBA1DAC3C1800A4D18B /* MGLShape_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLShape_Private.h; sourceTree = ""; }; - 40CFA6501D787579008103BD /* MGLGeoJSONSourceTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLGeoJSONSourceTests.mm; path = ../../darwin/test/MGLGeoJSONSourceTests.mm; sourceTree = ""; }; + 40CFA6501D787579008103BD /* MGLShapeSourceTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLShapeSourceTests.mm; path = ../../darwin/test/MGLShapeSourceTests.mm; sourceTree = ""; }; 40EDA1BD1CFE0D4A00D9EA68 /* MGLAnnotationContainerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAnnotationContainerView.h; sourceTree = ""; }; 40EDA1BE1CFE0D4A00D9EA68 /* MGLAnnotationContainerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLAnnotationContainerView.m; sourceTree = ""; }; - 40F8876F1D7A1DB8008ECB67 /* MGLGeoJSONSource_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLGeoJSONSource_Private.h; sourceTree = ""; }; + 40F8876F1D7A1DB8008ECB67 /* MGLShapeSource_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLShapeSource_Private.h; sourceTree = ""; }; 40FDA7691CCAAA6800442548 /* MBXAnnotationView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MBXAnnotationView.h; sourceTree = ""; }; 40FDA76A1CCAAA6800442548 /* MBXAnnotationView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MBXAnnotationView.m; sourceTree = ""; }; 554180411D2E97DE00012372 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; }; @@ -598,6 +615,8 @@ 7E016D7D1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MGLPolyline+MGLAdditions.m"; sourceTree = ""; }; 7E016D821D9E890300A29A21 /* MGLPolygon+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MGLPolygon+MGLAdditions.h"; sourceTree = ""; }; 7E016D831D9E890300A29A21 /* MGLPolygon+MGLAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MGLPolygon+MGLAdditions.m"; sourceTree = ""; }; + DA00FC8C1D5EEB0D009AABC8 /* MGLAttributionInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAttributionInfo.h; sourceTree = ""; }; + DA00FC8D1D5EEB0D009AABC8 /* MGLAttributionInfo.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLAttributionInfo.mm; sourceTree = ""; }; DA0CD58F1CF56F6A00A5F5A5 /* MGLFeatureTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLFeatureTests.mm; path = ../../darwin/test/MGLFeatureTests.mm; sourceTree = ""; }; DA17BE2F1CC4BAC300402C41 /* MGLMapView_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLMapView_Private.h; sourceTree = ""; }; DA1DC94A1CB6C1C2006E619F /* Mapbox GL.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Mapbox GL.app"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -616,11 +635,11 @@ DA1DC99A1CB6E064006E619F /* MBXViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MBXViewController.m; sourceTree = ""; }; DA1DC99C1CB6E076006E619F /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; DA1DC99E1CB6E088006E619F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - DA2207BD1DC0805F0002F84D /* test-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "test-Bridging-Header.h"; sourceTree = ""; }; DA2207BE1DC0805F0002F84D /* MGLStyleValueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MGLStyleValueTests.swift; path = ../../darwin/test/MGLStyleValueTests.swift; sourceTree = ""; }; DA25D5B91CCD9EDE00607828 /* Settings.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Settings.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; DA25D5BF1CCD9F8400607828 /* Root.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Root.plist; sourceTree = ""; }; DA25D5C51CCDA06800607828 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Root.strings; sourceTree = ""; }; + DA2784FB1DF02FF4001D5B8D /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Media.xcassets; path = ../../darwin/test/Media.xcassets; sourceTree = ""; }; DA27C24D1CBB3811000B0ECD /* GLKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLKit.framework; path = System/Library/Frameworks/GLKit.framework; sourceTree = SDKROOT; }; DA2DBBCC1D51E80400D38FF9 /* MGLStyleLayerTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MGLStyleLayerTests.h; path = ../../darwin/test/MGLStyleLayerTests.h; sourceTree = ""; }; DA2DBBCD1D51E80400D38FF9 /* MGLStyleLayerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLStyleLayerTests.m; path = ../../darwin/test/MGLStyleLayerTests.m; sourceTree = ""; }; @@ -646,6 +665,8 @@ DA4A26961CB6E795000B7809 /* Mapbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Mapbox.framework; sourceTree = BUILT_PRODUCTS_DIR; }; DA6408D91DA4E7D300908C90 /* MGLVectorStyleLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLVectorStyleLayer.h; sourceTree = ""; }; DA6408DA1DA4E7D300908C90 /* MGLVectorStyleLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLVectorStyleLayer.m; sourceTree = ""; }; + DA7262091DEEE3480043BB89 /* MGLOpenGLStyleLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLOpenGLStyleLayer.h; sourceTree = ""; }; + DA72620A1DEEE3480043BB89 /* MGLOpenGLStyleLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLOpenGLStyleLayer.mm; sourceTree = ""; }; DA737EE01D056A4E005BDA16 /* MGLMapViewDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLMapViewDelegate.h; sourceTree = ""; }; DA821D041CCC6D59007508D4 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; DA821D051CCC6D59007508D4 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; @@ -697,7 +718,6 @@ DA8848351CBAFB8500AB86E3 /* MGLCalloutView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLCalloutView.h; sourceTree = ""; }; DA8848361CBAFB8500AB86E3 /* MGLMapView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLMapView.h; sourceTree = ""; }; DA8848371CBAFB8500AB86E3 /* MGLMapView+IBAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MGLMapView+IBAdditions.h"; sourceTree = ""; }; - DA8848381CBAFB8500AB86E3 /* MGLMapView+MGLCustomStyleLayerAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MGLMapView+MGLCustomStyleLayerAdditions.h"; sourceTree = ""; }; DA8848391CBAFB8500AB86E3 /* MGLUserLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLUserLocation.h; sourceTree = ""; }; DA8848401CBAFB9800AB86E3 /* MGLAnnotationImage_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAnnotationImage_Private.h; sourceTree = ""; }; DA8848411CBAFB9800AB86E3 /* MGLAnnotationImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLAnnotationImage.m; sourceTree = ""; }; @@ -742,7 +762,7 @@ DA8963341CC549A100684375 /* sprites */ = {isa = PBXFileReference; lastKnownFileType = folder; path = sprites; sourceTree = ""; }; DA8963351CC549A100684375 /* styles */ = {isa = PBXFileReference; lastKnownFileType = folder; path = styles; sourceTree = ""; }; DA8963361CC549A100684375 /* tiles */ = {isa = PBXFileReference; lastKnownFileType = folder; path = tiles; sourceTree = ""; }; - DA8F25B91D51D2570010E6B5 /* MGLRuntimeStylingTests.m.ejs */ = {isa = PBXFileReference; lastKnownFileType = text; path = MGLRuntimeStylingTests.m.ejs; sourceTree = ""; }; + DA8F25B91D51D2570010E6B5 /* MGLStyleLayerTests.m.ejs */ = {isa = PBXFileReference; lastKnownFileType = text; name = MGLStyleLayerTests.m.ejs; path = ../test/MGLStyleLayerTests.m.ejs; sourceTree = ""; }; DA8F25BA1D51D2570010E6B5 /* MGLStyleLayer.h.ejs */ = {isa = PBXFileReference; lastKnownFileType = text; path = MGLStyleLayer.h.ejs; sourceTree = ""; }; DA8F25BB1D51D2570010E6B5 /* MGLStyleLayer.mm.ejs */ = {isa = PBXFileReference; lastKnownFileType = text; path = MGLStyleLayer.mm.ejs; sourceTree = ""; }; DAA4E4021CBB5C2F00178DFB /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; @@ -768,9 +788,13 @@ DAD1656A1CF41981001FF4B9 /* MGLFeature_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLFeature_Private.h; sourceTree = ""; }; DAD1656B1CF41981001FF4B9 /* MGLFeature.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLFeature.mm; sourceTree = ""; }; DAD165761CF4CDFF001FF4B9 /* MGLShapeCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLShapeCollection.h; sourceTree = ""; }; - DAD165771CF4CDFF001FF4B9 /* MGLShapeCollection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLShapeCollection.m; sourceTree = ""; }; + DAD165771CF4CDFF001FF4B9 /* MGLShapeCollection.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLShapeCollection.mm; sourceTree = ""; }; DAED38611D62D0FC00D7640F /* NSURL+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSURL+MGLAdditions.h"; sourceTree = ""; }; DAED38621D62D0FC00D7640F /* NSURL+MGLAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSURL+MGLAdditions.m"; sourceTree = ""; }; + DAEDC4331D603417000224FF /* MGLAttributionInfoTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLAttributionInfoTests.m; path = ../../darwin/test/MGLAttributionInfoTests.m; sourceTree = ""; }; + DAF0D80F1DFE0EA000B28378 /* MGLRasterSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLRasterSource_Private.h; sourceTree = ""; }; + DAF0D8121DFE0EC500B28378 /* MGLVectorSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLVectorSource_Private.h; sourceTree = ""; }; + DAF0D8171DFE6B2800B28378 /* MGLAttributionInfo_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAttributionInfo_Private.h; sourceTree = ""; }; DD0902A21DB18DE700C5BDCE /* MGLNetworkConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLNetworkConfiguration.m; sourceTree = ""; }; DD0902A41DB18F1B00C5BDCE /* MGLNetworkConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLNetworkConfiguration.h; sourceTree = ""; }; DD4823721D94AE6C00EB71B7 /* fill_filter_style.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = fill_filter_style.json; sourceTree = ""; }; @@ -831,19 +855,21 @@ 35136D491D4277EA00C20EFD /* Sources */ = { isa = PBXGroup; children = ( + 3566C76A1D4A8DFA008152BC /* MGLRasterSource.h */, + DAF0D80F1DFE0EA000B28378 /* MGLRasterSource_Private.h */, + 3566C76B1D4A8DFA008152BC /* MGLRasterSource.mm */, + 3566C7641D4A77BA008152BC /* MGLShapeSource.h */, + 40F8876F1D7A1DB8008ECB67 /* MGLShapeSource_Private.h */, + 3566C7651D4A77BA008152BC /* MGLShapeSource.mm */, 35136D4A1D4277FC00C20EFD /* MGLSource.h */, 3566C7701D4A9198008152BC /* MGLSource_Private.h */, 35136D4B1D4277FC00C20EFD /* MGLSource.mm */, + 404C26E01D89B877000AA13D /* MGLTileSource.h */, + 404C26E61D89C515000AA13D /* MGLTileSource_Private.h */, + 404C26E11D89B877000AA13D /* MGLTileSource.mm */, 350098B91D480108004B2AF0 /* MGLVectorSource.h */, + DAF0D8121DFE0EC500B28378 /* MGLVectorSource_Private.h */, 350098BA1D480108004B2AF0 /* MGLVectorSource.mm */, - 3566C7641D4A77BA008152BC /* MGLGeoJSONSource.h */, - 40F8876F1D7A1DB8008ECB67 /* MGLGeoJSONSource_Private.h */, - 3566C7651D4A77BA008152BC /* MGLGeoJSONSource.mm */, - 3566C76A1D4A8DFA008152BC /* MGLRasterSource.h */, - 3566C76B1D4A8DFA008152BC /* MGLRasterSource.mm */, - 404C26E01D89B877000AA13D /* MGLTileSet.h */, - 404C26E61D89C515000AA13D /* MGLTileSet_Private.h */, - 404C26E11D89B877000AA13D /* MGLTileSet.mm */, ); name = Sources; sourceTree = ""; @@ -861,6 +887,8 @@ 3538AA1C1D542239008EC33D /* MGLForegroundStyleLayer.m */, 353933F71D3FB79F003F57D7 /* MGLLineStyleLayer.h */, 35136D3E1D42273000C20EFD /* MGLLineStyleLayer.mm */, + DA7262091DEEE3480043BB89 /* MGLOpenGLStyleLayer.h */, + DA72620A1DEEE3480043BB89 /* MGLOpenGLStyleLayer.mm */, 353933FA1D3FB7C0003F57D7 /* MGLRasterStyleLayer.h */, 35136D411D42274500C20EFD /* MGLRasterStyleLayer.mm */, 35D13AB51D3D15E300AFB4E0 /* MGLStyleLayer.h */, @@ -903,9 +931,10 @@ children = ( 3575798F1D513EF1000B822E /* Layers */, 35B8E08B1D6C8B5100E768D2 /* MGLFilterTests.mm */, + 357F09091DF84F3800941873 /* MGLStyleValueTests.h */, + 3599A3E51DF708BC00E77FB2 /* MGLStyleValueTests.m */, DA2207BE1DC0805F0002F84D /* MGLStyleValueTests.swift */, 40CFA64E1D78754A008103BD /* Sources */, - DA2207BD1DC0805F0002F84D /* test-Bridging-Header.h */, ); name = Styling; sourceTree = ""; @@ -949,7 +978,7 @@ 40CFA64E1D78754A008103BD /* Sources */ = { isa = PBXGroup; children = ( - 40CFA6501D787579008103BD /* MGLGeoJSONSourceTests.mm */, + 40CFA6501D787579008103BD /* MGLShapeSourceTests.mm */, 4085AF081D933DEA00F11B22 /* MGLTileSetTests.mm */, ); name = Sources; @@ -1055,6 +1084,7 @@ isa = PBXGroup; children = ( 357579811D502AD4000B822E /* Styling */, + DAEDC4331D603417000224FF /* MGLAttributionInfoTests.m */, 353D23951D0B0DFE002BE09D /* MGLAnnotationViewTests.m */, DA35A2C31CCA9F8300E826B2 /* MGLClockDirectionFormatterTests.m */, DA35A2C41CCA9F8300E826B2 /* MGLCompassDirectionFormatterTests.m */, @@ -1068,6 +1098,7 @@ DA2E88601CC0382C00F24E7B /* MGLStyleTests.mm */, DD58A4C51D822BD000E1F038 /* MGLExpressionTests.mm */, DA2E88551CC036F400F24E7B /* Info.plist */, + DA2784FB1DF02FF4001D5B8D /* Media.xcassets */, ); name = "SDK Tests"; path = test; @@ -1101,10 +1132,13 @@ DA8847DF1CBAFA5100AB86E3 /* MGLAccountManager.h */, DA8847FF1CBAFA6200AB86E3 /* MGLAccountManager_Private.h */, DA8848001CBAFA6200AB86E3 /* MGLAccountManager.m */, - DD0902A41DB18F1B00C5BDCE /* MGLNetworkConfiguration.h */, - DD0902A21DB18DE700C5BDCE /* MGLNetworkConfiguration.m */, + DA00FC8C1D5EEB0D009AABC8 /* MGLAttributionInfo.h */, + DAF0D8171DFE6B2800B28378 /* MGLAttributionInfo_Private.h */, + DA00FC8D1D5EEB0D009AABC8 /* MGLAttributionInfo.mm */, DA8847E21CBAFA5100AB86E3 /* MGLMapCamera.h */, DA8848031CBAFA6200AB86E3 /* MGLMapCamera.mm */, + DD0902A41DB18F1B00C5BDCE /* MGLNetworkConfiguration.h */, + DD0902A21DB18DE700C5BDCE /* MGLNetworkConfiguration.m */, DA8847EC1CBAFA5100AB86E3 /* MGLStyle.h */, 35E0CFE51D3E501500188327 /* MGLStyle_Private.h */, DA88480F1CBAFA6200AB86E3 /* MGLStyle.mm */, @@ -1126,7 +1160,6 @@ DA8848361CBAFB8500AB86E3 /* MGLMapView.h */, DA17BE2F1CC4BAC300402C41 /* MGLMapView_Private.h */, DA8848371CBAFB8500AB86E3 /* MGLMapView+IBAdditions.h */, - DA8848381CBAFB8500AB86E3 /* MGLMapView+MGLCustomStyleLayerAdditions.h */, DA737EE01D056A4E005BDA16 /* MGLMapViewDelegate.h */, DA88484A1CBAFB9800AB86E3 /* MGLMapView.mm */, DA88487F1CBB033F00AB86E3 /* Fabric */, @@ -1216,9 +1249,9 @@ DA8F25BC1D51D2570010E6B5 /* Foundation Templates */ = { isa = PBXGroup; children = ( - DA8F25B91D51D2570010E6B5 /* MGLRuntimeStylingTests.m.ejs */, DA8F25BA1D51D2570010E6B5 /* MGLStyleLayer.h.ejs */, DA8F25BB1D51D2570010E6B5 /* MGLStyleLayer.mm.ejs */, + DA8F25B91D51D2570010E6B5 /* MGLStyleLayerTests.m.ejs */, 4032C5B71DE1EBB90062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.h.ejs */, 4032C5BC1DE1FAFC0062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.mm.ejs */, ); @@ -1285,8 +1318,8 @@ DA8847E11CBAFA5100AB86E3 /* MGLGeometry.h */, DA8848011CBAFA6200AB86E3 /* MGLGeometry_Private.h */, DA8848021CBAFA6200AB86E3 /* MGLGeometry.mm */, - DA8848041CBAFA6200AB86E3 /* MGLMultiPoint_Private.h */, DA8847E31CBAFA5100AB86E3 /* MGLMultiPoint.h */, + DA8848041CBAFA6200AB86E3 /* MGLMultiPoint_Private.h */, DA8848051CBAFA6200AB86E3 /* MGLMultiPoint.mm */, DA8847E71CBAFA5100AB86E3 /* MGLOverlay.h */, DA8847E81CBAFA5100AB86E3 /* MGLPointAnnotation.h */, @@ -1302,7 +1335,7 @@ 40CF6DBA1DAC3C1800A4D18B /* MGLShape_Private.h */, DA88480E1CBAFA6200AB86E3 /* MGLShape.mm */, DAD165761CF4CDFF001FF4B9 /* MGLShapeCollection.h */, - DAD165771CF4CDFF001FF4B9 /* MGLShapeCollection.m */, + DAD165771CF4CDFF001FF4B9 /* MGLShapeCollection.mm */, ); name = Geometry; sourceTree = ""; @@ -1415,6 +1448,7 @@ 353933FE1D3FB7DD003F57D7 /* MGLSymbolStyleLayer.h in Headers */, DA8848861CBB033F00AB86E3 /* Fabric+FABKits.h in Headers */, DA8848201CBAFA6200AB86E3 /* MGLOfflinePack_Private.h in Headers */, + DA00FC8E1D5EEB0D009AABC8 /* MGLAttributionInfo.h in Headers */, DA8847FA1CBAFA5100AB86E3 /* MGLPolyline.h in Headers */, 3566C7711D4A9198008152BC /* MGLSource_Private.h in Headers */, 4018B1C91CDC288A00F666AF /* MGLAnnotationView_Private.h in Headers */, @@ -1423,7 +1457,7 @@ 7E016D7E1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.h in Headers */, 35D13AB71D3D15E300AFB4E0 /* MGLStyleLayer.h in Headers */, DA88488E1CBB047F00AB86E3 /* reachability.h in Headers */, - 40F887701D7A1E58008ECB67 /* MGLGeoJSONSource_Private.h in Headers */, + 40F887701D7A1E58008ECB67 /* MGLShapeSource_Private.h in Headers */, 350098DC1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.h in Headers */, DA8848231CBAFA6200AB86E3 /* MGLOfflineStorage_Private.h in Headers */, 404326891D5B9B27007111BD /* MGLAnnotationContainerView_Private.h in Headers */, @@ -1437,12 +1471,12 @@ DA88485A1CBAFB9800AB86E3 /* MGLUserLocation_Private.h in Headers */, DA27C24F1CBB4C11000B0ECD /* MGLAccountManager_Private.h in Headers */, DA8847FC1CBAFA5100AB86E3 /* MGLStyle.h in Headers */, + DAF0D8131DFE0EC500B28378 /* MGLVectorSource_Private.h in Headers */, 354B83961D2E873E005D9406 /* MGLUserLocationAnnotationView.h in Headers */, DA8847F01CBAFA5100AB86E3 /* MGLAnnotation.h in Headers */, 7E016D841D9E890300A29A21 /* MGLPolygon+MGLAdditions.h in Headers */, 400533011DB0862B0069F638 /* NSArray+MGLAdditions.h in Headers */, 4049C29D1DB6CD6C00B3F799 /* MGLPointCollection.h in Headers */, - DA88483E1CBAFB8500AB86E3 /* MGLMapView+MGLCustomStyleLayerAdditions.h in Headers */, 40CF6DBB1DAC3C6600A4D18B /* MGLShape_Private.h in Headers */, 4018B1CA1CDC288E00F666AF /* MGLAnnotationView.h in Headers */, 35E79F201D41266300957B9E /* MGLStyleLayer_Private.h in Headers */, @@ -1467,10 +1501,11 @@ DAD165781CF4CDFF001FF4B9 /* MGLShapeCollection.h in Headers */, DAED38631D62D0FC00D7640F /* NSURL+MGLAdditions.h in Headers */, DA88481E1CBAFA6200AB86E3 /* MGLMultiPoint_Private.h in Headers */, - 3566C7661D4A77BA008152BC /* MGLGeoJSONSource.h in Headers */, + 3566C7661D4A77BA008152BC /* MGLShapeSource.h in Headers */, 35CE61821D4165D9004F2359 /* UIColor+MGLAdditions.h in Headers */, 35B82BF81D6C5F8400B1B721 /* NSPredicate+MGLAdditions.h in Headers */, DA35A29E1CC9E94C00E826B2 /* MGLCoordinateFormatter.h in Headers */, + DAF0D8181DFE6B2800B28378 /* MGLAttributionInfo_Private.h in Headers */, DAAF722B1DA903C700312FA4 /* MGLStyleValue.h in Headers */, DA8847F71CBAFA5100AB86E3 /* MGLOverlay.h in Headers */, DA35A2B11CCA141D00E826B2 /* MGLCompassDirectionFormatter.h in Headers */, @@ -1497,16 +1532,18 @@ DA8848851CBB033F00AB86E3 /* FABKitProtocol.h in Headers */, DA88481B1CBAFA6200AB86E3 /* MGLGeometry_Private.h in Headers */, 3510FFF91D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.h in Headers */, - 404C26E71D89C55D000AA13D /* MGLTileSet_Private.h in Headers */, + DA72620B1DEEE3480043BB89 /* MGLOpenGLStyleLayer.h in Headers */, + 404C26E71D89C55D000AA13D /* MGLTileSource_Private.h in Headers */, DA88485C1CBAFB9800AB86E3 /* MGLFaux3DUserLocationAnnotationView.h in Headers */, DA8848871CBB033F00AB86E3 /* Fabric.h in Headers */, 35305D4A1D22AA6A0007D005 /* NSData+MGLAdditions.h in Headers */, 359F57461D2FDDA6005217F1 /* MGLUserLocationAnnotationView_Private.h in Headers */, - 404C26E21D89B877000AA13D /* MGLTileSet.h in Headers */, + 404C26E21D89B877000AA13D /* MGLTileSource.h in Headers */, DA8848841CBB033F00AB86E3 /* FABAttributes.h in Headers */, DA8847FD1CBAFA5100AB86E3 /* MGLTilePyramidOfflineRegion.h in Headers */, DA88482F1CBAFA6200AB86E3 /* NSProcessInfo+MGLAdditions.h in Headers */, DA8848601CBAFC2E00AB86E3 /* Mapbox.h in Headers */, + DAF0D8101DFE0EA000B28378 /* MGLRasterSource_Private.h in Headers */, 350098BB1D480108004B2AF0 /* MGLVectorSource.h in Headers */, DA8847F61CBAFA5100AB86E3 /* MGLOfflineStorage.h in Headers */, DAD1656E1CF41981001FF4B9 /* MGLFeature_Private.h in Headers */, @@ -1529,10 +1566,9 @@ DABFB8641CBE99E500D62B32 /* MGLOfflineStorage.h in Headers */, DAD165791CF4CDFF001FF4B9 /* MGLShapeCollection.h in Headers */, 4049C29E1DB6CD6C00B3F799 /* MGLPointCollection.h in Headers */, - 3566C7671D4A77BA008152BC /* MGLGeoJSONSource.h in Headers */, + 3566C7671D4A77BA008152BC /* MGLShapeSource.h in Headers */, DA35A29F1CC9E94C00E826B2 /* MGLCoordinateFormatter.h in Headers */, - DABFB8711CBE9A0F00D62B32 /* MGLMapView+MGLCustomStyleLayerAdditions.h in Headers */, - 404C26E31D89B877000AA13D /* MGLTileSet.h in Headers */, + 404C26E31D89B877000AA13D /* MGLTileSource.h in Headers */, DABFB8611CBE99E500D62B32 /* MGLMultiPoint.h in Headers */, 3510FFF11D6D9D8C00F413B2 /* NSExpression+MGLAdditions.h in Headers */, 35E0CFE71D3E501500188327 /* MGLStyle_Private.h in Headers */, @@ -1553,9 +1589,10 @@ DABFB8701CBE9A0F00D62B32 /* MGLMapView+IBAdditions.h in Headers */, 353AFA151D65AB17005A69F4 /* NSDate+MGLAdditions.h in Headers */, 3510FFFA1D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.h in Headers */, + DA72620C1DEEE3480043BB89 /* MGLOpenGLStyleLayer.h in Headers */, 35CE61831D4165D9004F2359 /* UIColor+MGLAdditions.h in Headers */, DABFB8671CBE99E500D62B32 /* MGLPolygon.h in Headers */, - 404C26E81D89C55D000AA13D /* MGLTileSet_Private.h in Headers */, + 404C26E81D89C55D000AA13D /* MGLTileSource_Private.h in Headers */, DAAF722C1DA903C700312FA4 /* MGLStyleValue.h in Headers */, DABFB8651CBE99E500D62B32 /* MGLOverlay.h in Headers */, 35E79F211D41266300957B9E /* MGLStyleLayer_Private.h in Headers */, @@ -1566,11 +1603,13 @@ 353933F31D3FB753003F57D7 /* MGLCircleStyleLayer.h in Headers */, 3538AA1E1D542239008EC33D /* MGLForegroundStyleLayer.h in Headers */, 30E578181DAA85520050F07E /* UIImage+MGLAdditions.h in Headers */, - 40F887711D7A1E59008ECB67 /* MGLGeoJSONSource_Private.h in Headers */, + 40F887711D7A1E59008ECB67 /* MGLShapeSource_Private.h in Headers */, DABFB8631CBE99E500D62B32 /* MGLOfflineRegion.h in Headers */, DA35A2B21CCA141D00E826B2 /* MGLCompassDirectionFormatter.h in Headers */, + DAF0D8141DFE0EC500B28378 /* MGLVectorSource_Private.h in Headers */, DABFB8731CBE9A9900D62B32 /* Mapbox.h in Headers */, 354B83971D2E873E005D9406 /* MGLUserLocationAnnotationView.h in Headers */, + DAF0D8111DFE0EA000B28378 /* MGLRasterSource_Private.h in Headers */, DABFB86B1CBE99E500D62B32 /* MGLTilePyramidOfflineRegion.h in Headers */, 4018B1CB1CDC288E00F666AF /* MGLAnnotationView.h in Headers */, DABFB85F1CBE99E500D62B32 /* MGLGeometry.h in Headers */, @@ -1585,7 +1624,9 @@ DABFB86E1CBE9A0F00D62B32 /* MGLCalloutView.h in Headers */, DABFB8601CBE99E500D62B32 /* MGLMapCamera.h in Headers */, DA737EE21D056A4E005BDA16 /* MGLMapViewDelegate.h in Headers */, + DAF0D8191DFE6B2800B28378 /* MGLAttributionInfo_Private.h in Headers */, DABFB86A1CBE99E500D62B32 /* MGLStyle.h in Headers */, + DA00FC8F1D5EEB0D009AABC8 /* MGLAttributionInfo.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1809,6 +1850,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + DA2784FC1DF02FF4001D5B8D /* Media.xcassets in Resources */, 353BAEF71D646370009A8DA9 /* amsterdam.geojson in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1895,6 +1937,7 @@ buildActionMask = 2147483647; files = ( DA2E88631CC0382C00F24E7B /* MGLOfflineRegionTests.m in Sources */, + 3599A3E61DF708BC00E77FB2 /* MGLStyleValueTests.m in Sources */, DA2E88651CC0382C00F24E7B /* MGLStyleTests.mm in Sources */, DA2E88611CC0382C00F24E7B /* MGLGeometryTests.mm in Sources */, 357579801D501E09000B822E /* MGLFillStyleLayerTests.m in Sources */, @@ -1903,11 +1946,12 @@ DA35A2C61CCA9F8300E826B2 /* MGLCompassDirectionFormatterTests.m in Sources */, 3575798E1D502EC7000B822E /* MGLRuntimeStylingHelper.m in Sources */, 4085AF091D933DEA00F11B22 /* MGLTileSetTests.mm in Sources */, + DAEDC4341D603417000224FF /* MGLAttributionInfoTests.m in Sources */, 357579851D502AF5000B822E /* MGLSymbolStyleLayerTests.m in Sources */, 357579871D502AFE000B822E /* MGLLineStyleLayerTests.m in Sources */, 357579891D502B06000B822E /* MGLCircleStyleLayerTests.m in Sources */, DA2207BF1DC0805F0002F84D /* MGLStyleValueTests.swift in Sources */, - 40CFA6511D7875BB008103BD /* MGLGeoJSONSourceTests.mm in Sources */, + 40CFA6511D7875BB008103BD /* MGLShapeSourceTests.mm in Sources */, DA35A2C51CCA9F8300E826B2 /* MGLClockDirectionFormatterTests.m in Sources */, 35B8E08C1D6C8B5100E768D2 /* MGLFilterTests.mm in Sources */, DD58A4C61D822BD000E1F038 /* MGLExpressionTests.mm in Sources */, @@ -1939,10 +1983,11 @@ 35136D3C1D42272500C20EFD /* MGLCircleStyleLayer.mm in Sources */, 350098DE1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.mm in Sources */, DA6408DD1DA4E7D300908C90 /* MGLVectorStyleLayer.m in Sources */, - 3566C7681D4A77BA008152BC /* MGLGeoJSONSource.mm in Sources */, + 3566C7681D4A77BA008152BC /* MGLShapeSource.mm in Sources */, 400533021DB0862B0069F638 /* NSArray+MGLAdditions.mm in Sources */, 35136D421D42274500C20EFD /* MGLRasterStyleLayer.mm in Sources */, 3538AA1F1D542239008EC33D /* MGLForegroundStyleLayer.m in Sources */, + DA00FC901D5EEB0D009AABC8 /* MGLAttributionInfo.mm in Sources */, DA88482D1CBAFA6200AB86E3 /* NSBundle+MGLAdditions.m in Sources */, DA88485B1CBAFB9800AB86E3 /* MGLUserLocation.m in Sources */, 350098BD1D480108004B2AF0 /* MGLVectorSource.mm in Sources */, @@ -1950,7 +1995,7 @@ DA88488C1CBB037E00AB86E3 /* SMCalloutView.m in Sources */, 35136D4E1D4277FC00C20EFD /* MGLSource.mm in Sources */, DA35A2B81CCA9A5D00E826B2 /* MGLClockDirectionFormatter.m in Sources */, - DAD1657A1CF4CDFF001FF4B9 /* MGLShapeCollection.m in Sources */, + DAD1657A1CF4CDFF001FF4B9 /* MGLShapeCollection.mm in Sources */, 35136D451D42275100C20EFD /* MGLSymbolStyleLayer.mm in Sources */, 35599DED1D46F14E0048254D /* MGLStyleValue.mm in Sources */, DA8848211CBAFA6200AB86E3 /* MGLOfflinePack.mm in Sources */, @@ -1971,7 +2016,7 @@ DA88481F1CBAFA6200AB86E3 /* MGLMultiPoint.mm in Sources */, DA88482B1CBAFA6200AB86E3 /* MGLTypes.m in Sources */, 4018B1C71CDC287F00F666AF /* MGLAnnotationView.mm in Sources */, - 404C26E41D89B877000AA13D /* MGLTileSet.mm in Sources */, + 404C26E41D89B877000AA13D /* MGLTileSource.mm in Sources */, DA88481D1CBAFA6200AB86E3 /* MGLMapCamera.mm in Sources */, DA8848261CBAFA6200AB86E3 /* MGLPolygon.mm in Sources */, 35B82BFA1D6C5F8400B1B721 /* NSPredicate+MGLAdditions.mm in Sources */, @@ -1985,6 +2030,7 @@ DA88482A1CBAFA6200AB86E3 /* MGLTilePyramidOfflineRegion.mm in Sources */, 4049C29F1DB6CD6C00B3F799 /* MGLPointCollection.mm in Sources */, 35136D3F1D42273000C20EFD /* MGLLineStyleLayer.mm in Sources */, + DA72620D1DEEE3480043BB89 /* MGLOpenGLStyleLayer.mm in Sources */, DA88481A1CBAFA6200AB86E3 /* MGLAccountManager.m in Sources */, 3510FFFB1D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.mm in Sources */, DA8848271CBAFA6200AB86E3 /* MGLPolyline.mm in Sources */, @@ -2012,10 +2058,11 @@ 35136D3D1D42272500C20EFD /* MGLCircleStyleLayer.mm in Sources */, 350098DF1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.mm in Sources */, DA6408DE1DA4E7D300908C90 /* MGLVectorStyleLayer.m in Sources */, - 3566C7691D4A77BA008152BC /* MGLGeoJSONSource.mm in Sources */, + 3566C7691D4A77BA008152BC /* MGLShapeSource.mm in Sources */, 400533031DB086490069F638 /* NSArray+MGLAdditions.mm in Sources */, 35136D431D42274500C20EFD /* MGLRasterStyleLayer.mm in Sources */, 3538AA201D542239008EC33D /* MGLForegroundStyleLayer.m in Sources */, + DA00FC911D5EEB0D009AABC8 /* MGLAttributionInfo.mm in Sources */, DAA4E4201CBB730400178DFB /* MGLOfflinePack.mm in Sources */, DAA4E4331CBB730400178DFB /* MGLUserLocation.m in Sources */, 350098BE1D480108004B2AF0 /* MGLVectorSource.mm in Sources */, @@ -2023,7 +2070,7 @@ DAA4E4351CBB730400178DFB /* SMCalloutView.m in Sources */, 35136D4F1D4277FC00C20EFD /* MGLSource.mm in Sources */, DA35A2B91CCA9A5D00E826B2 /* MGLClockDirectionFormatter.m in Sources */, - DAD1657B1CF4CDFF001FF4B9 /* MGLShapeCollection.m in Sources */, + DAD1657B1CF4CDFF001FF4B9 /* MGLShapeCollection.mm in Sources */, DAA4E4251CBB730400178DFB /* MGLShape.mm in Sources */, 35136D461D42275100C20EFD /* MGLSymbolStyleLayer.mm in Sources */, 35599DEE1D46F14E0048254D /* MGLStyleValue.mm in Sources */, @@ -2044,7 +2091,7 @@ DAA4E4301CBB730400178DFB /* MGLLocationManager.m in Sources */, DAA4E4321CBB730400178DFB /* MGLMapView.mm in Sources */, DAA4E41E1CBB730400178DFB /* MGLMapCamera.mm in Sources */, - 404C26E51D89B877000AA13D /* MGLTileSet.mm in Sources */, + 404C26E51D89B877000AA13D /* MGLTileSource.mm in Sources */, 4018B1C81CDC287F00F666AF /* MGLAnnotationView.mm in Sources */, DAA4E4341CBB730400178DFB /* MGLFaux3DUserLocationAnnotationView.m in Sources */, 35B82BFB1D6C5F8400B1B721 /* NSPredicate+MGLAdditions.mm in Sources */, @@ -2058,6 +2105,7 @@ DAA4E4211CBB730400178DFB /* MGLOfflineStorage.mm in Sources */, 4049C2A01DB6CD6C00B3F799 /* MGLPointCollection.mm in Sources */, 35136D401D42273000C20EFD /* MGLLineStyleLayer.mm in Sources */, + DA72620E1DEEE3480043BB89 /* MGLOpenGLStyleLayer.mm in Sources */, DAA4E42F1CBB730400178DFB /* MGLCompactCalloutView.m in Sources */, 3510FFFC1D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.mm in Sources */, DAA4E4271CBB730400178DFB /* MGLTilePyramidOfflineRegion.mm in Sources */, @@ -2327,7 +2375,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.mapbox.test; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "test/test-Bridging-Header.h"; + SWIFT_OBJC_BRIDGING_HEADER = "../darwin/test/test-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 3.0; }; @@ -2350,7 +2398,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.mapbox.test; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "test/test-Bridging-Header.h"; + SWIFT_OBJC_BRIDGING_HEADER = "../darwin/test/test-Bridging-Header.h"; SWIFT_VERSION = 3.0; }; name = Release; diff --git a/platform/ios/jazzy.yml b/platform/ios/jazzy.yml index c19d9e388..0f7e9cced 100644 --- a/platform/ios/jazzy.yml +++ b/platform/ios/jazzy.yml @@ -63,12 +63,14 @@ custom_categories: - MGLStyleLayer - MGLSymbolStyleLayer - MGLVectorStyleLayer - - name: Data Sources + - name: Content Sources children: - - MGLSource - - MGLGeoJSONSource + - MGLAttributionInfo - MGLRasterSource - - MGLTileSet + - MGLShapeSource + - MGLSource + - MGLTileCoordinateSystem + - MGLTileSource - MGLVectorSource - name: Offline Maps children: diff --git a/platform/ios/originals/screenshot.sketch b/platform/ios/originals/screenshot.sketch new file mode 100644 index 000000000..6b938457f Binary files /dev/null and b/platform/ios/originals/screenshot.sketch differ diff --git a/platform/ios/originals/screenshots.sketch b/platform/ios/originals/screenshots.sketch deleted file mode 100644 index 9098b3db6..000000000 Binary files a/platform/ios/originals/screenshots.sketch and /dev/null differ diff --git a/platform/ios/resources/Base.lproj/Localizable.strings b/platform/ios/resources/Base.lproj/Localizable.strings index c4569fe23..63bed7e32 100644 --- a/platform/ios/resources/Base.lproj/Localizable.strings +++ b/platform/ios/resources/Base.lproj/Localizable.strings @@ -19,12 +19,6 @@ /* Compass abbreviation for north */ "COMPASS_NORTH" = "N"; -/* Copyright notice in attribution sheet */ -"COPY_MAPBOX" = "© Mapbox"; - -/* Copyright notice in attribution sheet */ -"COPY_OSM" = "© OpenStreetMap"; - /* Instructions in Interface Builder designable; {key}, {plist file name} */ "DESIGNABLE" = "To display a Mapbox-hosted map here, set %1$@ to your access token in %2$@\n\nFor detailed instructions, see:"; @@ -46,9 +40,6 @@ /* Map accessibility value */ "MAP_A11Y_VALUE" = "Zoom %1$dx\n%2$ld annotation(s) visible"; -/* Action in attribution sheet */ -"MAP_FEEDBACK" = "Improve This Map"; - /* Action sheet title */ "SDK_NAME" = "Mapbox iOS SDK"; diff --git a/platform/ios/screenshot.png b/platform/ios/screenshot.png index 6f5f7bb7d..62c04746d 100644 Binary files a/platform/ios/screenshot.png and b/platform/ios/screenshot.png differ diff --git a/platform/ios/scripts/document.sh b/platform/ios/scripts/document.sh index 4160749e2..fddf5abb0 100755 --- a/platform/ios/scripts/document.sh +++ b/platform/ios/scripts/document.sh @@ -32,6 +32,9 @@ mkdir -p ${OUTPUT} cp platform/ios/screenshot.png "${OUTPUT}" +DEFAULT_THEME="platform/darwin/docs/theme" +THEME=${JAZZY_THEME:-$DEFAULT_THEME} + jazzy \ --config platform/ios/jazzy.yml \ --sdk iphonesimulator \ @@ -40,8 +43,8 @@ jazzy \ --readme ${README} \ --documentation="platform/ios/docs/Info.plist Keys.md" \ --root-url https://www.mapbox.com/ios-sdk/api/${RELEASE_VERSION}/ \ - --theme platform/darwin/docs/theme \ + --theme ${THEME} \ --output ${OUTPUT} # https://github.com/realm/jazzy/issues/411 find ${OUTPUT} -name *.html -exec \ - perl -pi -e 's/Mapbox\s+(Docs|Reference)/Mapbox iOS SDK $1/' {} \; + perl -pi -e 's/BRANDLESS_DOCSET_TITLE/iOS SDK $1/, s/Mapbox\s+(Docs|Reference)/Mapbox iOS SDK $1/' {} \; diff --git a/platform/ios/src/MGLMapView+MGLCustomStyleLayerAdditions.h b/platform/ios/src/MGLMapView+MGLCustomStyleLayerAdditions.h deleted file mode 100644 index de4dc01f9..000000000 --- a/platform/ios/src/MGLMapView+MGLCustomStyleLayerAdditions.h +++ /dev/null @@ -1,26 +0,0 @@ -#import "MGLMapView.h" - -NS_ASSUME_NONNULL_BEGIN - -typedef void (^MGLCustomStyleLayerPreparationHandler)(void); - -typedef void (^MGLCustomStyleLayerDrawingHandler)(CGSize size, - CLLocationCoordinate2D centerCoordinate, - double zoomLevel, - CLLocationDirection direction, - CGFloat pitch, - CGFloat perspectiveSkew); - -typedef void (^MGLCustomStyleLayerCompletionHandler)(void); - -@interface MGLMapView (MGLCustomStyleLayerAdditions) - -- (void)insertCustomStyleLayerWithIdentifier:(NSString *)identifier preparationHandler:(MGLCustomStyleLayerPreparationHandler)preparation drawingHandler:(MGLCustomStyleLayerDrawingHandler)drawing completionHandler:(MGLCustomStyleLayerCompletionHandler)completion belowStyleLayerWithIdentifier:(nullable NSString *)otherIdentifier; - -- (void)removeCustomStyleLayerWithIdentifier:(NSString *)identifier; - -- (void)setCustomStyleLayersNeedDisplay; - -@end - -NS_ASSUME_NONNULL_END diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index fad354013..608acf016 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -55,6 +55,7 @@ #import "MGLCompactCalloutView.h" #import "MGLAnnotationContainerView.h" #import "MGLAnnotationContainerView_Private.h" +#import "MGLAttributionInfo.h" #include #include @@ -310,6 +311,8 @@ public: BOOL _delegateHasLineWidthsForShapeAnnotations; MGLCompassDirectionFormatter *_accessibilityCompassFormatter; + + NS_ARRAY_OF(MGLAttributionInfo *) *_attributionInfos; } #pragma mark - Setup & Teardown - @@ -378,6 +381,11 @@ public: self.styleURL = styleURL; } +- (mbgl::Map *)mbglMap +{ + return _mbglMap; +} + - (void)commonInit { MGLinitializeRunLoop(); @@ -1717,44 +1725,27 @@ public: - (void)showAttribution { - if ( ! self.attributionSheet) + self.attributionSheet = [[UIActionSheet alloc] initWithTitle:NSLocalizedStringWithDefaultValue(@"SDK_NAME", nil, nil, @"Mapbox iOS SDK", @"Action sheet title") + delegate:self + cancelButtonTitle:NSLocalizedStringWithDefaultValue(@"CANCEL", nil, nil, @"Cancel", @"") + destructiveButtonTitle:nil + otherButtonTitles:nil]; + + _attributionInfos = [self.style attributionInfosWithFontSize:[UIFont buttonFontSize] linkColor:nil]; + for (MGLAttributionInfo *info in _attributionInfos) { - self.attributionSheet = [[UIActionSheet alloc] initWithTitle:NSLocalizedStringWithDefaultValue(@"SDK_NAME", nil, nil, @"Mapbox iOS SDK", @"Action sheet title") - delegate:self - cancelButtonTitle:NSLocalizedStringWithDefaultValue(@"CANCEL", nil, nil, @"Cancel", @"") - destructiveButtonTitle:nil - otherButtonTitles: - NSLocalizedStringWithDefaultValue(@"COPY_MAPBOX", nil, nil, @"© Mapbox", @"Copyright notice in attribution sheet"), - NSLocalizedStringWithDefaultValue(@"COPY_OSM", nil, nil, @"© OpenStreetMap", @"Copyright notice in attribution sheet"), - NSLocalizedStringWithDefaultValue(@"MAP_FEEDBACK", nil, nil, @"Improve This Map", @"Action in attribution sheet"), - NSLocalizedStringWithDefaultValue(@"TELEMETRY_NAME", nil, nil, @"Mapbox Telemetry", @"Action in attribution sheet"), - nil]; - + NSString *title = [info.title.string capitalizedStringWithLocale:[NSLocale currentLocale]]; + [self.attributionSheet addButtonWithTitle:title]; } - + + [self.attributionSheet addButtonWithTitle:NSLocalizedStringWithDefaultValue(@"TELEMETRY_NAME", nil, nil, @"Mapbox Telemetry", @"Action in attribution sheet")]; + [self.attributionSheet showFromRect:self.attributionButton.frame inView:self animated:YES]; } - (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex { - if (buttonIndex == actionSheet.firstOtherButtonIndex) - { - [[UIApplication sharedApplication] openURL: - [NSURL URLWithString:@"https://www.mapbox.com/about/maps/"]]; - } - else if (buttonIndex == actionSheet.firstOtherButtonIndex + 1) - { - [[UIApplication sharedApplication] openURL: - [NSURL URLWithString:@"http://www.openstreetmap.org/about/"]]; - } - else if (buttonIndex == actionSheet.firstOtherButtonIndex + 2) - { - NSString *feedbackURL = [NSString stringWithFormat:@"https://www.mapbox.com/map-feedback/#/%.5f/%.5f/%i", - self.longitude, self.latitude, (int)round(self.zoomLevel + 1)]; - [[UIApplication sharedApplication] openURL: - [NSURL URLWithString:feedbackURL]]; - } - else if (buttonIndex == actionSheet.firstOtherButtonIndex + 3) + if (buttonIndex == actionSheet.numberOfButtons - 1) { NSString *message; NSString *participate; @@ -1780,6 +1771,19 @@ public: otherButtonTitles:NSLocalizedStringWithDefaultValue(@"TELEMETRY_MORE", nil, nil, @"Tell Me More", @"Telemetry prompt button"), optOut, nil]; [alert show]; } + else if (buttonIndex > 0) + { + MGLAttributionInfo *info = _attributionInfos[buttonIndex + actionSheet.firstOtherButtonIndex]; + NSURL *url = info.URL; + if (url) + { + if (info.feedbackLink) + { + url = [info feedbackURLAtCenterCoordinate:self.centerCoordinate zoomLevel:self.zoomLevel]; + } + [[UIApplication sharedApplication] openURL:url]; + } + } } - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex @@ -4562,7 +4566,23 @@ public: || self.userTrackingMode == MGLUserTrackingModeNone || self.userTrackingState != MGLUserTrackingStateChanged) { - [self deselectAnnotation:self.selectedAnnotation animated:NO]; + // Deselect annotation if it lies outside the viewport + if (self.selectedAnnotation) { + MGLAnnotationTag tag = [self annotationTagForAnnotation:self.selectedAnnotation]; + MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(tag); + MGLAnnotationView *annotationView = annotationContext.annotationView; + + CGRect rect = [self positioningRectForCalloutForAnnotationWithTag:tag]; + + if (annotationView) + { + rect = annotationView.frame; + } + + if ( ! CGRectIntersectsRect(rect, self.frame)) { + [self deselectAnnotation:self.selectedAnnotation animated:NO]; + } + } } if ( ! [self isSuppressingChangeDelimiters] && [self.delegate respondsToSelector:@selector(mapView:regionWillChangeAnimated:)]) @@ -4661,6 +4681,7 @@ public: [self.style didChangeValueForKey:@"layers"]; } [self updateAnnotationViews]; + [self updateCalloutView]; if ([self.delegate respondsToSelector:@selector(mapViewDidFinishRenderingFrame:fullyRendered:)]) { [self.delegate mapViewDidFinishRenderingFrame:self fullyRendered:(change == mbgl::MapChangeDidFinishRenderingFrameFullyRendered)]; @@ -4680,6 +4701,10 @@ public: } break; } + case mbgl::MapChangeSourceDidChange: + { + break; + } } } @@ -4728,8 +4753,8 @@ public: if (!annotationView) { // This will dequeue views if the delegate implements the dequeue call - MGLAnnotationView *annotationView = [self annotationViewForAnnotation:annotationContext.annotation]; - + annotationView = [self annotationViewForAnnotation:annotationContext.annotation]; + if (annotationView) { annotationView.mapView = self; @@ -4748,14 +4773,9 @@ public: annotationView.center = [self convertCoordinate:annotationContext.annotation.coordinate toPointToView:self]; } } - - CGPoint upperLeft = {_largestAnnotationViewSize.width,_largestAnnotationViewSize.height}; - CGPoint lowerRight = {CGRectGetWidth(self.bounds) + _largestAnnotationViewSize.width, - CGRectGetHeight(self.bounds) + _largestAnnotationViewSize.height}; - - CLLocationCoordinate2D upperLeftCoordinate = [self convertPoint:upperLeft toCoordinateFromView:self]; - CLLocationCoordinate2D lowerRightCoordinate = [self convertPoint:lowerRight toCoordinateFromView:self]; - + + MGLCoordinateBounds coordinateBounds = [self convertRect:viewPort toCoordinateBoundsFromView:self]; + // Enqueue (and move if required) offscreen annotation views for (id annotation in offscreenAnnotations) { @@ -4778,17 +4798,16 @@ public: // moved and the enqueue operation is avoided. This allows us to keep the performance benefit of // using the mbgl query result. It also forces views that have just gone offscreen to be cleared // fully from view. - if ((coordinate.latitude > upperLeftCoordinate.latitude || coordinate.latitude < lowerRightCoordinate.latitude) || - (coordinate.longitude < upperLeftCoordinate.longitude || coordinate.longitude > lowerRightCoordinate.longitude)) + if (MGLCoordinateInCoordinateBounds(coordinate, coordinateBounds)) { - CGRect adjustedFrame = annotationView.frame; - adjustedFrame.origin.x = -CGRectGetWidth(adjustedFrame) * 2.0; - annotationView.frame = adjustedFrame; - [self enqueueAnnotationViewForAnnotationContext:annotationContext]; + annotationView.center = [self convertCoordinate:annotationContext.annotation.coordinate toPointToView:self]; } else { - annotationView.center = [self convertCoordinate:annotationContext.annotation.coordinate toPointToView:self]; + CGRect adjustedFrame = annotationView.frame; + adjustedFrame.origin.x = CGRectGetWidth(annotationView.layer.presentationLayer.frame) * -2.0; + annotationView.frame = adjustedFrame; + [self enqueueAnnotationViewForAnnotationContext:annotationContext]; } } } @@ -4796,6 +4815,32 @@ public: [CATransaction commit]; } +- (void)updateCalloutView +{ + UIView *calloutView = self.calloutViewForSelectedAnnotation; + id annotation = calloutView.representedObject; + + if (calloutView && annotation) + { + MGLAnnotationTag tag = [self annotationTagForAnnotation:annotation]; + MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(tag); + MGLAnnotationView *annotationView = annotationContext.annotationView; + + CGRect rect = [self positioningRectForCalloutForAnnotationWithTag:tag]; + + if (annotationView) + { + rect = annotationView.frame; + } + + CGPoint point = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect)); + + if ( ! CGPointEqualToPoint(calloutView.center, point)) { + calloutView.center = point; + } + } +} + - (void)enqueueAnnotationViewForAnnotationContext:(MGLAnnotationContext &)annotationContext { MGLAnnotationView *annotationView = annotationContext.annotationView; @@ -5296,84 +5341,3 @@ private: } @end - -#pragma mark - MGLCustomStyleLayerAdditions methods - -class MGLCustomStyleLayerHandlers -{ -public: - MGLCustomStyleLayerHandlers(MGLCustomStyleLayerPreparationHandler p, - MGLCustomStyleLayerDrawingHandler d, - MGLCustomStyleLayerCompletionHandler f) - : prepare(p), draw(d), finish(f) {} - - MGLCustomStyleLayerPreparationHandler prepare; - MGLCustomStyleLayerDrawingHandler draw; - MGLCustomStyleLayerCompletionHandler finish; -}; - -void MGLPrepareCustomStyleLayer(void *context) -{ - MGLCustomStyleLayerPreparationHandler prepare = reinterpret_cast(context)->prepare; - if (prepare) - { - prepare(); - } -} - -void MGLDrawCustomStyleLayer(void *context, const mbgl::style::CustomLayerRenderParameters ¶ms) -{ - CGSize size = CGSizeMake(params.width, params.height); - CLLocationCoordinate2D centerCoordinate = CLLocationCoordinate2DMake(params.latitude, params.longitude); - double zoomLevel = params.zoom; - CLLocationDirection direction = mbgl::util::wrap(params.bearing, 0., 360.); - CGFloat pitch = params.pitch; - CGFloat perspectiveSkew = params.altitude; - MGLCustomStyleLayerDrawingHandler draw = reinterpret_cast(context)->draw; - if (draw) - { - draw(size, centerCoordinate, zoomLevel, direction, pitch, perspectiveSkew); - } -} - -void MGLFinishCustomStyleLayer(void *context) -{ - MGLCustomStyleLayerHandlers *handlers = reinterpret_cast(context); - MGLCustomStyleLayerCompletionHandler finish = handlers->finish; - if (finish) - { - finish(); - } - delete handlers; -} - -@implementation MGLMapView (MGLCustomStyleLayerAdditions) - -- (void)insertCustomStyleLayerWithIdentifier:(NSString *)identifier preparationHandler:(void (^)())preparation drawingHandler:(MGLCustomStyleLayerDrawingHandler)drawing completionHandler:(void (^)())completion belowStyleLayerWithIdentifier:(nullable NSString *)otherIdentifier -{ - NSAssert(identifier, @"Style layer needs an identifier"); - MGLCustomStyleLayerHandlers *context = new MGLCustomStyleLayerHandlers(preparation, drawing, completion); - try { - _mbglMap->addLayer(std::make_unique(identifier.UTF8String, MGLPrepareCustomStyleLayer, - MGLDrawCustomStyleLayer, MGLFinishCustomStyleLayer, context), - otherIdentifier ? mbgl::optional(otherIdentifier.UTF8String) : mbgl::optional()); - } catch (std::runtime_error & err) { - [NSException raise:@"MGLRedundantLayerIdentifierException" format:@"%s", err.what()]; - } -} - -- (void)removeCustomStyleLayerWithIdentifier:(NSString *)identifier -{ - _mbglMap->removeLayer(identifier.UTF8String); -} - -- (void)setCustomStyleLayersNeedDisplay -{ - [self setNeedsGLDisplay]; -} - -- (mbgl::Map *)mbglMap { - return _mbglMap; -} - -@end diff --git a/platform/ios/src/MGLMapboxEvents.m b/platform/ios/src/MGLMapboxEvents.m index 01c46b5c8..2c25cf0a6 100644 --- a/platform/ios/src/MGLMapboxEvents.m +++ b/platform/ios/src/MGLMapboxEvents.m @@ -656,12 +656,13 @@ const NSTimeInterval MGLFlushInterval = 180; double accuracy = 10000000; double lat = floor(loc.coordinate.latitude * accuracy) / accuracy; double lng = floor(loc.coordinate.longitude * accuracy) / accuracy; + double horizontalAccuracy = round(loc.horizontalAccuracy); NSString *formattedDate = [self.rfc3339DateFormatter stringFromDate:loc.timestamp]; [MGLMapboxEvents pushEvent:MGLEventTypeLocation withAttributes:@{MGLEventKeyCreated: formattedDate, MGLEventKeyLatitude: @(lat), MGLEventKeyLongitude: @(lng), MGLEventKeyAltitude: @(round(loc.altitude)), - MGLEventHorizontalAccuracy: @(loc.horizontalAccuracy)}]; + MGLEventHorizontalAccuracy: @(horizontalAccuracy)}]; } } diff --git a/platform/ios/src/Mapbox.h b/platform/ios/src/Mapbox.h index 766469531..69c718dde 100644 --- a/platform/ios/src/Mapbox.h +++ b/platform/ios/src/Mapbox.h @@ -19,7 +19,6 @@ FOUNDATION_EXPORT const unsigned char MapboxVersionString[]; #import "MGLMapCamera.h" #import "MGLMapView.h" #import "MGLMapView+IBAdditions.h" -#import "MGLMapView+MGLCustomStyleLayerAdditions.h" #import "MGLMapViewDelegate.h" #import "MGLMultiPoint.h" #import "MGLOfflinePack.h" @@ -42,9 +41,11 @@ FOUNDATION_EXPORT const unsigned char MapboxVersionString[]; #import "MGLRasterStyleLayer.h" #import "MGLCircleStyleLayer.h" #import "MGLBackgroundStyleLayer.h" +#import "MGLOpenGLStyleLayer.h" #import "MGLSource.h" +#import "MGLTileSource.h" #import "MGLVectorSource.h" -#import "MGLGeoJSONSource.h" +#import "MGLShapeSource.h" #import "MGLRasterSource.h" #import "MGLTilePyramidOfflineRegion.h" #import "MGLTypes.h" @@ -53,4 +54,4 @@ FOUNDATION_EXPORT const unsigned char MapboxVersionString[]; #import "NSValue+MGLAdditions.h" #import "NSValue+MGLStyleEnumAttributeAdditions.h" #import "MGLStyleValue.h" -#import "MGLTileSet.h" +#import "MGLAttributionInfo.h" diff --git a/platform/ios/src/UIImage+MGLAdditions.h b/platform/ios/src/UIImage+MGLAdditions.h index 411220c50..f291a302c 100644 --- a/platform/ios/src/UIImage+MGLAdditions.h +++ b/platform/ios/src/UIImage+MGLAdditions.h @@ -2,8 +2,14 @@ #include +NS_ASSUME_NONNULL_BEGIN + @interface UIImage (MGLAdditions) +- (nullable instancetype)initWithMGLSpriteImage:(const mbgl::SpriteImage *)spriteImage; + - (std::unique_ptr)mgl_spriteImage; @end + +NS_ASSUME_NONNULL_END diff --git a/platform/ios/src/UIImage+MGLAdditions.mm b/platform/ios/src/UIImage+MGLAdditions.mm index 215b23faf..7b5737f5e 100644 --- a/platform/ios/src/UIImage+MGLAdditions.mm +++ b/platform/ios/src/UIImage+MGLAdditions.mm @@ -2,6 +2,20 @@ @implementation UIImage (MGLAdditions) +- (nullable instancetype)initWithMGLSpriteImage:(const mbgl::SpriteImage *)spriteImage +{ + std::string png = encodePNG(spriteImage->image); + NSData *data = [[NSData alloc] initWithBytes:png.data() length:png.size()]; + if (self = [self initWithData:data scale:spriteImage->pixelRatio]) + { + if (spriteImage->sdf) + { + self = [self imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + } + } + return self; +} + - (std::unique_ptr)mgl_spriteImage { CGImageRef cgImage = self.CGImage; @@ -21,7 +35,8 @@ CGContextRelease(context); CGColorSpaceRelease(colorSpace); - return std::make_unique(std::move(cPremultipliedImage), float(self.scale)); + BOOL isTemplate = self.renderingMode == UIImageRenderingModeAlwaysTemplate; + return std::make_unique(std::move(cPremultipliedImage), float(self.scale), isTemplate); } @end diff --git a/platform/ios/test/test-Bridging-Header.h b/platform/ios/test/test-Bridging-Header.h deleted file mode 100644 index e11d920b1..000000000 --- a/platform/ios/test/test-Bridging-Header.h +++ /dev/null @@ -1,3 +0,0 @@ -// -// Use this file to import your target's public headers that you would like to expose to Swift. -// diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md index b20b79d62..2495cd0e0 100644 --- a/platform/macos/CHANGELOG.md +++ b/platform/macos/CHANGELOG.md @@ -19,13 +19,14 @@ * A new runtime styling API allows you to adjust the style and content of the base map dynamically. All the options available in [Mapbox Studio](https://www.mapbox.com/studio/) are now exposed via MGLStyle and subclasses of MGLStyleLayer and MGLSource. ([#5727](https://github.com/mapbox/mapbox-gl-native/pull/5727)) * MGLMapView’s `styleURL` property can now be set to an absolute file URL. ([#6026](https://github.com/mapbox/mapbox-gl-native/pull/6026)) -* GeoJSON sources specified by the stylesheet at design time now support `cluster`, `clusterMaxZoom`, and `clusterRadius` attributes for clustering point features on the base map. ([#5724](https://github.com/mapbox/mapbox-gl-native/pull/5724)) +* MGLShapeSource objects, as well as GeoJSON sources specified by the stylesheet at design time, now support `cluster`, `clusterMaxZoom`, and `clusterRadius` attributes for clustering point features on the base map. ([#5724](https://github.com/mapbox/mapbox-gl-native/pull/5724)) * TileJSON manifests can now specify `"scheme": "tms"` to indicate the use of [TMS](https://en.wikipedia.org/wiki/Tile_Map_Service) coordinates. ([#2270](https://github.com/mapbox/mapbox-gl-native/pull/2270)) * Fixed an issue causing abstract `MGLMultiPointFeature` objects to be returned in feature query results. Now concrete `MGLPointCollectionFeature` objects are returned. ([#6742](https://github.com/mapbox/mapbox-gl-native/pull/6742)) * Fixed rendering artifacts and missing glyphs that occurred after viewing a large number of CJK characters on the map. ([#5908](https://github.com/mapbox/mapbox-gl-native/pull/5908)) * Fixed an issue where the style zoom levels were not respected when deciding when to render a layer. ([#5811](https://github.com/mapbox/mapbox-gl-native/issues/5811)) * Fixed an issue where feature querying sometimes failed to return the expected features when the map was tilted. ([#6773](https://github.com/mapbox/mapbox-gl-native/pull/6773)) * MGLFeature’s `attributes` and `identifier` properties are now writable. ([#6728](https://github.com/mapbox/mapbox-gl-native/pull/6728)) +* Attribution views now display the correct attribution for the current style. ([#5999](https://github.com/mapbox/mapbox-gl-native/pull/5999)) * If MGLMapView is unable to obtain or parse a style, it now calls its delegate’s `-mapViewDidFailLoadingMap:withError:` method. ([#6145](https://github.com/mapbox/mapbox-gl-native/pull/6145)) * Added the `-[MGLMapViewDelegate mapView:didFinishLoadingStyle:]` delegate method, which offers the earliest opportunity to modify the layout or appearance of the current style before the map view is displayed to the user. ([#6636](https://github.com/mapbox/mapbox-gl-native/pull/6636)) * Fixed an issue causing stepwise zoom functions to be misinterpreted. ([#6328](https://github.com/mapbox/mapbox-gl-native/pull/6328)) @@ -38,7 +39,7 @@ ### Annotations * Added `showAnnotations:animated:` and `showAnnotations:edgePadding:animated:`, which moves the map viewport to show the specified annotations. ([#5749](https://github.com/mapbox/mapbox-gl-native/pull/5749)) -* Added new methods to MGLMultiPoint for changing or appending vertices along polyline annotations and the exteriors of polygon annotations. ([#6565](https://github.com/mapbox/mapbox-gl-native/pull/6565)) +* Added new methods to MGLMultiPoint for changing the vertices along a polyline annotation or the exterior of a polygon annotation. ([#6565](https://github.com/mapbox/mapbox-gl-native/pull/6565)) * Added new APIs to MGLMapView to query for visible annotations. ([6061](https://github.com/mapbox/mapbox-gl-native/pull/6061)) * Deprecated `-[MGLMapViewDelegate mapView:alphaForShapeAnnotation:]` in favor of specifying an alpha component via `-[MGLMapViewDelegate mapView:strokeColorForShapeAnnotation:]` or `-[MGLMapViewDelegate mapView:fillColorForPolygonAnnotation:]`. ([#6706](https://github.com/mapbox/mapbox-gl-native/pull/6706)) * Various method arguments that are represented as C arrays of `CLLocationCoordinate2D` instances have been marked `const` to streamline bridging to Swift. ([#7215](https://github.com/mapbox/mapbox-gl-native/pull/7215)) diff --git a/platform/macos/INSTALL.md b/platform/macos/INSTALL.md index 665af128c..a4b944611 100644 --- a/platform/macos/INSTALL.md +++ b/platform/macos/INSTALL.md @@ -28,6 +28,7 @@ In a storyboard or XIB: 3. MGLMapView needs to be layer-backed: * You can make the window layer-backed by selecting the window and checking Full Size Content View in the Attributes inspector. This allows the map view to underlap the title bar and toolbar. * Alternatively, if you don’t want the entire window to be layer-backed, you can make just the map view layer-backed by selecting it and checking its entry under the View Effects inspector’s Core Animation Layer section. +4. Add a map feedback item to your Help menu. (Drag Menu Item from the Object library into Main Menu ‣ Help ‣ Menu.) Title it “Improve This Map” or similar, and connect it to the `giveFeedback:` action of First Responder. If you need to manipulate the map view programmatically: diff --git a/platform/macos/app/Base.lproj/MainMenu.xib b/platform/macos/app/Base.lproj/MainMenu.xib index cb9905d4a..9faf1ba04 100644 --- a/platform/macos/app/Base.lproj/MainMenu.xib +++ b/platform/macos/app/Base.lproj/MainMenu.xib @@ -537,6 +537,12 @@ + + + + + + diff --git a/platform/macos/app/LimeGreenStyleLayer.h b/platform/macos/app/LimeGreenStyleLayer.h new file mode 100644 index 000000000..35480963a --- /dev/null +++ b/platform/macos/app/LimeGreenStyleLayer.h @@ -0,0 +1,5 @@ +#import + +@interface LimeGreenStyleLayer : MGLOpenGLStyleLayer + +@end diff --git a/platform/macos/app/LimeGreenStyleLayer.m b/platform/macos/app/LimeGreenStyleLayer.m new file mode 100644 index 000000000..0d2e642db --- /dev/null +++ b/platform/macos/app/LimeGreenStyleLayer.m @@ -0,0 +1,60 @@ +#import "LimeGreenStyleLayer.h" + +#include +#include + +@implementation LimeGreenStyleLayer { + GLuint _program; + GLuint _vertexShader; + GLuint _fragmentShader; + GLuint _buffer; + GLuint _aPos; +} + +- (void)didMoveToMapView:(MGLMapView *)mapView { + static const GLchar *vertexShaderSource = "attribute vec2 a_pos; void main() { gl_Position = vec4(a_pos, 0, 1); }"; + static const GLchar *fragmentShaderSource = "void main() { gl_FragColor = vec4(0, 1, 0, 1); }"; + + _program = glCreateProgram(); + _vertexShader = glCreateShader(GL_VERTEX_SHADER); + _fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + + glShaderSource(_vertexShader, 1, &vertexShaderSource, NULL); + glCompileShader(_vertexShader); + glAttachShader(_program, _vertexShader); + glShaderSource(_fragmentShader, 1, &fragmentShaderSource, NULL); + glCompileShader(_fragmentShader); + glAttachShader(_program, _fragmentShader); + glLinkProgram(_program); + _aPos = glGetAttribLocation(_program, "a_pos"); + + GLfloat background[] = { -1,-1, 1,-1, -1,1, 1,1 }; + glGenBuffers(1, &_buffer); + glBindBuffer(GL_ARRAY_BUFFER, _buffer); + glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), background, GL_STATIC_DRAW); +} + +- (void)drawInMapView:(MGLMapView *)mapView withContext:(MGLStyleLayerDrawingContext)context { + glUseProgram(_program); + glBindBuffer(GL_ARRAY_BUFFER, _buffer); + glEnableVertexAttribArray(_aPos); + glVertexAttribPointer(_aPos, 2, GL_FLOAT, GL_FALSE, 0, NULL); + glDisable(GL_STENCIL_TEST); + glDisable(GL_DEPTH_TEST); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +} + +- (void)willMoveFromMapView:(MGLMapView *)mapView { + if (!_program) { + return; + } + + glDeleteBuffers(1, &_buffer); + glDetachShader(_program, _vertexShader); + glDetachShader(_program, _fragmentShader); + glDeleteShader(_vertexShader); + glDeleteShader(_fragmentShader); + glDeleteProgram(_program); +} + +@end diff --git a/platform/macos/app/MapDocument.m b/platform/macos/app/MapDocument.m index d2e6a0f81..2c3161077 100644 --- a/platform/macos/app/MapDocument.m +++ b/platform/macos/app/MapDocument.m @@ -1,6 +1,7 @@ #import "MapDocument.h" #import "AppDelegate.h" +#import "LimeGreenStyleLayer.h" #import "DroppedPinAnnotation.h" #import @@ -604,6 +605,37 @@ NS_ARRAY_OF(id ) *MBXFlattenedShapes(NS_ARRAY_OF(id ) *MBXFlattenedShapes(NS_ARRAY_OF(id ) *MBXFlattenedShapes(NS_ARRAY_OF(id valueWithRawValue:[NSColor greenColor]]; fillLayer.predicate = [NSPredicate predicateWithFormat:@"%K == %@", @"type", @"park"]; [self.mapView.style addLayer:fillLayer]; + + NSImage *image = [NSImage imageNamed:NSImageNameIChatTheaterTemplate]; + [self.mapView.style setImage:image forName:NSImageNameIChatTheaterTemplate]; + + MGLSource *streetsSource = [self.mapView.style sourceWithIdentifier:@"composite"]; + MGLSymbolStyleLayer *theaterLayer = [[MGLSymbolStyleLayer alloc] initWithIdentifier:@"theaters" source:streetsSource]; + theaterLayer.sourceLayerIdentifier = @"poi_label"; + theaterLayer.predicate = [NSPredicate predicateWithFormat:@"maki == 'theatre'"]; + theaterLayer.iconImageName = [MGLStyleValue valueWithRawValue:NSImageNameIChatTheaterTemplate]; + theaterLayer.iconScale = [MGLStyleValue valueWithRawValue:@2]; + theaterLayer.iconColor = [MGLStyleValue valueWithStops:@{ + @16.0: [MGLStyleValue valueWithRawValue:[NSColor redColor]], + @18.0: [MGLStyleValue valueWithRawValue:[NSColor yellowColor]], + @20.0: [MGLStyleValue valueWithRawValue:[NSColor blackColor]], + }]; + [self.mapView.style addLayer:theaterLayer]; } - (IBAction)dropPin:(NSMenuItem *)sender { @@ -876,6 +915,9 @@ NS_ARRAY_OF(id ) *MBXFlattenedShapes(NS_ARRAY_OF(id 0; } diff --git a/platform/macos/jazzy.yml b/platform/macos/jazzy.yml index 42f978283..9a7d258f7 100644 --- a/platform/macos/jazzy.yml +++ b/platform/macos/jazzy.yml @@ -57,12 +57,14 @@ custom_categories: - MGLStyleLayer - MGLSymbolStyleLayer - MGLVectorStyleLayer - - name: Data Sources + - name: Content Sources children: - - MGLSource - - MGLGeoJSONSource + - MGLAttributionInfo - MGLRasterSource - - MGLTileSet + - MGLShapeSource + - MGLSource + - MGLTileCoordinateSystem + - MGLTileSource - MGLVectorSource - name: Offline Maps children: diff --git a/platform/macos/macos.xcodeproj/project.pbxproj b/platform/macos/macos.xcodeproj/project.pbxproj index ede5503fa..106c37099 100644 --- a/platform/macos/macos.xcodeproj/project.pbxproj +++ b/platform/macos/macos.xcodeproj/project.pbxproj @@ -15,8 +15,8 @@ 352742821D4C243B00A1ECE6 /* MGLSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 352742801D4C243B00A1ECE6 /* MGLSource.mm */; }; 352742851D4C244700A1ECE6 /* MGLRasterSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 352742831D4C244700A1ECE6 /* MGLRasterSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; 352742861D4C244700A1ECE6 /* MGLRasterSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 352742841D4C244700A1ECE6 /* MGLRasterSource.mm */; }; - 352742891D4C245800A1ECE6 /* MGLGeoJSONSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 352742871D4C245800A1ECE6 /* MGLGeoJSONSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3527428A1D4C245800A1ECE6 /* MGLGeoJSONSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 352742881D4C245800A1ECE6 /* MGLGeoJSONSource.mm */; }; + 352742891D4C245800A1ECE6 /* MGLShapeSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 352742871D4C245800A1ECE6 /* MGLShapeSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3527428A1D4C245800A1ECE6 /* MGLShapeSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 352742881D4C245800A1ECE6 /* MGLShapeSource.mm */; }; 3527428D1D4C24AB00A1ECE6 /* MGLCircleStyleLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 3527428B1D4C24AB00A1ECE6 /* MGLCircleStyleLayer.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3527428E1D4C24AB00A1ECE6 /* MGLCircleStyleLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3527428C1D4C24AB00A1ECE6 /* MGLCircleStyleLayer.mm */; }; 352742A11D4C25BD00A1ECE6 /* MGLStyleValue.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3527429E1D4C25BD00A1ECE6 /* MGLStyleValue.mm */; }; @@ -34,6 +34,7 @@ 35602C001D3EA9B40050646F /* MGLForegroundStyleLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 35602BFD1D3EA9B40050646F /* MGLForegroundStyleLayer.h */; settings = {ATTRIBUTES = (Public, ); }; }; 35602C011D3EA9B40050646F /* MGLForegroundStyleLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 35602BFE1D3EA9B40050646F /* MGLForegroundStyleLayer.m */; }; 35724FC41D630502002A4AB4 /* amsterdam.geojson in Resources */ = {isa = PBXBuildFile; fileRef = 358EB3AE1D61F0DB00E46D9C /* amsterdam.geojson */; }; + 3599A3E81DF70E2000E77FB2 /* MGLStyleValueTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3599A3E71DF70E2000E77FB2 /* MGLStyleValueTests.m */; }; 35C5D8471D6DD66D00E95907 /* NSComparisonPredicate+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 35C5D8431D6DD66D00E95907 /* NSComparisonPredicate+MGLAdditions.h */; }; 35C5D8481D6DD66D00E95907 /* NSComparisonPredicate+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35C5D8441D6DD66D00E95907 /* NSComparisonPredicate+MGLAdditions.mm */; }; 35C5D8491D6DD66D00E95907 /* NSCompoundPredicate+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 35C5D8451D6DD66D00E95907 /* NSCompoundPredicate+MGLAdditions.h */; }; @@ -59,8 +60,11 @@ 5548BE781D09E718005DDE81 /* libmbgl-core.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAE6C3451CC31D1200DB3429 /* libmbgl-core.a */; }; 558F18221D0B13B100123F46 /* libmbgl-loop.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 558F18211D0B13B000123F46 /* libmbgl-loop.a */; }; 55D9B4B11D005D3900C1CCE2 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 55D9B4B01D005D3900C1CCE2 /* libz.tbd */; }; + DA00FC8A1D5EEAC3009AABC8 /* MGLAttributionInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DA00FC881D5EEAC3009AABC8 /* MGLAttributionInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DA00FC8B1D5EEAC3009AABC8 /* MGLAttributionInfo.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA00FC891D5EEAC3009AABC8 /* MGLAttributionInfo.mm */; }; DA0CD58E1CF56F5800A5F5A5 /* MGLFeatureTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA0CD58D1CF56F5800A5F5A5 /* MGLFeatureTests.mm */; }; DA2207BC1DC076940002F84D /* MGLStyleValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA2207BB1DC076940002F84D /* MGLStyleValueTests.swift */; }; + DA2784FE1DF03060001D5B8D /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DA2784FD1DF03060001D5B8D /* Media.xcassets */; }; DA2DBBCB1D51E30A00D38FF9 /* MGLStyleLayerTests.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA2DBBCA1D51E30A00D38FF9 /* MGLStyleLayerTests.xib */; }; DA35A2A41CC9EB1A00E826B2 /* MGLCoordinateFormatter.h in Headers */ = {isa = PBXBuildFile; fileRef = DA35A2A31CC9EB1A00E826B2 /* MGLCoordinateFormatter.h */; settings = {ATTRIBUTES = (Public, ); }; }; DA35A2A61CC9EB2700E826B2 /* MGLCoordinateFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = DA35A2A51CC9EB2700E826B2 /* MGLCoordinateFormatter.m */; }; @@ -73,21 +77,25 @@ DA35A2C21CCA9F4A00E826B2 /* MGLClockDirectionFormatterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA35A2C11CCA9F4A00E826B2 /* MGLClockDirectionFormatterTests.m */; }; DA35A2CF1CCAAED300E826B2 /* NSValue+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = DA35A2CD1CCAAED300E826B2 /* NSValue+MGLAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; DA35A2D01CCAAED300E826B2 /* NSValue+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = DA35A2CE1CCAAED300E826B2 /* NSValue+MGLAdditions.m */; }; - DA551B821DB496AC0009AFAF /* MGLTileSet.h in Headers */ = {isa = PBXBuildFile; fileRef = DA551B7F1DB496AC0009AFAF /* MGLTileSet.h */; }; - DA551B831DB496AC0009AFAF /* MGLTileSet_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA551B801DB496AC0009AFAF /* MGLTileSet_Private.h */; }; - DA551B841DB496AC0009AFAF /* MGLTileSet.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA551B811DB496AC0009AFAF /* MGLTileSet.mm */; }; + DA551B821DB496AC0009AFAF /* MGLTileSource.h in Headers */ = {isa = PBXBuildFile; fileRef = DA551B7F1DB496AC0009AFAF /* MGLTileSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DA551B831DB496AC0009AFAF /* MGLTileSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA551B801DB496AC0009AFAF /* MGLTileSource_Private.h */; }; + DA551B841DB496AC0009AFAF /* MGLTileSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA551B811DB496AC0009AFAF /* MGLTileSource.mm */; }; DA5589771D320C41006B7F64 /* wms.json in Resources */ = {isa = PBXBuildFile; fileRef = DA5589761D320C41006B7F64 /* wms.json */; }; DA6408D71DA4E5DA00908C90 /* MGLVectorStyleLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = DA6408D51DA4E5DA00908C90 /* MGLVectorStyleLayer.h */; settings = {ATTRIBUTES = (Public, ); }; }; DA6408D81DA4E5DA00908C90 /* MGLVectorStyleLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6408D61DA4E5DA00908C90 /* MGLVectorStyleLayer.m */; }; + DA7262071DEEDD460043BB89 /* MGLOpenGLStyleLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = DA7262051DEEDD460043BB89 /* MGLOpenGLStyleLayer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DA7262081DEEDD460043BB89 /* MGLOpenGLStyleLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA7262061DEEDD460043BB89 /* MGLOpenGLStyleLayer.mm */; }; + DA7DC9811DED5F5C0027472F /* MGLVectorSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA7DC9801DED5F5C0027472F /* MGLVectorSource_Private.h */; }; + DA7DC9831DED647F0027472F /* MGLRasterSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA7DC9821DED647F0027472F /* MGLRasterSource_Private.h */; }; DA839E971CC2E3400062CAFB /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DA839E961CC2E3400062CAFB /* AppDelegate.m */; }; DA839E9A1CC2E3400062CAFB /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DA839E991CC2E3400062CAFB /* main.m */; }; DA839E9D1CC2E3400062CAFB /* MapDocument.m in Sources */ = {isa = PBXBuildFile; fileRef = DA839E9C1CC2E3400062CAFB /* MapDocument.m */; }; DA839EA01CC2E3400062CAFB /* MapDocument.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA839E9E1CC2E3400062CAFB /* MapDocument.xib */; }; DA839EA21CC2E3400062CAFB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DA839EA11CC2E3400062CAFB /* Assets.xcassets */; }; DA839EA51CC2E3400062CAFB /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA839EA31CC2E3400062CAFB /* MainMenu.xib */; }; - DA87A9981DC9D88400810D09 /* MGLGeoJSONSourceTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA87A9961DC9D88400810D09 /* MGLGeoJSONSourceTests.mm */; }; + DA87A9981DC9D88400810D09 /* MGLShapeSourceTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA87A9961DC9D88400810D09 /* MGLShapeSourceTests.mm */; }; DA87A9991DC9D88400810D09 /* MGLTileSetTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA87A9971DC9D88400810D09 /* MGLTileSetTests.mm */; }; - DA87A99C1DC9D8DD00810D09 /* MGLGeoJSONSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA87A99B1DC9D8DD00810D09 /* MGLGeoJSONSource_Private.h */; }; + DA87A99C1DC9D8DD00810D09 /* MGLShapeSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA87A99B1DC9D8DD00810D09 /* MGLShapeSource_Private.h */; }; DA87A99E1DC9DC2100810D09 /* MGLFilterTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35C5D84B1D6DD75B00E95907 /* MGLFilterTests.mm */; }; DA87A9A01DC9DC6200810D09 /* MGLValueEvaluator.h in Headers */ = {isa = PBXBuildFile; fileRef = DA87A99F1DC9DC6200810D09 /* MGLValueEvaluator.h */; }; DA87A9A11DC9DCB400810D09 /* MGLRuntimeStylingHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F257B1D51C5F40010E6B5 /* MGLRuntimeStylingHelper.m */; }; @@ -116,12 +124,13 @@ DA8F25B21D51CB270010E6B5 /* NSValue+MGLStyleAttributeAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8F25A61D51CB270010E6B5 /* NSValue+MGLStyleAttributeAdditions.h */; }; DA8F25B31D51CB270010E6B5 /* NSValue+MGLStyleAttributeAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA8F25A71D51CB270010E6B5 /* NSValue+MGLStyleAttributeAdditions.mm */; }; DAA48EFD1D6A4731006A7E36 /* StyleLayerIconTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = DAA48EFC1D6A4731006A7E36 /* StyleLayerIconTransformer.m */; }; + DAB2CCE51DF632ED001B2FE1 /* LimeGreenStyleLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = DAB2CCE41DF632ED001B2FE1 /* LimeGreenStyleLayer.m */; }; DAC2ABC51CC6D343006D18C4 /* MGLAnnotationImage_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DAC2ABC41CC6D343006D18C4 /* MGLAnnotationImage_Private.h */; }; DACC22141CF3D3E200D220D9 /* MGLFeature.h in Headers */ = {isa = PBXBuildFile; fileRef = DACC22121CF3D3E200D220D9 /* MGLFeature.h */; settings = {ATTRIBUTES = (Public, ); }; }; DACC22151CF3D3E200D220D9 /* MGLFeature.mm in Sources */ = {isa = PBXBuildFile; fileRef = DACC22131CF3D3E200D220D9 /* MGLFeature.mm */; }; DACC22181CF3D4F700D220D9 /* MGLFeature_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DACC22171CF3D4F700D220D9 /* MGLFeature_Private.h */; }; DAD165741CF4CD7A001FF4B9 /* MGLShapeCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = DAD165721CF4CD7A001FF4B9 /* MGLShapeCollection.h */; settings = {ATTRIBUTES = (Public, ); }; }; - DAD165751CF4CD7A001FF4B9 /* MGLShapeCollection.m in Sources */ = {isa = PBXBuildFile; fileRef = DAD165731CF4CD7A001FF4B9 /* MGLShapeCollection.m */; }; + DAD165751CF4CD7A001FF4B9 /* MGLShapeCollection.mm in Sources */ = {isa = PBXBuildFile; fileRef = DAD165731CF4CD7A001FF4B9 /* MGLShapeCollection.mm */; }; DAE0DD7A1D5F015A005A6BB1 /* libmbgl-core.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAE6C3451CC31D1200DB3429 /* libmbgl-core.a */; }; DAE6C2E21CC304F900DB3429 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = DAE6C2E11CC304F900DB3429 /* Credits.rtf */; }; DAE6C2ED1CC3050F00DB3429 /* DroppedPinAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = DAE6C2E41CC3050F00DB3429 /* DroppedPinAnnotation.m */; }; @@ -179,7 +188,7 @@ DAE6C3A61CC31E9400DB3429 /* MGLMapViewDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = DAE6C3A21CC31E9400DB3429 /* MGLMapViewDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; DAE6C3B11CC31EF300DB3429 /* MGLAnnotationImage.m in Sources */ = {isa = PBXBuildFile; fileRef = DAE6C3A71CC31EF300DB3429 /* MGLAnnotationImage.m */; }; DAE6C3B21CC31EF300DB3429 /* MGLAttributionButton.h in Headers */ = {isa = PBXBuildFile; fileRef = DAE6C3A81CC31EF300DB3429 /* MGLAttributionButton.h */; }; - DAE6C3B31CC31EF300DB3429 /* MGLAttributionButton.m in Sources */ = {isa = PBXBuildFile; fileRef = DAE6C3A91CC31EF300DB3429 /* MGLAttributionButton.m */; }; + DAE6C3B31CC31EF300DB3429 /* MGLAttributionButton.mm in Sources */ = {isa = PBXBuildFile; fileRef = DAE6C3A91CC31EF300DB3429 /* MGLAttributionButton.mm */; }; DAE6C3B41CC31EF300DB3429 /* MGLCompassCell.h in Headers */ = {isa = PBXBuildFile; fileRef = DAE6C3AA1CC31EF300DB3429 /* MGLCompassCell.h */; }; DAE6C3B51CC31EF300DB3429 /* MGLCompassCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DAE6C3AB1CC31EF300DB3429 /* MGLCompassCell.m */; }; DAE6C3B61CC31EF300DB3429 /* MGLMapView_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DAE6C3AC1CC31EF300DB3429 /* MGLMapView_Private.h */; }; @@ -198,6 +207,10 @@ DAE6C3D61CC34C9900DB3429 /* MGLStyleTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = DAE6C3CC1CC34BD800DB3429 /* MGLStyleTests.mm */; }; DAED385F1D62CED700D7640F /* NSURL+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = DAED385D1D62CED700D7640F /* NSURL+MGLAdditions.h */; }; DAED38601D62CED700D7640F /* NSURL+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = DAED385E1D62CED700D7640F /* NSURL+MGLAdditions.m */; }; + DAEDC4321D6033F1000224FF /* MGLAttributionInfoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DAEDC4311D6033F1000224FF /* MGLAttributionInfoTests.m */; }; + DAEDC4371D606291000224FF /* MGLAttributionButtonTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DAEDC4361D606291000224FF /* MGLAttributionButtonTests.m */; }; + DAF0D80E1DFE0E5D00B28378 /* MGLPointCollection_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DAF0D80D1DFE0E5D00B28378 /* MGLPointCollection_Private.h */; }; + DAF0D8161DFE6B1800B28378 /* MGLAttributionInfo_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DAF0D8151DFE6B1800B28378 /* MGLAttributionInfo_Private.h */; }; DD0902B21DB1AC6400C5BDCE /* MGLNetworkConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = DD0902AF1DB1AC6400C5BDCE /* MGLNetworkConfiguration.m */; }; DD0902B31DB1AC6400C5BDCE /* MGLNetworkConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = DD0902B01DB1AC6400C5BDCE /* MGLNetworkConfiguration.h */; }; DD58A4C91D822C6700E1F038 /* MGLExpressionTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = DD58A4C71D822C6200E1F038 /* MGLExpressionTests.mm */; }; @@ -243,13 +256,14 @@ 352742801D4C243B00A1ECE6 /* MGLSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLSource.mm; sourceTree = ""; }; 352742831D4C244700A1ECE6 /* MGLRasterSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLRasterSource.h; sourceTree = ""; }; 352742841D4C244700A1ECE6 /* MGLRasterSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLRasterSource.mm; sourceTree = ""; }; - 352742871D4C245800A1ECE6 /* MGLGeoJSONSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLGeoJSONSource.h; sourceTree = ""; }; - 352742881D4C245800A1ECE6 /* MGLGeoJSONSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLGeoJSONSource.mm; sourceTree = ""; }; + 352742871D4C245800A1ECE6 /* MGLShapeSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLShapeSource.h; sourceTree = ""; }; + 352742881D4C245800A1ECE6 /* MGLShapeSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLShapeSource.mm; sourceTree = ""; }; 3527428B1D4C24AB00A1ECE6 /* MGLCircleStyleLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLCircleStyleLayer.h; sourceTree = ""; }; 3527428C1D4C24AB00A1ECE6 /* MGLCircleStyleLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLCircleStyleLayer.mm; sourceTree = ""; }; 3527429E1D4C25BD00A1ECE6 /* MGLStyleValue.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLStyleValue.mm; sourceTree = ""; }; 352903991D6C63B80002C7DF /* NSPredicate+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSPredicate+MGLAdditions.h"; sourceTree = ""; }; 3529039A1D6C63B80002C7DF /* NSPredicate+MGLAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSPredicate+MGLAdditions.mm"; sourceTree = ""; }; + 353722EB1DF850ED004D2F3F /* MGLStyleValueTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLStyleValueTests.h; sourceTree = ""; }; 3537CA731D3F93A600380318 /* MGLStyle_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLStyle_Private.h; sourceTree = ""; }; 3538AA211D542685008EC33D /* MGLStyleLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLStyleLayer.h; sourceTree = ""; }; 3538AA221D542685008EC33D /* MGLStyleLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLStyleLayer.mm; sourceTree = ""; }; @@ -261,6 +275,7 @@ 35602BFD1D3EA9B40050646F /* MGLForegroundStyleLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLForegroundStyleLayer.h; sourceTree = ""; }; 35602BFE1D3EA9B40050646F /* MGLForegroundStyleLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLForegroundStyleLayer.m; sourceTree = ""; }; 358EB3AE1D61F0DB00E46D9C /* amsterdam.geojson */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = amsterdam.geojson; path = ../../darwin/test/amsterdam.geojson; sourceTree = ""; }; + 3599A3E71DF70E2000E77FB2 /* MGLStyleValueTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLStyleValueTests.m; sourceTree = ""; }; 35C5D8431D6DD66D00E95907 /* NSComparisonPredicate+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSComparisonPredicate+MGLAdditions.h"; sourceTree = ""; }; 35C5D8441D6DD66D00E95907 /* NSComparisonPredicate+MGLAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSComparisonPredicate+MGLAdditions.mm"; sourceTree = ""; }; 35C5D8451D6DD66D00E95907 /* NSCompoundPredicate+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSCompoundPredicate+MGLAdditions.h"; sourceTree = ""; }; @@ -293,9 +308,12 @@ 558F18211D0B13B000123F46 /* libmbgl-loop.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libmbgl-loop.a"; path = "../../build/osx/Debug/libmbgl-loop.a"; sourceTree = ""; }; 55D9B4B01D005D3900C1CCE2 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; 55FE0E8D1D100A0900FD240B /* config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = config.xcconfig; path = ../../build/macos/config.xcconfig; sourceTree = ""; }; + DA00FC881D5EEAC3009AABC8 /* MGLAttributionInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAttributionInfo.h; sourceTree = ""; }; + DA00FC891D5EEAC3009AABC8 /* MGLAttributionInfo.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLAttributionInfo.mm; sourceTree = ""; }; DA0CD58D1CF56F5800A5F5A5 /* MGLFeatureTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLFeatureTests.mm; path = ../../darwin/test/MGLFeatureTests.mm; sourceTree = ""; }; DA2207BA1DC076930002F84D /* test-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "test-Bridging-Header.h"; sourceTree = ""; }; DA2207BB1DC076940002F84D /* MGLStyleValueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MGLStyleValueTests.swift; sourceTree = ""; }; + DA2784FD1DF03060001D5B8D /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Media.xcassets; path = ../../darwin/test/Media.xcassets; sourceTree = ""; }; DA2DBBCA1D51E30A00D38FF9 /* MGLStyleLayerTests.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MGLStyleLayerTests.xib; sourceTree = ""; }; DA35A2A31CC9EB1A00E826B2 /* MGLCoordinateFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLCoordinateFormatter.h; sourceTree = ""; }; DA35A2A51CC9EB2700E826B2 /* MGLCoordinateFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLCoordinateFormatter.m; sourceTree = ""; }; @@ -308,12 +326,16 @@ DA35A2C11CCA9F4A00E826B2 /* MGLClockDirectionFormatterTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLClockDirectionFormatterTests.m; path = ../../darwin/test/MGLClockDirectionFormatterTests.m; sourceTree = ""; }; DA35A2CD1CCAAED300E826B2 /* NSValue+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSValue+MGLAdditions.h"; sourceTree = ""; }; DA35A2CE1CCAAED300E826B2 /* NSValue+MGLAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSValue+MGLAdditions.m"; sourceTree = ""; }; - DA551B7F1DB496AC0009AFAF /* MGLTileSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLTileSet.h; sourceTree = ""; }; - DA551B801DB496AC0009AFAF /* MGLTileSet_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLTileSet_Private.h; sourceTree = ""; }; - DA551B811DB496AC0009AFAF /* MGLTileSet.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLTileSet.mm; sourceTree = ""; }; + DA551B7F1DB496AC0009AFAF /* MGLTileSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLTileSource.h; sourceTree = ""; }; + DA551B801DB496AC0009AFAF /* MGLTileSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLTileSource_Private.h; sourceTree = ""; }; + DA551B811DB496AC0009AFAF /* MGLTileSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLTileSource.mm; sourceTree = ""; }; DA5589761D320C41006B7F64 /* wms.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = wms.json; sourceTree = ""; }; DA6408D51DA4E5DA00908C90 /* MGLVectorStyleLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLVectorStyleLayer.h; sourceTree = ""; }; DA6408D61DA4E5DA00908C90 /* MGLVectorStyleLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLVectorStyleLayer.m; sourceTree = ""; }; + DA7262051DEEDD460043BB89 /* MGLOpenGLStyleLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLOpenGLStyleLayer.h; sourceTree = ""; }; + DA7262061DEEDD460043BB89 /* MGLOpenGLStyleLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLOpenGLStyleLayer.mm; sourceTree = ""; }; + DA7DC9801DED5F5C0027472F /* MGLVectorSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLVectorSource_Private.h; sourceTree = ""; }; + DA7DC9821DED647F0027472F /* MGLRasterSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLRasterSource_Private.h; sourceTree = ""; }; DA839E921CC2E3400062CAFB /* Mapbox GL.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Mapbox GL.app"; sourceTree = BUILT_PRODUCTS_DIR; }; DA839E951CC2E3400062CAFB /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; DA839E961CC2E3400062CAFB /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; @@ -324,9 +346,9 @@ DA839EA11CC2E3400062CAFB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; DA839EA41CC2E3400062CAFB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; DA839EA61CC2E3400062CAFB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - DA87A9961DC9D88400810D09 /* MGLGeoJSONSourceTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLGeoJSONSourceTests.mm; sourceTree = ""; }; + DA87A9961DC9D88400810D09 /* MGLShapeSourceTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLShapeSourceTests.mm; sourceTree = ""; }; DA87A9971DC9D88400810D09 /* MGLTileSetTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLTileSetTests.mm; sourceTree = ""; }; - DA87A99B1DC9D8DD00810D09 /* MGLGeoJSONSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLGeoJSONSource_Private.h; sourceTree = ""; }; + DA87A99B1DC9D8DD00810D09 /* MGLShapeSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLShapeSource_Private.h; sourceTree = ""; }; DA87A99F1DC9DC6200810D09 /* MGLValueEvaluator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLValueEvaluator.h; sourceTree = ""; }; DA8933A61CCD287300E68420 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MGLAnnotationCallout.xib; sourceTree = ""; }; DA8933AC1CCD290700E68420 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = ""; }; @@ -354,17 +376,19 @@ DA8F259B1D51CB000010E6B5 /* MGLStyleValue_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLStyleValue_Private.h; sourceTree = ""; }; DA8F25A61D51CB270010E6B5 /* NSValue+MGLStyleAttributeAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSValue+MGLStyleAttributeAdditions.h"; sourceTree = ""; }; DA8F25A71D51CB270010E6B5 /* NSValue+MGLStyleAttributeAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSValue+MGLStyleAttributeAdditions.mm"; sourceTree = ""; }; - DA8F25B51D51D2240010E6B5 /* MGLRuntimeStylingTests.m.ejs */ = {isa = PBXFileReference; lastKnownFileType = text; path = MGLRuntimeStylingTests.m.ejs; sourceTree = ""; }; + DA8F25B51D51D2240010E6B5 /* MGLStyleLayerTests.m.ejs */ = {isa = PBXFileReference; lastKnownFileType = text; name = MGLStyleLayerTests.m.ejs; path = ../test/MGLStyleLayerTests.m.ejs; sourceTree = ""; }; DA8F25B61D51D2240010E6B5 /* MGLStyleLayer.h.ejs */ = {isa = PBXFileReference; lastKnownFileType = text; path = MGLStyleLayer.h.ejs; sourceTree = ""; }; DA8F25B71D51D2240010E6B5 /* MGLStyleLayer.mm.ejs */ = {isa = PBXFileReference; lastKnownFileType = text; path = MGLStyleLayer.mm.ejs; sourceTree = ""; }; DAA48EFB1D6A4731006A7E36 /* StyleLayerIconTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleLayerIconTransformer.h; sourceTree = ""; }; DAA48EFC1D6A4731006A7E36 /* StyleLayerIconTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StyleLayerIconTransformer.m; sourceTree = ""; }; + DAB2CCE31DF632ED001B2FE1 /* LimeGreenStyleLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LimeGreenStyleLayer.h; sourceTree = ""; }; + DAB2CCE41DF632ED001B2FE1 /* LimeGreenStyleLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LimeGreenStyleLayer.m; sourceTree = ""; }; DAC2ABC41CC6D343006D18C4 /* MGLAnnotationImage_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAnnotationImage_Private.h; sourceTree = ""; }; DACC22121CF3D3E200D220D9 /* MGLFeature.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLFeature.h; sourceTree = ""; }; DACC22131CF3D3E200D220D9 /* MGLFeature.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLFeature.mm; sourceTree = ""; }; DACC22171CF3D4F700D220D9 /* MGLFeature_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLFeature_Private.h; sourceTree = ""; }; DAD165721CF4CD7A001FF4B9 /* MGLShapeCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLShapeCollection.h; sourceTree = ""; }; - DAD165731CF4CD7A001FF4B9 /* MGLShapeCollection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLShapeCollection.m; sourceTree = ""; }; + DAD165731CF4CD7A001FF4B9 /* MGLShapeCollection.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLShapeCollection.mm; sourceTree = ""; }; DAE6C2E11CC304F900DB3429 /* Credits.rtf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.rtf; path = Credits.rtf; sourceTree = ""; }; DAE6C2E31CC3050F00DB3429 /* DroppedPinAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DroppedPinAnnotation.h; sourceTree = ""; }; DAE6C2E41CC3050F00DB3429 /* DroppedPinAnnotation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DroppedPinAnnotation.m; sourceTree = ""; }; @@ -428,7 +452,7 @@ DAE6C3A21CC31E9400DB3429 /* MGLMapViewDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLMapViewDelegate.h; sourceTree = ""; }; DAE6C3A71CC31EF300DB3429 /* MGLAnnotationImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLAnnotationImage.m; sourceTree = ""; }; DAE6C3A81CC31EF300DB3429 /* MGLAttributionButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAttributionButton.h; sourceTree = ""; }; - DAE6C3A91CC31EF300DB3429 /* MGLAttributionButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLAttributionButton.m; sourceTree = ""; }; + DAE6C3A91CC31EF300DB3429 /* MGLAttributionButton.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLAttributionButton.mm; sourceTree = ""; }; DAE6C3AA1CC31EF300DB3429 /* MGLCompassCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLCompassCell.h; sourceTree = ""; }; DAE6C3AB1CC31EF300DB3429 /* MGLCompassCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLCompassCell.m; sourceTree = ""; }; DAE6C3AC1CC31EF300DB3429 /* MGLMapView_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLMapView_Private.h; sourceTree = ""; }; @@ -447,6 +471,10 @@ DAE6C3CC1CC34BD800DB3429 /* MGLStyleTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLStyleTests.mm; path = ../../darwin/test/MGLStyleTests.mm; sourceTree = ""; }; DAED385D1D62CED700D7640F /* NSURL+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSURL+MGLAdditions.h"; sourceTree = ""; }; DAED385E1D62CED700D7640F /* NSURL+MGLAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSURL+MGLAdditions.m"; sourceTree = ""; }; + DAEDC4311D6033F1000224FF /* MGLAttributionInfoTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLAttributionInfoTests.m; path = ../../darwin/test/MGLAttributionInfoTests.m; sourceTree = ""; }; + DAEDC4361D606291000224FF /* MGLAttributionButtonTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLAttributionButtonTests.m; sourceTree = ""; }; + DAF0D80D1DFE0E5D00B28378 /* MGLPointCollection_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLPointCollection_Private.h; sourceTree = ""; }; + DAF0D8151DFE6B1800B28378 /* MGLAttributionInfo_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAttributionInfo_Private.h; sourceTree = ""; }; DD0902AF1DB1AC6400C5BDCE /* MGLNetworkConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLNetworkConfiguration.m; sourceTree = ""; }; DD0902B01DB1AC6400C5BDCE /* MGLNetworkConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLNetworkConfiguration.h; sourceTree = ""; }; DD58A4C71D822C6200E1F038 /* MGLExpressionTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLExpressionTests.mm; path = ../../darwin/test/MGLExpressionTests.mm; sourceTree = ""; }; @@ -498,6 +526,8 @@ 35602BFE1D3EA9B40050646F /* MGLForegroundStyleLayer.m */, DA8F25891D51CA540010E6B5 /* MGLLineStyleLayer.h */, DA8F258A1D51CA540010E6B5 /* MGLLineStyleLayer.mm */, + DA7262051DEEDD460043BB89 /* MGLOpenGLStyleLayer.h */, + DA7262061DEEDD460043BB89 /* MGLOpenGLStyleLayer.mm */, DA8F258D1D51CA600010E6B5 /* MGLRasterStyleLayer.h */, DA8F258E1D51CA600010E6B5 /* MGLRasterStyleLayer.mm */, 3538AA211D542685008EC33D /* MGLStyleLayer.h */, @@ -525,19 +555,21 @@ 3527427E1D4C242B00A1ECE6 /* Sources */ = { isa = PBXGroup; children = ( + 352742831D4C244700A1ECE6 /* MGLRasterSource.h */, + DA7DC9821DED647F0027472F /* MGLRasterSource_Private.h */, + 352742841D4C244700A1ECE6 /* MGLRasterSource.mm */, + 352742871D4C245800A1ECE6 /* MGLShapeSource.h */, + DA87A99B1DC9D8DD00810D09 /* MGLShapeSource_Private.h */, + 352742881D4C245800A1ECE6 /* MGLShapeSource.mm */, 3527427F1D4C243B00A1ECE6 /* MGLSource.h */, DA8F25991D51CAD00010E6B5 /* MGLSource_Private.h */, 352742801D4C243B00A1ECE6 /* MGLSource.mm */, + DA551B7F1DB496AC0009AFAF /* MGLTileSource.h */, + DA551B801DB496AC0009AFAF /* MGLTileSource_Private.h */, + DA551B811DB496AC0009AFAF /* MGLTileSource.mm */, DA8F25951D51CAC70010E6B5 /* MGLVectorSource.h */, + DA7DC9801DED5F5C0027472F /* MGLVectorSource_Private.h */, DA8F25961D51CAC70010E6B5 /* MGLVectorSource.mm */, - 352742871D4C245800A1ECE6 /* MGLGeoJSONSource.h */, - DA87A99B1DC9D8DD00810D09 /* MGLGeoJSONSource_Private.h */, - 352742881D4C245800A1ECE6 /* MGLGeoJSONSource.mm */, - 352742831D4C244700A1ECE6 /* MGLRasterSource.h */, - 352742841D4C244700A1ECE6 /* MGLRasterSource.mm */, - DA551B7F1DB496AC0009AFAF /* MGLTileSet.h */, - DA551B801DB496AC0009AFAF /* MGLTileSet_Private.h */, - DA551B811DB496AC0009AFAF /* MGLTileSet.mm */, ); name = Sources; sourceTree = ""; @@ -584,6 +616,8 @@ DA839E961CC2E3400062CAFB /* AppDelegate.m */, DAE6C2E31CC3050F00DB3429 /* DroppedPinAnnotation.h */, DAE6C2E41CC3050F00DB3429 /* DroppedPinAnnotation.m */, + DAB2CCE31DF632ED001B2FE1 /* LimeGreenStyleLayer.h */, + DAB2CCE41DF632ED001B2FE1 /* LimeGreenStyleLayer.m */, DAE6C2E51CC3050F00DB3429 /* LocationCoordinate2DTransformer.h */, DAE6C2E61CC3050F00DB3429 /* LocationCoordinate2DTransformer.m */, DA839E9B1CC2E3400062CAFB /* MapDocument.h */, @@ -618,7 +652,7 @@ DA87A99A1DC9D88800810D09 /* Sources */ = { isa = PBXGroup; children = ( - DA87A9961DC9D88400810D09 /* MGLGeoJSONSourceTests.mm */, + DA87A9961DC9D88400810D09 /* MGLShapeSourceTests.mm */, DA87A9971DC9D88400810D09 /* MGLTileSetTests.mm */, ); name = Sources; @@ -670,6 +704,8 @@ DA8F257C1D51C5F40010E6B5 /* Layers */, DA87A99A1DC9D88800810D09 /* Sources */, 35C5D84B1D6DD75B00E95907 /* MGLFilterTests.mm */, + 353722EB1DF850ED004D2F3F /* MGLStyleValueTests.h */, + 3599A3E71DF70E2000E77FB2 /* MGLStyleValueTests.m */, DA2207BB1DC076940002F84D /* MGLStyleValueTests.swift */, ); name = Styling; @@ -679,11 +715,11 @@ DA8F25B81D51D2280010E6B5 /* Foundation Templates */ = { isa = PBXGroup; children = ( - 4032C5BA1DE1EECB0062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.h.ejs */, - 4032C5C71DE1FEAB0062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.mm.ejs */, - DA8F25B51D51D2240010E6B5 /* MGLRuntimeStylingTests.m.ejs */, DA8F25B61D51D2240010E6B5 /* MGLStyleLayer.h.ejs */, DA8F25B71D51D2240010E6B5 /* MGLStyleLayer.mm.ejs */, + DA8F25B51D51D2240010E6B5 /* MGLStyleLayerTests.m.ejs */, + 4032C5BA1DE1EECB0062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.h.ejs */, + 4032C5C71DE1FEAB0062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.mm.ejs */, ); name = "Foundation Templates"; path = ../../darwin/src; @@ -717,11 +753,11 @@ isa = PBXGroup; children = ( DAE6C34B1CC31E0400DB3429 /* MGLAnnotation.h */, - DACC22171CF3D4F700D220D9 /* MGLFeature_Private.h */, DACC22121CF3D3E200D220D9 /* MGLFeature.h */, + DACC22171CF3D4F700D220D9 /* MGLFeature_Private.h */, DACC22131CF3D3E200D220D9 /* MGLFeature.mm */, - DAE6C36C1CC31E2A00DB3429 /* MGLGeometry_Private.h */, DAE6C34C1CC31E0400DB3429 /* MGLGeometry.h */, + DAE6C36C1CC31E2A00DB3429 /* MGLGeometry_Private.h */, DAE6C36D1CC31E2A00DB3429 /* MGLGeometry.mm */, DAE6C34E1CC31E0400DB3429 /* MGLMultiPoint.h */, DAE6C36F1CC31E2A00DB3429 /* MGLMultiPoint_Private.h */, @@ -730,16 +766,17 @@ DAE6C3531CC31E0400DB3429 /* MGLPointAnnotation.h */, DAE6C3761CC31E2A00DB3429 /* MGLPointAnnotation.mm */, 4049C2A11DB6CE7800B3F799 /* MGLPointCollection.h */, + DAF0D80D1DFE0E5D00B28378 /* MGLPointCollection_Private.h */, 4049C2A71DB6D09B00B3F799 /* MGLPointCollection.mm */, DAE6C3541CC31E0400DB3429 /* MGLPolygon.h */, DAE6C3771CC31E2A00DB3429 /* MGLPolygon.mm */, DAE6C3551CC31E0400DB3429 /* MGLPolyline.h */, DAE6C3781CC31E2A00DB3429 /* MGLPolyline.mm */, - 408AA85A1DAEECF100022900 /* MGLShape_Private.h */, DAE6C3561CC31E0400DB3429 /* MGLShape.h */, + 408AA85A1DAEECF100022900 /* MGLShape_Private.h */, DAE6C3791CC31E2A00DB3429 /* MGLShape.mm */, DAD165721CF4CD7A001FF4B9 /* MGLShapeCollection.h */, - DAD165731CF4CD7A001FF4B9 /* MGLShapeCollection.m */, + DAD165731CF4CD7A001FF4B9 /* MGLShapeCollection.mm */, ); name = Geometry; sourceTree = ""; @@ -831,6 +868,8 @@ isa = PBXGroup; children = ( DA8F257D1D51C5F40010E6B5 /* Styling */, + DAEDC4311D6033F1000224FF /* MGLAttributionInfoTests.m */, + DAEDC4361D606291000224FF /* MGLAttributionButtonTests.m */, DA35A2C11CCA9F4A00E826B2 /* MGLClockDirectionFormatterTests.m */, DA35A2B51CCA14D700E826B2 /* MGLCompassDirectionFormatterTests.m */, DA35A2A71CC9F41600E826B2 /* MGLCoordinateFormatterTests.m */, @@ -842,6 +881,7 @@ DAE6C3CC1CC34BD800DB3429 /* MGLStyleTests.mm */, DD58A4C71D822C6200E1F038 /* MGLExpressionTests.mm */, DAE6C33A1CC30DB200DB3429 /* Info.plist */, + DA2784FD1DF03060001D5B8D /* Media.xcassets */, ); name = "SDK Tests"; path = test; @@ -858,10 +898,13 @@ DAE6C34A1CC31E0400DB3429 /* MGLAccountManager.h */, DAE6C36A1CC31E2A00DB3429 /* MGLAccountManager_Private.h */, DAE6C36B1CC31E2A00DB3429 /* MGLAccountManager.m */, - DD0902B01DB1AC6400C5BDCE /* MGLNetworkConfiguration.h */, - DD0902AF1DB1AC6400C5BDCE /* MGLNetworkConfiguration.m */, + DA00FC881D5EEAC3009AABC8 /* MGLAttributionInfo.h */, + DAF0D8151DFE6B1800B28378 /* MGLAttributionInfo_Private.h */, + DA00FC891D5EEAC3009AABC8 /* MGLAttributionInfo.mm */, DAE6C34D1CC31E0400DB3429 /* MGLMapCamera.h */, DAE6C36E1CC31E2A00DB3429 /* MGLMapCamera.mm */, + DD0902B01DB1AC6400C5BDCE /* MGLNetworkConfiguration.h */, + DD0902AF1DB1AC6400C5BDCE /* MGLNetworkConfiguration.m */, DAE6C3571CC31E0400DB3429 /* MGLStyle.h */, 3537CA731D3F93A600380318 /* MGLStyle_Private.h */, DAE6C37A1CC31E2A00DB3429 /* MGLStyle.mm */, @@ -881,7 +924,7 @@ DAC2ABC41CC6D343006D18C4 /* MGLAnnotationImage_Private.h */, DAE6C3A71CC31EF300DB3429 /* MGLAnnotationImage.m */, DAE6C3A81CC31EF300DB3429 /* MGLAttributionButton.h */, - DAE6C3A91CC31EF300DB3429 /* MGLAttributionButton.m */, + DAE6C3A91CC31EF300DB3429 /* MGLAttributionButton.mm */, DAE6C3AA1CC31EF300DB3429 /* MGLCompassCell.h */, DAE6C3AB1CC31EF300DB3429 /* MGLCompassCell.m */, DAE6C3A01CC31E9400DB3429 /* MGLMapView.h */, @@ -915,11 +958,13 @@ DA8F258F1D51CA600010E6B5 /* MGLRasterStyleLayer.h in Headers */, 3508EC641D749D39009B0EE4 /* NSExpression+MGLAdditions.h in Headers */, DAE6C38D1CC31E2A00DB3429 /* MGLOfflineRegion_Private.h in Headers */, + DA7DC9831DED647F0027472F /* MGLRasterSource_Private.h in Headers */, 408AA8651DAEEE3400022900 /* MGLPolygon+MGLAdditions.h in Headers */, DA8F259C1D51CB000010E6B5 /* MGLStyleValue_Private.h in Headers */, DAE6C35B1CC31E0400DB3429 /* MGLAnnotation.h in Headers */, DAE6C3B61CC31EF300DB3429 /* MGLMapView_Private.h in Headers */, 3527428D1D4C24AB00A1ECE6 /* MGLCircleStyleLayer.h in Headers */, + DA00FC8A1D5EEAC3009AABC8 /* MGLAttributionInfo.h in Headers */, DAE6C3B21CC31EF300DB3429 /* MGLAttributionButton.h in Headers */, 40B77E451DB11BC9003DA2FE /* NSArray+MGLAdditions.h in Headers */, 35C5D8471D6DD66D00E95907 /* NSComparisonPredicate+MGLAdditions.h in Headers */, @@ -931,6 +976,7 @@ DAE6C35E1CC31E0400DB3429 /* MGLMultiPoint.h in Headers */, 35602BFF1D3EA9B40050646F /* MGLStyleLayer_Private.h in Headers */, 4032C5C51DE1FE930062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.h in Headers */, + DAF0D8161DFE6B1800B28378 /* MGLAttributionInfo_Private.h in Headers */, DAE6C3971CC31E2A00DB3429 /* NSBundle+MGLAdditions.h in Headers */, DAED385F1D62CED700D7640F /* NSURL+MGLAdditions.h in Headers */, DAD165741CF4CD7A001FF4B9 /* MGLShapeCollection.h in Headers */, @@ -940,6 +986,7 @@ DAE6C39C1CC31E2A00DB3429 /* NSString+MGLAdditions.h in Headers */, 3529039B1D6C63B80002C7DF /* NSPredicate+MGLAdditions.h in Headers */, DA8F25971D51CAC70010E6B5 /* MGLVectorSource.h in Headers */, + DA7DC9811DED5F5C0027472F /* MGLVectorSource_Private.h in Headers */, DAE6C3861CC31E2A00DB3429 /* MGLGeometry_Private.h in Headers */, DAE6C3841CC31E2A00DB3429 /* MGLAccountManager_Private.h in Headers */, DAE6C3691CC31E0400DB3429 /* MGLTypes.h in Headers */, @@ -948,7 +995,8 @@ 4049C2A51DB6CE7F00B3F799 /* MGLPointCollection.h in Headers */, 30E5781B1DAA857E0050F07E /* NSImage+MGLAdditions.h in Headers */, DAE6C3661CC31E0400DB3429 /* MGLShape.h in Headers */, - DA551B831DB496AC0009AFAF /* MGLTileSet_Private.h in Headers */, + DA551B831DB496AC0009AFAF /* MGLTileSource_Private.h in Headers */, + DA7262071DEEDD460043BB89 /* MGLOpenGLStyleLayer.h in Headers */, 352742811D4C243B00A1ECE6 /* MGLSource.h in Headers */, DAE6C3C21CC31F4500DB3429 /* Mapbox.h in Headers */, DAE6C3641CC31E0400DB3429 /* MGLPolygon.h in Headers */, @@ -974,15 +1022,16 @@ 3538AA231D542685008EC33D /* MGLStyleLayer.h in Headers */, DAE6C35C1CC31E0400DB3429 /* MGLGeometry.h in Headers */, DAE6C35A1CC31E0400DB3429 /* MGLAccountManager.h in Headers */, - DA551B821DB496AC0009AFAF /* MGLTileSet.h in Headers */, + DA551B821DB496AC0009AFAF /* MGLTileSource.h in Headers */, 35602C001D3EA9B40050646F /* MGLForegroundStyleLayer.h in Headers */, DAE6C35D1CC31E0400DB3429 /* MGLMapCamera.h in Headers */, DAE6C3B41CC31EF300DB3429 /* MGLCompassCell.h in Headers */, - DA87A99C1DC9D8DD00810D09 /* MGLGeoJSONSource_Private.h in Headers */, + DA87A99C1DC9D8DD00810D09 /* MGLShapeSource_Private.h in Headers */, 3537CA741D3F93A600380318 /* MGLStyle_Private.h in Headers */, DA8F259A1D51CAD00010E6B5 /* MGLSource_Private.h in Headers */, DA8F25931D51CA750010E6B5 /* MGLSymbolStyleLayer.h in Headers */, DAE6C3B91CC31EF300DB3429 /* MGLOpenGLLayer.h in Headers */, + DAF0D80E1DFE0E5D00B28378 /* MGLPointCollection_Private.h in Headers */, 35D65C5A1D65AD5500722C23 /* NSDate+MGLAdditions.h in Headers */, DAE6C3891CC31E2A00DB3429 /* MGLMultiPoint_Private.h in Headers */, DAE6C3A51CC31E9400DB3429 /* MGLMapView+IBAdditions.h in Headers */, @@ -991,7 +1040,7 @@ 408AA85B1DAEECFE00022900 /* MGLShape_Private.h in Headers */, DACC22181CF3D4F700D220D9 /* MGLFeature_Private.h in Headers */, DA6408D71DA4E5DA00908C90 /* MGLVectorStyleLayer.h in Headers */, - 352742891D4C245800A1ECE6 /* MGLGeoJSONSource.h in Headers */, + 352742891D4C245800A1ECE6 /* MGLShapeSource.h in Headers */, 408AA8671DAEEE3900022900 /* NSDictionary+MGLAdditions.h in Headers */, DAE6C3671CC31E0400DB3429 /* MGLStyle.h in Headers */, ); @@ -1150,6 +1199,7 @@ buildActionMask = 2147483647; files = ( 35724FC41D630502002A4AB4 /* amsterdam.geojson in Resources */, + DA2784FE1DF03060001D5B8D /* Media.xcassets in Resources */, DA2DBBCB1D51E30A00D38FF9 /* MGLStyleLayerTests.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1165,6 +1215,7 @@ DA839E9D1CC2E3400062CAFB /* MapDocument.m in Sources */, DAE6C2ED1CC3050F00DB3429 /* DroppedPinAnnotation.m in Sources */, DAE6C2EE1CC3050F00DB3429 /* LocationCoordinate2DTransformer.m in Sources */, + DAB2CCE51DF632ED001B2FE1 /* LimeGreenStyleLayer.m in Sources */, DAE6C2F11CC3050F00DB3429 /* TimeIntervalTransformer.m in Sources */, DA839E9A1CC2E3400062CAFB /* main.m in Sources */, DA839E971CC2E3400062CAFB /* AppDelegate.m in Sources */, @@ -1187,8 +1238,9 @@ DAE6C3B11CC31EF300DB3429 /* MGLAnnotationImage.m in Sources */, 3508EC651D749D39009B0EE4 /* NSExpression+MGLAdditions.mm in Sources */, DACC22151CF3D3E200D220D9 /* MGLFeature.mm in Sources */, + DA7262081DEEDD460043BB89 /* MGLOpenGLStyleLayer.mm in Sources */, 355BA4EE1D41633E00CCC6D5 /* NSColor+MGLAdditions.mm in Sources */, - DAE6C3B31CC31EF300DB3429 /* MGLAttributionButton.m in Sources */, + DAE6C3B31CC31EF300DB3429 /* MGLAttributionButton.mm in Sources */, 35602BFB1D3EA99F0050646F /* MGLFillStyleLayer.mm in Sources */, DAE6C3931CC31E2A00DB3429 /* MGLShape.mm in Sources */, 352742861D4C244700A1ECE6 /* MGLRasterSource.mm in Sources */, @@ -1200,7 +1252,7 @@ 35602C011D3EA9B40050646F /* MGLForegroundStyleLayer.m in Sources */, 408AA86A1DAEEE5D00022900 /* NSDictionary+MGLAdditions.mm in Sources */, DA8F25881D51C9E10010E6B5 /* MGLBackgroundStyleLayer.mm in Sources */, - DA551B841DB496AC0009AFAF /* MGLTileSet.mm in Sources */, + DA551B841DB496AC0009AFAF /* MGLTileSource.mm in Sources */, DAE6C3B81CC31EF300DB3429 /* MGLMapView+IBAdditions.mm in Sources */, DA35A2D01CCAAED300E826B2 /* NSValue+MGLAdditions.m in Sources */, 3538AA241D542685008EC33D /* MGLStyleLayer.mm in Sources */, @@ -1222,11 +1274,12 @@ 408AA8681DAEEE5200022900 /* MGLPolygon+MGLAdditions.m in Sources */, DAE6C3951CC31E2A00DB3429 /* MGLTilePyramidOfflineRegion.mm in Sources */, DAE6C3851CC31E2A00DB3429 /* MGLAccountManager.m in Sources */, + DA00FC8B1D5EEAC3009AABC8 /* MGLAttributionInfo.mm in Sources */, DAE6C3921CC31E2A00DB3429 /* MGLPolyline.mm in Sources */, - 3527428A1D4C245800A1ECE6 /* MGLGeoJSONSource.mm in Sources */, + 3527428A1D4C245800A1ECE6 /* MGLShapeSource.mm in Sources */, DAE6C3B51CC31EF300DB3429 /* MGLCompassCell.m in Sources */, DA8F25901D51CA600010E6B5 /* MGLRasterStyleLayer.mm in Sources */, - DAD165751CF4CD7A001FF4B9 /* MGLShapeCollection.m in Sources */, + DAD165751CF4CD7A001FF4B9 /* MGLShapeCollection.mm in Sources */, 35C5D8481D6DD66D00E95907 /* NSComparisonPredicate+MGLAdditions.mm in Sources */, DA35A2AE1CCA091800E826B2 /* MGLCompassDirectionFormatter.m in Sources */, DA8F258C1D51CA540010E6B5 /* MGLLineStyleLayer.mm in Sources */, @@ -1246,6 +1299,7 @@ DAE6C3D41CC34C9900DB3429 /* MGLOfflineRegionTests.m in Sources */, DA87A9A11DC9DCB400810D09 /* MGLRuntimeStylingHelper.m in Sources */, DAE6C3D61CC34C9900DB3429 /* MGLStyleTests.mm in Sources */, + DAEDC4371D606291000224FF /* MGLAttributionButtonTests.m in Sources */, DA35A2B61CCA14D700E826B2 /* MGLCompassDirectionFormatterTests.m in Sources */, DAE6C3D21CC34C9900DB3429 /* MGLGeometryTests.mm in Sources */, DA87A9A41DCACC5000810D09 /* MGLSymbolStyleLayerTests.m in Sources */, @@ -1260,8 +1314,10 @@ DA87A9A31DCACC5000810D09 /* MGLRasterStyleLayerTests.m in Sources */, DA87A9991DC9D88400810D09 /* MGLTileSetTests.mm in Sources */, DA35A2A81CC9F41600E826B2 /* MGLCoordinateFormatterTests.m in Sources */, - DA87A9981DC9D88400810D09 /* MGLGeoJSONSourceTests.mm in Sources */, + DA87A9981DC9D88400810D09 /* MGLShapeSourceTests.mm in Sources */, DA87A9A21DC9DCF100810D09 /* MGLFillStyleLayerTests.m in Sources */, + 3599A3E81DF70E2000E77FB2 /* MGLStyleValueTests.m in Sources */, + DAEDC4321D6033F1000224FF /* MGLAttributionInfoTests.m in Sources */, DA0CD58E1CF56F5800A5F5A5 /* MGLFeatureTests.mm in Sources */, DA2207BC1DC076940002F84D /* MGLStyleValueTests.swift in Sources */, ); diff --git a/platform/macos/scripts/document.sh b/platform/macos/scripts/document.sh index fc026d08f..d03ad9167 100755 --- a/platform/macos/scripts/document.sh +++ b/platform/macos/scripts/document.sh @@ -43,4 +43,4 @@ jazzy \ --output ${OUTPUT} # https://github.com/realm/jazzy/issues/411 find ${OUTPUT} -name *.html -exec \ - perl -pi -e 's/Mapbox\s+(Docs|Reference)/Mapbox macOS SDK $1/' {} \; + perl -pi -e 's/BRANDLESS_DOCSET_TITLE/macOS SDK $1/, s/Mapbox\s+(Docs|Reference)/Mapbox macOS SDK $1/' {} \; diff --git a/platform/macos/sdk/Base.lproj/Localizable.strings b/platform/macos/sdk/Base.lproj/Localizable.strings index 818c82b2e..b7a4a2117 100644 --- a/platform/macos/sdk/Base.lproj/Localizable.strings +++ b/platform/macos/sdk/Base.lproj/Localizable.strings @@ -1,18 +1,3 @@ -/* Linked part of copyright notice */ -"COPYRIGHT_MAPBOX" = "Mapbox"; - -/* Copyright notice link */ -"COPYRIGHT_MAPBOX_LINK" = "https://www.mapbox.com/about/maps/"; - -/* Linked part of copyright notice */ -"COPYRIGHT_OSM" = "OpenStreetMap"; - -/* Copyright notice link */ -"COPYRIGHT_OSM_LINK" = "http://www.openstreetmap.org/about/"; - -/* Copyright notice prefix */ -"COPYRIGHT_PREFIX" = "© "; - /* Accessibility title */ "MAP_A11Y_TITLE" = "Mapbox"; diff --git a/platform/macos/src/MGLAttributionButton.h b/platform/macos/src/MGLAttributionButton.h index 9ff313784..88fcdadf7 100644 --- a/platform/macos/src/MGLAttributionButton.h +++ b/platform/macos/src/MGLAttributionButton.h @@ -1,15 +1,23 @@ #import +#import "MGLTypes.h" + +NS_ASSUME_NONNULL_BEGIN + +@class MGLAttributionInfo; + /// Button that looks like a hyperlink and opens a URL. @interface MGLAttributionButton : NSButton -/// Returns an `MGLAttributionButton` instance with the given title and URL. -- (instancetype)initWithTitle:(NSString *)title URL:(NSURL *)url; +/// Returns an `MGLAttributionButton` instance with the given info. +- (instancetype)initWithAttributionInfo:(MGLAttributionInfo *)info; /// The URL to open and display as a tooltip. -@property (nonatomic) NSURL *URL; +@property (nonatomic, readonly, nullable) NSURL *URL; /// Opens the URL. -- (IBAction)openURL:(id)sender; +- (IBAction)openURL:(nullable id)sender; @end + +NS_ASSUME_NONNULL_END diff --git a/platform/macos/src/MGLAttributionButton.m b/platform/macos/src/MGLAttributionButton.m deleted file mode 100644 index e21b86079..000000000 --- a/platform/macos/src/MGLAttributionButton.m +++ /dev/null @@ -1,50 +0,0 @@ -#import "MGLAttributionButton.h" - -#import "NSBundle+MGLAdditions.h" - -@implementation MGLAttributionButton { - NSTrackingRectTag _trackingAreaTag; -} - -- (instancetype)initWithTitle:(NSString *)title URL:(NSURL *)url { - if (self = [super initWithFrame:NSZeroRect]) { - self.bordered = NO; - self.bezelStyle = NSRegularSquareBezelStyle; - - // Start with a copyright symbol. The whole string will be mini. - NSMutableAttributedString *attributedTitle = [[NSMutableAttributedString alloc] initWithString:NSLocalizedStringWithDefaultValue(@"COPYRIGHT_PREFIX", nil, nil, @"© ", @"Copyright notice prefix") attributes:@{ - NSFontAttributeName: [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSMiniControlSize]], - }]; - // Append the specified title, underlining it like a hyperlink. - [attributedTitle appendAttributedString: - [[NSAttributedString alloc] initWithString:title - attributes:@{ - NSFontAttributeName: [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSMiniControlSize]], - NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle), - }]]; - self.attributedTitle = attributedTitle; - [self sizeToFit]; - - _URL = url; - self.toolTip = _URL.absoluteString; - - self.target = self; - self.action = @selector(openURL:); - } - return self; -} - -- (BOOL)wantsLayer { - return YES; -} - -- (void)resetCursorRects { - // The whole button gets a pointing hand cursor, just like a hyperlink. - [self addCursorRect:self.bounds cursor:[NSCursor pointingHandCursor]]; -} - -- (IBAction)openURL:(__unused id)sender { - [[NSWorkspace sharedWorkspace] openURL:self.URL]; -} - -@end diff --git a/platform/macos/src/MGLAttributionButton.mm b/platform/macos/src/MGLAttributionButton.mm new file mode 100644 index 000000000..ed8bb18a6 --- /dev/null +++ b/platform/macos/src/MGLAttributionButton.mm @@ -0,0 +1,55 @@ +#import "MGLAttributionButton.h" +#import "MGLAttributionInfo.h" + +#import "NSBundle+MGLAdditions.h" +#import "NSString+MGLAdditions.h" + +@implementation MGLAttributionButton + +- (instancetype)initWithAttributionInfo:(MGLAttributionInfo *)info { + if (self = [super initWithFrame:NSZeroRect]) { + self.bordered = NO; + self.bezelStyle = NSRegularSquareBezelStyle; + + // Extract any prefix consisting of intellectual property symbols. + NSScanner *scanner = [NSScanner scannerWithString:info.title.string]; + NSCharacterSet *symbolSet = [NSCharacterSet characterSetWithCharactersInString:@"©℗®℠™ &"]; + NSString *symbol; + [scanner scanCharactersFromSet:symbolSet intoString:&symbol]; + + // Remove the underline from the symbol for aesthetic reasons. + NSMutableAttributedString *title = info.title.mutableCopy; + [title removeAttribute:NSUnderlineStyleAttributeName range:NSMakeRange(0, symbol.length)]; + + self.attributedTitle = title; + [self sizeToFit]; + + _URL = info.URL; + if (_URL) { + self.toolTip = _URL.absoluteString; + } + + self.target = self; + self.action = @selector(openURL:); + } + return self; +} + +- (BOOL)wantsLayer { + return YES; +} + +- (void)resetCursorRects { + if (self.URL) { + // The whole button gets a pointing hand cursor, just like a hyperlink. + [self addCursorRect:self.bounds cursor:[NSCursor pointingHandCursor]]; + } +} + +- (IBAction)openURL:(__unused id)sender { + if (self.URL) { + [[NSWorkspace sharedWorkspace] openURL:self.URL]; + } +} + +@end diff --git a/platform/macos/src/MGLMapView.h b/platform/macos/src/MGLMapView.h index 88745db21..ea87f3b33 100644 --- a/platform/macos/src/MGLMapView.h +++ b/platform/macos/src/MGLMapView.h @@ -950,6 +950,25 @@ IB_DESIGNABLE */ - (CLLocationDistance)metersPerPointAtLatitude:(CLLocationDegrees)latitude; +#pragma mark Giving Feedback to Improve the Map + +/** + Opens one or more webpages in the default Web browser in which the user can + provide feedback about the map data. + + You should add a menu item to the Help menu of your application that invokes + this method. Title it “Improve This Map” or similar. Set its target to the + first responder and its action to `giveFeedback:`. + + This map view searches the current style’s sources for webpages to open. + Specifically, each source’s tile set has an `attribution` property containing + HTML code; if an <a> tag (link) within that code has an + class attribute set to mapbox-improve-map, its + href attribute defines the URL to open. Such links are omitted + from the attribution view. + */ +- (IBAction)giveFeedback:(id)sender; + #pragma mark Debugging the Map /** diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm index 90d2907d1..92aa0a6c6 100644 --- a/platform/macos/src/MGLMapView.mm +++ b/platform/macos/src/MGLMapView.mm @@ -1,6 +1,7 @@ #import "MGLMapView_Private.h" #import "MGLAnnotationImage_Private.h" #import "MGLAttributionButton.h" +#import "MGLAttributionInfo.h" #import "MGLCompassCell.h" #import "MGLOpenGLLayer.h" #import "MGLStyle.h" @@ -83,23 +84,6 @@ const CGFloat MGLAnnotationImagePaddingForHitTest = 4; /// Distance from the callout’s anchor point to the annotation it points to. const CGFloat MGLAnnotationImagePaddingForCallout = 4; -/// Copyright notices displayed in the attribution view. -struct MGLAttribution { - /// Attribution button label text. A copyright symbol is prepended to this string. - NSString *title; - /// URL to open when the attribution button is clicked. - NSString *urlString; -} MGLAttributions[] = { - { - .title = NSLocalizedStringWithDefaultValue(@"COPYRIGHT_MAPBOX", nil, nil, @"Mapbox", @"Linked part of copyright notice"), - .urlString = NSLocalizedStringWithDefaultValue(@"COPYRIGHT_MAPBOX_LINK", nil, nil, @"https://www.mapbox.com/about/maps/", @"Copyright notice link"), - }, - { - .title = NSLocalizedStringWithDefaultValue(@"COPYRIGHT_OSM", nil, nil, @"OpenStreetMap", @"Linked part of copyright notice"), - .urlString = NSLocalizedStringWithDefaultValue(@"COPYRIGHT_OSM_LINK", nil, nil, @"http://www.openstreetmap.org/about/", @"Copyright notice link"), - }, -}; - /// Unique identifier representing a single annotation in mbgl. typedef uint32_t MGLAnnotationTag; @@ -378,6 +362,7 @@ public: /// Adds legally required map attribution to the lower-left corner. - (void)installAttributionView { + [_attributionView removeFromSuperview]; _attributionView = [[NSView alloc] initWithFrame:NSZeroRect]; _attributionView.wantsLayer = YES; @@ -440,37 +425,69 @@ public: /// Updates the attribution view to reflect the sources used. For now, this is /// hard-coded to the standard Mapbox and OpenStreetMap attribution. - (void)updateAttributionView { - self.attributionView.subviews = @[]; - - for (NSUInteger i = 0; i < sizeof(MGLAttributions) / sizeof(MGLAttributions[0]); i++) { + NSView *attributionView = self.attributionView; + for (NSView *button in attributionView.subviews) { + [button removeConstraints:button.constraints]; + } + attributionView.subviews = @[]; + [attributionView removeConstraints:attributionView.constraints]; + + // Make the whole string mini by default. + // Force links to be black, because the default blue is distracting. + CGFloat miniSize = [NSFont systemFontSizeForControlSize:NSMiniControlSize]; + NSArray *attributionInfos = [self.style attributionInfosWithFontSize:miniSize linkColor:[NSColor blackColor]]; + for (MGLAttributionInfo *info in attributionInfos) { + // Feedback links are added to the Help menu. + if (info.feedbackLink) { + continue; + } + // For each attribution, add a borderless button that responds to clicks // and feels like a hyperlink. - NSURL *url = [NSURL URLWithString:MGLAttributions[i].urlString]; - NSButton *button = [[MGLAttributionButton alloc] initWithTitle:MGLAttributions[i].title URL:url]; + NSButton *button = [[MGLAttributionButton alloc] initWithAttributionInfo:info]; button.controlSize = NSMiniControlSize; button.translatesAutoresizingMaskIntoConstraints = NO; // Set the new button flush with the buttom of the container and to the // right of the previous button, with standard spacing. If there is no // previous button, align to the container instead. - NSView *previousView = self.attributionView.subviews.lastObject; - [self.attributionView addSubview:button]; - [_attributionView addConstraint: + NSView *previousView = attributionView.subviews.lastObject; + [attributionView addSubview:button]; + [attributionView addConstraint: [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual - toItem:_attributionView + toItem:attributionView attribute:NSLayoutAttributeBottom multiplier:1 constant:0]]; - [_attributionView addConstraint: + [attributionView addConstraint: [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual - toItem:previousView ? previousView : _attributionView + toItem:previousView ? previousView : attributionView attribute:previousView ? NSLayoutAttributeTrailing : NSLayoutAttributeLeading multiplier:1 constant:8]]; + [attributionView addConstraint: + [NSLayoutConstraint constraintWithItem:button + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:attributionView + attribute:NSLayoutAttributeTop + multiplier:1 + constant:0]]; + } + + if (attributionInfos.count) { + [attributionView addConstraint: + [NSLayoutConstraint constraintWithItem:attributionView + attribute:NSLayoutAttributeTrailing + relatedBy:NSLayoutRelationEqual + toItem:attributionView.subviews.lastObject + attribute:NSLayoutAttributeTrailing + multiplier:1 + constant:8]]; } } @@ -738,20 +755,6 @@ public: attribute:NSLayoutAttributeTrailing multiplier:1 constant:8]]; - [self addConstraint:[NSLayoutConstraint constraintWithItem:_attributionView.subviews.firstObject - attribute:NSLayoutAttributeTop - relatedBy:NSLayoutRelationEqual - toItem:_attributionView - attribute:NSLayoutAttributeTop - multiplier:1 - constant:0]]; - [self addConstraint:[NSLayoutConstraint constraintWithItem:_attributionView - attribute:NSLayoutAttributeTrailing - relatedBy:NSLayoutRelationEqual - toItem:_attributionView.subviews.lastObject - attribute:NSLayoutAttributeTrailing - multiplier:1 - constant:8]]; [super updateConstraints]; } @@ -802,7 +805,7 @@ public: _mbglMap->setSourceTileCacheSize(cacheSize); } -- (void)invalidate { +- (void)setNeedsGLDisplay { MGLAssertIsMainThread(); [self.layer setNeedsDisplay]; @@ -930,6 +933,12 @@ public: } break; } + case mbgl::MapChangeSourceDidChange: + { + [self installAttributionView]; + self.needsUpdateConstraints = YES; + break; + } } } @@ -937,7 +946,7 @@ public: - (void)print:(__unused id)sender { _isPrinting = YES; - [self invalidate]; + [self setNeedsGLDisplay]; } - (void)printWithImage:(NSImage *)image { @@ -1646,6 +1655,23 @@ public: [self setDirection:-sender.doubleValue animated:YES]; } +- (IBAction)giveFeedback:(id)sender { + CLLocationCoordinate2D centerCoordinate = self.centerCoordinate; + double zoomLevel = self.zoomLevel; + NSMutableArray *urls = [NSMutableArray array]; + for (MGLAttributionInfo *info in [self.style attributionInfosWithFontSize:0 linkColor:nil]) { + NSURL *url = [info feedbackURLAtCenterCoordinate:centerCoordinate zoomLevel:zoomLevel]; + if (url) { + [urls addObject:url]; + } + } + [[NSWorkspace sharedWorkspace] openURLs:urls + withAppBundleIdentifier:nil + options:0 + additionalEventParamDescriptor:nil + launchIdentifiers:nil]; +} + #pragma mark Annotations - (nullable NS_ARRAY_OF(id ) *)annotations { @@ -2460,6 +2486,15 @@ public: return MGLFeaturesFromMBGLFeatures(features); } +#pragma mark User interface validation + +- (BOOL)validateMenuItem:(NSMenuItem *)menuItem { + if (menuItem.action == @selector(giveFeedback:)) { + return YES; + } + return [super validateMenuItem:menuItem]; +} + #pragma mark Interface Builder methods - (void)prepareForInterfaceBuilder { @@ -2629,7 +2664,7 @@ public: } void invalidate() override { - [nativeView invalidate]; + [nativeView setNeedsGLDisplay]; } void activate() override { diff --git a/platform/macos/src/MGLMapView_Private.h b/platform/macos/src/MGLMapView_Private.h index cf813e0bf..0980252fb 100644 --- a/platform/macos/src/MGLMapView_Private.h +++ b/platform/macos/src/MGLMapView_Private.h @@ -19,6 +19,9 @@ /// Center longitude set independently of the center latitude in an inspectable. @property (nonatomic) CLLocationDegrees pendingLongitude; +/// Asynchronously render a frame of the map. +- (void)setNeedsGLDisplay; + /// Synchronously render a frame of the map. - (void)renderSync; diff --git a/platform/macos/src/Mapbox.h b/platform/macos/src/Mapbox.h index 73b8624be..524ff1a93 100644 --- a/platform/macos/src/Mapbox.h +++ b/platform/macos/src/Mapbox.h @@ -39,12 +39,15 @@ FOUNDATION_EXPORT const unsigned char MapboxVersionString[]; #import "MGLRasterStyleLayer.h" #import "MGLCircleStyleLayer.h" #import "MGLBackgroundStyleLayer.h" +#import "MGLOpenGLStyleLayer.h" #import "MGLSource.h" +#import "MGLTileSource.h" #import "MGLVectorSource.h" -#import "MGLGeoJSONSource.h" +#import "MGLShapeSource.h" #import "MGLRasterSource.h" #import "MGLTilePyramidOfflineRegion.h" #import "MGLTypes.h" #import "NSValue+MGLAdditions.h" #import "NSValue+MGLStyleEnumAttributeAdditions.h" #import "MGLStyleValue.h" +#import "MGLAttributionInfo.h" diff --git a/platform/macos/src/NSImage+MGLAdditions.h b/platform/macos/src/NSImage+MGLAdditions.h index a2144e96a..ee01a763a 100644 --- a/platform/macos/src/NSImage+MGLAdditions.h +++ b/platform/macos/src/NSImage+MGLAdditions.h @@ -2,8 +2,14 @@ #include +NS_ASSUME_NONNULL_BEGIN + @interface NSImage (MGLAdditions) +- (nullable instancetype)initWithMGLSpriteImage:(const mbgl::SpriteImage *)spriteImage; + - (std::unique_ptr)mgl_spriteImage; @end + +NS_ASSUME_NONNULL_END diff --git a/platform/macos/src/NSImage+MGLAdditions.mm b/platform/macos/src/NSImage+MGLAdditions.mm index 2c4b16800..72ddec83f 100644 --- a/platform/macos/src/NSImage+MGLAdditions.mm +++ b/platform/macos/src/NSImage+MGLAdditions.mm @@ -2,6 +2,17 @@ @implementation NSImage (MGLAdditions) +- (nullable instancetype)initWithMGLSpriteImage:(const mbgl::SpriteImage *)spriteImage { + std::string png = encodePNG(spriteImage->image); + NSData *data = [[NSData alloc] initWithBytes:png.data() length:png.size()]; + NSBitmapImageRep *rep = [NSBitmapImageRep imageRepWithData:data]; + if ([self initWithSize:NSMakeSize(spriteImage->getWidth(), spriteImage->getHeight())]) { + [self addRepresentation:rep]; + [self setTemplate:spriteImage->sdf]; + } + return self; +} + - (std::unique_ptr)mgl_spriteImage { // Create a bitmap image representation from the image, respecting backing // scale factor and any resizing done on the image at runtime. @@ -10,13 +21,11 @@ NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithFocusedViewRect:{ NSZeroPoint, self.size }]; [self unlockFocus]; - // Get the image’s raw pixel data as an RGBA buffer. - std::string pixelString((const char *)rep.bitmapData, rep.pixelsWide * rep.pixelsHigh * 4 /* RGBA */); - mbgl::PremultipliedImage cPremultipliedImage({ static_cast(rep.pixelsWide), static_cast(rep.pixelsHigh) }); std::copy(rep.bitmapData, rep.bitmapData + cPremultipliedImage.bytes(), cPremultipliedImage.data.get()); return std::make_unique(std::move(cPremultipliedImage), - (float)(rep.pixelsWide / self.size.width)); + (float)(rep.pixelsWide / self.size.width), + [self isTemplate]); } @end diff --git a/platform/macos/test/MGLAttributionButtonTests.m b/platform/macos/test/MGLAttributionButtonTests.m new file mode 100644 index 000000000..f5c0aac85 --- /dev/null +++ b/platform/macos/test/MGLAttributionButtonTests.m @@ -0,0 +1,31 @@ +#import +#import + +#import "MGLAttributionButton.h" +#import "MGLAttributionInfo.h" + +@interface MGLAttributionButtonTests : XCTestCase + +@end + +@implementation MGLAttributionButtonTests + +- (void)testPlainSymbol { + NSAttributedString *title = [[NSAttributedString alloc] initWithString:@"® & ™ Mapbox" attributes:@{ + NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle), + }]; + MGLAttributionInfo *info = [[MGLAttributionInfo alloc] initWithTitle:title URL:nil]; + MGLAttributionButton *button = [[MGLAttributionButton alloc] initWithAttributionInfo:info]; + + NSRange symbolUnderlineRange; + NSNumber *symbolUnderline = [button.attributedTitle attribute:NSUnderlineStyleAttributeName atIndex:0 effectiveRange:&symbolUnderlineRange]; + XCTAssertNil(symbolUnderline); + XCTAssertEqual(symbolUnderlineRange.length, 6); + + NSRange wordUnderlineRange; + NSNumber *wordUnderline = [button.attributedTitle attribute:NSUnderlineStyleAttributeName atIndex:6 effectiveRange:&wordUnderlineRange]; + XCTAssertEqualObjects(wordUnderline, @(NSUnderlineStyleSingle)); + XCTAssertEqual(wordUnderlineRange.length, 6); +} + +@end diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index f94075a51..d76044cd4 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -923,6 +923,13 @@ void Map::removeImage(const std::string& name) { impl->onUpdate(Update::Repaint); } +const SpriteImage* Map::getImage(const std::string& name) { + if (impl->style) { + return impl->style->spriteAtlas->getSprite(name).get(); + } + return nullptr; +} + #pragma mark - Defaults std::string Map::getStyleName() const { diff --git a/test/fixtures/map/get_icon/expected.png b/test/fixtures/map/get_icon/expected.png new file mode 100644 index 000000000..b112096c1 Binary files /dev/null and b/test/fixtures/map/get_icon/expected.png differ diff --git a/test/map/map.test.cpp b/test/map/map.test.cpp index 0df7c7c2a..8eedeb3c0 100644 --- a/test/map/map.test.cpp +++ b/test/map/map.test.cpp @@ -396,6 +396,18 @@ TEST(Map, RemoveImage) { test::checkImage("test/fixtures/map/remove_icon", test::render(map, test.view)); } +TEST(Map, GetImage) { + MapTest test; + + Map map(test.backend, test.view.size, 1, test.fileSource, test.threadPool, MapMode::Still); + auto decoded = decodeImage(util::read_file("test/fixtures/sprites/default_marker.png")); + auto image = std::make_unique(std::move(decoded), 1.0); + + map.setStyleJSON(util::read_file("test/fixtures/api/icon_style.json")); + map.addImage("test-icon", std::move(image)); + test::checkImage("test/fixtures/map/get_icon", map.getImage("test-icon")->image); +} + TEST(Map, DontLoadUnneededTiles) { MapTest test;